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