omdl  v1.0
OpenSCAD Mechanical Design Library
triangle.scad
Go to the documentation of this file.
1 //! Triangle shapes, conversions, properties, and tests functions.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2015-2019, 2026
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \amu_define group_name (Triangles)
31  \amu_define group_brief (Triangle mathematical functions.)
32 
33  \amu_include (include/amu/doxyg_init_pd_gds_ipg.amu)
34 *******************************************************************************/
35 
36 // auto-tests (add to test results page)
37 /***************************************************************************//**
38  \amu_include (include/amu/validate_log.amu)
39  \amu_include (include/amu/validate_results.amu)
40 *******************************************************************************/
41 
42 // group(s) begin (test summary and includes-required)
43 /***************************************************************************//**
44  \amu_include (include/amu/doxyg_define_in_parent_open.amu)
45  \amu_include (include/amu/validate_summary.amu)
46  \amu_include (include/amu/includes_required.amu)
47 *******************************************************************************/
48 
49 // member-wide reference definitions
50 /***************************************************************************//**
51  \amu_define note_no_validation
52  (
53  \note No validation is performed on the input values. Degenerate or
54  invalid input will produce undef, nan, or inf without warning
55  unless an assert is present.
56  )
57 
58  \amu_define html_image_w (512)
59  \amu_define latex_image_w (2.25in)
60  \amu_include (include/amu/scope_diagram_2d_object.amu)
61 *******************************************************************************/
62 
63 // member-wide documentation and conventions
64 /***************************************************************************//**
65  \addtogroup \amu_eval(${group})
66  \details
67  \anchor \amu_eval(${group})_conventions
68  \par Conventions
69 
70  The following conventions apply to all functions in this group.
71  - \p c is always a list of three coordinate points \c [v1, v2, v3];
72  \p v is always a scalar input list (sides and/or angles), with
73  element order encoded in the function name
74  (e.g. triangle_sas2sss takes \c [s1, a3, s2]).
75  - Side lengths s1, s2, s3 are each \b opposite the corresponding
76  vertex; angles a1, a2, a3 are \b at the corresponding vertex,
77  in \b degrees.
78  - \p vi is the vertex-selector parameter (1-indexed: \b 1 = v1,
79  \b 2 = v2, \b 3 = v3); out-of-range values return a stated
80  fallback without error.
81  - \p d controls output dimensionality: \p d = \b 2 (default)
82  silently discards the z-component of 3d input; \p d = \b 3
83  preserves it; \p d = \b 0 auto-detects from the minimum
84  coordinate length of \p c.
85  - \p cw = \b true (default) orders output vertices \b clockwise;
86  \p s = \b true in triangle2d_area() returns a signed area --
87  \b negative for clockwise, \b positive for counter-clockwise --
88  matching polygon_area().
89  - No input validation is performed unless an explicit \c assert is
90  present; degenerate input (collinear vertices, zero sides,
91  angles >= 180 degrees) produces \b undef, \b nan, or \b inf silently.
92  - The rounding functions triangle2d_vround3_center() and
93  triangle2d_vround3_tangents() operate on vertex \b v2 (c[1])
94  only; rotate \p c to round a different vertex.
95  - Lengths are in the units of the input coordinate space; area in
96  square units; angles in degrees.
97 
98  See [Wikipedia](https://en.wikipedia.org/wiki/Triangle) for more
99  general information.
100 *******************************************************************************/
101 
102 //----------------------------------------------------------------------------//
103 // members
104 //----------------------------------------------------------------------------//
105 
106 //----------------------------------------------------------------------------//
107 // shape generation
108 //----------------------------------------------------------------------------//
109 
110 //! \name Shapes
111 //! @{
112 
113 //! Compute the side lengths of a triangle given its vertex coordinates.
114 /***************************************************************************//**
115  \param c <points-3d | points-2d> A list, [v1, v2, v3], the 3d or
116  2d vertex coordinates.
117 
118  \returns <decimal-list-3> A list of side lengths [s1, s2, s3].
119 
120  \details
121 
122  Each side length is opposite the corresponding vertex.
123 
124  \amu_eval ( object=triangle_ppp2sss ${object_diagram_2d} )
125 
126  See [Wikipedia] for more information.
127 
128  \amu_eval(${note_no_validation})
129 
130  [Wikipedia]: https://en.wikipedia.org/wiki/Solution_of_triangles
131 *******************************************************************************/
132 function triangle_ppp2sss
133 (
134  c
135 ) =
136  let
137  (
138  v1 = c[0],
139  v2 = c[1],
140  v3 = c[2],
141 
142  s1 = distance_pp(v2, v3),
143  s2 = distance_pp(v3, v1),
144  s3 = distance_pp(v1, v2)
145  )
146  [s1, s2, s3];
147 
148 //! Compute the side lengths of a triangle given two sides and the included angle.
149 /***************************************************************************//**
150  \param v <decimal-list-3> A list, [s1, a3, s2], the side lengths
151  and the included angle.
152 
153  \returns <decimal-list-3> A list of side lengths [s1, s2, s3].
154 
155  \details
156 
157  Each side length is opposite the corresponding vertex.
158 
159  \amu_eval ( object=triangle_sas2sss ${object_diagram_2d} )
160 
161  See [Wikipedia] for more information.
162 
163  \amu_eval(${note_no_validation})
164 
165  [Wikipedia]: https://en.wikipedia.org/wiki/Solution_of_triangles
166 *******************************************************************************/
167 function triangle_sas2sss
168 (
169  v
170 ) =
171  let
172  (
173  s1 = v[0],
174  a3 = v[1],
175  s2 = v[2],
176 
177  s3 = sqrt( s1*s1 + s2*s2 - 2*s1*s2*cos(a3) )
178  )
179  [s1, s2, s3];
180 
181 //! Compute the side lengths of a triangle given a side and two adjacent angles.
182 /***************************************************************************//**
183  \param v <decimal-list-3> A list, [a1, s3, a2], the side length
184  and two adjacent angles.
185 
186  \returns <decimal-list-3> A list of side lengths [s1, s2, s3].
187 
188  \details
189 
190  Each side length is opposite the corresponding vertex.
191 
192  \amu_eval ( object=triangle_asa2sss ${object_diagram_2d} )
193 
194  No validation is performed on the input values. If \p a1 and \p a2
195  sum to 180° or more, the derived angle a3 = 180 - a1 - a2 is zero
196  or negative and sin(a3) is zero or negative, causing division by
197  zero or producing negative side lengths without warning.
198 
199  [Wikipedia]: https://en.wikipedia.org/wiki/Solution_of_triangles
200 *******************************************************************************/
201 function triangle_asa2sss
202 (
203  v
204 ) =
205  let
206  (
207  a1 = v[0],
208  s3 = v[1],
209  a2 = v[2],
210 
211  a3 = 180 - a1 - a2,
212 
213  s1 = s3 * sin( a1 ) / sin( a3 ),
214  s2 = s3 * sin( a2 ) / sin( a3 )
215  )
216  [s1, s2, s3];
217 
218 //! Compute the side lengths of a triangle given a side, one adjacent and the opposite angle.
219 /***************************************************************************//**
220  \param v <decimal-list-3> A list, [a1, a2, s1], a side length,
221  one adjacent and the opposite angle.
222 
223  \returns <decimal-list-3> A list of side lengths [s1, s2, s3].
224 
225  \details
226 
227  Each side length is opposite the corresponding vertex.
228 
229  \amu_eval ( object=triangle_aas2sss ${object_diagram_2d} )
230 
231  No validation is performed on the input values. If \p a1 and \p a2
232  sum to 180° or more, sin(a3) is zero or negative and division by
233  zero or negative side lengths result without warning. If \p a1 is
234  zero, division by sin(a1) also produces inf or nan.
235 
236  [Wikipedia]: https://en.wikipedia.org/wiki/Solution_of_triangles
237 *******************************************************************************/
238 function triangle_aas2sss
239 (
240  v
241 ) =
242  let
243  (
244  a1 = v[0],
245  a2 = v[1],
246  s1 = v[2],
247 
248  a3 = 180 - a1 - a2,
249 
250  s2 = s1 * sin( a2 ) / sin( a1 ),
251  s3 = s1 * sin( a3 ) / sin( a1 )
252  )
253  [s1, s2, s3];
254 
255 //! Compute a set of vertex coordinates for a triangle given its side lengths in 2D.
256 /***************************************************************************//**
257  \param v <decimal-list-3> A list, [s1, s2, s3], the side lengths.
258 
259  \param a <integer> The axis alignment index
260  < \b x_axis_ci | \b y_axis_ci >.
261 
262  \param cw <boolean> Order vertices clockwise.
263 
264  \returns <points-2d> A list of vertex coordinates [v1, v2, v3],
265  when \p cw = \b true, else [v1, v3, v2].
266 
267  \details
268 
269  Each side length is opposite the corresponding vertex. The triangle
270  will be constructed with \em v1 at the origin. Side \em s2 will be
271  on the 'x' axis or side \em s3 will be on the 'y' axis as
272  determined by parameter \p a.
273 
274  \amu_eval ( object=triangle2d_sss2ppp ${object_diagram_2d} )
275 
276  No verification is performed to ensure that the given sides specify
277  a valid triangle. See [Wikipedia] for more information.
278 
279  [Wikipedia]: https://en.wikipedia.org/wiki/Solution_of_triangles
280 *******************************************************************************/
281 function triangle2d_sss2ppp
282 (
283  v,
284  a = x_axis_ci,
285  cw = true
286 ) =
287  let
288  (
289  s1 = v[0],
290  s2 = v[1],
291  s3 = v[2],
292 
293  _ = assert
294  (
295  s1 > 0 && s2 > 0 && s3 > 0
296  && s1 < s2+s3 && s2 < s1+s3 && s3 < s1+s2,
297  "triangle2d_sss2ppp: sides must be positive and satisfy the triangle inequality."
298  ),
299 
300  v1 = origin2d,
301 
302  v2 = (a == x_axis_ci) ?
303  // law of cosines
304  let(x = (-s1*s1 + s2*s2 + s3*s3) / (2*s2))
305  [x, sqrt(s3*s3 - x*x)]
306  : [0, s3],
307 
308  v3 = (a == x_axis_ci) ?
309  [s2, 0]
310  // law of cosines
311  : let(y = (-s1*s1 + s2*s2 + s3*s3) / (2*s3))
312  [sqrt(s2*s2 - y*y), y]
313  )
314  (cw == true) ? [v1, v2, v3] : [v1, v3, v2];
315 
316 //! @}
317 
318 //----------------------------------------------------------------------------//
319 // shape properties
320 //----------------------------------------------------------------------------//
321 
322 //! \name Properties
323 //! @{
324 
325 //! Compute the area of a triangle given its vertex coordinates in 2D.
326 /***************************************************************************//**
327  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
328 
329  \param s <boolean> When \b true, return the signed area; when
330  \b false (default), return the absolute area.
331 
332  \returns <decimal> The area of the given triangle, signed when
333  \p s = \b true.
334 
335  \details
336 
337  When \p s = \b true the sign encodes vertex ordering: negative for
338  clockwise and positive for counter-clockwise, following the same
339  convention as polygon_area(). When \p s = \b false the absolute
340  value is returned regardless of vertex ordering.
341 
342  \amu_eval(${note_no_validation})
343 *******************************************************************************/
344 function triangle2d_area
345 (
346  c,
347  s = false
348 ) =
349  let
350  (
351  sa = is_left_ppp(p1=c[0], p2=c[1], p3=c[2]) / 2
352  )
353  (s == false) ? abs(sa) : sa;
354 
355 //! Compute the centroid of a triangle.
356 /***************************************************************************//**
357  \param c <points-3d | points-2d> A list of 3d or 2d vertex
358  coordinates [v1, v2, v3].
359 
360  \param d <integer> The number of dimensions [2:3].
361 
362  \returns <point-3d | point-2d> The centroid coordinate.
363 
364  \details
365 
366  The output dimensionality is controlled by \p d:
367  - \p d = \b 2 (default): returns a 2d point using only the x and y
368  components of each vertex. When 3d coordinates are passed with the
369  default \p d = \b 2, the z-component is silently discarded.
370  - \p d = \b 3: returns a 3d point using x, y, and z components.
371  - \p d = \b 0: auto-detects dimensionality as the minimum coordinate
372  length across all three vertices, useful for mixed-dimension input.
373 
374  See [Wikipedia] for more information.
375 
376  \amu_eval(${note_no_validation})
377 
378  [Wikipedia]: https://en.wikipedia.org/wiki/Centroid
379 *******************************************************************************/
380 function triangle_centroid
381 (
382  c,
383  d = 2
384 ) =
385  let
386  (
387  v1 = c[0],
388  v2 = c[1],
389  v3 = c[2],
390 
391  e = (d == 0) ? min(len(v1), len(v2), len(v3)) : d
392  )
393  [ for (i=[0:e-1]) (v1[i] + v2[i] + v3[i])/3 ];
394 
395 //! Compute the center coordinate of a triangle's incircle in 2D.
396 /***************************************************************************//**
397  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
398 
399  \returns <point-2d> The incircle center coordinate [x, y].
400 
401  \details
402 
403  The interior point for which distances to the sides of the triangle
404  are equal. See [Wikipedia] for more information.
405 
406  \amu_eval(${note_no_validation})
407 
408  [Wikipedia]: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
409 *******************************************************************************/
410 function triangle2d_incenter
411 (
412  c
413 ) =
414  let
415  (
416  v1 = c[0],
417  v2 = c[1],
418  v3 = c[2],
419 
420  d1 = distance_pp(v2, v3),
421  d2 = distance_pp(v3, v1),
422  d3 = distance_pp(v1, v2)
423  )
424  [
425  ( (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) / (d3 + d1 + d2) ),
426  ( (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) / (d3 + d1 + d2) )
427  ];
428 
429 //! Compute the inradius of a triangle's incircle in 2D.
430 /***************************************************************************//**
431  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
432 
433  \returns <decimal> The incircle radius.
434 
435  \details
436 
437  See [Wikipedia] for more information.
438 
439  \amu_eval(${note_no_validation})
440 
441  [Wikipedia]: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
442 *******************************************************************************/
443 function triangle2d_inradius
444 (
445  c
446 ) =
447  let
448  (
449  v1 = c[0],
450  v2 = c[1],
451  v3 = c[2],
452 
453  d1 = distance_pp(v2, v3),
454  d2 = distance_pp(v3, v1),
455  d3 = distance_pp(v1, v2)
456  )
457  sqrt( ((-d3+d1+d2) * (+d3-d1+d2) * (+d3+d1-d2)) / (d3+d1+d2) ) / 2;
458 
459 //! Compute the center coordinate of a triangle's excircle in 2D.
460 /***************************************************************************//**
461  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
462 
463  \param vi <integer> The vertex index (1, 2, or 3). Returns the
464  excircle center opposite vertex \p vi.
465 
466  \returns <point-2d> The excircle center coordinate [x, y].
467 
468  \details
469 
470  A circle outside of the triangle specified by \p v1, \p v2, and \p
471  v3, tangent to the side opposite vertex \p vi and tangent to the
472  extensions of the other two sides away from vertex \p vi. Returns
473  \b origin2d for any \p vi value other than 1, 2, or 3.
474  See [Wikipedia] for more information.
475 
476  \amu_eval(${note_no_validation})
477 
478  [Wikipedia]: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
479 *******************************************************************************/
480 function triangle2d_excenter
481 (
482  c,
483  vi = 1
484 ) =
485  let
486  (
487  v1 = c[0],
488  v2 = c[1],
489  v3 = c[2],
490 
491  d1 = distance_pp(v2, v3),
492  d2 = distance_pp(v3, v1),
493  d3 = distance_pp(v1, v2)
494  )
495  (vi == 1) ? [ ((-d1*v1[0]+d2*v2[0]+d3*v3[0])/(-d1+d2+d3)),
496  ((-d1*v1[1]+d2*v2[1]+d3*v3[1])/(-d1+d2+d3)) ]
497  : (vi == 2) ? [ ((+d1*v1[0]-d2*v2[0]+d3*v3[0])/(+d1-d2+d3)),
498  ((+d1*v1[1]-d2*v2[1]+d3*v3[1])/(+d1-d2+d3)) ]
499  : (vi == 3) ? [ ((+d1*v1[0]+d2*v2[0]-d3*v3[0])/(+d1+d2-d3)),
500  ((+d1*v1[1]+d2*v2[1]-d3*v3[1])/(+d1+d2-d3)) ]
501  : origin2d;
502 
503 //! Compute the exradius of a triangle's excircle in 2D.
504 /***************************************************************************//**
505  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
506 
507  \param vi <integer> The vertex index (1, 2, or 3). Returns the
508  exradius of the excircle opposite vertex \p vi.
509 
510  \returns <decimal> The excircle radius opposite vertex \p vi, or
511  \b 0 for any \p vi value other than 1, 2, or 3.
512 
513  \details
514 
515  The exradius opposite vertex \p vi is computed from the semi-perimeter
516  \em s and the three side lengths using the formula
517  r_i = sqrt(s * (s-s_j) * (s-s_k) / (s-s_i)), where s_i, s_j, s_k
518  are the sides opposite each vertex in order. See [Wikipedia] for
519  more information.
520 
521  \amu_eval(${note_no_validation})
522 
523  [Wikipedia]: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
524 *******************************************************************************/
525 function triangle2d_exradius
526 (
527  c,
528  vi = 1
529 ) =
530  let
531  (
532  v1 = c[0],
533  v2 = c[1],
534  v3 = c[2],
535 
536  d1 = distance_pp(v2, v3),
537  d2 = distance_pp(v3, v1),
538  d3 = distance_pp(v1, v2),
539  s = (+d1+d2+d3)/2
540  )
541  (vi == 1) ? sqrt(s * (s-d2) * (s-d3) / (s-d1))
542  : (vi == 2) ? sqrt(s * (s-d1) * (s-d3) / (s-d2))
543  : (vi == 3) ? sqrt(s * (s-d1) * (s-d2) / (s-d3))
544  : 0;
545 
546 //! Compute the coordinate of a triangle's circumcenter.
547 /***************************************************************************//**
548  \param c <points-3d | points-2d> A list of 3d or 2d vertex
549  coordinates [v1, v2, v3].
550 
551  \param d <integer> The number of dimensions [2:3].
552 
553  \returns <point-3d | point-2d> The circumcenter coordinate.
554 
555  \details
556 
557  The circumcenter is the center of the circumscribed circle — the
558  circle that passes through all three vertices. The circumradius is
559  the distance from the circumcenter to any vertex.
560 
561  The output dimensionality is controlled by \p d:
562  - \p d = \b 2 (default): returns a 2d point using only the x and y
563  components of each vertex. When 3d coordinates are passed with the
564  default \p d = \b 2, the z-component is silently discarded.
565  - \p d = \b 3: returns a 3d point using x, y, and z components.
566  - \p d = \b 0: auto-detects dimensionality as the minimum coordinate
567  length across all three vertices, useful for mixed-dimension input.
568 
569  See [Wikipedia] for more information.
570 
571  \amu_eval(${note_no_validation})
572 
573  [Wikipedia]: https://en.wikipedia.org/wiki/Circumscribed_circle
574 *******************************************************************************/
575 function triangle_circumcenter
576 (
577  c,
578  d = 2
579 ) =
580  let
581  (
582  v1 = c[0],
583  v2 = c[1],
584  v3 = c[2],
585 
586  s2a = sin( 2 * angle_ll([v1, v3], [v1, v2]) ),
587  s2b = sin( 2 * angle_ll([v2, v1], [v2, v3]) ),
588  s2c = sin( 2 * angle_ll([v3, v2], [v3, v1]) ),
589 
590  e = (d == 0) ? min(len(v1), len(v2), len(v3)) : d
591  )
592  [ for (i=[0:e-1]) (v1[i]*s2a + v2[i]*s2b + v3[i]*s2c) / (s2a+s2b+s2c) ];
593 
594 //! @}
595 
596 //----------------------------------------------------------------------------//
597 // shape property tests
598 //----------------------------------------------------------------------------//
599 
600 //! \name Tests
601 //! @{
602 
603 //! Test the vertex ordering, or orientation, of a triangle in 2D.
604 /***************************************************************************//**
605  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
606 
607  \returns <boolean> \b true if the vertices are ordered clockwise,
608  \b false if the vertices are ordered counterclockwise, and
609  \b undef if the ordering can not be determined.
610 *******************************************************************************/
611 function triangle2d_is_cw
612 (
613  c
614 ) =
615  let
616  (
617  il = is_left_ppp(p1=c[0], p2=c[1], p3=c[2])
618  )
619  (il < 0) ? true
620  : (il > 0) ? false
621  : undef;
622 
623 //! Test if a point is inside a triangle in 2d.
624 /***************************************************************************//**
625  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
626 
627  \param p <point-2d> A test point coordinate [x, y].
628 
629  \returns <boolean> \b true when the point is strictly inside the
630  triangle, \b false when it is strictly outside, and
631  \b undef when the triangle is degenerate (collinear vertices).
632 
633  \details
634 
635  Uses barycentric coordinates to test point inclusion. Points that
636  lie exactly on an edge or vertex of the triangle are considered
637  \b outside (strict interior test); the boundary is excluded.
638 
639  Returns \b undef when the three vertices are collinear (zero-area
640  triangle), matching the convention used by triangle2d_is_cw() and
641  triangle2d_area().
642 
643  See [Wikipedia] for more information.
644 
645  [Wikipedia]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system
646 *******************************************************************************/
647 function triangle2d_is_pit
648 (
649  c,
650  p
651 ) =
652  let
653  (
654  v1 = c[0],
655  v2 = c[1],
656  v3 = c[2],
657 
658  d = ((v2[1]-v3[1]) * (v1[0]-v3[0]) + (v3[0]-v2[0]) * (v1[1]-v3[1]))
659  )
660  (d == 0) ? undef
661  : let
662  (
663  a = ((v2[1]-v3[1]) * ( p[0]-v3[0]) + (v3[0]-v2[0]) * ( p[1]-v3[1])) / d
664  )
665  (a < 0) ? false
666  : let
667  (
668  b = ((v3[1]-v1[1]) * ( p[0]-v3[0]) + (v1[0]-v3[0]) * ( p[1]-v3[1])) / d
669  )
670  (b < 0) ? false
671  : ((a + b) < 1);
672 
673 //! @}
674 
675 //----------------------------------------------------------------------------//
676 // shape rounding
677 //----------------------------------------------------------------------------//
678 
679 //! \name Rounding
680 //! @{
681 
682 //! Compute the rounding center coordinate for a given radius of a triangle vertex in 2D.
683 /***************************************************************************//**
684  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
685 
686  \param r <decimal> The vertex rounding radius.
687 
688  \returns <point-2d> The rounding arc center coordinate for vertex v2.
689 
690  \details
691 
692  Computes the center of the circular arc of radius \p r that rounds
693  the corner at vertex \b v2 (c[1]). The arc is tangent to both edges
694  meeting at v2.
695 
696  \p r must satisfy \b 0 < r < ir, where \em ir is the triangle's
697  inradius (triangle2d_inradius()). Passing r >= ir causes division by
698  zero and is caught by an internal assert.
699 
700  \note Only vertex v2 (c[1]) is supported. To round v1 or v3, rotate
701  the vertex list so that the target vertex is at c[1] before
702  calling.
703 *******************************************************************************/
705 (
706  c,
707  r
708 ) = let
709  (
710  ir = triangle2d_inradius(c),
711  _ = assert
712  (
713  r < ir,
714  "triangle2d_vround3_center: r must be less than the inradius ir; r >= ir causes division by zero."
715  )
716  )
717  (c[1]-r/(r-ir) * triangle2d_incenter(c)) * (ir-r)/ir;
718 
719 //! Compute the rounding tangent coordinates for a given radius of a triangle vertex in 2D.
720 /***************************************************************************//**
721  \param c <points-2d> A list of vertex coordinates [v1, v2, v3].
722 
723  \param r <decimal> The vertex rounding radius.
724 
725  \returns <points-2d> A list [t1, t2] of the two tangent point
726  coordinates where the rounding arc meets the edges at v2.
727 
728  \details
729 
730  Computes the two points on the edges adjacent to vertex \b v2
731  (c[1]) at which a rounding arc of radius \p r is tangent. t1 lies
732  on the edge v2 to v1 and t2 lies on the edge v2 to v3.
733 
734  \p r must satisfy \b 0 < r < ir (the triangle's inradius); this
735  constraint is enforced by triangle2d_vround3_center(), which is
736  called internally.
737 
738  \note Only vertex v2 (c[1]) is supported. See
739  triangle2d_vround3_center() for the convention on rounding
740  other vertices.
741 *******************************************************************************/
743 (
744  c,
745  r
746 ) = let
747  (
748  rc = triangle2d_vround3_center(c, r),
749  im = sqrt( pow(distance_pp(c[1], rc),2) - pow(r,2) ),
750  t1 = c[1] + im * unit_l([c[1], c[0]]),
751  t2 = c[1] + im * unit_l([c[1], c[2]])
752  )
753  [t1, t2];
754 
755 //! @}
756 
757 //! @}
758 //! @}
759 
760 //----------------------------------------------------------------------------//
761 // openscad-amu auxiliary scripts
762 //----------------------------------------------------------------------------//
763 
764 /*
765 BEGIN_SCOPE validate;
766  BEGIN_OPENSCAD;
767  include <omdl-base.scad>;
768  include <common/validation.scad>;
769 
770  echo( str("openscad version ", version()) );
771  for (i=[1:16]) echo( "not tested:" );
772 
773  // end_include
774  END_OPENSCAD;
775 
776  BEGIN_MFSCRIPT;
777  include --path "${INCLUDE_PATH}" {var_init,var_gen_term}.mfs;
778  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
779  END_MFSCRIPT;
780 END_SCOPE;
781 */
782 
783 /*
784 BEGIN_SCOPE diagram;
785  BEGIN_OPENSCAD;
786  include <omdl-base.scad>;
787  include <transforms/base_cs.scad>;
788  include <tools/2d/drafting/draft-base.scad>;
789 
790  module dt (vl = empty_lst, al = empty_lst, sl = empty_lst)
791  {
792  s = 10;
793  t = [6, 8, 7];
794  r = min(t)/len(t)*s;
795 
796  c = triangle2d_sss2ppp(t)*s;
797 
798  draft_polygon(c, w=s*2/3);
799  draft_axes([[0,12], [0,7]]*s, ts=s/2);
800 
801  for (i = [0 : len(c)-1])
802  {
803  cv = c[i];
804  os = shift_cd(shift_cd(v=c, n=i, r=false), 1, r=false, d=true);
805 
806  if ( !is_empty( find( mv=i, v=vl )) )
807  draft_dim_leader(cv, v1=[mean(os), cv], l1=5, t=str("v", i+1), s=0, cmh=s*1, cmv=s);
808 
809  if ( !is_empty( find( mv=i, v=al )) )
810  draft_dim_angle(o=cv, r=r, v1=[cv, second(os)], v2=[cv, first(os)], t=str("a", i+1), a=0, cmh=s, cmv=s);
811 
812  if ( !is_empty( find( mv=i, v=sl )) )
813  draft_dim_line(p1=first(os), p2=second(os), t=str("s", i+1), cmh=s, cmv=s);
814  }
815  }
816 
817  object = "triangle_sas2sss";
818 
819  if (object == "triangle_ppp2sss") dt( vl = [0,1,2]);
820  if (object == "triangle_sas2sss") dt( vl = [0,1,2], al = [2], sl = [0,1]);
821  if (object == "triangle_asa2sss") dt( vl = [0,1,2], al = [0,1], sl = [2]);
822  if (object == "triangle_aas2sss") dt( vl = [0,1,2], al = [0,1], sl = [0]);
823  if (object == "triangle2d_sss2ppp") dt( sl = [0,1,2]);
824  END_OPENSCAD;
825 
826  BEGIN_MFSCRIPT;
827  include --path "${INCLUDE_PATH}" {var_init,var_gen_svg}.mfs;
828 
829  defines name "objects" define "object"
830  strings "
831  triangle_ppp2sss
832  triangle_sas2sss
833  triangle_asa2sss
834  triangle_aas2sss
835  triangle2d_sss2ppp
836  ";
837  variables add_opts_combine "objects";
838  variables add_opts "--viewall --autocenter";
839 
840  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
841  END_MFSCRIPT;
842 END_SCOPE;
843 */
844 
845 //----------------------------------------------------------------------------//
846 // end of file
847 //----------------------------------------------------------------------------//
x_axis_ci
<integer> The coordinate axis index for the Euclidean space x-axis.
Definition: constants.scad:395
origin2d
<point-2d> The origin point coordinate in 2d Euclidean space.
Definition: constants.scad:407
function angle_ll(l1, l2, s=true)
Compute the angle between two lines or vectors in a 3d or 2d-space.
function is_left_ppp(p1, p2, p3)
Test if a point is left, on, or right of an infinite line in a 2d-space.
function unit_l(l)
Compute the normalized unit vector of a line or vector.
function distance_pp(p1, p2)
Compute the distance between two points.
function triangle2d_exradius(c, vi=1)
Compute the exradius of a triangle's excircle in 2D.
function triangle2d_vround3_tangents(c, r)
Compute the rounding tangent coordinates for a given radius of a triangle vertex in 2D.
function triangle2d_excenter(c, vi=1)
Compute the center coordinate of a triangle's excircle in 2D.
function triangle_sas2sss(v)
Compute the side lengths of a triangle given two sides and the included angle.
function triangle_asa2sss(v)
Compute the side lengths of a triangle given a side and two adjacent angles.
function triangle2d_is_cw(c)
Test the vertex ordering, or orientation, of a triangle in 2D.
function triangle_centroid(c, d=2)
Compute the centroid of a triangle.
function triangle_aas2sss(v)
Compute the side lengths of a triangle given a side, one adjacent and the opposite angle.
function triangle_circumcenter(c, d=2)
Compute the coordinate of a triangle's circumcenter.
function triangle2d_inradius(c)
Compute the inradius of a triangle's incircle in 2D.
function triangle2d_is_pit(c, p)
Test if a point is inside a triangle in 2d.
function triangle2d_vround3_center(c, r)
Compute the rounding center coordinate for a given radius of a triangle vertex in 2D.
function triangle2d_area(c, s=false)
Compute the area of a triangle given its vertex coordinates in 2D.
function triangle2d_sss2ppp(v, a=x_axis_ci, cw=true)
Compute a set of vertex coordinates for a triangle given its side lengths in 2D.
function triangle_ppp2sss(c)
Compute the side lengths of a triangle given its vertex coordinates.
function triangle2d_incenter(c)
Compute the center coordinate of a triangle's incircle in 2D.