Triangulate2Polygons:
PUBLIC
PROC [
polygon0, polygon1: NatSequence,
points: TripleSequence]
RETURNS [triangles: Nat3Sequence]
~ {
ProjectToXYPlane:
PROC [poly: NatSequence, points: TripleSequence, o, x, y: Triple]
RETURNS [pairs: PairSequence]
~ {
pairs ¬ NEW[G3dBasic.PairSequenceRep[poly.length]];
pairs.length ¬ poly.length;
FOR n:
NAT
IN [0..pairs.length)
DO
q: Triple ~ G3dVector.Sub[points[poly[n]], o];
pairs[n] ¬ [G3dVector.Dot[q, x], G3dVector.Dot[q, y]];
ENDLOOP;
};
NewTriangle:
PROC [a, b, c:
NAT] ~ {
IF triangles.length >= triangles.maxLength
THEN {
old: Nat3Sequence ¬ triangles;
triangles ¬ NEW[Nat3SequenceRep[Real.Round[1.3*triangles.length]]];
FOR i: NAT IN [0..old.length) DO triangles[i] ¬ old[i]; ENDLOOP;
triangles.length ¬ old.length;
};
triangles[triangles.length] ¬ [a, b, c];
triangles.length ¬ triangles.length+1;
};
ScaleAndCenter:
PROC ~ {
PutInUnitSquare:
PROC [pairs: PairSequence] ~ {
FOR n:
NAT
IN [0..pairs.length)
DO
pairs[n] ¬ [sx*(pairs[n].x-cx), sy*(pairs[n].y-cy)];
ENDLOOP;
};
amm: G2dBasic.Box ¬ G2dVector.MinMaxSequence[apairs];
bmm: G2dBasic.Box ¬ G2dVector.MinMaxSequence[bpairs];
mm: G2dBasic.Box ¬ [
[MIN[amm.min.x, bmm.min.x], MIN[amm.min.y, bmm.min.y]],
[MAX[amm.max.x, bmm.max.x], MAX[amm.max.y, bmm.max.y]]];
cx: REAL ¬ 0.5*(mm.min.x+mm.max.x);
cy: REAL ¬ 0.5*(mm.min.y+mm.max.y);
sx: REAL ¬ IF mm.min.x # mm.max.x THEN 2.0/(mm.max.x-mm.min.x) ELSE 0.0;
sy: REAL ¬ IF mm.min.y # mm.max.y THEN 2.0/(mm.max.y-mm.min.y) ELSE 0.0;
PutInUnitSquare[apairs];
PutInUnitSquare[bpairs];
};
SetStartingPoints:
PROC ~ {
s, max: REAL ¬ 10000.0;
FOR n:
NAT
IN [0..a.length)
DO
FOR nn:
NAT
IN [0..b.length)
DO
IF (s ¬ G2dVector.SquareDistance[apairs[n], bpairs[nn]]) < max
THEN {astart ¬ a0 ¬ n; bstart ¬ b0 ¬ nn; max ¬ s};
ENDLOOP;
ENDLOOP;
};
a: NatSequence ~ polygon0;
b: NatSequence ~ PolygonReverse[G2dBasic.CopyNatSequence[polygon1]];
acenter: Triple ¬ PolygonCenter[points, a];
bcenter: Triple ¬ PolygonCenter[points, b];
center: Triple ¬ G3dVector.Mul[G3dVector.Add[acenter, bcenter], 0.5];
z: Triple ¬ G3dVector.Unit[G3dVector.Sub[bcenter, acenter]];
x: Triple ¬ G3dVector.Ortho[z, G3dBasic.yAxis];
y: Triple ¬ G3dVector.Unit[G3dVector.Cross[x, z]];
apairs: PairSequence ¬ ProjectToXYPlane[a, points, center, x, y];
bpairs: PairSequence ¬ ProjectToXYPlane[b, points, center, x, y];
a0, a1, astart, b0, b1, bstart: NAT ¬ 0;
nTriangles: NAT ¬ 0;
maxNTriangles: NAT ¬ polygon0.length+polygon1.length+2; -- +2 is for good luck
ScaleAndCenter[];
SetStartingPoints[];
a1 ¬ (a0+1) MOD a.length;
b1 ¬ (b0+1) MOD b.length;
triangles ¬ NEW[Nat3SequenceRep[points.length]];
DO
IF G2dVector.SquareDistance[apairs[a0], bpairs[b1]] <
G2dVector.SquareDistance[apairs[a1], bpairs[b0]]
THEN {
NewTriangle[a[a0], b[b0], b[b1]];
b0 ¬ b1;
b1 ¬ (b1+1) MOD b.length;
}
ELSE {
NewTriangle[a[a0], b[b0], a[a1]];
a0 ¬ a1;
a1 ¬ (a1+1) MOD a.length;
};
IF a0 = astart AND b0 = bstart THEN EXIT;
IF (nTriangles ¬ nTriangles+1) >= maxNTriangles THEN EXIT;
ENDLOOP;
};