LengthenTriangleSequence:
PUBLIC PROC [t: TriangleSequence]
RETURNS [TriangleSequence] ~ {
old: TriangleSequence ~ t;
t ← NEW[TriangleSequenceRep[Real.RoundI[1.3*old.length]]];
FOR i: NAT IN [0..old.length) DO t[i] ← old[i]; ENDLOOP;
t.length ← old.length;
RETURN[t];
};
Triangulate2Polygons:
PUBLIC
PROC [
poly0, poly1: REF NatSequence, points: TripleSequence]
RETURNS [triangles: TriangleSequence]
~ {
NewTriangle:
PROC [a, b, c:
NAT] ~ {
IF triangles.length >= triangles.maxLength
THEN triangles ← LengthenTriangleSequence[triangles];
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: MinMaxPairs ← GetMinMaxPairs[apairs];
bmm: MinMaxPairs ← GetMinMaxPairs[bpairs];
mm: MinMaxPairs ← [
[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 ← SquarePairDistance[apairs[n], bpairs[nn]]) < max
THEN {astart ← a0 ← n; bstart ← b0 ← nn; max ← s};
ENDLOOP;
ENDLOOP;
};
a: REF NatSequence ~ poly0;
b: REF NatSequence ~ ReversePolygon[CopyPolygon[poly1]];
acenter: Triple ← CenterOfPolygon[a, points];
bcenter: Triple ← CenterOfPolygon[b, points];
center: Triple ← Vector3d.Mul[Vector3d.Add[acenter, bcenter], 0.5];
z: Triple ← Vector3d.Normalize[Vector3d.Sub[bcenter, acenter]];
x: Triple ← Vector3d.Ortho[z, yAxis];
y: Triple ← Vector3d.Normalize[Vector3d.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 ← poly0.length+poly1.length+2; -- +2 is for good luck
ScaleAndCenter[];
SetStartingPoints[];
a1 ← (a0+1) MOD a.length;
b1 ← (b0+1) MOD b.length;
triangles ← NEW[TriangleSequenceRep[points.length]];
DO
IF SquarePairDistance[apairs[a0], bpairs[b1]] < SquarePairDistance[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;
};