1//////////////////////////////////////////////////////////////////////
  2// LibFile: trigonometry.scad
  3//   Trigonometry shortcuts for people who can't be bothered to remember
  4//   all the function relations, or silly acronyms like SOHCAHTOA.
  5// Includes:
  6//   include <BOSL2/std.scad>
  7// FileGroup: Math
  8// FileSummary: Trigonometry shortcuts for when you can't recall the mnemonic SOHCAHTOA.
  9// FileFootnotes: STD=Included in std.scad
 10//////////////////////////////////////////////////////////////////////
 11
 12
 13
 14// Section: 2D General Triangle Functions
 15
 16
 17// Function: law_of_cosines()
 18// Synopsis: Applies the Law of Cosines for an arbitrary triangle.
 19// Topics: Geometry, Trigonometry, Triangles
 20// See Also: law_of_sines()
 21// Usage:
 22//   C = law_of_cosines(a, b, c);
 23//   c = law_of_cosines(a, b, C=);
 24// Description:
 25//   Applies the Law of Cosines for an arbitrary triangle.  Given three side lengths, returns the
 26//   angle in degrees for the corner opposite of the third side.  Given two side lengths, and the
 27//   angle between them, returns the length of the third side.
 28// Figure(2D):
 29//   stroke([[-50,0], [10,60], [50,0]], closed=true);
 30//   color("black") {
 31//       translate([ 33,35]) text(text="a", size=8, halign="center", valign="center");
 32//       translate([  0,-6]) text(text="b", size=8, halign="center", valign="center");
 33//       translate([-22,35]) text(text="c", size=8, halign="center", valign="center");
 34//   }
 35//   color("blue") {
 36//       translate([-37, 6]) text(text="A", size=8, halign="center", valign="center");
 37//       translate([  9,51]) text(text="B", size=8, halign="center", valign="center");
 38//       translate([ 38, 6]) text(text="C", size=8, halign="center", valign="center");
 39//   }
 40// Arguments:
 41//   a = The length of the first side.
 42//   b = The length of the second side.
 43//   c = The length of the third side.
 44//   ---
 45//   C = The angle in degrees of the corner opposite of the third side.
 46function law_of_cosines(a, b, c, C) =
 47    // Triangle Law of Cosines:
 48    //   c^2 = a^2 + b^2 - 2*a*b*cos(C)
 49    assert(num_defined([c,C]) == 1, "Must give exactly one of c= or C=.")
 50    is_undef(c) ? sqrt(a*a + b*b - 2*a*b*cos(C)) :
 51    acos(constrain((a*a + b*b - c*c) / (2*a*b), -1, 1));
 52
 53
 54// Function: law_of_sines()
 55// Synopsis: Applies the Law of Sines for an arbitrary triangle.
 56// Topics: Geometry, Trigonometry, Triangles
 57// See Also: law_of_cosines()
 58// Usage:
 59//   B = law_of_sines(a, A, b);
 60//   b = law_of_sines(a, A, B=);
 61// Description:
 62//   Applies the Law of Sines for an arbitrary triangle.  Given two triangle side lengths and the
 63//   angle between them, returns the angle of the corner opposite of the second side.  Given a side
 64//   length, the opposing angle, and a second angle, returns the length of the side opposite of the
 65//   second angle.
 66// Figure(2D):
 67//   stroke([[-50,0], [10,60], [50,0]], closed=true);
 68//   color("black") {
 69//       translate([ 33,35]) text(text="a", size=8, halign="center", valign="center");
 70//       translate([  0,-6]) text(text="b", size=8, halign="center", valign="center");
 71//       translate([-22,35]) text(text="c", size=8, halign="center", valign="center");
 72//   }
 73//   color("blue") {
 74//       translate([-37, 6]) text(text="A", size=8, halign="center", valign="center");
 75//       translate([  9,51]) text(text="B", size=8, halign="center", valign="center");
 76//       translate([ 38, 6]) text(text="C", size=8, halign="center", valign="center");
 77//   }
 78// Arguments:
 79//   a = The length of the first side.
 80//   A = The angle in degrees of the corner opposite of the first side.
 81//   b = The length of the second side.
 82//   ---
 83//   B = The angle in degrees of the corner opposite of the second side.
 84function law_of_sines(a, A, b, B) =
 85    // Triangle Law of Sines:
 86    //   a/sin(A) = b/sin(B) = c/sin(C)
 87    assert(num_defined([b,B]) == 1, "Must give exactly one of b= or B=.")
 88    let( r = a/sin(A) )
 89    is_undef(b) ? r*sin(B) :
 90    asin(constrain(b/r, -1, 1));
 91
 92
 93
 94// Section: 2D Right Triangle Functions
 95//   This is a set of functions to make it easier to perform trig calculations on right triangles.
 96//   In general, all these functions are named using these abbreviations:
 97//   - **hyp**: The length of the Hypotenuse.
 98//   - **adj**: The length of the side adjacent to the angle.
 99//   - **opp**: The length of the side opposite to the angle.
100//   - **ang**: The angle size in degrees.
101//   .
102//   If you know two of those, and want to know the value of a third, you will need to call a
103//   function named like `AAA_BBB_to_CCC()`.  For example, if you know the length of the hypotenuse,
104//   and the length of the side adjacent to the angle, and want to learn the length of the side
105//   opposite to the angle, you will call `opp = hyp_adj_to_opp(hyp,adj);`.
106// Figure(2D):
107//   color("brown") {
108//       stroke([[40,0], [40,10], [50,10]]);
109//       left(50) stroke(arc(r=37,angle=30));
110//   }
111//   color("lightgreen") stroke([[-50,0], [50,60], [50,0]], closed=true);
112//   color("black") {
113//       translate([ 62,25]) text(text="opp", size=8, halign="center", valign="center");
114//       translate([  0,-6]) text(text="adj", size=8, halign="center", valign="center");
115//       translate([  0,40]) text(text="hyp", size=8, halign="center", valign="center");
116//       translate([-25, 5]) text(text="ang", size=7, halign="center", valign="center");
117//   }
118
119
120// Function: hyp_opp_to_adj()
121// Alias: opp_hyp_to_adj()
122// Synopsis: Returns the adjacent side length from the lengths of the hypotenuse and the opposite side.
123// Topics: Geometry, Trigonometry, Triangles
124// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
125// Usage:
126//   adj = hyp_opp_to_adj(hyp,opp);
127//   adj = opp_hyp_to_adj(opp,hyp);
128// Description:
129//   Given the lengths of the hypotenuse and opposite side of a right triangle, returns the length
130//   of the adjacent side.
131// Arguments:
132//   hyp = The length of the hypotenuse of the right triangle.
133//   opp = The length of the side of the right triangle that is opposite from the primary angle.
134// Example:
135//   hyp = hyp_opp_to_adj(5,3);  // Returns: 4
136function hyp_opp_to_adj(hyp,opp) =
137    assert(is_finite(hyp+opp) && hyp>=0 && opp>=0,
138           "Triangle side lengths should be a positive numbers." )
139    sqrt(hyp*hyp-opp*opp);
140
141function opp_hyp_to_adj(opp,hyp) = hyp_opp_to_adj(hyp,opp);
142
143
144// Function: hyp_ang_to_adj()
145// Alias: ang_hyp_to_adj()
146// Synopsis: Returns the adjacent side length from the length of the hypotenuse and the angle.
147// Topics: Geometry, Trigonometry, Triangles
148// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
149// Usage:
150//   adj = hyp_ang_to_adj(hyp,ang);
151//   adj = ang_hyp_to_adj(ang,hyp);
152// Description:
153//   Given the length of the hypotenuse and the angle of the primary corner of a right triangle,
154//   returns the length of the adjacent side.
155// Arguments:
156//   hyp = The length of the hypotenuse of the right triangle.
157//   ang = The angle in degrees of the primary corner of the right triangle.
158// Example:
159//   adj = hyp_ang_to_adj(8,60);  // Returns: 4
160function hyp_ang_to_adj(hyp,ang) =
161    assert(is_finite(hyp) && hyp>=0, "Triangle side length should be a positive number." )
162    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
163    hyp*cos(ang);
164
165function ang_hyp_to_adj(ang,hyp) = hyp_ang_to_adj(hyp, ang);
166
167
168// Function: opp_ang_to_adj()
169// Alias: ang_opp_to_adj()
170// Synopsis: Returns the adjacent side length from the length of the opposite side and the angle.
171// Topics: Geometry, Trigonometry, Triangles
172// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
173// Usage:
174//   adj = opp_ang_to_adj(opp,ang);
175//   adj = ang_opp_to_adj(ang,opp);
176// Description:
177//   Given the angle of the primary corner of a right triangle, and the length of the side opposite of it,
178//   returns the length of the adjacent side.
179// Arguments:
180//   opp = The length of the side of the right triangle that is opposite from the primary angle.
181//   ang = The angle in degrees of the primary corner of the right triangle.
182// Example:
183//   adj = opp_ang_to_adj(8,30);  // Returns: 4
184function opp_ang_to_adj(opp,ang) =
185    assert(is_finite(opp) && opp>=0, "Triangle side length should be a positive number." )
186    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
187    opp/tan(ang);
188
189function ang_opp_to_adj(ang,opp) = opp_ang_to_adj(opp,ang);
190
191
192// Function: hyp_adj_to_opp()
193// Alias: adj_hyp_to_opp()
194// Synopsis: Returns the opposite side length from the lengths of the hypotenuse and the adjacent side.
195// Topics: Geometry, Trigonometry, Triangles
196// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
197// Usage:
198//   opp = hyp_adj_to_opp(hyp,adj);
199//   opp = adj_hyp_to_opp(adj,hyp);
200// Description:
201//   Given the length of the hypotenuse and the adjacent side, returns the length of the opposite side.
202// Arguments:
203//   hyp = The length of the hypotenuse of the right triangle.
204//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
205// Example:
206//   opp = hyp_adj_to_opp(5,4);  // Returns: 3
207function hyp_adj_to_opp(hyp,adj) =
208    assert(is_finite(hyp) && hyp>=0 && is_finite(adj) && adj>=0,
209           "Triangle side lengths should be a positive numbers." )
210    sqrt(hyp*hyp-adj*adj);
211
212function adj_hyp_to_opp(adj,hyp) = hyp_adj_to_opp(hyp,adj);
213
214
215// Function: hyp_ang_to_opp()
216// Alias: ang_hyp_to_opp()
217// Synopsis: Returns the opposite side length from the length of the hypotenuse and the angle.
218// Topics: Geometry, Trigonometry, Triangles
219// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
220// Usage:
221//   opp = hyp_ang_to_opp(hyp,ang);
222//   opp = ang_hyp_to_opp(ang,hyp);
223// Description:
224//   Given the length of the hypotenuse of a right triangle, and the angle of the corner, returns the length of the opposite side.
225// Arguments:
226//   hyp = The length of the hypotenuse of the right triangle.
227//   ang = The angle in degrees of the primary corner of the right triangle.
228// Example:
229//   opp = hyp_ang_to_opp(8,30);  // Returns: 4
230function hyp_ang_to_opp(hyp,ang) =
231    assert(is_finite(hyp)&&hyp>=0, "Triangle side length should be a positive number." )
232    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
233    hyp*sin(ang);
234
235function ang_hyp_to_opp(ang,hyp) = hyp_ang_to_opp(hyp,ang);
236
237
238// Function: adj_ang_to_opp()
239// Alias: ang_adj_to_opp()
240// Synopsis: Returns the opposite side length from the length of the adjacent side and the angle.
241// Topics: Geometry, Trigonometry, Triangles
242// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
243// Usage:
244//   opp = adj_ang_to_opp(adj,ang);
245//   opp = ang_adj_to_opp(ang,adj);
246// Description:
247//   Given the length of the adjacent side of a right triangle, and the angle of the corner, returns the length of the opposite side.
248// Arguments:
249//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
250//   ang = The angle in degrees of the primary corner of the right triangle.
251// Example:
252//   opp = adj_ang_to_opp(8,45);  // Returns: 8
253function adj_ang_to_opp(adj,ang) =
254    assert(is_finite(adj)&&adj>=0, "Triangle side length should be a positive number." )
255    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
256    adj*tan(ang);
257
258function ang_adj_to_opp(ang,adj) = adj_ang_to_opp(adj,ang);
259
260
261// Function: adj_opp_to_hyp()
262// Alias: opp_adj_to_hyp()
263// Synopsis: Returns the hypotenuse length from the lengths of the adjacent and opposite sides.
264// Topics: Geometry, Trigonometry, Triangles
265// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
266// Usage:
267//   hyp = adj_opp_to_hyp(adj,opp);
268//   hyp = opp_adj_to_hyp(opp,adj);
269// Description:
270//   Given the length of the adjacent and opposite sides of a right triangle, returns the length of the hypotenuse.
271// Arguments:
272//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
273//   opp = The length of the side of the right triangle that is opposite from the primary angle.
274// Example:
275//   hyp = adj_opp_to_hyp(3,4);  // Returns: 5
276function adj_opp_to_hyp(adj,opp) =
277    assert(is_finite(opp) && opp>=0 && is_finite(adj) && adj>=0,
278           "Triangle side lengths should be a positive numbers." )
279    norm([opp,adj]);
280
281function opp_adj_to_hyp(opp,adj) = adj_opp_to_hyp(adj,opp);
282
283
284// Function: adj_ang_to_hyp()
285// Alias: ang_adj_to_hyp()
286// Synopsis: Returns the hypotenuse length from the length of the adjacent and the angle.
287// Topics: Geometry, Trigonometry, Triangles
288// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
289// Usage:
290//   hyp = adj_ang_to_hyp(adj,ang);
291//   hyp = ang_adj_to_hyp(ang,adj);
292// Description:
293//   For a right triangle, given the length of the adjacent side, and the corner angle, returns the length of the hypotenuse.
294// Arguments:
295//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
296//   ang = The angle in degrees of the primary corner of the right triangle.
297// Example:
298//   hyp = adj_ang_to_hyp(4,60);  // Returns: 8
299function adj_ang_to_hyp(adj,ang) =
300    assert(is_finite(adj) && adj>=0, "Triangle side length should be a positive number." )
301    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
302    adj/cos(ang);
303
304function ang_adj_to_hyp(ang,adj) = adj_ang_to_hyp(adj,ang);
305
306
307// Function: opp_ang_to_hyp()
308// Alias: ang_opp_to_hyp()
309// Synopsis: Returns the hypotenuse length from the length of the opposite side and the angle.
310// Topics: Geometry, Trigonometry, Triangles
311// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
312// Usage:
313//   hyp = opp_ang_to_hyp(opp,ang);
314//   hyp = ang_opp_to_hyp(ang,opp);
315// Description:
316//   For a right triangle, given the length of the opposite side, and the corner angle, returns the length of the hypotenuse.
317// Arguments:
318//   opp = The length of the side of the right triangle that is opposite from the primary angle.
319//   ang = The angle in degrees of the primary corner of the right triangle.
320// Example:
321//   hyp = opp_ang_to_hyp(4,30);  // Returns: 8
322function opp_ang_to_hyp(opp,ang) =
323    assert(is_finite(opp) && opp>=0, "Triangle side length should be a positive number." )
324    assert(is_finite(ang) && ang>-90 && ang<90, "The angle should be an acute angle." )
325    opp/sin(ang);
326
327function ang_opp_to_hyp(ang,opp) = opp_ang_to_hyp(opp,ang);
328
329
330// Function: hyp_adj_to_ang()
331// Alias: adj_hyp_to_ang()
332// Synopsis: Returns the angle from the lengths of the hypotenuse and the adjacent side.
333// Topics: Geometry, Trigonometry, Triangles
334// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
335// Usage:
336//   ang = hyp_adj_to_ang(hyp,adj);
337//   ang = adj_hyp_to_ang(adj,hyp);
338// Description:
339//   For a right triangle, given the lengths of the hypotenuse and the adjacent sides, returns the angle of the corner.
340// Arguments:
341//   hyp = The length of the hypotenuse of the right triangle.
342//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
343// Example:
344//   ang = hyp_adj_to_ang(8,4);  // Returns: 60 degrees
345function hyp_adj_to_ang(hyp,adj) =
346    assert(is_finite(hyp) && hyp>0 && is_finite(adj) && adj>=0,
347            "Triangle side lengths should be positive numbers." )
348    acos(adj/hyp);
349
350function adj_hyp_to_ang(adj,hyp) = hyp_adj_to_ang(hyp,adj);
351
352
353// Function: hyp_opp_to_ang()
354// Alias: opp_hyp_to_ang()
355// Synopsis: Returns the angle from the lengths of the hypotenuse and the opposite side.
356// Topics: Geometry, Trigonometry, Triangles
357// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
358// Usage:
359//   ang = hyp_opp_to_ang(hyp,opp);
360//   ang = opp_hyp_to_ang(opp,hyp);
361// Description:
362//   For a right triangle, given the lengths of the hypotenuse and the opposite sides, returns the angle of the corner.
363// Arguments:
364//   hyp = The length of the hypotenuse of the right triangle.
365//   opp = The length of the side of the right triangle that is opposite from the primary angle.
366// Example:
367//   ang = hyp_opp_to_ang(8,4);  // Returns: 30 degrees
368function hyp_opp_to_ang(hyp,opp) =
369    assert(is_finite(hyp+opp) && hyp>0 && opp>=0,
370            "Triangle side lengths should be positive numbers." )
371    asin(opp/hyp);
372
373function opp_hyp_to_ang(opp,hyp) = hyp_opp_to_ang(hyp,opp);
374
375
376// Function: adj_opp_to_ang()
377// Alias: opp_adj_to_ang()
378// Synopsis: Returns the angle from the lengths of the adjacent and opposite sides.
379// Topics: Geometry, Trigonometry, Triangles
380// See Also: adj_ang_to_hyp(), adj_ang_to_opp(), adj_opp_to_ang(), adj_opp_to_hyp(), hyp_adj_to_ang(), hyp_adj_to_opp(), hyp_ang_to_adj(), hyp_ang_to_opp(), hyp_opp_to_adj(), hyp_opp_to_ang(), opp_ang_to_adj(), opp_ang_to_hyp()
381// Usage:
382//   ang = adj_opp_to_ang(adj,opp);
383//   ang = opp_adj_to_ang(opp,adj);
384// Description:
385//   For a right triangle, given the lengths of the adjacent and opposite sides, returns the angle of the corner.
386// Arguments:
387//   adj = The length of the side of the right triangle that is adjacent to the primary angle.
388//   opp = The length of the side of the right triangle that is opposite from the primary angle.
389// Example:
390//   ang = adj_opp_to_ang(sqrt(3)/2,0.5);  // Returns: 30 degrees
391function adj_opp_to_ang(adj,opp) =
392    assert(is_finite(adj+opp) && adj>0 && opp>=0,
393            "Triangle side lengths should be positive numbers." )
394    atan2(opp,adj);
395
396function opp_adj_to_ang(opp,adj) = adj_opp_to_ang(adj,opp);
397
398
399
400// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap