Determine if two triangles overlap: Difference between revisions

Added Easylang
m (→‎{{header|Phix}}: IupCloseOnEscape no longer needed)
(Added Easylang)
 
(19 intermediate revisions by 14 users not shown)
Line 20:
:::*   (0,0),(1,0),(0,1)   and   (1,0),(2,0),(1,1)
<br><br>
 
;Related tasks
* [[Check_if_two_polygons_overlap|Check if two polygons overlap]]
* [[Check_if_a_polygon_overlaps_with_a_rectangle|Check if a polygon overlaps with a rectangle]]
<br><br>
 
=={{header|11l}}==
{{trans|D}}
 
<syntaxhighlight lang="11l">T Triangle
(Float, Float) p1, p2, p3
 
F (p1, p2, p3)
.p1 = p1
.p2 = p2
.p3 = p3
 
F String()
R ‘Triangle: #., #., #.’.format(.p1, .p2, .p3)
 
F.const det2D()
R .p1[0] * (.p2[1] - .p3[1])
+ .p2[0] * (.p3[1] - .p1[1])
+ .p3[0] * (.p1[1] - .p2[1])
 
F checkTriWinding(Triangle &t; allowReversed)
V detTri = t.det2D()
I detTri < 0.0
assert(allowReversed, ‘Triangle has wrong winding direction’)
swap(&t.p2, &t.p3)
 
F boundaryCollideChk(Triangle t, Float eps)
R t.det2D() < eps
 
F boundaryDoesntCollideChk(Triangle t, Float eps)
R t.det2D() <= eps
 
F triTri2D(Triangle &t1, &t2; eps = 0.0, allowReversed = 0B, onBoundary = 1B)
checkTriWinding(&t1, allowReversed)
checkTriWinding(&t2, allowReversed)
V chkEdge = I onBoundary {:boundaryCollideChk} E :boundaryDoesntCollideChk
V lp1 = [t1.p1, t1.p2, t1.p3]
V lp2 = [t2.p1, t2.p2, t2.p3]
 
L(i) 3
V j = (i + 1) % 3
I chkEdge(Triangle(lp1[i], lp1[j], lp2[0]), eps) &
chkEdge(Triangle(lp1[i], lp1[j], lp2[1]), eps) &
chkEdge(Triangle(lp1[i], lp1[j], lp2[2]), eps)
R 0B
 
L(i) 3
V j = (i + 1) % 3
I chkEdge(Triangle(lp2[i], lp2[j], lp1[0]), eps) &
chkEdge(Triangle(lp2[i], lp2[j], lp1[1]), eps) &
chkEdge(Triangle(lp2[i], lp2[j], lp1[2]), eps)
R 0B
 
R 1B
 
F overlap(Triangle &t1, &t2; eps = 0.0, allowReversed = 0B, onBoundary = 1B)
I triTri2D(&t1, &t2, eps, allowReversed, onBoundary)
print(‘overlap’)
E
print(‘do not overlap’)
 
V t1 = Triangle((0.0, 0.0), (5.0, 0.0), (0.0, 5.0))
V t2 = Triangle((0.0, 0.0), (5.0, 0.0), (0.0, 6.0))
print(t1" and\n"t2)
overlap(&t1, &t2)
print()
 
t1 = Triangle((0.0, 0.0), (0.0, 5.0), (5.0, 0.0))
t2 = t1
print(t1" and\n"t2)
overlap(&t1, &t2, 0.0, 1B)
print()
 
t1 = Triangle((0.0, 0.0), (5.0, 0.0), (0.0, 5.0))
t2 = Triangle((-10.0, 0.0), (-5.0, 0.0), (-1.0, 6.0))
print(t1" and\n"t2)
overlap(&t1, &t2)
print()
 
t1.p3 = (2.5, 5.0)
t2 = Triangle((0.0, 4.0), (2.5, -1.0), (5.0, 4.0))
print(t1" and\n"t2)
overlap(&t1, &t2)
print()
 
t1 = Triangle((0.0, 0.0), (1.0, 1.0), (0.0, 2.0))
t2 = Triangle((2.0, 1.0), (3.0, 0.0), (3.0, 2.0))
print(t1" and\n"t2)
overlap(&t1, &t2)
print()
 
t2 = Triangle((2.0, 1.0), (3.0, -2.0), (3.0, 4.0))
print(t1" and\n"t2)
overlap(&t1, &t2)
print()
 
t1 = Triangle((0.0, 0.0), (1.0, 0.0), (0.0, 1.0))
t2 = Triangle((1.0, 0.0), (2.0, 0.0), (1.0, 1.1))
print(t1" and\n"t2)
print(‘which have only a single corner in contact, if boundary points collide’)
overlap(&t1, &t2)
print()
 
print(t1" and\n"t2)
print(‘which have only a single corner in contact, if boundary points do not collide’)
overlap(&t1, &t2, 0.0, 0B, 0B)</syntaxhighlight>
 
{{out}}
<pre>
Triangle: (0, 0), (5, 0), (0, 5) and
Triangle: (0, 0), (5, 0), (0, 6)
overlap
 
Triangle: (0, 0), (0, 5), (5, 0) and
Triangle: (0, 0), (0, 5), (5, 0)
overlap
 
Triangle: (0, 0), (5, 0), (0, 5) and
Triangle: (-10, 0), (-5, 0), (-1, 6)
do not overlap
 
Triangle: (0, 0), (5, 0), (2.5, 5) and
Triangle: (0, 4), (2.5, -1), (5, 4)
overlap
 
Triangle: (0, 0), (1, 1), (0, 2) and
Triangle: (2, 1), (3, 0), (3, 2)
do not overlap
 
Triangle: (0, 0), (1, 1), (0, 2) and
Triangle: (2, 1), (3, -2), (3, 4)
do not overlap
 
Triangle: (0, 0), (1, 0), (0, 1) and
Triangle: (1, 0), (2, 0), (1, 1.1)
which have only a single corner in contact, if boundary points collide
overlap
 
Triangle: (0, 0), (1, 0), (0, 1) and
Triangle: (1, 0), (2, 0), (1, 1.1)
which have only a single corner in contact, if boundary points do not collide
do not overlap
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">
WITH Ada.Text_IO; USE Ada.Text_IO;
 
Line 62 ⟶ 210:
Put ((0.0, 0.0, 1.0, 0.0, 0.0, 1.0), (1.0, 0.0, 2.0, 0.0, 1.0, 1.0));
END Main;
</syntaxhighlight>
</lang>
{{out}}
<pre>true
Line 71 ⟶ 219:
false
true
</pre>
 
=={{header|ALGOL 68}}==
Uses the code from the Algol 68 sample for the [[Check if two polygons overlap]] task.<br>
Triangles with a single point in contact are considerfed to overlap.
<syntaxhighlight lang="algol68">
BEGIN # test for overlapping 2D triangles - using the code from the Algol 68 #
# sample for the Check if two polygons overlap task, the code of which #
# is based on a translation of that tasks' Go which is a translation #
# of Wren #
 
# In the following a polygon is represented as a row of vertices #
# and a vertex ( POINT ) by a pair of x, y coordinates in the plane #
 
MODE POINT = STRUCT( REAL x, y );
MODE PROJECTION = STRUCT( REAL min, max );
MODE POLYGON = FLEX[ 1 : 0 ]POINT;
 
PRIO DOT = 3;
OP DOT = ( POINT v, other )REAL:
( x OF v * x OF other ) + ( y OF v * y OF other );
 
# returns the axes of the polygon defined by poly #
OP AXES = ( POLYGON poly )[]POINT:
BEGIN
[ LWB poly : UPB poly ]POINT result;
FOR i FROM LWB poly TO UPB poly DO
INT j = IF i = UPB poly THEN LWB poly ELSE i + 1 FI;
POINT vertex1 = poly[ i ];
POINT vertex2 = poly[ j ];
POINT edge = ( x OF vertex1 - x OF vertex2, y OF vertex1 - y OF vertex2 );
result[ i ] := ( - y OF edge, x OF edge )
OD;
result
END # AXES # ;
 
# returns the projection of poly onto axis #
PRIO PROJECTONTO = 3;
OP PROJECTONTO = ( POLYGON poly, POINT axis )PROJECTION:
BEGIN
REAL min := axis DOT poly[ LWB poly ];
REAL max := min;
FOR i FROM LWB poly + 1 TO UPB poly DO
REAL p = axis DOT poly[ i ];
IF p < min THEN
min := p
ELIF p > max THEN
max := p
FI
OD;
PROJECTION( min, max )
END # PROJECTONTO # ;
 
PRIO OVERLAPS = 5;
# returns TRUE if the projections proj1 and proj2 overlap, #
# FALSE otherrwise #
OP OVERLAPS = ( PROJECTION proj1, proj2 )BOOL:
IF max OF proj1 < min OF proj2 THEN FALSE
ELIF max OF proj2 < min OF proj1 THEN FALSE
ELSE TRUE
FI # OVERLAPS # ;
 
# returns TRUE if the ppolygons poly1 and poly2 overlap, #
# FALSE otherrwise #
OP OVERLAPS = ( POLYGON poly1, poly2 )BOOL:
BEGIN
[]POINT axes1 = AXES poly1, axes2 = AXES poly2;
BOOL does overlap := TRUE;
FOR a FROM LWB axes1 TO UPB axes1 WHILE does overlap DO
does overlap := ( poly1 PROJECTONTO axes1[ a ] )
OVERLAPS ( poly2 PROJECTONTO axes1[ a ] )
OD;
FOR a FROM LWB axes2 TO UPB axes2 WHILE does overlap DO
does overlap := ( poly1 PROJECTONTO axes2[ a ] )
OVERLAPS ( poly2 PROJECTONTO axes2[ a ] )
OD;
does overlap
END # OVERLAPS # ;
 
# returns x as a string without trailing 0 decoimals #
OP TOSTRING = ( REAL x )STRING:
BEGIN
STRING v := fixed( x, -14, 11 );
INT end pos := UPB v;
WHILE IF end pos < LWB v THEN FALSE ELSE v[ end pos ] = "0" FI DO
end pos -:= 1
OD;
IF end pos >= LWB v THEN
IF v[ end pos ] = "." THEN end pos -:= 1 FI
FI;
INT start pos := LWB v;
WHILE IF start pos > end pos THEN FALSE ELSE v[ start pos ] = " " FI DO
start pos +:= 1
OD;
IF end pos < start pos THEN "0" ELSE v[ start pos : end pos ] FI
END # TOSTRING # ;
 
# returns a string representation of the POINT p #
OP TOSTRING = ( POINT p )STRING: "( " + TOSTRING x OF p + ", " + TOSTRING y OF p + " )";
 
# returns a string representation of the points of p #
OP TOSTRING = ( POLYGON p )STRING:
BEGIN
STRING result := "(", separator := "";
FOR i FROM LWB p TO UPB p DO
result +:= separator + " " + TOSTRING p[ i ];
separator := ","
OD;
result + " )"
END # TOSTRING # ;
 
# code specific to thius task #
# test cases - using the general POLYGON MODE to represent triangles #
[,]POLYGON triangle pairs
= ( ( ( ( 0, 0 ), ( 5, 0 ), ( 0, 5 ) ), ( ( 0, 0 ), ( 5, 0 ), ( 0, 6 ) ) )
, ( ( ( 0, 0 ), ( 0, 5 ), ( 5, 0 ) ), ( ( 0, 0 ), ( 0, 5 ), ( 5, 0 ) ) )
, ( ( ( 0, 0 ), ( 5, 0 ), ( 0, 5 ) ), ( (-10, 0 ), ( -5, 0 ), ( -1, 6 ) ) )
, ( ( ( 0, 0 ), ( 5, 0 ), ( 2.5, 5 ) ), ( ( 0, 4 ), ( 2.5, -1 ), ( 5, 4 ) ) )
, ( ( ( 0, 0 ), ( 1, 1 ), ( 0, 2 ) ), ( ( 2, 1 ), ( 3, 0 ), ( 3, 2 ) ) )
, ( ( ( 0, 0 ), ( 1, 1 ), ( 0, 2 ) ), ( ( 2, 1 ), ( 3, -2 ), ( 3, 4 ) ) )
, ( ( ( 0, 0 ), ( 1, 0 ), ( 0, 1 ) ), ( ( 1, 0 ), ( 2, 0 ), ( 1, 1 ) ) )
);
FOR t pos FROM LWB triangle pairs TO UPB triangle pairs DO
[]POLYGON tpair = triangle pairs[ t pos, : ];
POLYGON t1 = tpair[ LWB tpair ];
POLYGON t2 = tpair[ UPB tpair ];
print( ( TOSTRING t1
, IF t1 OVERLAPS t2 THEN " overlaps " ELSE " does not overlap " FI
, TOSTRING t2
, newline
)
)
OD
END
</syntaxhighlight>
{{out}}
<pre>
( ( 0, 0 ), ( 5, 0 ), ( 0, 5 ) ) overlaps ( ( 0, 0 ), ( 5, 0 ), ( 0, 6 ) )
( ( 0, 0 ), ( 0, 5 ), ( 5, 0 ) ) overlaps ( ( 0, 0 ), ( 0, 5 ), ( 5, 0 ) )
( ( 0, 0 ), ( 5, 0 ), ( 0, 5 ) ) does not overlap ( ( -10, 0 ), ( -5, 0 ), ( -1, 6 ) )
( ( 0, 0 ), ( 5, 0 ), ( 2.5, 5 ) ) overlaps ( ( 0, 4 ), ( 2.5, -1 ), ( 5, 4 ) )
( ( 0, 0 ), ( 1, 1 ), ( 0, 2 ) ) does not overlap ( ( 2, 1 ), ( 3, 0 ), ( 3, 2 ) )
( ( 0, 0 ), ( 1, 1 ), ( 0, 2 ) ) does not overlap ( ( 2, 1 ), ( 3, -2 ), ( 3, 4 ) )
( ( 0, 0 ), ( 1, 0 ), ( 0, 1 ) ) overlaps ( ( 1, 0 ), ( 2, 0 ), ( 1, 1 ) )
</pre>
 
Line 76 ⟶ 368:
{{Trans|Kotlin}}
... with different output format (based on Modula 2).
<langsyntaxhighlight lang="algolw">begin % determine if two triangles overlap %
record Point ( real x, y );
record Triangle ( reference(Point) p1, p2, p3 );
Line 198 ⟶ 490:
CheckOverlap( t1, t2, 0.0, false, false );
end
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 209 ⟶ 501:
Triangles (0.0, 0.0), (1.0, 0.0), (0.0, 1.0) and (1.0, 0.0), (2.0, 0.0), (1.0, 1.1) overlap
Triangles (0.0, 0.0), (1.0, 0.0), (0.0, 1.0) and (1.0, 0.0), (2.0, 0.0), (1.0, 1.1) do not overlap
</pre>
 
=={{header|ATS}}==
<syntaxhighlight lang="ATS">
(* Given that the context is collision detection, we will consider
containment of one triangle entirely inside the other as ‘overlap’
and test for that, as well as for overlap of the triangle sides
themselves. One must agree that, if one triangle has become buried
entirely inside another, then the two have collided. There are
consequences for the conservation of momentum.
 
Besides, the full set of overlap tests, INCLUDING containment of
one polygonal hull inside another, is relevant to the problem of
finding intersections of Bézier curves. See
https://rosettacode.org/wiki/B%C3%A9zier_curves/Intersections
 
This code specifically tests for overlapping vertices, in case the
main tests fail to catch such overlaps. Approximate equality is
employed rather than exact floating-point equality. *)
 
#include "share/atspre_staload.hats"
 
%{^
#include <math.h>
#include <float.h>
%}
 
macdef dbl_epsilon = $extval (double, "DBL_EPSILON")
 
(* We will use some simple homogeneous geometric algebra. *)
 
typedef point =
@{e1 = double,
e2 = double,
e0 = double}
 
macdef Pt (x, y) = (* Shorthand for creating a normalized point. *)
@{e1 = ,(x),
e2 = ,(y),
e0 = 1.0} : point
 
typedef line =
@{e0_e1 = double,
e0_e2 = double,
e1_e2 = double}
 
typedef triangle = @(point, point, point)
 
fn
outer_product_point_point (a : point, b : point) : line =
@{e0_e1 = ~(~a.e0 * b.e1 + a.e1 * b.e0),
e0_e2 = ~(~a.e0 * b.e2 + a.e2 * b.e0),
e1_e2 = (a.e1 * b.e2 - a.e2 * b.e1)}
 
fn
left_contraction_point_line (a : point, b : line) : point =
@{e1 = (a.e0 * b.e0_e1 - a.e2 * b.e1_e2),
e2 = (a.e0 * b.e0_e2 + a.e1 * b.e1_e2),
e0 = (~a.e1 * b.e0_e1 - a.e2 * b.e0_e2)}
 
fn
left_contraction_point_point (a : point, b : point) : double =
(* This is the same as the scalar product but saves us having to add
an operator for which I cannot think of a good symbol. *)
(a.e1 * b.e1) + (a.e2 * b.e2) + (a.e0 * b.e0)
 
fn
dual_line (a : line) : point =
@{e1 = ~a.e0_e2,
e2 = a.e0_e1,
e0 = a.e1_e2}
 
overload outer_product with outer_product_point_point
overload left_contraction with left_contraction_point_line
overload left_contraction with left_contraction_point_point
overload dual with dual_line (* Orthogonal complement. *)
infixl ( * ) ^ .|
overload ^ with outer_product
overload .| with left_contraction
 
fn
intersection_line_line (a : line, b : line) : point =
let
val p = dual a .| b
in
if p.e0 = 0.0 then
(* The lines are parallel (or coincident, if p is all zeros). *)
p
else
(* Normalize the intersection point. *)
@{e1 = p.e1 / p.e0,
e2 = p.e2 / p.e0,
e0 = 1.0}
end
 
fn
which_side_point_line (a : point, b : line) : Sgn =
(* 1 = left, 0 = lies on the line, ~1 = right *)
let
val x = dual b .| a
in
if x < 0.0 then
~1
else if x > 0.0 then
1
else
0
end
 
overload intersection with intersection_line_line
overload which_side with which_side_point_line
 
fn
orientation_triangle (t : triangle) : Sgn =
(* 1 = counterclockwise, 0 = collinear, ~1 = clockwise *)
which_side (t.2, t.0 ^ t.1)
 
overload orientation with orientation_triangle
 
fn
set_orientation_triangle {s : int | abs s == 1}
(t : triangle, s : int s) : triangle =
(* 1 = counterclockwise, ~1 = clockwise. If the triangle is
collinear, leave it unchanged. If the triangle does need
rearrangement, do so by swapping vertices t.1 and t.2. *)
let
val s0 = orientation t
in
if (s = 0) + (s = s0) then
t
else
@(t.0, t.2, t.1)
end
 
overload set_orientation with set_orientation_triangle
 
fn
overlap_triangle_triangle (t1 : triangle, t2 : triangle) : bool =
let
val t1 = set_orientation (t1, 1)
and t2 = set_orientation (t2, 1)
 
(* The lines that form the sides of the triangles. *)
val s1 = @(t1.0 ^ t1.1, t1.1 ^ t1.2, t1.2 ^ t1.0)
val s2 = @(t2.0 ^ t2.1, t2.1 ^ t2.2, t2.2 ^ t2.0)
 
fn
sides_intersect (pa : point, pb : point, ln_p : line,
qa : point, qb : point, ln_q : line) : bool =
let
val x = intersection (ln_p, ln_q)
in
if x.e0 <> 0.0 then
let
val px_min = min (pa.e1, pb.e1)
and px_max = max (pa.e1, pb.e1)
and py_min = min (pa.e2, pb.e1)
and py_max = max (pa.e2, pb.e1)
 
val px_min2 = px_min + px_min
and px_max2 = px_max + px_max
and py_min2 = py_min + py_min
and py_max2 = py_max + py_max
 
val px_min_eps = abs (px_min) * dbl_epsilon
and px_max_eps = abs (px_max) * dbl_epsilon
val py_min_eps = abs (py_min) * dbl_epsilon
and py_max_eps = abs (py_max) * dbl_epsilon
in
if px_min2 - px_min_eps <= x.e1 + x.e1
&& x.e1 + x.e1 <= px_max2 + px_max_eps
&& py_min2 - py_min_eps <= x.e2 + x.e2
&& x.e2 + x.e2 <= py_max2 + py_max_eps then
let
val qx_min = min (qa.e1, qb.e1)
and qx_max = max (qa.e1, qb.e1)
and qy_min = min (qa.e2, qb.e1)
and qy_max = max (qa.e2, qb.e1)
 
val qx_min2 = qx_min + qx_min
and qx_max2 = qx_max + qx_max
and qy_min2 = qy_min + qy_min
and qy_max2 = qy_max + qy_max
 
val qx_min_eps = abs (qx_min) * dbl_epsilon
and qx_max_eps = abs (qx_max) * dbl_epsilon
val qy_min_eps = abs (qy_min) * dbl_epsilon
and qy_max_eps = abs (qy_max) * dbl_epsilon
in
qx_min2 - qx_min_eps <= x.e1 + x.e1
&& x.e1 + x.e1 <= qx_max2 + qx_max_eps
&& qy_min2 - qy_min_eps <= x.e2 + x.e2
&& x.e2 + x.e2 <= qy_max2 + qy_max_eps
end
else
false
end
else if x.e1 = 0.0 && x.e2 = 0.0 then
(* The lines are coincident *)
~(max (qa.e1, qb.e1) < min (pa.e1, pb.e1)
|| max (pa.e1, pb.e1) < min (qa.e1, qb.e1))
&& ~(max (qa.e2, qb.e2) < min (pa.e2, pb.e2)
|| max (pa.e2, pb.e2) < min (qa.e2, qb.e2))
else
(* The lines are parallel. *)
false
end
 
fn
sides_intersection_tests () : bool =
sides_intersect (t1.0, t1.1, s1.0, t2.0, t2.1, s2.0)
|| sides_intersect (t1.0, t1.1, s1.0, t2.1, t2.2, s2.1)
|| sides_intersect (t1.0, t1.1, s1.0, t2.2, t2.0, s2.2)
|| sides_intersect (t1.1, t1.2, s1.1, t2.0, t2.1, s2.0)
|| sides_intersect (t1.1, t1.2, s1.1, t2.1, t2.2, s2.1)
|| sides_intersect (t1.1, t1.2, s1.1, t2.2, t2.0, s2.2)
|| sides_intersect (t1.2, t1.0, s1.2, t2.0, t2.1, s2.0)
|| sides_intersect (t1.2, t1.0, s1.2, t2.1, t2.2, s2.1)
|| sides_intersect (t1.2, t1.0, s1.2, t2.2, t2.0, s2.2)
 
fn
points_approx_equal (p : point, q : point) : bool =
let
val @{e1 = px, e2 = py, e0 = _} = p
and @{e1 = qx, e2 = qy, e0 = _} = q
 
val x_max_eps = max (abs px, abs qx) * dbl_epsilon
and y_max_eps = max (abs py, abs py) * dbl_epsilon
in
abs ((px + px) - (qx + qx)) <= x_max_eps
&& abs ((py + py) - (qy + qy)) <= y_max_eps
end
 
fn
vertex_vertex_tests () : bool =
points_approx_equal (t1.0, t2.0)
|| points_approx_equal (t1.0, t2.1)
|| points_approx_equal (t1.0, t2.2)
|| points_approx_equal (t1.1, t2.0)
|| points_approx_equal (t1.1, t2.1)
|| points_approx_equal (t1.1, t2.2)
|| points_approx_equal (t1.2, t2.0)
|| points_approx_equal (t1.2, t2.1)
|| points_approx_equal (t1.2, t2.2)
 
fn
is_inside (a : point, b : @(line, line, line)) : bool =
which_side (a, b.0) = 1
&& which_side (a, b.1) = 1
&& which_side (a, b.2) = 1
 
fn
vertex_insideness_tests () : bool =
is_inside (t1.0, s2)
|| is_inside (t1.1, s2)
|| is_inside (t1.2, s2)
|| is_inside (t2.0, s1)
|| is_inside (t2.1, s1)
|| is_inside (t2.2, s1)
in
sides_intersection_tests ()
|| vertex_vertex_tests ()
|| vertex_insideness_tests ()
end
 
overload overlap with overlap_triangle_triangle
 
fn
println_triangle (t : triangle) : void =
println! ("(", t.0.e1, ",", t.0.e2, ")--(",
t.1.e1, ",", t.1.e2, ")--(",
t.2.e1, ",", t.2.e2, ")--cycle")
 
fn
test_triangles (t1 : triangle, t2 : triangle) : void =
begin
println_triangle t1;
println_triangle t2;
println! (" overlap: ", overlap (t1, t2))
end
 
implement
main () =
begin
println! ();
test_triangles (@(Pt (0.0, 0.0),
Pt (5.0, 0.0),
Pt (0.0, 5.0)),
@(Pt (0.0, 0.0),
Pt (5.0, 0.0),
Pt (0.0, 6.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (0.0, 5.0),
Pt (5.0, 0.0)),
@(Pt (0.0, 0.0),
Pt (0.0, 5.0),
Pt (5.0, 0.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (5.0, 0.0),
Pt (0.0, 5.0)),
@(Pt (~10.0, 0.0),
Pt ( ~5.0, 0.0),
Pt ( ~1.0, 6.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (5.0, 0.0),
Pt (2.5, 5.0)),
@(Pt (0.0, 4.0),
Pt (2.5, ~1.0),
Pt (5.0, 4.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (1.0, 1.0),
Pt (0.0, 2.0)),
@(Pt (2.0, 1.0),
Pt (3.0, 0.0),
Pt (3.0, 2.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (1.0, 1.0),
Pt (0.0, 2.0)),
@(Pt (2.0, 1.0),
Pt (3.0, ~2.0),
Pt (3.0, 4.0)));
test_triangles (@(Pt (0.0, 0.0),
Pt (1.0, 0.0),
Pt (0.0, 1.0)),
@(Pt (1.0, 0.0),
Pt (2.0, 0.0),
Pt (1.0, 1.0)));
 
println! ();
println! ("What follows is a test where one triangle is ",
"contained entirely");
println! ("inside the other. Without such a test, our ",
"algorithm would have");
println! ("one of its features undemonstrated.");
println! ();
test_triangles (@(Pt ( 0.0, 0.0),
Pt (10.0, 0.0),
Pt ( 5.0, 10.0)),
@(Pt ( 4.0, 1.0),
Pt ( 5.0, 2.0),
Pt ( 6.0, 1.0)));
println! ();
 
0
end
</syntaxhighlight>
 
{{out}}
<pre>$ patscc -g -O3 -march=native -pipe -std=gnu2x overlapping_triangles.dats && ./a.out
 
(0.000000,0.000000)--(5.000000,0.000000)--(0.000000,5.000000)--cycle
(0.000000,0.000000)--(5.000000,0.000000)--(0.000000,6.000000)--cycle
overlap: true
(0.000000,0.000000)--(0.000000,5.000000)--(5.000000,0.000000)--cycle
(0.000000,0.000000)--(0.000000,5.000000)--(5.000000,0.000000)--cycle
overlap: true
(0.000000,0.000000)--(5.000000,0.000000)--(0.000000,5.000000)--cycle
(-10.000000,0.000000)--(-5.000000,0.000000)--(-1.000000,6.000000)--cycle
overlap: false
(0.000000,0.000000)--(5.000000,0.000000)--(2.500000,5.000000)--cycle
(0.000000,4.000000)--(2.500000,-1.000000)--(5.000000,4.000000)--cycle
overlap: true
(0.000000,0.000000)--(1.000000,1.000000)--(0.000000,2.000000)--cycle
(2.000000,1.000000)--(3.000000,0.000000)--(3.000000,2.000000)--cycle
overlap: false
(0.000000,0.000000)--(1.000000,1.000000)--(0.000000,2.000000)--cycle
(2.000000,1.000000)--(3.000000,-2.000000)--(3.000000,4.000000)--cycle
overlap: false
(0.000000,0.000000)--(1.000000,0.000000)--(0.000000,1.000000)--cycle
(1.000000,0.000000)--(2.000000,0.000000)--(1.000000,1.000000)--cycle
overlap: true
 
What follows is a test where one triangle is contained entirely
inside the other. Without such a test, our algorithm would have
one of its features undemonstrated.
 
(0.000000,0.000000)--(10.000000,0.000000)--(5.000000,10.000000)--cycle
(4.000000,1.000000)--(5.000000,2.000000)--(6.000000,1.000000)--cycle
overlap: true
 
</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">TrianglesIntersect(T1, T2){ ; T1 := [[x1,y1],[x2,y2],[x3,y3]] , T2 :=[[x4,y4],[x5,y5],[x6,y6]]
counter := 0
for i, Pt in T1
Line 256 ⟶ 928:
isBetween(x, p1, p2){
return !((x>p1 && x>p2) || (x<p1 && x<p2))
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">result := ""
result .= TrianglesIntersect([[0,0],[5,0],[0,5]], [[0,0],[5,0],[0,6]]) "`n"
result .= TrianglesIntersect([[0,0],[0,5],[5,0]], [[0,0],[0,5],[5,0]]) "`n"
Line 266 ⟶ 938:
result .= TrianglesIntersect([[0,0],[1,0],[0,1]], [[1,0],[2,0],[1,1]]) "`n"
MsgBox % result
return</langsyntaxhighlight>
Outputs:<pre>1
1
Line 277 ⟶ 949:
=={{header|C}}==
{{trans|C++}}
<langsyntaxhighlight lang="c">#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
Line 420 ⟶ 1,092:
 
return EXIT_SUCCESS;
}</langsyntaxhighlight>
{{out}}
<pre>1,true
Line 432 ⟶ 1,104:
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
 
Line 584 ⟶ 1,256:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0, 0), (5, 0), (0, 5) and
Line 621 ⟶ 1,293:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <vector>
#include <iostream>
#include <stdexcept>
Line 740 ⟶ 1,412:
cout << TriTri2D(t1, t2, 0.0, false, false) << "," << false << endl;}
 
}</langsyntaxhighlight>
 
{{out}}
Line 754 ⟶ 1,426:
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight Dlang="d">import std.stdio;
import std.typecons;
 
Line 894 ⟶ 1,566:
writeln("which have only a single corner in contact, if boundary points do not collide");
overlap(t1, t2, 0.0, false, false);
}</langsyntaxhighlight>
 
{{out}}
Line 930 ⟶ 1,602:
which have only a single corner in contact, if boundary points do not collide
do not overlap</pre>
=={{header|Delphi}}==
See [https://rosettacode.org/wiki/Determine_if_two_triangles_overlap#Pascal Pascal].
 
=={{header|F#|F sharpEasyLang}}==
{{trans|C#}}
<syntaxhighlight>
func det2d t[][] .
return t[1][1] * (t[2][2] - t[3][2]) + t[2][1] * (t[3][2] - t[1][2]) + t[3][1] * (t[1][2] - t[2][2])
.
proc triwind . t[][] .
det = det2d t[][]
if det < 0
swap t[1][] t[2][]
.
.
func overlap t1[][] t2[][] .
triwind t1[][]
triwind t2[][]
for t to 2
for i to 3
j = (i + 1) mod1 3
for k to 3
if det2d [ t1[i][] t1[j][] t2[k][] ] >= 0
break 1
.
.
if k = 4
return 0
.
.
swap t1[][] t2[][]
.
return 1
.
print overlap [ [ 0 0 ] [ 5 0 ] [ 0 5 ] ] [ [ 0 0 ] [ 5 0 ] [ 0 6 ] ]
print overlap [ [ 0 0 ] [ 0 5 ] [ 5 0 ] ] [ [ 0 0 ] [ 0 5 ] [ 5 0 ] ]
print overlap [ [ 0 0 ] [ 5 0 ] [ 0 5 ] ] [ [ -10 0 ] [ -5 0 ] [ -1 6 ] ]
print overlap [ [ 0 0 ] [ 5 0 ] [ 2.5 5 ] ] [ [ 0 4 ] [ 2.5 -1 ] [ 5 4 ] ]
print overlap [ [ 0 0 ] [ 1 1 ] [ 0 2 ] ] [ [ 2 1 ] [ 3 0 ] [ 3 2 ] ]
print overlap [ [ 0 0 ] [ 1 1 ] [ 0 2 ] ] [ [ 2 1 ] [ 3 -2 ] [ 3 4 ] ]
</syntaxhighlight>
{{out}}
<pre>
1
1
0
1
0
0
</pre>
 
=={{header|F Sharp|F#}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="fsharp">open System
 
type Point = double * double
Line 1,031 ⟶ 1,753:
Console.WriteLine("{0} and\n{1}\nwhich have only a single corner in contact, if boundary points do not collide\n{2}", t11, t12, if TriTri2D 0.0 false false t11 t12 then "overlap" else "do not overlap")
 
0 // return an integer exit code</langsyntaxhighlight>
{{out}}
<pre>((0, 0), (5, 0), (0, 5)) and
Line 1,068 ⟶ 1,790:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">#macro min(x,y)
Iif(x>y,y,x)
#endmacro
Line 1,161 ⟶ 1,883:
print triangle_overlap( a(), b() )
next t
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,175 ⟶ 1,897:
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,322 ⟶ 2,044:
overlapping = triTri2D(t1, t2, 0.0, false, false)
fmt.Println(iff(overlapping, "overlap", "do not overlap"))
}</langsyntaxhighlight>
 
{{out}}
Line 1,331 ⟶ 2,053:
=={{header|Groovy}}==
{{trans|Java}}
<langsyntaxhighlight lang="groovy">import java.util.function.BiFunction
 
class TriangleOverlap {
Line 1,504 ⟶ 2,226:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0.0, 0.0), (5.0, 0.0), (0.0, 5.0) and
Line 1,539 ⟶ 2,261:
which have only a single corner in contact, if boundary points do not collide
do not overlap</pre>
 
=={{header|Haskell}}==
Uses the solution of the task [[Find_if_a_point_is_within_a_triangle#Haskell]]
 
<syntaxhighlight lang="haskell">isOverlapping :: Triangle Double -> Triangle Double -> Bool
isOverlapping t1 t2 = vertexInside || midLineInside
where
vertexInside =
any (isInside t1) (vertices t2) ||
any (isInside t2) (vertices t1)
 
isInside t = (Outside /=) . overlapping t
midLineInside =
any (\p -> isInside t1 p && isInside t2 p) midPoints
midPoints =
[ intersections l1 l2 | l1 <- midLines t1
, l2 <- midLines t2 ]
 
intersections (a1,b1,c1) (a2,b2,c2) =
( -(-b2*c1+b1*c2)/(a2*b1-a1*b2)
, -(a2*c1-a1*c2)/(a2*b1-a1*b2) )
 
midLines (Triangle a b c) =
[line a b c, line b c a, line c a b]
 
line (x,y) (ax, ay) (bx, by) =
(ay+by-2*y, -ax-bx+2*x, -ay*x-by*x+ax*y+bx*y)
 
test = map (uncurry isOverlapping)
[ (Triangle (0,0) (5,0) (0,5), Triangle (0,0) (5,0) (0,6))
, (Triangle (0,0) (0,5) (5,0), Triangle (0,0) (0,5) (5,0))
, (Triangle (0,0) (5,0) (0,5), Triangle (-10,0) (-5,0) (-1,6))
, (Triangle (0,0) (5,0) (2.5,5), Triangle (0,4) (2.5,-1) (5,4))
, (Triangle (0,0) (1,1) (0,2), Triangle (2,1) (3,0) (3,2))
, (Triangle (0,0) (1,1) (0,2), Triangle (2,1) (3,-2) (3,4))
, (Triangle (0,0) (1,0) (0,1), Triangle (1,0) (2,0) (1,1))]</syntaxhighlight>
 
<pre>λ> test
[True,True,False,True,False,False,True]</pre>
 
=={{header|Java}}==
{{trans|Kotlin}}
{{works with|Java|8}}
<langsyntaxhighlight Javalang="java">import java.util.function.BiFunction;
 
public class TriangleOverlap {
Line 1,718 ⟶ 2,481:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0.0, 0.0), (5.0, 0.0), (0.0, 5.0) and
Line 1,753 ⟶ 2,516:
which have only a single corner in contact, if boundary points do not collide
do not overlap</pre>
 
=={{header|jq}}==
{{trans|Wren}}
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq"># Points are realized as arrays of two numbers [x, y]
# Triangles are realized as triples of Points [p1, p2, p3]
 
# Input: a Triangle
def det2D:
. as [ [$p1x, $p1y], [$p2x, $p2y], [$p3x, $p3y]]
| $p1x * ($p2y - $p3y) +
$p2x * ($p3y - $p1y) +
$p3x * ($p1y - $p2y) ;
 
# Input: a Triangle
def checkTriWinding(allowReversed):
if det2D < 0
then if allowReversed
then . as [$p1, $p2, $p3]
| [$p1, $p3, $p2 ]
else "Triangle has wrong winding direction" | error
end
else .
end;
def boundaryCollideChk(eps): det2D < eps;
def boundaryDoesntCollideChk(eps): det2D <= eps;
def triTri2D($t1; $t2; $eps; $allowReversed; $onBoundary):
def chkEdge:
if $onBoundary then boundaryCollideChk($eps)
else boundaryDoesntCollideChk($eps)
end;
 
# Triangles must be expressed anti-clockwise
($t1|checkTriWinding($allowReversed))
| ($t2|checkTriWinding($allowReversed))
# 'onBoundary' determines whether points on boundary are considered as colliding or not
# for each edge E of t1
| first( range(0;3) as $i
| (($i + 1) % 3) as $j
# Check all points of t2 lie on the external side of edge E.
# If they do, the triangles do not overlap.
| if ([$t1[$i], $t1[$j], $t2[0]]| chkEdge) and
([$t1[$i], $t1[$j], $t2[1]]| chkEdge) and
([$t1[$i], $t1[$j], $t2[2]]| chkEdge)
then 0
else empty
end) // true
| if . == 0 then false
else
# for each edge E of t2
first( range(0;3) as $i
| (($i + 1) % 3) as $j
# Check all points of t1 lie on the external side of edge E.
# If they do, the triangles do not overlap.
| if ([$t2[$i], $t2[$j], $t1[0]] | chkEdge) and
([$t2[$i], $t2[$j], $t1[1]] | chkEdge) and
([$t2[$i], $t2[$j], $t1[2]] | chkEdge)
then 0
else empty
end) // true
| if . == 0 then false
else true # The triangles overlap
end
end ;</syntaxhighlight>
'''The Task'''
<syntaxhighlight lang="jq">def task:
def t: "Triangle: ";
def printTris(t1; t2; nl):
"\(nl)\(t)\(t1) and\n\(t)\(t2)" ;
 
def overlap(t1; t2):
if triTri2D(t1; t2; 0; false; true) then "overlap" else "do not overlap" end;
 
def overlapr(t1; t2):
if triTri2D(t1; t2; 0; true; true) then "overlap (reversed)" else "do not overlap" end;
 
([ [0, 0], [5, 0], [0, 5] ] as $t1
| [ [0, 0], [5, 0], [0, 6] ] as $t2
| printTris($t1; $t2; ""),
overlap($t1; $t2) ),
 
([ [0, 0], [0, 5], [5, 0] ] as $t1
| $t1 as $t2
| printTris($t1; $t2; "\n"),
# need to allow reversed for this pair to avoid exception
overlapr($t1; $t2) ),
 
([ [0, 0], [5, 0], [0, 5] ] as $t1
| [ [-10, 0], [-5, 0], [-1, 6] ] as $t2
| printTris($t1; $t2; "\n"),
overlap($t1; $t2) ),
 
([ [0, 0], [5, 0], [2.5, 5] ] as $t1
| [ [0, 4], [2.5, -1], [5, 4] ] as $t2
| printTris($t1; $t2; "\n"),
overlap($t1; $t2) ),
 
([ [0, 0], [1, 1], [0, 2] ] as $t1
| ([ [2, 1], [3, 0], [3, 2] ] as $t2
| printTris($t1; $t2; "\n"),
overlap($t1; $t2) ),
( [[2, 1], [3, -2], [3, 4]] as $t2
| printTris($t1; $t2; "\n"),
overlap($t1; $t2) )),
 
([ [0, 0], [1, 0], [0, 1] ] as $t1
| [ [1, 0], [2, 0], [1, 1.1] ] as $t2
| (printTris($t1; $t2; ""),
"which have only a single corner in contact, if boundary points collide",
overlap($t1; $t2) ),
 
(printTris($t1; $t2; "\n"),
"which have only a single corner in contact, if boundary points do not collide",
if triTri2D($t1; $t2; 0; false; false) then "overlap" else "do not overlap" end) );
 
task</syntaxhighlight>
{{out}}
<pre>
Triangle: [[0,0],[5,0],[0,5]] and
Triangle: [[0,0],[5,0],[0,6]]
overlap
 
Triangle: [[0,0],[0,5],[5,0]] and
Triangle: [[0,0],[0,5],[5,0]]
overlap (reversed)
 
Triangle: [[0,0],[5,0],[0,5]] and
Triangle: [[-10,0],[-5,0],[-1,6]]
do not overlap
 
Triangle: [[0,0],[5,0],[2.5,5]] and
Triangle: [[0,4],[2.5,-1],[5,4]]
overlap
 
Triangle: [[0,0],[1,1],[0,2]] and
Triangle: [[2,1],[3,0],[3,2]]
do not overlap
 
Triangle: [[0,0],[1,1],[0,2]] and
Triangle: [[2,1],[3,-2],[3,4]]
do not overlap
Triangle: [[0,0],[1,0],[0,1]] and
Triangle: [[1,0],[2,0],[1,1.1]]
which have only a single corner in contact, if boundary points collide
overlap
 
Triangle: [[0,0],[1,0],[0,1]] and
Triangle: [[1,0],[2,0],[1,1.1]]
which have only a single corner in contact, if boundary points do not collide
do not overlap
</pre>
 
 
=={{header|Julia}}==
{{trans|Python}}
'''Module''':
<langsyntaxhighlight lang="julia">module Triangles
 
using LinearAlgebra
Line 1,808 ⟶ 2,728:
end
 
end # module Triangles</langsyntaxhighlight>
 
'''Main''':
<langsyntaxhighlight lang="julia">using .Triangles
 
t1 = [0 0; 5 0; 0 5]
Line 1,845 ⟶ 2,765:
t1 = [0 0; 1 0; 0 1]
t2 = [1 0; 2 0; 1 1]
@show Triangles.overlap(t1, t2, MildCheck())</langsyntaxhighlight>
 
{{out}}
Line 1,859 ⟶ 2,779:
=={{header|Kotlin}}==
{{trans|C++}}
<langsyntaxhighlight lang="scala">// version 1.1.0
 
typealias Point = Pair<Double, Double>
Line 1,964 ⟶ 2,884:
println("which have only a single corner in contact, if boundary points do not collide")
println(if (triTri2D(t1, t2, 0.0, false, false)) "overlap" else "do not overlap")
}</langsyntaxhighlight>
 
{{out}}
Line 2,004 ⟶ 2,924:
 
=={{header|Lambdatalk}}==
<langsyntaxhighlight lang="scheme">
Here we present a rasterized version based on a single function "isInside".
 
Line 2,130 ⟶ 3,050:
.............................11
..............................1
</syntaxhighlight>
</lang>
 
=={{header|Lua}}==
{{trans|C++}}
<langsyntaxhighlight lang="lua">function det2D(p1,p2,p3)
return p1.x * (p2.y - p3.y)
+ p2.x * (p3.y - p1.y)
Line 2,273 ⟶ 3,193:
print(formatTri(t1).." and")
print(formatTri(t2))
print(overlap(t1,t2,0.0,false,false))</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0, 0), (5, 0), (0, 5) and
Line 2,306 ⟶ 3,226:
Triangle: (1, 0), (2, 0), (1, 1)
overlap</pre>
 
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">p1 = Polygon@{{0, 0}, {5, 0}, {0, 5}};
p2 = Polygon@{{0, 0}, {5, 0}, {0, 6}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {0, 5}, {5, 0}};
p2 = Polygon@{{0, 0}, {0, 5}, {5, 0}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {5, 0}, {0, 5}};
p2 = Polygon@{{-10, 0}, {-5, 0}, {-1, 6}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {5, 0}, {2.5, 5}};
p2 = Polygon@{{0, 4}, {2.5, -1}, {5, 4}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {1, 1}, {0, 2}};
p2 = Polygon@{{2, 1}, {3, 0}, {3, 2}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {1, 1}, {0, 2}};
p2 = Polygon@{{2, 1}, {3, -2}, {3, 4}};
! RegionDisjoint[p1, p2]
 
p1 = Polygon@{{0, 0}, {1, 0}, {0, 1}};
p2 = Polygon@{{1, 0}, {2, 0}, {1, 1}};
! RegionDisjoint[p1, p2]</syntaxhighlight>
{{out}}
<pre>True
True
False
True
False
False
True</pre>
 
=={{header|Modula-2}}==
<langsyntaxhighlight lang="modula2">MODULE Overlap;
FROM EXCEPTIONS IMPORT AllocateSource,ExceptionSource,GetMessage,RAISE;
FROM LongStr IMPORT RealToFixed;
Line 2,493 ⟶ 3,451:
 
ReadChar
END Overlap.</langsyntaxhighlight>
 
=={{header|Nim}}==
{{trans|Go}}
<langsyntaxhighlight Nimlang="nim">import strformat
 
type Point = tuple[x, y: float]
Line 2,610 ⟶ 3,568:
echo "which have only a single corner in contact, if boundary points do not collide"
overlapping = triTri2D(t1, t2, 0, false, false)
echo if overlapping: "overlap\n" else: "do not overlap\n"</langsyntaxhighlight>
 
{{out}}
Line 2,648 ⟶ 3,606:
 
=={{header|ooRexx}}==
<langsyntaxhighlight lang="oorexx">/*--------------------------------------------------------------------
* Determine if two triangles overlap
* Fully (?) tested with integer coordinates of the 6 corners
* This was/is an exercise with ooRexx
* Removed the fraction arithmetic
* add test for triangles' validity
*-------------------------------------------------------------------*/
Parse Version v
 
oid='trioo.txt'; 'erase' oid
Call o v
Line 2,671 ⟶ 3,629:
Call trio_test '0 0 1 1 0 2 2 1 3 -2 3 4'
Call trio_test '0 0 1 0 0 1 1 0 2 0 1 1'
Call trio_test '0 0 0 0 2 2 1 1 2 1 1 2' -- two points are identical
Call trio_test '0 0 0 3 2 2 1 1 2 2 3 3' -- three points on a line
Exit
/* Other test cases */
Line 2,704 ⟶ 3,664:
tlist=space(tlist)
tl1=tlist ; Call trio_t tl1
If result=-1 Then Return
tl2=reversex(tlist) ; Call trio_t tl2
tl3=''
Line 2,714 ⟶ 3,675:
tl4=reversex(tl3) ; Call trio_t tl4
tl5=subword(tl4,7) subword(tl4,1,6) ; Call trio_t tl5
tl6=''
tl6=subword(tl5,7) subword(tl5,1,6) ; Call trio_t tl6
tl=tlist
Do While tl<>''
Parse Var tl x y tl
tl6=tl6 y x
End
Call trio_t tl6
Return
 
Line 2,720 ⟶ 3,687:
Parse Arg tlist
tlist=space(tlist)
Say '>' tlist
case+=1
Parse Arg ax ay bx by cx cy dx dy ex ey fx fy
Line 2,728 ⟶ 3,695:
a=.point~new(ax,ay); b=.point~new(bx,by); c=.point~new(cx,cy)
d=.point~new(dx,dy); e=.point~new(ex,ey); f=.point~new(fx,fy)
If area(a,b,c)=0 Then Do
Say a b c 'is not a valid triangle'
Return -1
End
If area(d,e,f)=0 Then Do
Say d e f 'is not a valid triangle'
Return -1
End
abc=.triangle~new(a,b,c)
def=.triangle~new(d,e,f)
Line 2,932 ⟶ 3,907:
expose point edge
use arg p1,p2,p3
If area(p1,p2,p3)=0 Then Do
Say p1 p2 p3 'is not a valid triangle!'
Return .nil
End
point=.array~new
point[1]=p1
Line 3,194 ⟶ 4,173:
res=res word(list,i)
End
Return res </lang>
 
::ROUTINE distpp PUBLIC --Compute the distance between the points A and B
/***********************************************************************
* Compute the distance between the points A and B
***********************************************************************/
Use Arg A,B
ax=A~x; ay=A~y; bx=B~x; by=B~y
res=rxCalcsqrt((bx-ax)**2+(by-ay)**2)
Return res
 
::ROUTINE area PUBLIC --Compute the area of the triangla A B C
/***********************************************************************
* Compute the area of the triangla A B C
***********************************************************************/
Use Arg A,B,C
ax=A~x; ay=A~y; bx=B~x; by=B~y; cx=C~x; cy=C~y
ab=distpp(A,B)
bc=distpp(B,C)
ca=distpp(C,A)
s=(ab+bc+ca)/2
area=rxCalcsqrt(s*(s-ab)*(s-bc)*(s-ca))
Return area
::REQUIRES rxMath Library</syntaxhighlight>
{{out}}
<pre> 0 0 4 0 0 4 1 1 2 1 1 2
Triangle: ABC: (0,0) (4,0) (0,4)
Triangle: DEF: (1,1) (2,1) (1,2)
(1,1) (2,1) (1,2) is fully contained in (0,0) (4,0) (0,4)
 
> 2 1 1 2 1 1 4 0 0 4 0 0
Triangle: ABC: (2,1) (1,2) (1,1)
Triangle: DEF: (4,0) (0,4) (0,0)
(2,1) (1,2) (1,1) is fully contained in (4,0) (0,4) (0,0)
 
> 1 2 2 1 1 1 0 4 4 0 0 0
Triangle: ABC: (1,2) (2,1) (1,1)
Triangle: DEF: (0,4) (4,0) (0,0)
(1,2) (2,1) (1,1) is fully contained in (0,4) (4,0) (0,0)
 
> 0 0 0 4 4 0 1 1 1 2 2 1
Triangle: ABC: (0,0) (0,4) (4,0)
Triangle: DEF: (1,1) (1,2) (2,1)
(1,1) (1,2) (2,1) is fully contained in (0,0) (0,4) (4,0)
 
> 1 1 1 2 2 1 0 0 0 4 4 0
Triangle: ABC: (1,1) (1,2) (2,1)
Triangle: DEF: (0,0) (0,4) (4,0)
(1,1) (1,2) (2,1) is fully contained in (0,0) (0,4) (4,0)
 
0> 01 01 4 4 0 12 1 1 2 20 10 4 0 0 4
Triangle: ABC: (01,01) (02,41) (41,02)
Triangle: DEF: (10,10) (14,20) (20,14)
(1,1) (1,2,1) (2,1,2) is fully contained in (0,0) (0,4,0) (4,0,4)
 
> 0 0 0 6 8 3 8 0 8 8 0 3
Triangle: ABC: (0,0) (0,6) (8,3)
Triangle: DEF: (8,0) (8,8) (0,3)
Corner(s) that touch the other triangle: (0,3) (8,3)
Triangles overlap and touch on (0,3) (8,3)
> 3 0 8 8 0 8 3 8 6 0 0 0
Triangle: ABC: (3,0) (8,8) (0,8)
Triangle: DEF: (3,8) (6,0) (0,0)
Corner(s) that touch the other triangle: (3,8) (3,0)
Triangles overlap and touch on (3,8) (3,0)
> 0 3 8 8 8 0 8 3 0 6 0 0
Triangle: ABC: (0,3) (8,8) (8,0)
Triangle: DEF: (8,3) (0,6) (0,0)
Corner(s) that touch the other triangle: (8,3) (0,3)
Triangles overlap and touch on (8,3) (0,3)
> 0 0 6 0 3 8 0 8 8 8 3 0
Triangle: ABC: (0,0) (6,0) (3,8)
Triangle: DEF: (0,8) (8,8) (3,0)
Corner(s) that touch the other triangle: (3,0) (3,8)
Triangles overlap and touch on (3,0) (3,8)
> 0 8 8 8 3 0 0 0 6 0 3 8
Triangle: ABC: (0,8) (8,8) (3,0)
Triangle: DEF: (0,0) (6,0) (3,8)
Corner(s) that touch the other triangle: (3,8) (3,0)
Triangles overlap and touch on (3,8) (3,0)
0> 8 0 68 8 0 3 80 0 80 86 8 3 0
Triangle: ABC: (08,0) (68,08) (30,83)
Triangle: DEF: (0,80) (80,86) (8,3,0)
Corner(s) that touch the other triangle: (38,03) (30,83)
Triangles overlap and touch on (38,03) (30,83)
> 0 0 0 2 2 0 0 0 4 0 0 6
Triangle: ABC: (0,0) (0,2) (2,0)
Triangle: DEF: (0,0) (4,0) (0,6)
Line 3,262 ⟶ 4,264:
Triangles overlap and touch on (0,0) (0,2) (2,0)
 
> 6 0 0 4 0 0 0 2 2 0 0 0
Triangle: ABC: (6,0) (0,4) (0,0)
Triangle: DEF: (0,2) (2,0) (0,0)
Line 3,268 ⟶ 4,270:
Triangles overlap and touch on (0,2) (2,0) (0,0)
 
> 0 6 4 0 0 0 2 0 0 2 0 0
Triangle: ABC: (0,6) (4,0) (0,0)
Triangle: DEF: (2,0) (0,2) (0,0)
Line 3,274 ⟶ 4,276:
Triangles overlap and touch on (2,0) (0,2) (0,0)
 
> 0 0 2 0 0 2 0 0 0 4 6 0
Triangle: ABC: (0,0) (2,0) (0,2)
Triangle: DEF: (0,0) (0,4) (6,0)
Line 3,280 ⟶ 4,282:
Triangles overlap and touch on (0,0) (2,0) (0,2)
 
> 0 0 0 4 6 0 0 0 2 0 0 2
Triangle: ABC: (0,0) (0,4) (6,0)
Triangle: DEF: (0,0) (2,0) (0,2)
Line 3,286 ⟶ 4,288:
Triangles overlap and touch on (0,0) (2,0) (0,2)
 
> 0 0 24 0 0 26 0 0 0 42 62 0
Triangle: ABC: (0,0) (24,0) (0,26)
Triangle: DEF: (0,0) (0,42) (62,0)
Corner(s) that touch the other triangle: (0,0) (2,0,2) (0,2,0)
Triangles overlap and touch on (0,0) (2,0,2) (0,2,0)
 
> 0 0 5 0 0 5 0 0 5 0 0 6
Triangle: ABC: (0,0) (5,0) (0,5)
Triangle: DEF: (0,0) (5,0) (0,6)
Line 3,298 ⟶ 4,300:
Triangles have an edge in common: (0,0) (5,0)
 
> 6 0 0 5 0 0 5 0 0 5 0 0
Triangle: ABC: (6,0) (0,5) (0,0)
Triangle: DEF: (5,0) (0,5) (0,0)
Line 3,304 ⟶ 4,306:
Triangles have an edge in common: (0,5) (0,0)
 
> 0 6 5 0 0 0 0 5 5 0 0 0
Triangle: ABC: (0,6) (5,0) (0,0)
Triangle: DEF: (0,5) (5,0) (0,0)
Line 3,310 ⟶ 4,312:
Triangles have an edge in common: (5,0) (0,0)
 
> 0 0 0 5 5 0 0 0 0 5 6 0
Triangle: ABC: (0,0) (0,5) (5,0)
Triangle: DEF: (0,0) (0,5) (6,0)
Line 3,316 ⟶ 4,318:
Triangles have an edge in common: (0,0) (0,5)
 
> 0 0 0 5 6 0 0 0 0 5 5 0
Triangle: ABC: (0,0) (0,5) (6,0)
Triangle: DEF: (0,0) (0,5) (5,0)
Line 3,322 ⟶ 4,324:
Triangles have an edge in common: (0,0) (0,5)
 
0> 0 0 5 5 0 0 6 0 0 5 60 0 5
Triangle: ABC: (0,0) (5,0,5) (50,06)
Triangle: DEF: (0,0) (0,5,0) (6,0,5)
Corner(s) that touch the other triangle: (0,0) (0,5,0) (5,0,5)
Triangles have an edge in common: (0,0) (0,5,0)
 
> 0 0 0 5 5 0 0 0 0 5 5 0
Triangle: ABC: (0,0) (0,5) (5,0)
Triangle: DEF: (0,0) (0,5) (5,0)
Line 3,334 ⟶ 4,336:
Triangles are identical
 
> 0 5 5 0 0 0 0 5 5 0 0 0
Triangle: ABC: (0,5) (5,0) (0,0)
Triangle: DEF: (0,5) (5,0) (0,0)
Line 3,340 ⟶ 4,342:
Triangles are identical
 
> 5 0 0 5 0 0 5 0 0 5 0 0
Triangle: ABC: (5,0) (0,5) (0,0)
Triangle: DEF: (5,0) (0,5) (0,0)
Line 3,346 ⟶ 4,348:
Triangles are identical
 
> 0 0 5 0 0 5 0 0 5 0 0 5
Triangle: ABC: (0,0) (5,0) (0,5)
Triangle: DEF: (0,0) (5,0) (0,5)
Line 3,352 ⟶ 4,354:
Triangles are identical
 
> 0 0 5 0 0 5 0 0 5 0 0 5
Triangle: ABC: (0,0) (5,0) (0,5)
Triangle: DEF: (0,0) (5,0) (0,5)
Line 3,358 ⟶ 4,360:
Triangles are identical
 
0> 0 5 0 0 5 5 0 0 5 0 0 5 5 0
Triangle: ABC: (0,0) (5,0,5) (0,5,0)
Triangle: DEF: (0,0) (5,0,5) (0,5,0)
Corner(s) that touch the other triangle: (0,0) (5,0,5) (0,5,0)
Triangles are identical
 
> 0 0 5 0 0 5 -10 0 -5 0 -1 6
Triangle: ABC: (0,0) (5,0) (0,5)
Triangle: DEF: (-10,0) (-5,0) (-1,6)
(0,0) (5,0) (0,5) and (-10,0) (-5,0) (-1,6) don't overlap
 
> 6 -1 0 -5 0 -10 5 0 0 5 0 0
Triangle: ABC: (6,-1) (0,-5) (0,-10)
Triangle: DEF: (5,0) (0,5) (0,0)
(6,-1) (0,-5) (0,-10) and (5,0) (0,5) (0,0) don't overlap
 
> -1 6 -5 0 -10 0 0 5 5 0 0 0
Triangle: ABC: (-1,6) (-5,0) (-10,0)
Triangle: DEF: (0,5) (5,0) (0,0)
(-1,6) (-5,0) (-10,0) and (0,5) (5,0) (0,0) don't overlap
 
> 0 0 0 5 5 0 0 -10 0 -5 6 -1
Triangle: ABC: (0,0) (0,5) (5,0)
Triangle: DEF: (0,-10) (0,-5) (6,-1)
(0,0) (0,5) (5,0) and (0,-10) (0,-5) (6,-1) don't overlap
 
> 0 -10 0 -5 6 -1 0 0 0 5 5 0
Triangle: ABC: (0,-10) (0,-5) (6,-1)
Triangle: DEF: (0,0) (0,5) (5,0)
(0,-10) (0,-5) (6,-1) and (0,0) (0,5) (5,0) don't overlap
 
0> 0-10 0 5 -5 0 0 -101 6 0 0 -5 60 -10 5
Triangle: ABC: (0-10,0) (-5,0,5) (5-1,06)
Triangle: DEF: (0,-100) (0,-5,0) (60,-15)
(0-10,0) (0,-5,0) (5-1,06) and (0,-100) (0,-5,0) (60,-15) don't overlap
 
> 0 0 5 0 2.5 5 0 4 2.5 -1 5 4
Triangle: ABC: (0,0) (5,0) (2.5,5)
Triangle: DEF: (0,4) (2.5,-1) (5,4)
(0,0) (5,0) (2.5,5) and (0,4) (2.5,-1) (5,4) overlap
 
> 4 5 -1 2.5 4 0 5 2.5 0 5 0 0
Triangle: ABC: (4,5) (-1,2.5) (4,0)
Triangle: DEF: (5,2.5) (0,5) (0,0)
(4,5) (-1,2.5) (4,0) and (5,2.5) (0,5) (0,0) overlap
 
> 5 4 2.5 -1 0 4 2.5 5 5 0 0 0
Triangle: ABC: (5,4) (2.5,-1) (0,4)
Triangle: DEF: (2.5,5) (5,0) (0,0)
(5,4) (2.5,-1) (0,4) and (2.5,5) (5,0) (0,0) overlap
 
> 0 0 0 5 5 2.5 4 0 -1 2.5 4 5
Triangle: ABC: (0,0) (0,5) (5,2.5)
Triangle: DEF: (4,0) (-1,2.5) (4,5)
(0,0) (0,5) (5,2.5) and (4,0) (-1,2.5) (4,5) overlap
 
> 4 0 -1 2.5 4 5 0 0 0 5 5 2.5
Triangle: ABC: (4,0) (-1,2.5) (4,5)
Triangle: DEF: (0,0) (0,5) (5,2.5)
(4,0) (-1,2.5) (4,5) and (0,0) (0,5) (5,2.5) overlap
 
0> 0 04 2.5 5-1 2.5 4 0 -10 5 0 2.5 4 5
Triangle: ABC: (0,04) (02.5,5-1) (5,2.54)
Triangle: DEF: (40,0) (-1,2.5,0) (42.5,5)
(0,04) (0,2.5,-1) (5,2.54) and (40,0) (-1,2.5,0) (42.5,5) overlap
 
> 0 0 1 1 0 2 2 1 3 0 3 2
Triangle: ABC: (0,0) (1,1) (0,2)
Triangle: DEF: (2,1) (3,0) (3,2)
(0,0) (1,1) (0,2) and (2,1) (3,0) (3,2) don't overlap
 
> 2 3 0 3 1 2 2 0 1 1 0 0
Triangle: ABC: (2,3) (0,3) (1,2)
Triangle: DEF: (2,0) (1,1) (0,0)
(2,3) (0,3) (1,2) and (2,0) (1,1) (0,0) don't overlap
 
> 3 2 3 0 2 1 0 2 1 1 0 0
Triangle: ABC: (3,2) (3,0) (2,1)
Triangle: DEF: (0,2) (1,1) (0,0)
(3,2) (3,0) (2,1) and (0,2) (1,1) (0,0) don't overlap
 
> 0 0 1 1 2 0 1 2 0 3 2 3
Triangle: ABC: (0,0) (1,1) (2,0)
Triangle: DEF: (1,2) (0,3) (2,3)
(0,0) (1,1) (2,0) and (1,2) (0,3) (2,3) don't overlap
 
> 1 2 0 3 2 3 0 0 1 1 2 0
Triangle: ABC: (1,2) (0,3) (2,3)
Triangle: DEF: (0,0) (1,1) (2,0)
(1,2) (0,3) (2,3) and (0,0) (1,1) (2,0) don't overlap
 
0> 02 1 13 0 3 2 0 0 1 21 0 3 2 3
Triangle: ABC: (02,01) (13,10) (3,2,0)
Triangle: DEF: (10,20) (01,31) (20,32)
(02,01) (13,10) (23,02) and (10,20) (01,31) (20,32) don't overlap
 
> 0 0 1 1 0 2 2 1 3 -2 3 4
Triangle: ABC: (0,0) (1,1) (0,2)
Triangle: DEF: (2,1) (3,-2) (3,4)
(0,0) (1,1) (0,2) and (2,1) (3,-2) (3,4) don't overlap
 
> 4 3 -2 3 1 2 2 0 1 1 0 0
Triangle: ABC: (4,3) (-2,3) (1,2)
Triangle: DEF: (2,0) (1,1) (0,0)
(4,3) (-2,3) (1,2) and (2,0) (1,1) (0,0) don't overlap
 
> 3 4 3 -2 2 1 0 2 1 1 0 0
Triangle: ABC: (3,4) (3,-2) (2,1)
Triangle: DEF: (0,2) (1,1) (0,0)
(3,4) (3,-2) (2,1) and (0,2) (1,1) (0,0) don't overlap
 
> 0 0 1 1 2 0 1 2 -2 3 4 3
Triangle: ABC: (0,0) (1,1) (2,0)
Triangle: DEF: (1,2) (-2,3) (4,3)
(0,0) (1,1) (2,0) and (1,2) (-2,3) (4,3) don't overlap
 
> 1 2 -2 3 4 3 0 0 1 1 2 0
Triangle: ABC: (1,2) (-2,3) (4,3)
Triangle: DEF: (0,0) (1,1) (2,0)
(1,2) (-2,3) (4,3) and (0,0) (1,1) (2,0) don't overlap
 
0 0 1 1> 2 0 1 23 -2 3 4 30 0 1 1 0 2
Triangle: ABC: (02,01) (13,1-2) (23,04)
Triangle: DEF: (10,20) (-21,31) (40,32)
(02,01) (13,1-2) (23,04) and (10,20) (-21,31) (40,32) don't overlap
 
> 0 0 1 0 0 1 1 0 2 0 1 1
Triangle: ABC: (0,0) (1,0) (0,1)
Triangle: DEF: (1,0) (2,0) (1,1)
Line 3,492 ⟶ 4,494:
(0,0) (1,0) (0,1) and (1,0) (2,0) (1,1) don't overlap but touch on (1,0)
 
> 1 1 0 2 0 1 1 0 0 1 0 0
Triangle: ABC: (1,1) (0,2) (0,1)
Triangle: DEF: (1,0) (0,1) (0,0)
Line 3,500 ⟶ 4,502:
(1,1) (0,2) (0,1) and (1,0) (0,1) (0,0) don't overlap but touch on (0,1)
 
> 1 1 2 0 1 0 0 1 1 0 0 0
Triangle: ABC: (1,1) (2,0) (1,0)
Triangle: DEF: (0,1) (1,0) (0,0)
Line 3,508 ⟶ 4,510:
(1,1) (2,0) (1,0) and (0,1) (1,0) (0,0) overlap and touch on (1,0)
 
> 0 0 0 1 1 0 0 1 0 2 1 1
Triangle: ABC: (0,0) (0,1) (1,0)
Triangle: DEF: (0,1) (0,2) (1,1)
Line 3,516 ⟶ 4,518:
(0,0) (0,1) (1,0) and (0,1) (0,2) (1,1) don't overlap but touch on (0,1)
 
> 0 1 0 2 1 1 0 0 0 1 1 0
Triangle: ABC: (0,1) (0,2) (1,1)
Triangle: DEF: (0,0) (0,1) (1,0)
Line 3,524 ⟶ 4,526:
(0,1) (0,2) (1,1) and (0,0) (0,1) (1,0) don't overlap but touch on (0,1)
 
0> 1 0 2 0 1 1 0 0 1 0 2 10 1
Triangle: ABC: (01,0) (2,0,1) (1,01)
Triangle: DEF: (0,10) (01,20) (10,1)
Corner(s) that touch the other triangle: (0,1,0)
Triangles touch on (0,1,0)
we analyze further
(01,0) (02,10) (1,01) and (0,10) (01,20) (10,1) don't overlap but touch on (0,1,0)</pre>
 
> 0 0 0 0 2 2 1 1 2 1 1 2
(0,0) (0,0) (2,2) is not a valid triangle
> 0 0 0 3 2 2 1 1 2 2 3 3
(1,1) (2,2) (3,3) is not a valid triangle</pre>
 
=={{header|Pascal}}==
A console application in Free Pascal, created with the Lazarus IDE. It recognizes three possible outcomes: disjoint, positive overlap, and borderline (overlap at a point or line segment).
<langsyntaxhighlight lang="pascal">
program TrianglesOverlap;
{
Line 3,546 ⟶ 4,553:
If there's no separator, then the triangles have an overlap of positive area.
}
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$mode objfpc}{$H+}
{$ENDIF}}
 
uses Math, SysUtils;
Line 3,670 ⟶ 4,679:
TestTrianglePair( 0,0,1,0,0,1, 1,0,2,0,1,1);
end.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,684 ⟶ 4,693:
=={{header|Perl}}==
===Port of Lua===
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 3,845 ⟶ 4,854:
@t1 = ({x=>0, y=>0}, {x=>1, y=>0}, {x=>0, y=>1});
@t2 = ({x=>1, y=>0}, {x=>2, y=>0}, {x=>1, y=>1});
print formatTri(\@t1), " and\n", formatTri(\@t2), "\n", overlap(\@t1, \@t2, 0.0, 0, 0), "\n";</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0, 0), (5, 0), (0, 5) and
Line 3,880 ⟶ 4,889:
 
===More Idiomatic===
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 3,964 ⟶ 4,973:
);
 
say overlap(\$_->[0], \$_->[1], $_->[2], $_->[3], $_->[4]) for @tests;</langsyntaxhighlight>
{{out}}
<pre> overlap: (0,0), (5,0), (0,5) and (0,0), (5,0), (0,6)
Line 3,978 ⟶ 4,987:
{{trans|zkl}}
Plus draw all eight pairs of triangles for visual confirmation.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>include pGUI.e
<span style="color: #000080;font-style:italic;">--
 
-- demo\rosetta\Determine_if_two_triangles_overlap.exw
Ihandle dlg, canvas
--</span>
cdCanvas cddbuffer, cdcanvas
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
constant triangles = {{{{0,0},{5,0},{0,5}},{{0,0},{5,0},{0,6}}},
{{{0,0},{0,5},{5,0}},{{0,0},{0,5},{5,0}}},
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
{{{0,0},{5,0},{0,5}},{{-10,0},{-5,0},{-1,6}}},
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
{{{0,0},{5,0},{2.5,5}},{{0,4},{2.5,-1},{5,4}}},
{{{0,0},{1,1},{0,2}},{{2,1},{3,0},{3,2}}},
{{{0,0},{1,1},{0,2}},{{2,1},{3,-2},{3,4}}},
{{{0,0},{1,0},{0,1}},{{1,0},{2,0},{1,1}}},
{{{0,0},{1,0},{0,1}},{{1,0},{2,0},{1,1}}}}
 
procedure draw_triangle(sequence t, integer cx,cy, c)
cdCanvasSetForeground(cddbuffer, c)
cdCanvasBegin(cddbuffer,CD_CLOSED_LINES)
for c=1 to 3 do
atom {x,y} = t[c]
cdCanvasVertex(cddbuffer, cx+x*10, cy+y*10)
end for
cdCanvasEnd(cddbuffer)
end procedure
 
function det2D(sequence triangle)
atom {{p1x,p1y},{p2x,p2y},{p3x,p3y}} := triangle
return p1x*(p2y-p3y) + p2x*(p3y-p1y) + p3x*(p1y-p2y)
end function
 
bool bReversed
function checkWinding(sequence triangle, bool allowReversed)
atom detTri := det2D(triangle);
if detTri<0.0 then
if allowReversed then
bReversed = true
triangle = extract(triangle,{1,3,2})
else
throw("triangle has wrong winding direction")
end if
end if
return triangle
end function
 
function overlap(sequence t1, t2, atom epsilon=0.0, bool allowReversed=false, onBoundary=true)
-- Trangles must be expressed anti-clockwise
bReversed = false
t1 = checkWinding(t1, allowReversed)
t2 = checkWinding(t2, allowReversed)
<span style="color: #008080;">constant</span> <span style="color: #000000;">triangles</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}}},</span>
for t=1 to 2 do -- check t1 then t2
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
for edge=1 to 3 do -- check each edge
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},{{-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}}},</span>
sequence p1 = t1[edge],
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}}},</span>
p2 = t1[mod(edge,3)+1]
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}}},</span>
-- Check all points of trangle 2 lay on the external side
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}}},</span>
-- of the edge E. If they do, the triangles do not collide.
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}},</span>
integer onside = 0
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}}}</span>
for k=1 to 3 do
integer c = compare(det2D({p1,p2,t2[k]}),epsilon)
<span style="color: #008080;">procedure</span> <span style="color: #000000;">draw_triangle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
if onBoundary then
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
if not (c<0) then exit end if
<span style="color: #7060A8;">cdCanvasBegin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_CLOSED_LINES</span><span style="color: #0000FF;">)</span>
else
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
if not (c<=0) then exit end if
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #7060A8;">cdCanvasVertex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
-- -- (the following incomprehensible one-liner is equivalent:)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
-- if compare(det2D({p1,p2,t2[k]}),epsilon)>-onBoundary then exit end if
<span style="color: #7060A8;">cdCanvasEnd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
onside += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
end for
if onside=3 then
<span style="color: #008080;">function</span> <span style="color: #000000;">det2D</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">triangle</span><span style="color: #0000FF;">)</span>
return iff(onBoundary?"no overlap":"no overlap (no boundary)")
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">p1x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p1y</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">p2x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2y</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">p3x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p3y</span><span style="color: #0000FF;">}}</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">triangle</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">p1x</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">p2y</span><span style="color: #0000FF;">-</span><span style="color: #000000;">p3y</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">p2x</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">p3y</span><span style="color: #0000FF;">-</span><span style="color: #000000;">p1y</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">p3x</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">p1y</span><span style="color: #0000FF;">-</span><span style="color: #000000;">p2y</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
{t2,t1} = {t1,t2} -- flip and re-test
end for
<span style="color: #004080;">bool</span> <span style="color: #000000;">bReversed</span>
return iff(bReversed?"overlap (reversed)":"overlap")
<span style="color: #008080;">function</span> <span style="color: #000000;">checkWinding</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">triangle</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">allowReversed</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #004080;">atom</span> <span style="color: #000000;">detTri</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">det2D</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangle</span><span style="color: #0000FF;">);</span>
 
<span style="color: #008080;">if</span> <span style="color: #000000;">detTri</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0.0</span> <span style="color: #008080;">then</span>
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
<span style="color: #008080;">if</span> <span style="color: #000000;">allowReversed</span> <span style="color: #008080;">then</span>
cdCanvasActivate(cddbuffer)
<span style="color: #000000;">bReversed</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
integer cy = 200, cx = 100
<span style="color: #000000;">triangle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">extract</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangle</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">})</span>
for i=1 to length(triangles) do
<span style="color: #008080;">else</span>
sequence {t1,t2} = triangles[i]
<span style="color: #008080;">throw</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"triangle has wrong winding direction"</span><span style="color: #0000FF;">)</span>
draw_triangle(t1,cx,cy,CD_RED)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer s = (i<=2) -- (smudge tests[1..2] by one
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- pixel to show them better)
<span style="color: #008080;">return</span> <span style="color: #000000;">triangle</span>
draw_triangle(t2,cx+s,cy+s,CD_BLUE)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
cdCanvasSetForeground(cddbuffer, CD_BLACK)
cdCanvasText(cddbuffer,cx+10,cy-40,overlap(t1,t2,0,i=2,i!=8))
<span style="color: #008080;">function</span> <span style="color: #000000;">overlap</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">epsilon</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">allowReversed</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">onBoundary</span><span style="color: #0000FF;">=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
if i=4 then
<span style="color: #000080;font-style:italic;">-- Trangles must be expressed anti-clockwise</span>
cy = 100
<span style="color: #000000;">bReversed</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
cx = 100
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">checkWinding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">allowReversed</span><span style="color: #0000FF;">)</span>
else
<span style="color: #000000;">t2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">checkWinding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">allowReversed</span><span style="color: #0000FF;">)</span>
cx += 300
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- check t1 then t2</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">edge</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- check each edge</span>
cdCanvasFlush(cddbuffer)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t1</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edge</span><span style="color: #0000FF;">],</span>
return IUP_DEFAULT
<span style="color: #000000;">p2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t1</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edge</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
end function
<span style="color: #000080;font-style:italic;">-- Check all points of trangle 2 lay on the external side
 
-- of the edge E. If they do, the triangles do not collide.</span>
function map_cb(Ihandle ih)
<span style="color: #004080;">integer</span> <span style="color: #000000;">onside</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
cdcanvas = cdCreateCanvas(CD_IUP, ih)
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">det2D</span><span style="color: #0000FF;">({</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]}),</span><span style="color: #000000;">epsilon</span><span style="color: #0000FF;">)</span>
cdCanvasSetBackground(cddbuffer, CD_WHITE)
<span style="color: #008080;">if</span> <span style="color: #000000;">onBoundary</span> <span style="color: #008080;">then</span>
return IUP_DEFAULT
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">else</span>
 
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
procedure main()
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
IupOpen()
<span style="color: #000080;font-style:italic;">-- -- (the following incomprehensible one-liner is equivalent:)
-- if compare(det2D({p1,p2,t2[k]}),epsilon)&gt;-onBoundary then exit end if</span>
canvas = IupCanvas(NULL)
<span style="color: #000000;">onside</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
IupSetAttribute(canvas, "RASTERSIZE", "1250x300")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
<span style="color: #008080;">if</span> <span style="color: #000000;">onside</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
 
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">onBoundary</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"no overlap"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"no overlap (no boundary)"</span><span style="color: #0000FF;">)</span>
dlg = IupDialog(canvas,"DIALOGFRAME=YES")
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
IupSetAttribute(dlg, "TITLE", "Triangle overlap")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
<span style="color: #0000FF;">{</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- flip and re-test</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bReversed</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"overlap (reversed)"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"overlap"</span><span style="color: #0000FF;">)</span>
IupSetAttribute(canvas, "RASTERSIZE", NULL)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
IupMainLoop()
IupClose()
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">cy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span>
main()</lang>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">triangles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">triangles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">draw_triangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (smudge tests[1..2] by one
-- pixel to show them better)</span>
<span style="color: #000000;">draw_triangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #004600;">CD_BLUE</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_BLACK</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasText</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">overlap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">8</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">cy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span>
<span style="color: #000000;">cx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">cx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">300</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RASTERSIZE=1250x300"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetCallbacks</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">),</span>
<span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`RESIZE=NO, TITLE="Triangle overlap"`</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
 
=={{header|Python}}==
{{libheader|NumPy}}
Using numpy:
<langsyntaxhighlight lang="python">from __future__ import print_function
import numpy as np
 
Line 4,190 ⟶ 5,202:
t1 = [[0,0],[1,0],[0,1]]
t2 = [[1,0],[2,0],[1,1]]
print (TriTri2D(t1, t2, onBoundary = False), False)</langsyntaxhighlight>
 
{{out}}
Line 4,203 ⟶ 5,215:
{{libheader|Shapely}}
Using shapely:
<langsyntaxhighlight lang="python">from __future__ import print_function
from shapely.geometry import Polygon
 
Line 4,239 ⟶ 5,251:
t1 = [[0,0],[1,0],[0,1]]
t2 = [[1,0],[2,0],[1,1]]
print (PolyOverlaps(t1, t2), "?")</langsyntaxhighlight>
 
{{out}}
Line 4,251 ⟶ 5,263:
 
=={{header|QB64}}==
<syntaxhighlight lang="qb64">
<lang QB64>
DATA 0,0,5,0,0,5,0,0,5,0,0,6
DATA 0,0,0,5,5,0,0,0,0,5,5,0
Line 4,329 ⟶ 5,341:
p.y = (10 + p.y) * 30
END SUB
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
{{trans|Zkl}}
 
<langsyntaxhighlight lang="racket">#lang racket
 
;; A triangle is a list of three pairs of points: '((x . y) (x . y) (x . y))
Line 4,397 ⟶ 5,409:
(check-true (tri-tri-2d? c1 c2 #:on-boundary? #t))
(check-false (tri-tri-2d? c1 c2 #:on-boundary? #f))))
</syntaxhighlight>
</lang>
 
No output &rarr; all tests passed
Line 4,404 ⟶ 5,416:
(formerly Perl 6)
First, check if any vertex is inside each other triangle (that should cover most overlapping cases including enclosures). Then see if an edge of triangle A intersects any of two edges of B (for shapes like Star of David [https://en.wikipedia.org/wiki/Star_of_David])
<syntaxhighlight lang="raku" perl6line># Reference:
# https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
# https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
 
use v6;
 
sub if-overlap ($triangle-pair) {
Line 4,415 ⟶ 5,425:
 
sub sign (\T) {
return (T.[0][;0] - T[2][;0]) *× (T[1][;1] - T[2][;1]) -
(T[1][;0] - T[2][;0]) *× (T[0][;1] - T[2][;1]);
}
 
sub point-in-triangle (\pt, \Y --> Bool) {
my ($d1 = sign (pt, $d2Y[0], $d3Y[1]);
my Bool$d2 = sign ($has_negpt, $has_posY[1], Y[2]);
my $d3 = sign (pt, Y[2], Y[0]);
 
my $d1has_neg = sign[or] (pt$d1 < 0, Y.[$d2 < 0], Y.[1])$d3 < 0;
my $d2has_pos = sign[or] (pt$d1 > 0, Y.[1]$d2 > 0, Y.[2])$d3 > 0;
$d3 = sign (pt, Y.[2], Y.[0]);
 
$has_negreturn =not ($d1has_neg <and 0) || ($d2 < 0) || ($d3 < 0has_pos);
$has_pos = ($d1 > 0) || ($d2 > 0) || ($d3 > 0);
 
return !($has_neg && $has_pos);
}
 
sub orientation(\P, \Q, \R --> Int) {
my \val = (Q.[1] - P.[1]) *× (R.[0] - Q.[0]) -
(Q.[0] - P.[0]) *× (R.[1] - Q.[1]);
 
return 0 if val == 0; # colinear
return val > 0 ?? 1 !! 2; # clock or counterclock wise
 
return (val > 0) ?? 1 !! 2; # clock or counterclock wise
}
 
sub onSegment(\P, \Q, \R --> Bool) {
Q.[0] <= max(P.[0], R.[0]) &&and Q.[0] >= min(P.[0], R.[0]) &&and
Q.[1] <= max(P.[1], R.[1]) &&and Q.[1] >= min(P.[0], R.[1])
?? True !! False;
}
 
sub intersect(\A,\B,\C,\D --> Bool) {
my \o1 = orientation A, C, D;
my \o2 = orientation B, C, D;
my \o3 = orientation A, B, C;
my \o4 = orientation A, B, D;
 
return True if o1 != o2 &&and o3 != o4;
or o1 == 0 and onSegment A, C, D
 
returnor True if (o1o2 == 0 &&and onSegment(A B, C, D)) ;
returnor True if (o2o3 == 0 &&and onSegment( A, B, C, D)) ;
returnor True if (o3o4 == 0 &&and onSegment( A, B, C)) ;D
return True if (o4?? == 0 && onSegment(A, B,True D))!! ;False
 
return False;
}
 
for ^3 {
{ $result = True; last } if point-in-triangle A.[$^i] , B or
point-in-triangle BA.[$^i] , AB ;or
point-in-triangle B.[$^i], A ;
}
 
unless $result {
$result = True if intersect A.[0], A.[1], B.[0], B.[1] or
intersect A.[0], A.[1], B.[0], B.[1] or
intersect A.[0], A.[1], B.[0], B.[2]
}
 
say "{A, ".gist} and ", {B, ".gist} do",{' NOT' unless $result ?? "" !! " NOT" , "} overlap.";
}
 
Line 4,487 ⟶ 5,493:
];
 
if-overlap $_ for DATA ;</langsyntaxhighlight>
{{out}}
{{out}}<pre>[(0 0) (5 0) (0 5)] and [(0 0) (5 0) (0 6)] do overlap.
<pre>[(0 0) (5 0) (0 5)] and [(0 0) (5 0) (0 6)] do overlap.
[(0 0) (0 5) (5 0)] and [(0 0) (0 5) (5 0)] do overlap.
[(0 0) (5 0) (0 5)] and [(-10 0) (-5 0) (-1 6)] do NOT overlap.
Line 4,494 ⟶ 5,501:
[(0 0) (1 1) (0 2)] and [(2 1) (3 0) (3 2)] do NOT overlap.
[(0 0) (1 1) (0 2)] and [(2 1) (3 -2) (3 4)] do NOT overlap.
[(0 0) (1 0) (0 1)] and [(1 0) (2 0) (1 1)] do overlap.</pre>
</pre>
 
=={{header|REXX}}==
Note: The triangles must be real triangles (no edge of length 0)
<langsyntaxhighlight lang="rexx">/* REXX */
Signal On Halt
Signal On Novalue
Line 5,075 ⟶ 6,081:
Nop
End
Exit 12</langsyntaxhighlight>
{{out}}
<pre>ABC: (0/0) (5/0) (0/5)
Line 5,151 ⟶ 6,157:
=={{header|Ruby}}==
{{trans|C}}
<langsyntaxhighlight lang="ruby">require "matrix"
 
def det2D(p1, p2, p3)
Line 5,268 ⟶ 6,274:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>Triangle: [Vector[0, 0], Vector[5, 0], Vector[0, 5]]
Line 5,304 ⟶ 6,310:
=={{header|Scala}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="scala">object Overlap {
type Point = (Double, Double)
 
Line 5,407 ⟶ 6,413:
println(if (triTri2D(t1, t2, onBoundary = false)) "overlap" else "do not overlap")
}
}</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0.0,0.0), (5.0,0.0), (0.0,5.0) and
Line 5,445 ⟶ 6,451:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Module Module1
 
Class Triangle
Line 5,593 ⟶ 6,599:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>Triangle: (0, 0), (5, 0), (0, 5) and
Line 5,628 ⟶ 6,634:
which have only a single corner in contact, if boundary points do not collide
do not overlap</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">struct Point {
x f64
y f64
}
fn (p Point) str() string {
return "(${p.x:.1f}, ${p.y:.1f})"
}
struct Triangle {
mut:
p1 Point
p2 Point
p3 Point
}
fn (t Triangle) str() string {
return "Triangle $t.p1, $t.p2, $t.p3"
}
fn (t Triangle) det_2d() f64 {
return t.p1.x * (t.p2.y - t.p3.y) +
t.p2.x * (t.p3.y - t.p1.y) +
t.p3.x * (t.p1.y - t.p2.y)
}
fn (mut t Triangle) check_tri_winding(allow_reversed bool) {
det_tri := t.det_2d()
if det_tri < 0.0 {
if allow_reversed {
a := t.p3
t.p3 = t.p2
t.p2 = a
} else {
panic("Triangle has wrong winding direction.")
}
}
}
fn boundary_collide_chk(t Triangle, eps f64, does bool) bool {
if does {
return t.det_2d() < eps
}
return t.det_2d() <= eps
}
fn tri_tri_2d(mut t1 Triangle, mut t2 Triangle, eps f64, allow_reversed bool, on_boundary bool) bool {
// Triangles must be expressed anti-clockwise.
t1.check_tri_winding(allow_reversed)
t2.check_tri_winding(allow_reversed)
lp1 := [t1.p1, t1.p2, t1.p3]
lp2 := [t2.p1, t2.p2, t2.p3]
// for each edge E of t1
for i in 0..3 {
j := (i + 1) % 3
// Check all Points of t2 lay on the external side of edge E.
// If they do, the Triangles do not overlap.
tri1 := Triangle{lp1[i], lp1[j], lp2[0]}
tri2 := Triangle{lp1[i], lp1[j], lp2[1]}
tri3 := Triangle{lp1[i], lp1[j], lp2[2]}
if boundary_collide_chk(tri1, eps,on_boundary) && boundary_collide_chk(tri2, eps,on_boundary) && boundary_collide_chk(tri3, eps,on_boundary) {
return false
}
}
// for each edge E of t2
for i in 0..3 {
j := (i + 1) % 3
// Check all Points of t1 lay on the external side of edge E.
// If they do, the Triangles do not overlap.
tri1 := Triangle{lp2[i], lp2[j], lp1[0]}
tri2 := Triangle{lp2[i], lp2[j], lp1[1]}
tri3 := Triangle{lp2[i], lp2[j], lp1[2]}
if boundary_collide_chk(tri1, eps,on_boundary) && boundary_collide_chk(tri2, eps,on_boundary) && boundary_collide_chk(tri3, eps,on_boundary) {
return false
}
}
// The Triangles overlap.
return true
}
fn iff(cond bool, s1 string, s2 string) string {
if cond {
return s1
}
return s2
}
fn main() {
mut t1 := Triangle{Point{0.0, 0.0}, Point{5.0, 0.0}, Point{0.0, 5.0}}
mut t2 := Triangle{Point{0.0, 0.0}, Point{5.0, 0.0}, Point{0.0, 6.0}}
println("\n$t1 and\n$t2")
mut overlapping := tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
// Need to allow reversed for this pair to avoid panic.
t1 = Triangle{Point{0.0, 0.0}, Point{0.0, 5.0}, Point{5.0, 0.0}}
t2 = t1
println("\n$t1 and\n$t2")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, true, true)
println(iff(overlapping, "overlap (reversed)", "do not overlap"))
t1 = Triangle{Point{0.0, 0.0}, Point{5.0, 0.0}, Point{0.0, 5.0}}
t2 = Triangle{Point{-10.0, 0.0}, Point{-5.0, 0.0}, Point{-1.0, 6.0}}
println("\n$t1 and\n$t2")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
t1.p3 = Point{2.5, 5.0}
t2 = Triangle{Point{0.0, 4.0}, Point{2.5, -1.0}, Point{5.0, 4.0}}
println("\n$t1 and\n$t2")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
t1 = Triangle{Point{0.0, 0.0}, Point{1.0, 1.0}, Point{0.0, 2.0}}
t2 = Triangle{Point{2.0, 1.0}, Point{3.0, 0.0}, Point{3.0, 2.0}}
println("\n$t1 and\n$t2")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
t2 = Triangle{Point{2.0, 1.0}, Point{3.0, -2.0}, Point{3.0, 4.0}}
println("\n$t1 and\n$t2")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
t1 = Triangle{Point{0.0, 0.0}, Point{1.0, 0.0}, Point{0.0, 1.0}}
t2 = Triangle{Point{1.0, 0.0}, Point{2.0, 0.0}, Point{1.0, 1.1}}
println("\n$t1 and\n$t2")
println("which have only a single corner in contact, if boundary Points collide")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, true)
println(iff(overlapping, "overlap", "do not overlap"))
println("\n$t1 and\n$t2")
println("which have only a single corner in contact, if boundary Points do not collide")
overlapping = tri_tri_2d(mut t1, mut t2, 0.0, false, false)
println(iff(overlapping, "overlap", "do not overlap"))
}</syntaxhighlight>
 
{{out}}
<pre>Same as Kotlin Entry</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "./dynamic" for Tuple, Struct
 
var Point = Tuple.create("Point", ["x", "y"])
 
var Triangle = Struct.create("Triangle", ["p1", "p2", "p3"])
 
var det2D = Fn.new { |t|
return t.p1.x * (t.p2.y - t.p3.y) +
t.p2.x * (t.p3.y - t.p1.y) +
t.p3.x * (t.p1.y - t.p2.y)
}
 
var checkTriWinding = Fn.new { |t, allowReversed|
var detTri = det2D.call(t)
if (detTri < 0) {
if (allowReversed) {
var a = t.p3
t.p3 = t.p2
t.p2 = a
} else Fiber.abort("Triangle has wrong winding direction")
}
}
 
var boundaryCollideChk = Fn.new { |t, eps| det2D.call(t) < eps }
 
var boundaryDoesntCollideChk = Fn.new { |t, eps| det2D.call(t) <= eps }
 
var triTri2D = Fn.new { |t1, t2, eps, allowReversed, onBoundary|
// Triangles must be expressed anti-clockwise
checkTriWinding.call(t1, allowReversed)
checkTriWinding.call(t2, allowReversed)
// 'onBoundary' determines whether points on boundary are considered as colliding or not
var chkEdge = onBoundary ? boundaryCollideChk : boundaryDoesntCollideChk
var lp1 = [t1.p1, t1.p2, t1.p3]
var lp2 = [t2.p1, t2.p2, t2.p3]
 
// for each edge E of t1
for (i in 0..2) {
var j = (i + 1) % 3
// Check all points of t2 lay on the external side of edge E.
// If they do, the triangles do not overlap.
if (chkEdge.call(Triangle.new(lp1[i], lp1[j], lp2[0]), eps) &&
chkEdge.call(Triangle.new(lp1[i], lp1[j], lp2[1]), eps) &&
chkEdge.call(Triangle.new(lp1[i], lp1[j], lp2[2]), eps)) return false
}
 
// for each edge E of t2
for (i in 0..2) {
var j = (i + 1) % 3
// Check all points of t1 lay on the external side of edge E.
// If they do, the triangles do not overlap.
if (chkEdge.call(Triangle.new(lp2[i], lp2[j], lp1[0]), eps) &&
chkEdge.call(Triangle.new(lp2[i], lp2[j], lp1[1]), eps) &&
chkEdge.call(Triangle.new(lp2[i], lp2[j], lp1[2]), eps)) return false
}
 
// The triangles overlap
return true
}
 
var tr = "Triangle: "
var printTris = Fn.new { |t1, t2, nl| System.print("%(nl)%(tr)%(t1) and\n%(tr)%(t2)") }
 
var t1 = Triangle.new(Point.new(0, 0), Point.new(5, 0), Point.new(0, 5))
var t2 = Triangle.new(Point.new(0, 0), Point.new(5, 0), Point.new(0, 6))
printTris.call(t1, t2, "")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
// need to allow reversed for this pair to avoid exception
t1 = Triangle.new(Point.new(0, 0), Point.new(0, 5), Point.new(5, 0))
t2 = t1
printTris.call(t1, t2, "\n")
System.print(triTri2D.call(t1, t2, 0, true, true) ? "overlap (reversed)" : "do not overlap")
 
t1 = Triangle.new(Point.new(0, 0), Point.new(5, 0), Point.new(0, 5))
t2 = Triangle.new(Point.new(-10, 0), Point.new(-5, 0), Point.new(-1, 6))
printTris.call(t1, t2, "\n")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
t1.p3 = Point.new(2.5, 5)
t2 = Triangle.new(Point.new(0, 4), Point.new(2.5, -1), Point.new(5, 4))
printTris.call(t1, t2, "\n")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
t1 = Triangle.new(Point.new(0, 0), Point.new(1, 1), Point.new(0, 2))
t2 = Triangle.new(Point.new(2, 1), Point.new(3, 0), Point.new(3, 2))
printTris.call(t1, t2, "\n")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
t2 = Triangle.new(Point.new(2, 1), Point.new(3, -2), Point.new(3, 4))
printTris.call(t1, t2, "\n")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
t1 = Triangle.new(Point.new(0, 0), Point.new(1, 0), Point.new(0, 1))
t2 = Triangle.new(Point.new(1, 0), Point.new(2, 0), Point.new(1, 1.1))
printTris.call(t1, t2, "\n")
System.print("which have only a single corner in contact, if boundary points collide")
System.print(triTri2D.call(t1, t2, 0, false, true) ? "overlap" : "do not overlap")
 
printTris.call(t1, t2, "\n")
System.print("which have only a single corner in contact, if boundary points do not collide")
System.print(triTri2D.call(t1, t2, 0, false, false) ? "overlap" : "do not overlap")</syntaxhighlight>
 
{{out}}
<pre>
Triangle: ((0, 0), (5, 0), (0, 5)) and
Triangle: ((0, 0), (5, 0), (0, 6))
overlap
 
Triangle: ((0, 0), (0, 5), (5, 0)) and
Triangle: ((0, 0), (0, 5), (5, 0))
overlap (reversed)
 
Triangle: ((0, 0), (5, 0), (0, 5)) and
Triangle: ((-10, 0), (-5, 0), (-1, 6))
do not overlap
 
Triangle: ((0, 0), (5, 0), (2.5, 5)) and
Triangle: ((0, 4), (2.5, -1), (5, 4))
overlap
 
Triangle: ((0, 0), (1, 1), (0, 2)) and
Triangle: ((2, 1), (3, 0), (3, 2))
do not overlap
 
Triangle: ((0, 0), (1, 1), (0, 2)) and
Triangle: ((2, 1), (3, -2), (3, 4))
do not overlap
 
Triangle: ((0, 0), (1, 0), (0, 1)) and
Triangle: ((1, 0), (2, 0), (1, 1.1))
which have only a single corner in contact, if boundary points collide
overlap
 
Triangle: ((0, 0), (1, 0), (0, 1)) and
Triangle: ((1, 0), (2, 0), (1, 1.1))
which have only a single corner in contact, if boundary points do not collide
do not overlap
</pre>
 
=={{header|zkl}}==
{{trans|C++}}
<langsyntaxhighlight lang="zkl">// A triangle is three pairs of points: ( (x,y), (x,y), (x,y) )
 
fcn det2D(triangle){
Line 5,670 ⟶ 6,965:
}
True // The triangles collide
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn toTri(ax,ay,bx,by,cx,cy){ //-->( (ax,ay),(bx,by),(cx,cy) )
vm.arglist.apply("toFloat").pump(List,Void.Read)
}
Line 5,695 ⟶ 6,990:
c1,c2 := toTri(0,0, 1,0, 0,1), toTri(1,0, 2,0, 1,1);
println("Corner case (barely touching): ",triTri2D(c1,c2,0.0,False,True)); // True
println("Corner case (barely touching): ",triTri2D(c1,c2,0.0,False,False)); // False</langsyntaxhighlight>
{{out}}
<pre>
2,052

edits