xmsgeom  1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
triangulate.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
8 //------------------------------------------------------------------------------
9 
10 //----- Include Files ----------------------------------------------------------
11 
12 // 1. Precompiled header
13 
14 // 2. My own header
16 
17 // 3. Standard library headers
18 #include <cmath>
19 
20 // 4. External library headers
21 
22 // 5. Shared code headers
23 #include <xmscore/misc/XmLog.h> // XM_LOG
25 
26 // 6. Non-shared code headers
27 
28 //----- Forward declarations ---------------------------------------------------
29 
30 //----- External globals -------------------------------------------------------
31 
32 //----- Namespace declaration --------------------------------------------------
33 
35 namespace
36 {
37 using namespace xms;
38 //----- Constants / Enumerations -----------------------------------------------
39 
40 const int PLUS1MOD3[3] = {1, 2, 0};
41 const int MINUS1MOD3[3] = {2, 0, 1};
42 
43 #define pointmark(pt, idx) ((int*)(pt))[idx]
44 #define setpointmark(pt, value, idx) ((int*)(pt))[idx] = value
45 
46 // converts a ptr to an oriented triangle. The orientation is extracted from the
47 // two least significant bits of the pointer
48 #define decode(ptr, tedge) \
49  (tedge).orient = (int)((unsigned long long)(ptr) & (unsigned long long)3l); \
50  (tedge).tri = (Ttri*)((unsigned long long)(ptr) ^ (unsigned long long)(tedge).orient)
51 
52 // compresses an oriented triangle into a single ptr. Uses assumption that all
53 // triangles are aligned to four-byte boundaries, so the two least significant
54 // bits of (tedge).tri are 0
55 #define encode(tedge) (Ttri)((unsigned long long)(tedge).tri | (unsigned long long)(tedge).orient)
56 
57 // finds the abutting tri on the same edge. the edge direction is necessarily
58 // reversed, since triangle/edge handles are always directed counterclockwise
59 // around the triangle
60 #define sym(tedge1, tedge2) \
61  ptr = (tedge1).tri[(tedge1).orient]; \
62  decode(ptr, tedge2);
63 
64 #define symself(tedge) \
65  ptr = (tedge).tri[(tedge).orient]; \
66  decode(ptr, tedge);
67 
68 // finds the next edge (ccw) of a triangle
69 #define lnext(tedge1, tedge2) \
70  (tedge2).tri = (tedge1).tri; \
71  (tedge2).orient = PLUS1MOD3[(tedge1).orient]
72 
73 #define lnextself(tedge) (tedge).orient = PLUS1MOD3[(tedge).orient]
74 
75 // finds the previous edge (cw) of a triangle
76 #define lprev(tedge1, tedge2) \
77  (tedge2).tri = (tedge1).tri; \
78  (tedge2).orient = MINUS1MOD3[(tedge1).orient]
79 
80 #define lprevself(tedge) (tedge).orient = MINUS1MOD3[(tedge).orient]
81 
82 // These primitives determine or set the origin, destination, or apex of a
83 // triangle
84 #define org(tedge, pointptr) pointptr = (Tpt)(tedge).tri[PLUS1MOD3[(tedge).orient] + 3]
85 
86 #define dest(tedge, pointptr) pointptr = (Tpt)(tedge).tri[MINUS1MOD3[(tedge).orient] + 3]
87 
88 #define apex(tedge, pointptr) pointptr = (Tpt)(tedge).tri[(tedge).orient + 3]
89 
90 #define setorg(tedge, pointptr) (tedge).tri[PLUS1MOD3[(tedge).orient] + 3] = (Ttri)pointptr
91 
92 #define setdest(tedge, pointptr) (tedge).tri[MINUS1MOD3[(tedge).orient] + 3] = (Ttri)pointptr
93 
94 #define setapex(tedge, pointptr) (tedge).tri[(tedge).orient + 3] = (Ttri)pointptr
95 
96 // Bond two triangles together
97 #define bond(tedge1, tedge2) \
98  (tedge1).tri[(tedge1).orient] = encode(tedge2); \
99  (tedge2).tri[(tedge2).orient] = encode(tedge1)
100 
101 // Copy a triangle/edge handle
102 #define tedgecopy(tedge1, tedge2) \
103  (tedge2).tri = (tedge1).tri; \
104  (tedge2).orient = (tedge1).orient
105 
106 // Test for equality of triangle/edge handles
107 #define tedgeequal(tedge1, tedge2) \
108  (((tedge1).tri == (tedge2).tri) && ((tedge1).orient == (tedge2).orient))
109 
110 #define Fast_Two_Sum_Tail(a, b, x, y) \
111  bvirt = x - a; \
112  y = b - bvirt
113 
114 #define Fast_Two_Sum(a, b, x, y) \
115  x = (double)(a + b); \
116  Fast_Two_Sum_Tail(a, b, x, y)
117 
118 #define Two_Sum_Tail(a, b, x, y) \
119  bvirt = (double)(x - a); \
120  avirt = x - bvirt; \
121  bround = b - bvirt; \
122  around = a - avirt; \
123  y = around + bround
124 
125 #define Two_Sum(a, b, x, y) \
126  x = (double)(a + b); \
127  Two_Sum_Tail(a, b, x, y)
128 
129 #define Two_Diff_Tail(a, b, x, y) \
130  bvirt = (double)(a - x); \
131  avirt = x + bvirt; \
132  bround = bvirt - b; \
133  around = a - avirt; \
134  y = around + bround
135 
136 #define Two_Diff(a, b, x, y) \
137  x = (double)(a - b); \
138  Two_Diff_Tail(a, b, x, y)
139 
140 #define Split(splitter, a, ahi, alo) \
141  c = (double)(splitter * a); \
142  abig = (double)(c - a); \
143  ahi = c - abig; \
144  alo = a - ahi
145 
146 #define Two_Product_Tail(splitter, a, b, x, y) \
147  Split(splitter, a, ahi, alo); \
148  Split(splitter, b, bhi, blo); \
149  err1 = x - (ahi * bhi); \
150  err2 = err1 - (alo * bhi); \
151  err3 = err2 - (ahi * blo); \
152  y = (alo * blo) - err3
153 
154 #define Two_Product(splitter, a, b, x, y) \
155  x = (double)(a * b); \
156  Two_Product_Tail(splitter, a, b, x, y)
157 
158 // Two_Product_Presplit() is Two_Product() where one of the inputs has already
159 // been split. Avoids redundant splitting
160 #define Two_Product_Presplit(splitter, a, b, bhi, blo, x, y) \
161  x = (double)(a * b); \
162  Split(splitter, a, ahi, alo); \
163  err1 = x - (ahi * bhi); \
164  err2 = err1 - (alo * bhi); \
165  err3 = err2 - (ahi * blo); \
166  y = (alo * blo) - err3
167 
168 #define Square_Tail(splitter, a, x, y) \
169  Split(splitter, a, ahi, alo); \
170  err1 = x - (ahi * ahi); \
171  err3 = err1 - ((ahi + ahi) * alo); \
172  y = (alo * alo) - err3
173 
174 // done more quickly than Two_Product()
175 #define Square(splitter, a, x, y) \
176  x = (double)(a * a); \
177  Square_Tail(splitter, a, x, y)
178 
179 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
180  Two_Sum(a0, b, _i, x0); \
181  Two_Sum(a1, _i, x2, x1)
182 
183 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
184  Two_Diff(a0, b, _i, x0); \
185  Two_Sum(a1, _i, x2, x1)
186 
187 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
188  Two_One_Sum(a1, a0, b0, _j, _0, x0); \
189  Two_One_Sum(_j, _0, b1, x3, x2, x1)
190 
191 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
192  Two_One_Diff(a1, a0, b0, _j, _0, x0); \
193  Two_One_Diff(_j, _0, b1, x3, x2, x1)
194 
195 //----- Typdefs / Classes ------------------------------------------------------
196 
197 typedef double* Tpt;
198 typedef double** Ttri;
199 
200 typedef struct Tpool* Tmemtype;
201 typedef struct Tedge* Tedgetype;
202 
203 typedef struct Tedge
204 {
205  Ttri* tri;
206  int orient;
207 } Tedge;
208 
209 typedef struct Tpool
210 {
211  Tpool()
212  : firstblock(nullptr)
213  , nowblock(nullptr)
214  , nextitem(nullptr)
215  , deaditemstack(nullptr)
216  , pathblock(nullptr)
217  , pathitem(nullptr)
218  {
219  }
220  int **firstblock, **nowblock;
221  int *nextitem, *deaditemstack;
222  int **pathblock, *pathitem;
223  int alignbytes = 0;
224  int itembytes = 0;
225  int itemsperblock = 0;
226  int itemsfirstblock = 0;
227  long items = 0L;
228  long maxitems = 0L;
229  int unallocateditems = 0;
230  int pathitemsleft = 0;
231 } Tpool;
232 
233 // Label-signifies whether a record consists primarily of pointers or of
234 // floating-point words. Used align data.
235 enum Twordtype { TPOINTER, TFLOATINGPOINT };
236 
237 struct TriVars
238 {
239 public:
240  Tpool m_triangles;
241  Tpool m_points;
242 
243  Ttri* m_dummytri;
244  Ttri* m_dummytribase; // Keep base address so can free it later
245 
246  int m_numpoints; // Number of input points
247  int m_pointmarkindex; // Index in pt of boundary marker
248  // pt marker must be aligned to a sizeof(int)-byte address
249 
250  double m_resulterrbound;
251  double m_ccwerrboundA, m_ccwerrboundB, m_ccwerrboundC;
252  double m_iccerrboundA, m_iccerrboundB, m_iccerrboundC;
253 
254  double m_splitter;
255 
256 private:
257 };
258 
259 //----- Internal Function Prototypes -------------------------------------------
260 
261 static void triAlternateAxes(Tpt*, int, int);
262 static double triCounterClockwise(Tpt, Tpt, Tpt, TriVars&);
263 static double triCounterClockwiseAdapt(Tpt, Tpt, Tpt, double, TriVars&);
264 static bool triDivConqDelaunay(TriVars&);
265 static bool triDivConqRecurse(Tpt*, int, int, Tedgetype, Tedgetype, TriVars&);
266 static void triDummyInit(int, TriVars&);
267 static double triEstimate(int, double*);
268 static void triExactInit(TriVars&);
269 static int triFastExpansionSumZeroElim(int, double*, int, double*, double*);
270 static void triFillTriList(TrTriangulator& a_Client, TriVars&);
271 static bool triGetPoints(TrTriangulator&, TriVars&);
272 static double triInCircle(Tpt, Tpt, Tpt, Tpt, TriVars&);
273 static double triInCircleAdapt(Tpt, Tpt, Tpt, Tpt, double, TriVars&);
274 static void triInitTrianglePool(TriVars&);
275 static bool triMakeTriangle(Tedgetype, TriVars&);
276 static bool triMergeHulls(Tedgetype, Tedgetype, Tedgetype, Tedgetype, int, TriVars&);
277 static void triNumberNodes(TriVars&);
278 static void triPointMedian(Tpt*, int, int, int);
279 static void triPointSort(Tpt*, int);
280 static Tpt triPointTraverse(TriVars&);
281 static int* triPoolAlloc(Tmemtype);
282 static void triPoolDealloc(Tmemtype, int*);
283 static void triPoolDeinit(Tmemtype);
284 static bool triPoolInit(Tmemtype, int, int, int, int);
285 static void triPoolRestart(Tmemtype);
286 static unsigned long triRandomnation(unsigned int);
287 static void triRemoveGhosts(Tedgetype, TriVars&);
288 static int triScaleExpansionZeroElim(int, double*, double, double*, TriVars&);
289 static void triTraversalInit(Tmemtype);
290 static int* triTraverse(Tmemtype);
291 static void triTriangleDealloc(Ttri*, TriVars&);
292 static Ttri* triTriangleTraverse(TriVars&);
293 
294 //----- Internal Function Definitions ------------------------------------------
295 
296 //------------------------------------------------------------------------------
297 // FUNCTION triAlternateAxes
299 // algorithm with alternating cuts.
300 // NOTES
301 // Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1.
302 // For the base case, subsets containing only two or three points are
303 // always sorted by x-coordinate.
304 //------------------------------------------------------------------------------
305 static void triAlternateAxes(Tpt* sortarray, int arraysize, int axis)
306 {
307  int divider;
308  divider = arraysize >> 1;
309  if (arraysize <= 3)
310  {
311  /* Recursive base case: subsets of two or three points will be */
312  /* handled specially, and should always be sorted by x-coordinate. */
313  axis = 0;
314  }
315  /* Partition w/ a horizontal or vertical cut */
316  triPointMedian(sortarray, arraysize, divider, axis);
317  /* Recursively partition subsets w/ a cross cut */
318  if (arraysize - divider >= 2)
319  {
320  if (divider >= 2)
321  triAlternateAxes(sortarray, divider, 1 - axis);
322  triAlternateAxes(&sortarray[divider], arraysize - divider, 1 - axis);
323  }
324 } // triAlternateAxes
325 //------------------------------------------------------------------------------
326 // FUNCTION triCounterClockwise
328 // NOTES
329 //------------------------------------------------------------------------------
330 static double triCounterClockwise(Tpt pa, Tpt pb, Tpt pc, TriVars& t)
331 {
332  double detleft, detright, det, detsum, errbound;
333 
334  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
335  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
336  det = detleft - detright;
337 
338  if (detleft > 0.0)
339  {
340  if (detright <= 0.0)
341  return det;
342  else
343  detsum = detleft + detright;
344  }
345  else if (detleft < 0.0)
346  {
347  if (detright >= 0.0)
348  return det;
349  else
350  detsum = -detleft - detright;
351  }
352  else
353  return det;
354 
355  errbound = t.m_ccwerrboundA * detsum;
356  if ((det >= errbound) || (-det >= errbound))
357  return det;
358 
359  return triCounterClockwiseAdapt(pa, pb, pc, detsum, t);
360 } // triCounterClockwise
361 //------------------------------------------------------------------------------
362 // FUNCTION triCounterClockwiseAdapt
364 // counterclockwise order; a negative value if they occur in clockwise
365 // order; and zero if they are collinear. The result is also a rough
366 // approximation of twice the signed area of the triangle defined by
367 // the three points.
368 // NOTES
369 // Uses exact arithmetic if necessary to ensure a correct answer. The
370 // result returned is the determinant of a matrix. This determinant is
371 // computed adaptively, in the sense that exact arithmetic is used only to
372 // the degree it is needed to ensure that the returned value has the
373 // correct sign. Hence, this function is usually quite fast, but will run
374 // more slowly when the input points are collinear or nearly so.
375 //------------------------------------------------------------------------------
376 static double triCounterClockwiseAdapt(Tpt pa, Tpt pb, Tpt pc, double detsum, TriVars& t)
377 {
378  int C1length, C2length, Dlength;
379  double acx, acy, bcx, bcy;
380  double acxtail, acytail, bcxtail, bcytail;
381  double detleft, detright;
382  double detlefttail, detrighttail;
383  double det, errbound;
384  double B[4], C1[8], C2[12], D[16];
385  double B3;
386  double u[4];
387  double u3;
388  double s1, t1, s0, t0;
389  double bvirt, avirt, bround, around;
390  double c, abig, ahi, alo, bhi, blo;
391  double err1, err2, err3;
392  double _i, _j, _0;
393 
394  acx = (double)(pa[0] - pc[0]);
395  bcx = (double)(pb[0] - pc[0]);
396  acy = (double)(pa[1] - pc[1]);
397  bcy = (double)(pb[1] - pc[1]);
398 
399  Two_Product(t.m_splitter, acx, bcy, detleft, detlefttail);
400  Two_Product(t.m_splitter, acy, bcx, detright, detrighttail);
401 
402  Two_Two_Diff(detleft, detlefttail, detright, detrighttail, B3, B[2], B[1], B[0]);
403  B[3] = B3;
404 
405  det = triEstimate(4, B);
406  errbound = t.m_ccwerrboundB * detsum;
407  if ((det >= errbound) || (-det >= errbound))
408  return det;
409 
410  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
411  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
412  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
413  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
414 
415  if ((acxtail == 0.0) && (acytail == 0.0) && (bcxtail == 0.0) && (bcytail == 0.0))
416  {
417  return det;
418  }
419 
420  errbound = t.m_ccwerrboundC * detsum + t.m_resulterrbound * fabs(det);
421  det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
422  if ((det >= errbound) || (-det >= errbound))
423  return det;
424 
425  Two_Product(t.m_splitter, acxtail, bcy, s1, s0);
426  Two_Product(t.m_splitter, acytail, bcx, t1, t0);
427  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
428  u[3] = u3;
429  C1length = triFastExpansionSumZeroElim(4, B, 4, u, C1);
430 
431  Two_Product(t.m_splitter, acx, bcytail, s1, s0);
432  Two_Product(t.m_splitter, acy, bcxtail, t1, t0);
433  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
434  u[3] = u3;
435  C2length = triFastExpansionSumZeroElim(C1length, C1, 4, u, C2);
436 
437  Two_Product(t.m_splitter, acxtail, bcytail, s1, s0);
438  Two_Product(t.m_splitter, acytail, bcxtail, t1, t0);
439  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
440  u[3] = u3;
441  Dlength = triFastExpansionSumZeroElim(C2length, C2, 4, u, D);
442 
443  return (D[Dlength - 1]);
444 } // triCounterClockwiseAdapt
445 //------------------------------------------------------------------------------
446 // FUNCTION triDivConqDelaunay
448 // NOTES Sorts the points, calls a recursive procedure to triangulate them,
449 // and removes the bounding box, setting boundary markers as
450 // appropriate.
451 //------------------------------------------------------------------------------
452 static bool triDivConqDelaunay(TriVars& t)
453 {
454  int divider, i, j;
455  Tpt* sortarray;
456  Tedge hullleft = {0}, hullright = {0};
457  /* Allocate array of ptrs to pts for sorting. */
458  int size = t.m_numpoints * (int)sizeof(Tpt);
459 
460  sortarray = (Tpt*)malloc((unsigned int)size);
461 
462  if (sortarray == nullptr)
463  {
464  std::string s = "malloc failed: ";
465  s += __FUNCTION__;
466  XM_LOG(xmlog::error, s);
467  return false;
468  }
469  triTraversalInit(&t.m_points);
470  for (i = 0; i < t.m_numpoints; i++)
471  {
472  sortarray[i] = triPointTraverse(t);
473  }
474  /* Sort the points. */
475  triPointSort(sortarray, t.m_numpoints);
476  /* Discard duplicate pts (can mess up algorithm) */
477  i = 0;
478  for (j = 1; j < t.m_numpoints; j++)
479  {
480  if ((sortarray[i][0] == sortarray[j][0] && sortarray[i][1] == sortarray[j][1]))
481  {
482  // setpointmark(sortarray[j], -999);
483  }
484  else
485  {
486  i++;
487  sortarray[i] = sortarray[j];
488  }
489  }
490  i++;
491  /* Re-sort pts to accommodate alternating cuts */
492  divider = i >> 1;
493  // if divider is 0, this causes problems
494  if (divider == 0)
495  {
496  free(sortarray);
497  return false;
498  }
499  else if (i - divider >= 2)
500  {
501  if (divider >= 2)
502  {
503  triAlternateAxes(sortarray, divider, 1);
504  }
505  triAlternateAxes(&sortarray[divider], i - divider, 1);
506  }
507  /* Form the Delaunay triangulation. */
508  bool canTriangulate = triDivConqRecurse(sortarray, i, 0, &hullleft, &hullright, t);
509  if (!canTriangulate)
510  {
511  std::string str =
512  "Triangulation cannot be completed due to memory constraints. "
513  "A suggested work-around would be to divide the scattersets, "
514  "triangulate them seperately, then merge back into one scatterset. "
515  "It is suggested that the scatter set be broken into contiguous regions "
516  "of less than 5000000 points.";
517  XM_LOG(xmlog::error, str);
518  triPoolDeinit(&t.m_triangles); // clear the triangles before being added
519  free(sortarray);
520  if (t.m_dummytribase)
521  {
522  free(t.m_dummytribase);
523  }
524  return false;
525  }
526  free(sortarray);
527 
528  triRemoveGhosts(&hullleft, t);
529  return true;
530 } // triDivConqDelaunay
531 //------------------------------------------------------------------------------
532 // FUNCTION triDivConqRecurse
534 // method.
535 // NOTES
536 // Recursively breaks down the problem into smaller pieces, which are
537 // knitted together by triMergeHulls(). The base cases (problems of two or
538 // three points) are handled specially here.
539 //
540 // On completion, `farleft' and `farright' are bounding triangles such that
541 // the origin of `farleft' is the leftmost vertex (breaking ties by
542 // choosing the highest leftmost vertex), and the destination of
543 // `farright' is the rightmost vertex (breaking ties by choosing the
544 // lowest rightmost vertex).
545 //------------------------------------------------------------------------------
546 static bool triDivConqRecurse(Tpt* sortarray,
547  int vertices,
548  int axis,
549  Tedgetype farleft,
550  Tedgetype farright,
551  TriVars& t)
552 {
553  int divider;
554  double area;
555  Tedge midtri, tri1, tri2, tri3, innerleft, innerright;
556  bool canMakeTriangles = true;
557 
558  if (vertices == 2)
559  {
560  /* Triangulation of two vertices is an edge. *
561  * (represented by two bounding triangles) */
562  canMakeTriangles &= triMakeTriangle(farleft, t);
563  canMakeTriangles &= triMakeTriangle(farright, t);
564  if (!canMakeTriangles) // past 32-bit limit
565  {
566  return false;
567  }
568  setorg(*farleft, sortarray[0]);
569  setdest(*farleft, sortarray[1]);
570  /* The apex is intentionally left NULL. */
571  setorg(*farright, sortarray[1]);
572  setdest(*farright, sortarray[0]);
573  /* The apex is intentionally left NULL. */
574  bond(*farleft, *farright);
575  lprevself(*farleft);
576  lnextself(*farright);
577  bond(*farleft, *farright);
578  lprevself(*farleft);
579  lnextself(*farright);
580  bond(*farleft, *farright);
581  /* Ensure origin of `farleft' is sortarray[0] */
582  lprev(*farright, *farleft);
583 
584  return true;
585  }
586  else if (vertices == 3)
587  {
588  /* Triangulation of three vertices is either: *
589  * a triangle (with three bounding triangles) *
590  * two edges (with four bounding triangles). *
591  * In either case, four triangles are created */
592  canMakeTriangles &= triMakeTriangle(&midtri, t);
593  canMakeTriangles &= triMakeTriangle(&tri1, t);
594  canMakeTriangles &= triMakeTriangle(&tri2, t);
595  canMakeTriangles &= triMakeTriangle(&tri3, t);
596  if (!canMakeTriangles) // past 32-bit limit
597  {
598  return false;
599  }
600  area = triCounterClockwise(sortarray[0], sortarray[1], sortarray[2], t);
601  if (area == 0.0)
602  {
603  /* Three collinear points -> two edges */
604  setorg(midtri, sortarray[0]);
605  setdest(midtri, sortarray[1]);
606  setorg(tri1, sortarray[1]);
607  setdest(tri1, sortarray[0]);
608  setorg(tri2, sortarray[2]);
609  setdest(tri2, sortarray[1]);
610  setorg(tri3, sortarray[1]);
611  setdest(tri3, sortarray[2]);
612  /* All apices are intentionally left NULL. */
613  bond(midtri, tri1);
614  bond(tri2, tri3);
615  lnextself(midtri);
616  lprevself(tri1);
617  lnextself(tri2);
618  lprevself(tri3);
619  bond(midtri, tri3);
620  bond(tri1, tri2);
621  lnextself(midtri);
622  lprevself(tri1);
623  lnextself(tri2);
624  lprevself(tri3);
625  bond(midtri, tri1);
626  bond(tri2, tri3);
627  /* Ensure origin of `farleft' is sortarray[0]. */
628  tedgecopy(tri1, *farleft);
629  /* Ensure dest of `farright' is sortarray[2]. */
630  tedgecopy(tri2, *farright);
631  }
632  else
633  {
634  /* Three noncollinear pts; 1 triangle (midtri) */
635  setorg(midtri, sortarray[0]);
636  setdest(tri1, sortarray[0]);
637  setorg(tri3, sortarray[0]);
638  /* Apices of tri1, tri2, & tri3 are left NULL. */
639  if (area > 0.0)
640  {
641  /* The vertices are in ccw order. */
642  setdest(midtri, sortarray[1]);
643  setorg(tri1, sortarray[1]);
644  setdest(tri2, sortarray[1]);
645  setapex(midtri, sortarray[2]);
646  setorg(tri2, sortarray[2]);
647  setdest(tri3, sortarray[2]);
648  }
649  else
650  {
651  /* The vertices are in cw order. */
652  setdest(midtri, sortarray[2]);
653  setorg(tri1, sortarray[2]);
654  setdest(tri2, sortarray[2]);
655  setapex(midtri, sortarray[1]);
656  setorg(tri2, sortarray[1]);
657  setdest(tri3, sortarray[1]);
658  }
659  /* Topology does not depend on vertex ordering */
660  bond(midtri, tri1);
661  lnextself(midtri);
662  bond(midtri, tri2);
663  lnextself(midtri);
664  bond(midtri, tri3);
665  lprevself(tri1);
666  lnextself(tri2);
667  bond(tri1, tri2);
668  lprevself(tri1);
669  lprevself(tri3);
670  bond(tri1, tri3);
671  lnextself(tri2);
672  lprevself(tri3);
673  bond(tri2, tri3);
674  /* Ensure origin of `farleft' is sortarray[0]. */
675  tedgecopy(tri1, *farleft);
676  /* Ensure dest of `farright' is sortarray[2]. */
677  if (area > 0.0)
678  {
679  tedgecopy(tri2, *farright);
680  }
681  else
682  {
683  lnext(*farleft, *farright);
684  }
685  }
686  return true;
687  }
688  else
689  {
690  /* Split the vertices in half. */
691  divider = vertices >> 1;
692  /* Recursively triangulate each half. */
693  canMakeTriangles = triDivConqRecurse(sortarray, divider, 1 - axis, farleft, &innerleft, t);
694  if (!canMakeTriangles)
695  {
696  return false;
697  }
698  canMakeTriangles = triDivConqRecurse(&sortarray[divider], vertices - divider, 1 - axis,
699  &innerright, farright, t);
700  if (!canMakeTriangles)
701  {
702  return false;
703  }
704  /* Merge the two triangulations into one. */
705  canMakeTriangles = triMergeHulls(farleft, &innerleft, &innerright, farright, axis, t);
706  if (canMakeTriangles)
707  {
708  return true;
709  }
710  else
711  {
712  return false;
713  }
714  }
715 } // triDivConqRecurse
716 //------------------------------------------------------------------------------
717 // FUNCTION triDummyInit
719 // omnipresent shell edge.
720 // NOTES
721 // The triangle that fills "outer space", called `dummytri', is pointed to
722 // by every triangle and shell edge on a boundary (be it outer or inner) of
723 // the triangulation. Also, `dummytri' points to one of the triangles on
724 // the convex hull (until the concavities are carved), making it
725 // possible to find a starting triangle for point location.
726 // `trianglewords' is used by the mesh manipulation primitives
727 // to extract orientations of triangles and shell edges from pointers.
728 //------------------------------------------------------------------------------
729 static void triDummyInit(int trianglewords, TriVars& t)
730 {
731  unsigned long long alignptr;
732  /* Set up `dummytri', (occupies "outer space") */
733  t.m_dummytribase = (Ttri*)malloc(trianglewords * sizeof(Ttri) + t.m_triangles.alignbytes);
734  if (t.m_dummytribase == nullptr)
735  {
736  std::string s = "malloc failed: ";
737  s += __FUNCTION__;
738  XM_LOG(xmlog::error, s);
739  return;
740  }
741  /* Align `dummytri' on a
742  * `triangles.alignbytes'-byte boundary. */
743  alignptr = (unsigned long long)t.m_dummytribase;
744  t.m_dummytri = (Ttri*)(alignptr + (unsigned long long)t.m_triangles.alignbytes -
745  (alignptr % (unsigned long long)t.m_triangles.alignbytes));
746  /* Initialize the three adjoining triangles to be "outer space". These */
747  /* will eventually be changed by various bonding operations, but their */
748  /* values don't really matter, as long as they can legally be */
749  /* dereferenced. */
750  t.m_dummytri[0] = (Ttri)t.m_dummytri;
751  t.m_dummytri[1] = (Ttri)t.m_dummytri;
752  t.m_dummytri[2] = (Ttri)t.m_dummytri;
753  /* Three NULL vertex points. */
754  t.m_dummytri[3] = nullptr;
755  t.m_dummytri[4] = nullptr;
756  t.m_dummytri[5] = nullptr;
757 } // triDummyInit
758 //------------------------------------------------------------------------------
759 // FUNCTION triEstimate
761 // NOTES
762 //------------------------------------------------------------------------------
763 static double triEstimate(int elen, double* e)
764 {
765  int eindex;
766  double Q;
767 
768  Q = e[0];
769  for (eindex = 1; eindex < elen; eindex++)
770  Q += e[eindex];
771 
772  return Q;
773 } // triEstimate
774 //------------------------------------------------------------------------------
775 // FUNCTION triExactInit
777 // NOTES
778 // `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in
779 // floating-point arithmetic. `epsilon' bounds the relative roundoff
780 // error. It is used for floating-point error analysis.
781 //
782 // `splitter' is used to split floating-point numbers into two half-
783 // length significands for exact multiplication.
784 //
785 // I imagine that a highly optimizing compiler might be too smart for its
786 // own good, and somehow cause this routine to fail, if it pretends that
787 // floating-point arithmetic is too much like real arithmetic.
788 //
789 // Don't change this routine unless you fully understand it.
790 //------------------------------------------------------------------------------
791 static void triExactInit(TriVars& t)
792 {
793  double half, check, lastcheck, epsilon;
794  int every_other;
795  /* initialize variables */
796  t.m_splitter = 1.0; // AKZ - I added this initialization
797  every_other = 1;
798  half = 0.5;
799  epsilon = check = 1.0;
800  /* Repeatedly divide `epsilon' by two until it is too small to add to */
801  /* one without causing roundoff. (Also check if the sum is equal to */
802  /* the previous sum, for machines that round up instead of using exact */
803  /* rounding. Not that these routines will work on such machines anyway. */
804  do
805  {
806  lastcheck = check;
807  epsilon *= half;
808  if (every_other)
809  t.m_splitter *= 2.0;
810  every_other = !every_other;
811  check = 1.0 + epsilon;
812  } while ((check != 1.0) && (check != lastcheck));
813  t.m_splitter += 1.0;
814  /* Error bounds for orientation & incircle tests */
815  t.m_resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
816  t.m_ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
817  t.m_ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
818  t.m_ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
819  t.m_iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
820  t.m_iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
821  t.m_iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
822 } // triExactInit
823 //------------------------------------------------------------------------------
824 // FUNCTION triFastExpansionSumZeroElim
826 // expansion.
827 // NOTES
828 // Sets h = e + f.
829 // If round-to-even is used (as with IEEE 754), maintains the strongly
830 // nonoverlapping property. (That is, if e is strongly nonoverlapping, h
831 // will be also.) Does NOT maintain the nonoverlapping or nonadjacent
832 // properties. h cannot be e or f.
833 //------------------------------------------------------------------------------
834 static int triFastExpansionSumZeroElim(int elen, double* e, int flen, double* f, double* h)
835 {
836  int eindex, findex, hindex;
837  double Q, Qnew, hh, bvirt, avirt, bround, around, enow, fnow;
838  /* initialize Q */
839  enow = e[0];
840  fnow = f[0];
841  eindex = findex = 0;
842  if ((fnow > enow) == (fnow > -enow))
843  {
844  Q = enow;
845  enow = e[++eindex];
846  }
847  else
848  {
849  Q = fnow;
850  fnow = f[++findex];
851  }
852  hindex = 0;
853  if ((eindex < elen) && (findex < flen))
854  {
855  if ((fnow > enow) == (fnow > -enow))
856  {
857  Fast_Two_Sum(enow, Q, Qnew, hh);
858  enow = e[++eindex];
859  }
860  else
861  {
862  Fast_Two_Sum(fnow, Q, Qnew, hh);
863  fnow = f[++findex];
864  }
865  Q = Qnew;
866  if (hh != 0.0)
867  h[hindex++] = hh;
868  while ((eindex < elen) && (findex < flen))
869  {
870  if ((fnow > enow) == (fnow > -enow))
871  {
872  Two_Sum(Q, enow, Qnew, hh);
873  ++eindex;
874  if (eindex < elen)
875  enow = e[eindex];
876  else
877  enow = 0.0;
878  }
879  else
880  {
881  Two_Sum(Q, fnow, Qnew, hh);
882  ++findex;
883  if (findex < flen)
884  fnow = f[findex];
885  else
886  fnow = 0.0;
887  }
888  Q = Qnew;
889  if (hh != 0.0)
890  h[hindex++] = hh;
891  }
892  }
893  while (eindex < elen)
894  {
895  Two_Sum(Q, enow, Qnew, hh);
896  enow = e[++eindex];
897  Q = Qnew;
898  if (hh != 0.0)
899  h[hindex++] = hh;
900  }
901  while (findex < flen)
902  {
903  Two_Sum(Q, fnow, Qnew, hh);
904  fnow = f[++findex];
905  Q = Qnew;
906  if (hh != 0.0)
907  h[hindex++] = hh;
908  }
909  if ((Q != 0.0) || (hindex == 0))
910  h[hindex++] = Q;
911  return hindex;
912 } // triFastExpansionSumZeroElim
913 //------------------------------------------------------------------------------
914 // FUNCTION triFillTriList
916 // NOTES
917 //------------------------------------------------------------------------------
918 static void triFillTriList(TrTriangulator& a_Client, TriVars& t)
919 {
920  int id1, id2, id3;
921  Tedge triangleloop;
922  Tpt p1, p2, p3;
923 
924  // prepare to recieve trianlges
925  a_Client.PrepareToReceiveTriangles();
926 
927  triTraversalInit(&t.m_triangles);
928  triangleloop.tri = triTriangleTraverse(t);
929  triangleloop.orient = 0;
930  while (triangleloop.tri != nullptr)
931  {
932  // get the ids
933  org(triangleloop, p1);
934  dest(triangleloop, p2);
935  apex(triangleloop, p3);
936  id1 = pointmark(p1, t.m_pointmarkindex);
937  id2 = pointmark(p2, t.m_pointmarkindex);
938  id3 = pointmark(p3, t.m_pointmarkindex);
939 
940  // recieve the triangle
941  a_Client.ReceiveTriangle(id1, id2, id3);
942 
943  triangleloop.tri = triTriangleTraverse(t);
944  }
945 } // triFillTriList
946 //------------------------------------------------------------------------------
947 // FUNCTION triGetPoints
949 // NOTES
950 //------------------------------------------------------------------------------
951 static bool triGetPoints(TrTriangulator& a_Client, TriVars& t)
952 {
953 #define POINTPERBLOCK 4092
954 
955  int i, pointsize;
956  Pt3d loc;
957  Tpt pointloop;
958 
959  // number of points allocated at once
960  t.m_pointmarkindex = (3 * sizeof(double) + sizeof(int) - 1) / sizeof(int);
961  pointsize = (t.m_pointmarkindex + 1) * sizeof(int);
962 
963  // initialize the pool of points
964  // get the number of points
965  t.m_numpoints = a_Client.GetNPoints();
966 
967  if (!triPoolInit(&t.m_points, pointsize, POINTPERBLOCK,
968  t.m_numpoints > POINTPERBLOCK ? t.m_numpoints : POINTPERBLOCK, 0))
969  {
970  return false;
971  }
972 
973  // get the points
974  for (i = 0; i < t.m_numpoints; i++)
975  {
976  pointloop = (Tpt)triPoolAlloc(&t.m_points);
977 
978  // set the location
979  loc = a_Client.GetLocation();
980  pointloop[0] = loc.x;
981  pointloop[1] = loc.y;
982 
983  // save id for pt (used after triangulation)
984  pointloop[2] = a_Client.GetID();
985 
986  setpointmark(pointloop, 0, t.m_pointmarkindex);
987 
988  // go to the next point
989  a_Client.IncrementPoint();
990  }
991  return true;
992 } // triGetPoints
993 //------------------------------------------------------------------------------
994 // FUNCTION triInCircle
996 // NOTES
997 //------------------------------------------------------------------------------
998 static double triInCircle(Tpt pa, Tpt pb, Tpt pc, Tpt pd, TriVars& t)
999 {
1000  double adx, bdx, cdx, ady, bdy, cdy;
1001  double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
1002  double alift, blift, clift;
1003  double det;
1004  double permanent, errbound;
1005 
1006  adx = pa[0] - pd[0];
1007  bdx = pb[0] - pd[0];
1008  cdx = pc[0] - pd[0];
1009  ady = pa[1] - pd[1];
1010  bdy = pb[1] - pd[1];
1011  cdy = pc[1] - pd[1];
1012 
1013  bdxcdy = bdx * cdy;
1014  cdxbdy = cdx * bdy;
1015  alift = adx * adx + ady * ady;
1016 
1017  cdxady = cdx * ady;
1018  adxcdy = adx * cdy;
1019  blift = bdx * bdx + bdy * bdy;
1020 
1021  adxbdy = adx * bdy;
1022  bdxady = bdx * ady;
1023  clift = cdx * cdx + cdy * cdy;
1024 
1025  det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
1026 
1027  permanent = (fabs(bdxcdy) + fabs(cdxbdy)) * alift + (fabs(cdxady) + fabs(adxcdy)) * blift +
1028  (fabs(adxbdy) + fabs(bdxady)) * clift;
1029  errbound = t.m_iccerrboundA * permanent;
1030  if ((det > errbound) || (-det > errbound))
1031  return det;
1032 
1033  return triInCircleAdapt(pa, pb, pc, pd, permanent, t);
1034 } // triInCircle
1035 //------------------------------------------------------------------------------
1036 // FUNCTION triInCircleAdapt
1038 // passing through pa, pb, and pc; a negative value if it lies
1039 // outside; and zero if the four points are cocircular. The points pa,
1040 // pb, and pc must be in counterclockwise order, or the sign of the
1041 // result will be reversed.
1042 // NOTES Uses exact arithmetic if necessary to ensure a correct answer. The
1043 // result returned is the determinant of a matrix. This determinant is
1044 // computed adaptively, in the sense that exact arithmetic is used only to
1045 // the degree it is needed to ensure that the returned value has the
1046 // correct sign. Hence, this function is usually quite fast, but will run
1047 // more slowly when the input points are cocircular or nearly so.
1048 //------------------------------------------------------------------------------
1049 static double triInCircleAdapt(Tpt pa, Tpt pb, Tpt pc, Tpt pd, double permanent, TriVars& t)
1050 {
1051  int axbclen, axxbclen, aybclen, ayybclen, alen;
1052  int bxcalen, bxxcalen, bycalen, byycalen, blen;
1053  int cxablen, cxxablen, cyablen, cyyablen, clen;
1054  int ablen;
1055  int finlength;
1056  double adx, bdx, cdx, ady, bdy, cdy;
1057  double det, errbound;
1058  double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
1059  double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
1060  double bc[4], ca[4], ab[4];
1061  double bc3, ca3, ab3;
1062  double axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
1063  double bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
1064  double cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
1065  double abdet[64];
1066  double fin1[1152], fin2[1152];
1067  double *finnow, *finother, *finswap;
1068 
1069  int temp8len, temp16alen, temp16blen, temp16clen;
1070  int temp32alen, temp32blen, temp48len, temp64len;
1071  int axtbblen, axtcclen, aytbblen, aytcclen;
1072  int bxtaalen, bxtcclen, bytaalen, bytcclen;
1073  int cxtaalen, cxtbblen, cytaalen, cytbblen;
1074  int axtbclen = 0, aytbclen = 0, bxtcalen = 0;
1075  int bytcalen = 0, cxtablen = 0, cytablen = 0;
1076  int axtbctlen, bxtcatlen, cxtabtlen;
1077  int aytbctlen, bytcatlen, cytabtlen;
1078  int axtbcttlen, bxtcattlen, cxtabttlen;
1079  int aytbcttlen, bytcattlen, cytabttlen;
1080  int abtlen, bctlen, catlen;
1081  int abttlen, bcttlen, cattlen;
1082  double adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
1083  double adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
1084  double adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
1085  double aa[4], bb[4], cc[4];
1086  double aa3, bb3, cc3;
1087  double ti1, tj1;
1088  double ti0, tj0;
1089  double u[4], v[4];
1090  double u3, v3;
1091  double temp8[8], temp16a[16], temp16b[16], temp16c[16];
1092  double temp32a[32], temp32b[32], temp48[48], temp64[64];
1093  double axtbb[8], axtcc[8], aytbb[8], aytcc[8];
1094  double bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
1095  double cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
1096  double axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
1097  double axtbct[16], bxtcat[16], cxtabt[16];
1098  double aytbct[16], bytcat[16], cytabt[16];
1099  double axtbctt[8], aytbctt[8], bxtcatt[8];
1100  double bytcatt[8], cxtabtt[8], cytabtt[8];
1101  double abt[8], bct[8], cat[8];
1102  double abtt[4], bctt[4], catt[4];
1103  double abtt3, bctt3, catt3;
1104  double negate;
1105 
1106  double bvirt;
1107  double avirt, bround, around;
1108  double c;
1109  double abig, ahi, alo, bhi, blo;
1110  double err1, err2, err3;
1111  double _i, _j, _0;
1112 
1113  // Initialize all memory
1114  memset(bc, 0, 4 * sizeof(double));
1115  memset(ca, 0, 4 * sizeof(double));
1116  memset(ab, 0, 4 * sizeof(double));
1117 
1118  memset(axbc, 0, 8 * sizeof(double));
1119  memset(axxbc, 0, 16 * sizeof(double));
1120  memset(aybc, 0, 8 * sizeof(double));
1121  memset(ayybc, 0, 16 * sizeof(double));
1122  memset(adet, 0, 32 * sizeof(double));
1123 
1124  memset(bxca, 0, 8 * sizeof(double));
1125  memset(bxxca, 0, 16 * sizeof(double));
1126  memset(byca, 0, 8 * sizeof(double));
1127  memset(byyca, 0, 16 * sizeof(double));
1128  memset(bdet, 0, 32 * sizeof(double));
1129 
1130  memset(cxab, 0, 8 * sizeof(double));
1131  memset(cxxab, 0, 16 * sizeof(double));
1132  memset(cyab, 0, 8 * sizeof(double));
1133  memset(cyyab, 0, 16 * sizeof(double));
1134  memset(cdet, 0, 32 * sizeof(double));
1135 
1136  memset(abdet, 0, 64 * sizeof(double));
1137  memset(fin1, 0, 1152 * sizeof(double));
1138  memset(fin2, 0, 1152 * sizeof(double));
1139 
1140  memset(aa, 0, 4 * sizeof(double));
1141  memset(bb, 0, 4 * sizeof(double));
1142  memset(cc, 0, 4 * sizeof(double));
1143 
1144  memset(u, 0, 4 * sizeof(double));
1145  memset(v, 0, 4 * sizeof(double));
1146 
1147  memset(temp8, 0, 8 * sizeof(double));
1148  memset(temp16a, 0, 16 * sizeof(double));
1149  memset(temp16b, 0, 16 * sizeof(double));
1150  memset(temp16c, 0, 16 * sizeof(double));
1151 
1152  memset(temp32a, 0, 32 * sizeof(double));
1153  memset(temp32b, 0, 32 * sizeof(double));
1154  memset(temp48, 0, 48 * sizeof(double));
1155  memset(temp64, 0, 64 * sizeof(double));
1156 
1157  memset(axtbb, 0, 8 * sizeof(double));
1158  memset(axtcc, 0, 8 * sizeof(double));
1159  memset(aytbb, 0, 8 * sizeof(double));
1160  memset(aytcc, 0, 8 * sizeof(double));
1161 
1162  memset(bxtaa, 0, 8 * sizeof(double));
1163  memset(bxtcc, 0, 8 * sizeof(double));
1164  memset(bytaa, 0, 8 * sizeof(double));
1165  memset(bytcc, 0, 8 * sizeof(double));
1166 
1167  memset(cxtaa, 0, 8 * sizeof(double));
1168  memset(cxtbb, 0, 8 * sizeof(double));
1169  memset(cytaa, 0, 8 * sizeof(double));
1170  memset(cytbb, 0, 8 * sizeof(double));
1171 
1172  memset(axtbc, 0, 8 * sizeof(double));
1173  memset(aytbc, 0, 8 * sizeof(double));
1174  memset(bxtca, 0, 8 * sizeof(double));
1175  memset(bytca, 0, 8 * sizeof(double));
1176  memset(cxtab, 0, 8 * sizeof(double));
1177  memset(cytab, 0, 8 * sizeof(double));
1178 
1179  memset(axtbct, 0, 16 * sizeof(double));
1180  memset(bxtcat, 0, 16 * sizeof(double));
1181  memset(cxtabt, 0, 16 * sizeof(double));
1182 
1183  memset(aytbct, 0, 16 * sizeof(double));
1184  memset(bytcat, 0, 16 * sizeof(double));
1185  memset(cytabt, 0, 16 * sizeof(double));
1186 
1187  memset(axtbctt, 0, 8 * sizeof(double));
1188  memset(aytbctt, 0, 8 * sizeof(double));
1189  memset(bxtcatt, 0, 8 * sizeof(double));
1190 
1191  memset(bytcatt, 0, 8 * sizeof(double));
1192  memset(cxtabtt, 0, 8 * sizeof(double));
1193  memset(cytabtt, 0, 8 * sizeof(double));
1194 
1195  memset(abt, 0, 8 * sizeof(double));
1196  memset(bct, 0, 8 * sizeof(double));
1197  memset(cat, 0, 8 * sizeof(double));
1198 
1199  memset(abtt, 0, 4 * sizeof(double));
1200  memset(bctt, 0, 4 * sizeof(double));
1201  memset(catt, 0, 4 * sizeof(double));
1202 
1203  adx = (double)(pa[0] - pd[0]);
1204  bdx = (double)(pb[0] - pd[0]);
1205  cdx = (double)(pc[0] - pd[0]);
1206  ady = (double)(pa[1] - pd[1]);
1207  bdy = (double)(pb[1] - pd[1]);
1208  cdy = (double)(pc[1] - pd[1]);
1209 
1210  Two_Product(t.m_splitter, bdx, cdy, bdxcdy1, bdxcdy0);
1211  Two_Product(t.m_splitter, cdx, bdy, cdxbdy1, cdxbdy0);
1212  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
1213  bc[3] = bc3;
1214  axbclen = triScaleExpansionZeroElim(4, bc, adx, axbc, t);
1215  axxbclen = triScaleExpansionZeroElim(axbclen, axbc, adx, axxbc, t);
1216  aybclen = triScaleExpansionZeroElim(4, bc, ady, aybc, t);
1217  ayybclen = triScaleExpansionZeroElim(aybclen, aybc, ady, ayybc, t);
1218  alen = triFastExpansionSumZeroElim(axxbclen, axxbc, ayybclen, ayybc, adet);
1219 
1220  Two_Product(t.m_splitter, cdx, ady, cdxady1, cdxady0);
1221  Two_Product(t.m_splitter, adx, cdy, adxcdy1, adxcdy0);
1222  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
1223  ca[3] = ca3;
1224  bxcalen = triScaleExpansionZeroElim(4, ca, bdx, bxca, t);
1225  bxxcalen = triScaleExpansionZeroElim(bxcalen, bxca, bdx, bxxca, t);
1226  bycalen = triScaleExpansionZeroElim(4, ca, bdy, byca, t);
1227  byycalen = triScaleExpansionZeroElim(bycalen, byca, bdy, byyca, t);
1228  blen = triFastExpansionSumZeroElim(bxxcalen, bxxca, byycalen, byyca, bdet);
1229 
1230  Two_Product(t.m_splitter, adx, bdy, adxbdy1, adxbdy0);
1231  Two_Product(t.m_splitter, bdx, ady, bdxady1, bdxady0);
1232  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
1233  ab[3] = ab3;
1234  cxablen = triScaleExpansionZeroElim(4, ab, cdx, cxab, t);
1235  cxxablen = triScaleExpansionZeroElim(cxablen, cxab, cdx, cxxab, t);
1236  cyablen = triScaleExpansionZeroElim(4, ab, cdy, cyab, t);
1237  cyyablen = triScaleExpansionZeroElim(cyablen, cyab, cdy, cyyab, t);
1238  clen = triFastExpansionSumZeroElim(cxxablen, cxxab, cyyablen, cyyab, cdet);
1239 
1240  ablen = triFastExpansionSumZeroElim(alen, adet, blen, bdet, abdet);
1241  finlength = triFastExpansionSumZeroElim(ablen, abdet, clen, cdet, fin1);
1242 
1243  det = triEstimate(finlength, fin1);
1244  errbound = t.m_iccerrboundB * permanent;
1245  if ((det >= errbound) || (-det >= errbound))
1246  return det;
1247 
1248  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
1249  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
1250  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
1251  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
1252  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
1253  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
1254  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) && (adytail == 0.0) &&
1255  (bdytail == 0.0) && (cdytail == 0.0))
1256  {
1257  return det;
1258  }
1259 
1260  errbound = t.m_iccerrboundC * permanent + t.m_resulterrbound * fabs(det);
1261  det +=
1262  ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail)) +
1263  2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +
1264  ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail)) +
1265  2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +
1266  ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail)) +
1267  2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
1268  if ((det >= errbound) || (-det >= errbound))
1269  return det;
1270 
1271  finnow = fin1;
1272  finother = fin2;
1273 
1274  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) || (cdytail != 0.0))
1275  {
1276  Square(t.m_splitter, adx, adxadx1, adxadx0);
1277  Square(t.m_splitter, ady, adyady1, adyady0);
1278  Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
1279  aa[3] = aa3;
1280  }
1281  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) || (adytail != 0.0))
1282  {
1283  Square(t.m_splitter, bdx, bdxbdx1, bdxbdx0);
1284  Square(t.m_splitter, bdy, bdybdy1, bdybdy0);
1285  Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
1286  bb[3] = bb3;
1287  }
1288  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) || (bdytail != 0.0))
1289  {
1290  Square(t.m_splitter, cdx, cdxcdx1, cdxcdx0);
1291  Square(t.m_splitter, cdy, cdycdy1, cdycdy0);
1292  Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
1293  cc[3] = cc3;
1294  }
1295 
1296  if (adxtail != 0.0)
1297  {
1298  axtbclen = triScaleExpansionZeroElim(4, bc, adxtail, axtbc, t);
1299  temp16alen = triScaleExpansionZeroElim(axtbclen, axtbc, 2.0 * adx, temp16a, t);
1300 
1301  axtcclen = triScaleExpansionZeroElim(4, cc, adxtail, axtcc, t);
1302  temp16blen = triScaleExpansionZeroElim(axtcclen, axtcc, bdy, temp16b, t);
1303 
1304  axtbblen = triScaleExpansionZeroElim(4, bb, adxtail, axtbb, t);
1305  temp16clen = triScaleExpansionZeroElim(axtbblen, axtbb, -cdy, temp16c, t);
1306 
1307  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1308  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1309  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1310  finswap = finnow;
1311  finnow = finother;
1312  finother = finswap;
1313  }
1314  if (adytail != 0.0)
1315  {
1316  aytbclen = triScaleExpansionZeroElim(4, bc, adytail, aytbc, t);
1317  temp16alen = triScaleExpansionZeroElim(aytbclen, aytbc, 2.0 * ady, temp16a, t);
1318 
1319  aytbblen = triScaleExpansionZeroElim(4, bb, adytail, aytbb, t);
1320  temp16blen = triScaleExpansionZeroElim(aytbblen, aytbb, cdx, temp16b, t);
1321 
1322  aytcclen = triScaleExpansionZeroElim(4, cc, adytail, aytcc, t);
1323  temp16clen = triScaleExpansionZeroElim(aytcclen, aytcc, -bdx, temp16c, t);
1324 
1325  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1326  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1327  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1328  finswap = finnow;
1329  finnow = finother;
1330  finother = finswap;
1331  }
1332  if (bdxtail != 0.0)
1333  {
1334  bxtcalen = triScaleExpansionZeroElim(4, ca, bdxtail, bxtca, t);
1335  temp16alen = triScaleExpansionZeroElim(bxtcalen, bxtca, 2.0 * bdx, temp16a, t);
1336 
1337  bxtaalen = triScaleExpansionZeroElim(4, aa, bdxtail, bxtaa, t);
1338  temp16blen = triScaleExpansionZeroElim(bxtaalen, bxtaa, cdy, temp16b, t);
1339 
1340  bxtcclen = triScaleExpansionZeroElim(4, cc, bdxtail, bxtcc, t);
1341  temp16clen = triScaleExpansionZeroElim(bxtcclen, bxtcc, -ady, temp16c, t);
1342 
1343  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1344  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1345  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1346  finswap = finnow;
1347  finnow = finother;
1348  finother = finswap;
1349  }
1350  if (bdytail != 0.0)
1351  {
1352  bytcalen = triScaleExpansionZeroElim(4, ca, bdytail, bytca, t);
1353  temp16alen = triScaleExpansionZeroElim(bytcalen, bytca, 2.0 * bdy, temp16a, t);
1354 
1355  bytcclen = triScaleExpansionZeroElim(4, cc, bdytail, bytcc, t);
1356  temp16blen = triScaleExpansionZeroElim(bytcclen, bytcc, adx, temp16b, t);
1357 
1358  bytaalen = triScaleExpansionZeroElim(4, aa, bdytail, bytaa, t);
1359  temp16clen = triScaleExpansionZeroElim(bytaalen, bytaa, -cdx, temp16c, t);
1360 
1361  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1362  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1363  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1364  finswap = finnow;
1365  finnow = finother;
1366  finother = finswap;
1367  }
1368  if (cdxtail != 0.0)
1369  {
1370  cxtablen = triScaleExpansionZeroElim(4, ab, cdxtail, cxtab, t);
1371  temp16alen = triScaleExpansionZeroElim(cxtablen, cxtab, 2.0 * cdx, temp16a, t);
1372 
1373  cxtbblen = triScaleExpansionZeroElim(4, bb, cdxtail, cxtbb, t);
1374  temp16blen = triScaleExpansionZeroElim(cxtbblen, cxtbb, ady, temp16b, t);
1375 
1376  cxtaalen = triScaleExpansionZeroElim(4, aa, cdxtail, cxtaa, t);
1377  temp16clen = triScaleExpansionZeroElim(cxtaalen, cxtaa, -bdy, temp16c, t);
1378 
1379  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1380  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1381  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1382  finswap = finnow;
1383  finnow = finother;
1384  finother = finswap;
1385  }
1386  if (cdytail != 0.0)
1387  {
1388  cytablen = triScaleExpansionZeroElim(4, ab, cdytail, cytab, t);
1389  temp16alen = triScaleExpansionZeroElim(cytablen, cytab, 2.0 * cdy, temp16a, t);
1390 
1391  cytaalen = triScaleExpansionZeroElim(4, aa, cdytail, cytaa, t);
1392  temp16blen = triScaleExpansionZeroElim(cytaalen, cytaa, bdx, temp16b, t);
1393 
1394  cytbblen = triScaleExpansionZeroElim(4, bb, cdytail, cytbb, t);
1395  temp16clen = triScaleExpansionZeroElim(cytbblen, cytbb, -adx, temp16c, t);
1396 
1397  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1398  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1399  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1400  finswap = finnow;
1401  finnow = finother;
1402  finother = finswap;
1403  }
1404 
1405  if ((adxtail != 0.0) || (adytail != 0.0))
1406  {
1407  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) || (cdytail != 0.0))
1408  {
1409  Two_Product(t.m_splitter, bdxtail, cdy, ti1, ti0);
1410  Two_Product(t.m_splitter, bdx, cdytail, tj1, tj0);
1411  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1412  u[3] = u3;
1413  negate = -bdy;
1414  Two_Product(t.m_splitter, cdxtail, negate, ti1, ti0);
1415  negate = -bdytail;
1416  Two_Product(t.m_splitter, cdx, negate, tj1, tj0);
1417  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1418  v[3] = v3;
1419  bctlen = triFastExpansionSumZeroElim(4, u, 4, v, bct);
1420 
1421  Two_Product(t.m_splitter, bdxtail, cdytail, ti1, ti0);
1422  Two_Product(t.m_splitter, cdxtail, bdytail, tj1, tj0);
1423  Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
1424  bctt[3] = bctt3;
1425  bcttlen = 4;
1426  }
1427  else
1428  {
1429  bct[0] = 0.0;
1430  bctlen = 1;
1431  bctt[0] = 0.0;
1432  bcttlen = 1;
1433  }
1434 
1435  if (adxtail != 0.0)
1436  {
1437  temp16alen = triScaleExpansionZeroElim(axtbclen, axtbc, adxtail, temp16a, t);
1438  axtbctlen = triScaleExpansionZeroElim(bctlen, bct, adxtail, axtbct, t);
1439  temp32alen = triScaleExpansionZeroElim(axtbctlen, axtbct, 2.0 * adx, temp32a, t);
1440  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1441  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1442  finswap = finnow;
1443  finnow = finother;
1444  finother = finswap;
1445  if (bdytail != 0.0)
1446  {
1447  temp8len = triScaleExpansionZeroElim(4, cc, adxtail, temp8, t);
1448  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a, t);
1449  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1450  finswap = finnow;
1451  finnow = finother;
1452  finother = finswap;
1453  }
1454  if (cdytail != 0.0)
1455  {
1456  temp8len = triScaleExpansionZeroElim(4, bb, -adxtail, temp8, t);
1457  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a, t);
1458  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1459  finswap = finnow;
1460  finnow = finother;
1461  finother = finswap;
1462  }
1463 
1464  temp32alen = triScaleExpansionZeroElim(axtbctlen, axtbct, adxtail, temp32a, t);
1465  axtbcttlen = triScaleExpansionZeroElim(bcttlen, bctt, adxtail, axtbctt, t);
1466  temp16alen = triScaleExpansionZeroElim(axtbcttlen, axtbctt, 2.0 * adx, temp16a, t);
1467  temp16blen = triScaleExpansionZeroElim(axtbcttlen, axtbctt, adxtail, temp16b, t);
1468  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1469  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1470  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1471  finswap = finnow;
1472  finnow = finother;
1473  finother = finswap;
1474  }
1475  if (adytail != 0.0)
1476  {
1477  temp16alen = triScaleExpansionZeroElim(aytbclen, aytbc, adytail, temp16a, t);
1478  aytbctlen = triScaleExpansionZeroElim(bctlen, bct, adytail, aytbct, t);
1479  temp32alen = triScaleExpansionZeroElim(aytbctlen, aytbct, 2.0 * ady, temp32a, t);
1480  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1481  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1482  finswap = finnow;
1483  finnow = finother;
1484  finother = finswap;
1485 
1486  temp32alen = triScaleExpansionZeroElim(aytbctlen, aytbct, adytail, temp32a, t);
1487  aytbcttlen = triScaleExpansionZeroElim(bcttlen, bctt, adytail, aytbctt, t);
1488  temp16alen = triScaleExpansionZeroElim(aytbcttlen, aytbctt, 2.0 * ady, temp16a, t);
1489  temp16blen = triScaleExpansionZeroElim(aytbcttlen, aytbctt, adytail, temp16b, t);
1490  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1491  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1492  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1493  finswap = finnow;
1494  finnow = finother;
1495  finother = finswap;
1496  }
1497  }
1498  if ((bdxtail != 0.0) || (bdytail != 0.0))
1499  {
1500  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) || (adytail != 0.0))
1501  {
1502  Two_Product(t.m_splitter, cdxtail, ady, ti1, ti0);
1503  Two_Product(t.m_splitter, cdx, adytail, tj1, tj0);
1504  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1505  u[3] = u3;
1506  negate = -cdy;
1507  Two_Product(t.m_splitter, adxtail, negate, ti1, ti0);
1508  negate = -cdytail;
1509  Two_Product(t.m_splitter, adx, negate, tj1, tj0);
1510  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1511  v[3] = v3;
1512  catlen = triFastExpansionSumZeroElim(4, u, 4, v, cat);
1513 
1514  Two_Product(t.m_splitter, cdxtail, adytail, ti1, ti0);
1515  Two_Product(t.m_splitter, adxtail, cdytail, tj1, tj0);
1516  Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
1517  catt[3] = catt3;
1518  cattlen = 4;
1519  }
1520  else
1521  {
1522  cat[0] = 0.0;
1523  catlen = 1;
1524  catt[0] = 0.0;
1525  cattlen = 1;
1526  }
1527 
1528  if (bdxtail != 0.0)
1529  {
1530  temp16alen = triScaleExpansionZeroElim(bxtcalen, bxtca, bdxtail, temp16a, t);
1531  bxtcatlen = triScaleExpansionZeroElim(catlen, cat, bdxtail, bxtcat, t);
1532  temp32alen = triScaleExpansionZeroElim(bxtcatlen, bxtcat, 2.0 * bdx, temp32a, t);
1533  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1534  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1535  finswap = finnow;
1536  finnow = finother;
1537  finother = finswap;
1538  if (cdytail != 0.0)
1539  {
1540  temp8len = triScaleExpansionZeroElim(4, aa, bdxtail, temp8, t);
1541  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a, t);
1542  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1543  finswap = finnow;
1544  finnow = finother;
1545  finother = finswap;
1546  }
1547  if (adytail != 0.0)
1548  {
1549  temp8len = triScaleExpansionZeroElim(4, cc, -bdxtail, temp8, t);
1550  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a, t);
1551  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1552  finswap = finnow;
1553  finnow = finother;
1554  finother = finswap;
1555  }
1556 
1557  temp32alen = triScaleExpansionZeroElim(bxtcatlen, bxtcat, bdxtail, temp32a, t);
1558  bxtcattlen = triScaleExpansionZeroElim(cattlen, catt, bdxtail, bxtcatt, t);
1559  temp16alen = triScaleExpansionZeroElim(bxtcattlen, bxtcatt, 2.0 * bdx, temp16a, t);
1560  temp16blen = triScaleExpansionZeroElim(bxtcattlen, bxtcatt, bdxtail, temp16b, t);
1561  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1562  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1563  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1564  finswap = finnow;
1565  finnow = finother;
1566  finother = finswap;
1567  }
1568  if (bdytail != 0.0)
1569  {
1570  temp16alen = triScaleExpansionZeroElim(bytcalen, bytca, bdytail, temp16a, t);
1571  bytcatlen = triScaleExpansionZeroElim(catlen, cat, bdytail, bytcat, t);
1572  temp32alen = triScaleExpansionZeroElim(bytcatlen, bytcat, 2.0 * bdy, temp32a, t);
1573  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1574  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1575  finswap = finnow;
1576  finnow = finother;
1577  finother = finswap;
1578 
1579  temp32alen = triScaleExpansionZeroElim(bytcatlen, bytcat, bdytail, temp32a, t);
1580  bytcattlen = triScaleExpansionZeroElim(cattlen, catt, bdytail, bytcatt, t);
1581  temp16alen = triScaleExpansionZeroElim(bytcattlen, bytcatt, 2.0 * bdy, temp16a, t);
1582  temp16blen = triScaleExpansionZeroElim(bytcattlen, bytcatt, bdytail, temp16b, t);
1583  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1584  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1585  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1586  finswap = finnow;
1587  finnow = finother;
1588  finother = finswap;
1589  }
1590  }
1591  if ((cdxtail != 0.0) || (cdytail != 0.0))
1592  {
1593  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) || (bdytail != 0.0))
1594  {
1595  Two_Product(t.m_splitter, adxtail, bdy, ti1, ti0);
1596  Two_Product(t.m_splitter, adx, bdytail, tj1, tj0);
1597  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1598  u[3] = u3;
1599  negate = -ady;
1600  Two_Product(t.m_splitter, bdxtail, negate, ti1, ti0);
1601  negate = -adytail;
1602  Two_Product(t.m_splitter, bdx, negate, tj1, tj0);
1603  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1604  v[3] = v3;
1605  abtlen = triFastExpansionSumZeroElim(4, u, 4, v, abt);
1606 
1607  Two_Product(t.m_splitter, adxtail, bdytail, ti1, ti0);
1608  Two_Product(t.m_splitter, bdxtail, adytail, tj1, tj0);
1609  Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
1610  abtt[3] = abtt3;
1611  abttlen = 4;
1612  }
1613  else
1614  {
1615  abt[0] = 0.0;
1616  abtlen = 1;
1617  abtt[0] = 0.0;
1618  abttlen = 1;
1619  }
1620 
1621  if (cdxtail != 0.0)
1622  {
1623  temp16alen = triScaleExpansionZeroElim(cxtablen, cxtab, cdxtail, temp16a, t);
1624  cxtabtlen = triScaleExpansionZeroElim(abtlen, abt, cdxtail, cxtabt, t);
1625  temp32alen = triScaleExpansionZeroElim(cxtabtlen, cxtabt, 2.0 * cdx, temp32a, t);
1626  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1627  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1628  finswap = finnow;
1629  finnow = finother;
1630  finother = finswap;
1631  if (adytail != 0.0)
1632  {
1633  temp8len = triScaleExpansionZeroElim(4, bb, cdxtail, temp8, t);
1634  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a, t);
1635  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1636  finswap = finnow;
1637  finnow = finother;
1638  finother = finswap;
1639  }
1640  if (bdytail != 0.0)
1641  {
1642  temp8len = triScaleExpansionZeroElim(4, aa, -cdxtail, temp8, t);
1643  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a, t);
1644  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1645  finswap = finnow;
1646  finnow = finother;
1647  finother = finswap;
1648  }
1649 
1650  temp32alen = triScaleExpansionZeroElim(cxtabtlen, cxtabt, cdxtail, temp32a, t);
1651  cxtabttlen = triScaleExpansionZeroElim(abttlen, abtt, cdxtail, cxtabtt, t);
1652  temp16alen = triScaleExpansionZeroElim(cxtabttlen, cxtabtt, 2.0 * cdx, temp16a, t);
1653  temp16blen = triScaleExpansionZeroElim(cxtabttlen, cxtabtt, cdxtail, temp16b, t);
1654  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1655  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1656  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1657  finswap = finnow;
1658  finnow = finother;
1659  finother = finswap;
1660  }
1661  if (cdytail != 0.0)
1662  {
1663  temp16alen = triScaleExpansionZeroElim(cytablen, cytab, cdytail, temp16a, t);
1664  cytabtlen = triScaleExpansionZeroElim(abtlen, abt, cdytail, cytabt, t);
1665  temp32alen = triScaleExpansionZeroElim(cytabtlen, cytabt, 2.0 * cdy, temp32a, t);
1666  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1667  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1668  finswap = finnow;
1669  finnow = finother;
1670  finother = finswap;
1671 
1672  temp32alen = triScaleExpansionZeroElim(cytabtlen, cytabt, cdytail, temp32a, t);
1673  cytabttlen = triScaleExpansionZeroElim(abttlen, abtt, cdytail, cytabtt, t);
1674  temp16alen = triScaleExpansionZeroElim(cytabttlen, cytabtt, 2.0 * cdy, temp16a, t);
1675  temp16blen = triScaleExpansionZeroElim(cytabttlen, cytabtt, cdytail, temp16b, t);
1676  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1677  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1678  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1679  finswap = finnow;
1680  finnow = finother;
1681  finother = finswap;
1682  }
1683  }
1684 
1685  return finnow[finlength - 1];
1686 } // triInCircleAdapt
1687 //------------------------------------------------------------------------------
1688 // FUNCTION triInitTrianglePool
1690 // and initialize their memory pools.
1691 // NOTES This routine also computes the `highorderid', `elemattid',
1692 // indices used to find values within each triangle.
1693 // highorderid: index in each tri for extra nodes (above three)
1694 // associated with high order elements are found
1695 // There are 3 ptrs to other tris, 3 pts to corners,
1696 // & maybe 3 ptrs to shell edges before the extra nodes
1697 // elemattid: index in each tri for its attributes
1698 // where the index is measured in double
1699 //------------------------------------------------------------------------------
1700 static void triInitTrianglePool(TriVars& t)
1701 {
1702 #define TRIPERBLOCK 4092 /* # of tris allocated at once */
1703  int trisize, highorderid, elemattid;
1704  /* AKZ - we may be able to hack this based on no high order elements */
1705  highorderid = 6;
1706  /* # of bytes occupied by a triangle */
1707  trisize = (3 + (highorderid - 3)) * sizeof(Ttri);
1708  elemattid = (trisize + sizeof(double) - 1) / sizeof(double);
1709  /* Initialize triangle pool */
1710  triPoolInit(&t.m_triangles, trisize, TRIPERBLOCK, TRIPERBLOCK, 4);
1711  /* Initialize the "outer space" triangle */
1712  triDummyInit(t.m_triangles.itembytes, t);
1713 } // triInitTrianglePool
1714 //------------------------------------------------------------------------------
1715 // FUNCTION triMakeTriangle
1717 // NOTES
1718 //------------------------------------------------------------------------------
1719 static bool triMakeTriangle(Tedgetype newtedge, TriVars& t)
1720 {
1721  newtedge->tri = (Ttri*)triPoolAlloc(&t.m_triangles);
1722 
1723  /* Init the adjoining tris to be "outer space" */
1724  newtedge->tri[0] = (Ttri)t.m_dummytri;
1725  newtedge->tri[1] = (Ttri)t.m_dummytri;
1726  newtedge->tri[2] = (Ttri)t.m_dummytri;
1727  /* Three NULL vertex points. */
1728  newtedge->tri[3] = nullptr;
1729  newtedge->tri[4] = nullptr;
1730  newtedge->tri[5] = nullptr;
1731  newtedge->orient = 0;
1732  return true;
1733 } // triMakeNewTriangle
1734 //------------------------------------------------------------------------------
1735 // FUNCTION triMergeHulls
1737 // single Delaunay triangulation.
1738 // NOTES
1739 // This is similar to the algorithm given by Guibas and Stolfi, but uses
1740 // a triangle-based, rather than edge-based, data structure.
1741 //
1742 // The algorithm walks up the gap between the two triangulations, knitting
1743 // them together. As they are merged, some of their bounding triangles
1744 // are converted into real triangles of the triangulation. The procedure
1745 // pulls each hull's bounding triangles apart, then knits them together
1746 // like the teeth of two gears. The Delaunay property determines, at each
1747 // step, whether the next "tooth" is a bounding triangle of the left hull
1748 // or the right. When a bounding triangle becomes real, its apex is
1749 // changed from NULL to a real point.
1750 //
1751 // Only two new triangles need to be allocated. These become new bounding
1752 // triangles at the top and bottom of the seam. They are used to connect
1753 // the remaining bounding triangles (those that have not been converted
1754 // into real triangles) into a single fan.
1755 //
1756 // On entry, `farleft' and `innerleft' are bounding triangles of the left
1757 // triangulation. The origin of `farleft' is the leftmost vertex, and
1758 // the destination of `innerleft' is the rightmost vertex of the
1759 // triangulation. Similarly, `innerright' and `farright' are bounding
1760 // triangles of the right triangulation. The origin of `innerright' and
1761 // destination of `farright' are the leftmost and rightmost vertices.
1762 //
1763 // On completion, the origin of `farleft' is the leftmost vertex of the
1764 // merged triangulation, and the destination of `farright' is the rightmost
1765 // vertex.
1766 //------------------------------------------------------------------------------
1767 static bool triMergeHulls(Tedgetype farleft,
1768  Tedgetype innerleft,
1769  Tedgetype innerright,
1770  Tedgetype farright,
1771  int axis,
1772  TriVars& t)
1773 {
1774  int changemade, badedge, leftfinished, rightfinished;
1775  Tedge leftcand, rightcand, baseedge, nextedge;
1776  Tedge sidecasing, topcasing, outercasing, checkedge;
1777  Tpt innerleftdest, innerrightorg;
1778  Tpt innerleftapex, innerrightapex;
1779  Tpt farleftpt, farrightpt;
1780  Tpt farleftapex, farrightapex;
1781  Tpt lowerleft, lowerright;
1782  Tpt upperleft, upperright;
1783  Tpt nextapex, checkvertex;
1784  Ttri ptr; /* Temporary variable used by sym() */
1785  bool canMakeTriangles = true;
1786 
1787  dest(*innerleft, innerleftdest);
1788  apex(*innerleft, innerleftapex);
1789  org(*innerright, innerrightorg);
1790  apex(*innerright, innerrightapex);
1791  /* Special treatment for horizontal cuts */
1792  if (axis == 1)
1793  {
1794  org(*farleft, farleftpt);
1795  apex(*farleft, farleftapex);
1796  dest(*farright, farrightpt);
1797  apex(*farright, farrightapex);
1798  /* The pointers to the extremal points are shifted to point to the */
1799  /* topmost and bottommost point of each hull, rather than the */
1800  /* leftmost and rightmost points. */
1801  while (farleftapex[1] < farleftpt[1])
1802  {
1803  lnextself(*farleft);
1804  symself(*farleft);
1805  farleftpt = farleftapex;
1806  apex(*farleft, farleftapex);
1807  }
1808  sym(*innerleft, checkedge);
1809  apex(checkedge, checkvertex);
1810  while (checkvertex[1] > innerleftdest[1])
1811  {
1812  lnext(checkedge, *innerleft);
1813  innerleftapex = innerleftdest;
1814  innerleftdest = checkvertex;
1815  sym(*innerleft, checkedge);
1816  apex(checkedge, checkvertex);
1817  }
1818  while (innerrightapex[1] < innerrightorg[1])
1819  {
1820  lnextself(*innerright);
1821  symself(*innerright);
1822  innerrightorg = innerrightapex;
1823  apex(*innerright, innerrightapex);
1824  }
1825  sym(*farright, checkedge);
1826  apex(checkedge, checkvertex);
1827  while (checkvertex[1] > farrightpt[1])
1828  {
1829  lnext(checkedge, *farright);
1830  farrightapex = farrightpt;
1831  farrightpt = checkvertex;
1832  sym(*farright, checkedge);
1833  apex(checkedge, checkvertex);
1834  }
1835  }
1836  /* Find a line tangent to and below both hulls. */
1837  do
1838  {
1839  changemade = 0;
1840  /* Make innerleftdest the "bottommost" point
1841  * of the left hull. */
1842  if (triCounterClockwise(innerleftdest, innerleftapex, innerrightorg, t) > 0.0)
1843  {
1844  lprevself(*innerleft);
1845  symself(*innerleft);
1846  innerleftdest = innerleftapex;
1847  apex(*innerleft, innerleftapex);
1848  changemade = 1;
1849  }
1850  /* Make innerrightorg the "bottommost" point
1851  * of the right hull. */
1852  if (triCounterClockwise(innerrightapex, innerrightorg, innerleftdest, t) > 0.0)
1853  {
1854  lnextself(*innerright);
1855  symself(*innerright);
1856  innerrightorg = innerrightapex;
1857  apex(*innerright, innerrightapex);
1858  changemade = 1;
1859  }
1860  } while (changemade);
1861  /* Find the 2 candidates to be next "gear tooth" */
1862  sym(*innerleft, leftcand);
1863  sym(*innerright, rightcand);
1864  /* Create the bottom new bounding triangle. */
1865  canMakeTriangles = triMakeTriangle(&baseedge, t);
1866  if (!canMakeTriangles)
1867  {
1868  return false;
1869  }
1870  /* Connect it to the bounding boxes of the left
1871  * and right triangulations. */
1872  bond(baseedge, *innerleft);
1873  lnextself(baseedge);
1874  bond(baseedge, *innerright);
1875  lnextself(baseedge);
1876  setorg(baseedge, innerrightorg);
1877  setdest(baseedge, innerleftdest);
1878  /* Apex is intentionally left NULL. */
1879  /* Fix the extreme triangles if necessary. */
1880  org(*farleft, farleftpt);
1881  if (innerleftdest == farleftpt)
1882  {
1883  lnext(baseedge, *farleft);
1884  }
1885  dest(*farright, farrightpt);
1886  if (innerrightorg == farrightpt)
1887  {
1888  lprev(baseedge, *farright);
1889  }
1890  /* The vertices of the current knitting edge. */
1891  lowerleft = innerleftdest;
1892  lowerright = innerrightorg;
1893  /* The candidate vertices for knitting. */
1894  apex(leftcand, upperleft);
1895  apex(rightcand, upperright);
1896  /* Walk up the gap between the two triangulations,
1897  * knitting them together. */
1898  for (;;)
1899  {
1900  /* Have we reached the top? (This isn't quite the right question, */
1901  /* because even though the left triangulation might seem finished now, */
1902  /* moving up on the right triangulation might reveal a new point of */
1903  /* the left triangulation. And vice-versa.) */
1904  leftfinished = triCounterClockwise(upperleft, lowerleft, lowerright, t) <= 0.0;
1905  rightfinished = triCounterClockwise(upperright, lowerleft, lowerright, t) <= 0.0;
1906  if (leftfinished && rightfinished)
1907  {
1908  /* Create the top new bounding triangle. */
1909  canMakeTriangles = triMakeTriangle(&nextedge, t);
1910  if (!canMakeTriangles)
1911  {
1912  return false;
1913  }
1914  setorg(nextedge, lowerleft);
1915  setdest(nextedge, lowerright);
1916  /* Apex is intentionally left NULL. */
1917  /* Connect it to the bounding boxes of the
1918  * two triangulations. */
1919  bond(nextedge, baseedge);
1920  lnextself(nextedge);
1921  bond(nextedge, rightcand);
1922  lnextself(nextedge);
1923  bond(nextedge, leftcand);
1924  /* Special treatment for horizontal cuts. */
1925  if (axis == 1)
1926  {
1927  org(*farleft, farleftpt);
1928  apex(*farleft, farleftapex);
1929  dest(*farright, farrightpt);
1930  apex(*farright, farrightapex);
1931  sym(*farleft, checkedge);
1932  apex(checkedge, checkvertex);
1933  /* The pointers to the extremal points are restored to the leftmost */
1934  /* and rightmost points (rather than topmost and bottommost). */
1935  while (checkvertex[0] < farleftpt[0])
1936  {
1937  lprev(checkedge, *farleft);
1938  farleftapex = farleftpt;
1939  farleftpt = checkvertex;
1940  sym(*farleft, checkedge);
1941  apex(checkedge, checkvertex);
1942  }
1943  while (farrightapex[0] > farrightpt[0])
1944  {
1945  lprevself(*farright);
1946  symself(*farright);
1947  farrightpt = farrightapex;
1948  apex(*farright, farrightapex);
1949  }
1950  }
1951  return true;
1952  }
1953  /* Consider eliminating edges from the left
1954  * triangulation. */
1955  if (!leftfinished)
1956  {
1957  /* What vertex would be exposed if an edge
1958  * were deleted? */
1959  lprev(leftcand, nextedge);
1960  symself(nextedge);
1961  apex(nextedge, nextapex);
1962  /* If nextapex is NULL, then no vertex would be exposed; the */
1963  /* triangulation would have been eaten right through. */
1964  if (nextapex != nullptr)
1965  {
1966  /* Check whether the edge is Delaunay. */
1967  badedge = triInCircle(lowerleft, lowerright, upperleft, nextapex, t) > 0.0;
1968  while (badedge)
1969  {
1970  /* Eliminate the edge with an edge flip. As a result, the */
1971  /* left triangulation will have one more boundary triangle. */
1972  lnextself(nextedge);
1973  sym(nextedge, topcasing);
1974  lnextself(nextedge);
1975  sym(nextedge, sidecasing);
1976  bond(nextedge, topcasing);
1977  bond(leftcand, sidecasing);
1978  lnextself(leftcand);
1979  sym(leftcand, outercasing);
1980  lprevself(nextedge);
1981  bond(nextedge, outercasing);
1982  /* Correct vertices to reflect the edge flip. */
1983  setorg(leftcand, lowerleft);
1984  setdest(leftcand, nullptr);
1985  setapex(leftcand, nextapex);
1986  setorg(nextedge, nullptr);
1987  setdest(nextedge, upperleft);
1988  setapex(nextedge, nextapex);
1989  /* Consider the newly exposed vertex. */
1990  upperleft = nextapex;
1991  /* What vertex would be exposed if another
1992  * edge were deleted? */
1993  tedgecopy(sidecasing, nextedge);
1994  apex(nextedge, nextapex);
1995  if (nextapex != nullptr)
1996  {
1997  /* Check whether the edge is Delaunay. */
1998  badedge = triInCircle(lowerleft, lowerright, upperleft, nextapex, t) > 0.0;
1999  }
2000  else
2001  {
2002  /* Avoid eating right through the triangulation */
2003  badedge = 0;
2004  }
2005  }
2006  }
2007  }
2008  /* Consider eliminating edges from the
2009  * right triangulation. */
2010  if (!rightfinished)
2011  {
2012  /* What vertex would be exposed if an edge
2013  * were deleted? */
2014  lnext(rightcand, nextedge);
2015  symself(nextedge);
2016  apex(nextedge, nextapex);
2017  /* If nextapex is NULL, then no vertex would
2018  * be exposed; the triangulation would have been
2019  * eaten right through. */
2020  if (nextapex != nullptr)
2021  {
2022  /* Check whether the edge is Delaunay. */
2023  badedge = triInCircle(lowerleft, lowerright, upperright, nextapex, t) > 0.0;
2024  while (badedge)
2025  {
2026  /* Eliminate the edge with an edge flip.
2027  * As a result, the right triangulation will
2028  * have one more boundary triangle. */
2029  lprevself(nextedge);
2030  sym(nextedge, topcasing);
2031  lprevself(nextedge);
2032  sym(nextedge, sidecasing);
2033  bond(nextedge, topcasing);
2034  bond(rightcand, sidecasing);
2035  lprevself(rightcand);
2036  sym(rightcand, outercasing);
2037  lnextself(nextedge);
2038  bond(nextedge, outercasing);
2039  /* Correct vertices to reflect the edge flip. */
2040  setorg(rightcand, nullptr);
2041  setdest(rightcand, lowerright);
2042  setapex(rightcand, nextapex);
2043  setorg(nextedge, upperright);
2044  setdest(nextedge, nullptr);
2045  setapex(nextedge, nextapex);
2046  /* Consider the newly exposed vertex. */
2047  upperright = nextapex;
2048  /* What vertex would be exposed if another
2049  * edge were deleted? */
2050  tedgecopy(sidecasing, nextedge);
2051  apex(nextedge, nextapex);
2052  if (nextapex != nullptr)
2053  {
2054  /* Check whether the edge is Delaunay. */
2055  badedge = triInCircle(lowerleft, lowerright, upperright, nextapex, t) > 0.0;
2056  }
2057  else
2058  {
2059  /* Avoid eating right through the triangulation. */
2060  badedge = 0;
2061  }
2062  }
2063  }
2064  }
2065  if (leftfinished ||
2066  (!rightfinished && (triInCircle(upperleft, lowerleft, lowerright, upperright, t) > 0.0)))
2067  {
2068  /* Knit the triangulations, adding an edge
2069  * from `lowerleft' to `upperright' */
2070  bond(baseedge, rightcand);
2071  lprev(rightcand, baseedge);
2072  setdest(baseedge, lowerleft);
2073  lowerright = upperright;
2074  sym(baseedge, rightcand);
2075  apex(rightcand, upperright);
2076  }
2077  else
2078  {
2079  /* Knit the triangulations, adding an edge
2080  * from `upperleft' to `lowerright' */
2081  bond(baseedge, leftcand);
2082  lnext(leftcand, baseedge);
2083  setorg(baseedge, lowerright);
2084  lowerleft = upperleft;
2085  sym(baseedge, leftcand);
2086  apex(leftcand, upperleft);
2087  }
2088  }
2089 } // triMergeHulls
2090 //------------------------------------------------------------------------------
2091 // FUNCTION triNumberNodes
2093 // NOTES Each point is assigned a marker equal to its number.
2094 //------------------------------------------------------------------------------
2095 static void triNumberNodes(TriVars& t)
2096 {
2097  int pointnumber;
2098  Tpt pointloop;
2099 
2100  triTraversalInit(&t.m_points);
2101  pointloop = triPointTraverse(t);
2102  pointnumber = 1;
2103  while (pointloop != nullptr)
2104  {
2105  setpointmark(pointloop, pointnumber, t.m_pointmarkindex);
2106  pointloop = triPointTraverse(t);
2107  pointnumber++;
2108  }
2109 } // triNumberNodes
2110 //------------------------------------------------------------------------------
2111 // FUNCTION triPointMedian
2113 // of points so that the first `median' points occur
2114 // lexicographically before the remaining points.
2115 // NOTES
2116 // Uses the x-coordinate as the primary key if axis == 0; the y-coordinate
2117 // if axis == 1. Very similar to the triPointSort() procedure, but runs in
2118 // randomized linear time.
2119 //------------------------------------------------------------------------------
2120 static void triPointMedian(Tpt* sortarray, int arraysize, int median, int axis)
2121 {
2122  int left, right, pivot;
2123  double pivot1, pivot2;
2124  Tpt temp;
2125  /* Recursive base case. */
2126  if (arraysize == 2)
2127  {
2128  if ((sortarray[0][axis] > sortarray[1][axis]) ||
2129  ((sortarray[0][axis] == sortarray[1][axis]) &&
2130  (sortarray[0][1 - axis] > sortarray[1][1 - axis])))
2131  {
2132  temp = sortarray[1];
2133  sortarray[1] = sortarray[0];
2134  sortarray[0] = temp;
2135  }
2136  return;
2137  }
2138  else if (arraysize == 0)
2139  return;
2140  /* Choose a random pivot to split the array. */
2141  pivot = (int)triRandomnation((unsigned int)arraysize);
2142  pivot1 = sortarray[pivot][axis];
2143  pivot2 = sortarray[pivot][1 - axis];
2144  /* Split the array. */
2145  left = -1;
2146  right = arraysize;
2147  while (left < right)
2148  {
2149  /* Find a pt whose 'x' is > left */
2150  do
2151  {
2152  left++;
2153  } while ((left <= right) &&
2154  ((sortarray[left][axis] < pivot1) ||
2155  ((sortarray[left][axis] == pivot1) && (sortarray[left][1 - axis] < pivot2))));
2156  /* Find a pt whose 'x' is < right */
2157  do
2158  {
2159  right--;
2160  } while ((left <= right) &&
2161  ((sortarray[right][axis] > pivot1) ||
2162  ((sortarray[right][axis] == pivot1) && (sortarray[right][1 - axis] > pivot2))));
2163  if (left < right)
2164  {
2165  /* Swap the left and right points. */
2166  temp = sortarray[left];
2167  sortarray[left] = sortarray[right];
2168  sortarray[right] = temp;
2169  }
2170  }
2171  /* Recurse - only one condition can be true */
2172  if (left > median)
2173  {
2174  /* Recursively shuffle the left subset. */
2175  triPointMedian(sortarray, left, median, axis);
2176  }
2177  if (right < median - 1)
2178  {
2179  /* Recursively shuffle the right subset. */
2180  triPointMedian(&sortarray[right + 1], arraysize - right - 1, median - right - 1, axis);
2181  }
2182 } // triPointMedian
2183 //------------------------------------------------------------------------------
2184 // FUNCTION triPointSort
2186 // a secondary key.
2187 // NOTES
2188 // Uses quicksort. Randomized O(n log n) time. No, I did not make any of
2189 // the usual quicksort mistakes.
2190 //------------------------------------------------------------------------------
2191 static void triPointSort(Tpt* sortarray, int arraysize)
2192 {
2193  int left, right, pivot;
2194  double pivotx, pivoty;
2195  Tpt temp;
2196  /* Recursive base case. */
2197  if (arraysize == 2)
2198  {
2199  if ((sortarray[0][0] > sortarray[1][0]) ||
2200  ((sortarray[0][0] == sortarray[1][0]) && (sortarray[0][1] > sortarray[1][1])))
2201  {
2202  temp = sortarray[1];
2203  sortarray[1] = sortarray[0];
2204  sortarray[0] = temp;
2205  }
2206  return;
2207  }
2208  else if (arraysize == 0)
2209  return;
2210  /* Choose a random pivot to split the array. */
2211  pivot = (int)triRandomnation((unsigned int)arraysize);
2212  pivotx = sortarray[pivot][0];
2213  pivoty = sortarray[pivot][1];
2214  /* Split the array. */
2215  left = -1;
2216  right = arraysize;
2217  while (left < right)
2218  {
2219  /* Find a pt whose 'x' is > left */
2220  do
2221  {
2222  left++;
2223  } while ((left <= right) && ((sortarray[left][0] < pivotx) || ((sortarray[left][0] == pivotx) &&
2224  (sortarray[left][1] < pivoty))));
2225  /* Find a pt whose 'x' is < right */
2226  do
2227  {
2228  right--;
2229  } while ((left <= right) &&
2230  ((sortarray[right][0] > pivotx) ||
2231  ((sortarray[right][0] == pivotx) && (sortarray[right][1] > pivoty))));
2232  if (left < right)
2233  {
2234  /* Swap the left and right points. */
2235  temp = sortarray[left];
2236  sortarray[left] = sortarray[right];
2237  sortarray[right] = temp;
2238  }
2239  }
2240  if (left > 1)
2241  {
2242  /* Recursively sort the left subset. */
2243  triPointSort(sortarray, left);
2244  }
2245  if (right < arraysize - 2)
2246  {
2247  /* Recursively sort the right subset. */
2248  triPointSort(&sortarray[right + 1], arraysize - right - 1);
2249  }
2250 } // triPointSort
2251 //------------------------------------------------------------------------------
2252 // FUNCTION triPointTraverse
2254 // NOTES
2255 //------------------------------------------------------------------------------
2256 static Tpt triPointTraverse(TriVars& t)
2257 {
2258  Tpt newpoint;
2259 
2260  do
2261  {
2262  newpoint = (Tpt)triTraverse(&t.m_points);
2263  if (newpoint == nullptr)
2264  return nullptr;
2265  } while (pointmark(newpoint, t.m_pointmarkindex) == -999); // Skip dead ones.
2266  return newpoint;
2267 } // triPointTraverse
2268 //------------------------------------------------------------------------------
2269 // FUNCTION triPoolAlloc
2271 // NOTES
2272 //------------------------------------------------------------------------------
2273 static int* triPoolAlloc(Tmemtype pool)
2274 {
2275  int *newitem, **newblock;
2276  unsigned long long alignptr;
2277  /* use dead item before allocating a fresh one */
2278  if (pool->deaditemstack != nullptr)
2279  {
2280  newitem = pool->deaditemstack; /* Take first item in list */
2281  pool->deaditemstack = *(int**)pool->deaditemstack;
2282  }
2283  else
2284  {
2285  /* see if a new block must be allocated */
2286  if (pool->unallocateditems == 0)
2287  {
2288  if (*(pool->nowblock) == nullptr)
2289  {
2290  /* get a new block, add to linked list of blocks */
2291  newblock =
2292  (int**)malloc(pool->itemsperblock * pool->itembytes + sizeof(int*) + pool->alignbytes);
2293  if (newblock == nullptr)
2294  {
2295  std::string s = "malloc failed: ";
2296  s += __FUNCTION__;
2297  XM_LOG(xmlog::error, s);
2298  return nullptr;
2299  }
2300  *(pool->nowblock) = (int*)newblock;
2301  /* next block pointer is NULL. */
2302  *newblock = nullptr;
2303  }
2304  /* Move to the new block. */
2305  pool->nowblock = (int**)*(pool->nowblock);
2306  /* Find 1st item in pool. Inc by sizeof(int*) */
2307  alignptr = (unsigned long long)(pool->nowblock + 1);
2308  /* Align item on an `alignbytes'-byte boundary */
2309  pool->nextitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2310  (alignptr % (unsigned long long)pool->alignbytes));
2311  /* all items in block are unallocated */
2312  pool->unallocateditems = pool->itemsperblock;
2313  }
2314  /* Allocate a new item */
2315  newitem = pool->nextitem;
2316  /* Advance `nextitem' ptr to next item in block */
2317  pool->nextitem = (int*)((char*)pool->nextitem + pool->itembytes);
2318 
2319  pool->unallocateditems--;
2320  pool->maxitems++;
2321  }
2322  pool->items++;
2323  return newitem;
2324 } // triPoolAlloc
2325 //------------------------------------------------------------------------------
2326 // FUNCTION triPoolDealloc
2328 // NOTES The deallocated space is stored in a queue for later reuse.
2329 //------------------------------------------------------------------------------
2330 static void triPoolDealloc(Tmemtype pool, int* dyingitem)
2331 {
2332  /* Push freshly killed item onto stack. */
2333  *((int**)dyingitem) = pool->deaditemstack;
2334  pool->deaditemstack = dyingitem;
2335  pool->items--;
2336 } // triPoolDealloc
2337 //------------------------------------------------------------------------------
2338 // FUNCTION triPoolDeinit
2340 // NOTES
2341 //------------------------------------------------------------------------------
2342 static void triPoolDeinit(Tmemtype pool)
2343 {
2344  while (pool && pool->firstblock != nullptr)
2345  {
2346  pool->nowblock = (int**)*(pool->firstblock);
2347  free(pool->firstblock);
2348  pool->firstblock = pool->nowblock;
2349  }
2350 } // triPoolDeinit
2351 //------------------------------------------------------------------------------
2352 // FUNCTION triPoolInit
2354 // NOTES This routine initializes machinery for allocating items.
2355 // A `pool' is created with records of at least `bytecount' bytes.
2356 // Items will be allocated in `itemcount'- blocks.
2357 // Each item is assumed to be a collection of words, and either
2358 // pointers or floating-point values are assumed to be the
2359 // "primary" word type. (The "primary" word type is used
2360 // to determine alignment of items.)
2361 // If `alignment' isn't zero, all items will be `alignment'-byte
2362 // aligned in memory. `alignment' must be either a multiple or
2363 // a factor of the primary word size; powers of two are safe.
2364 // `alignment' is normally used to create a few unused bits at the
2365 // bottom of each item's pointer to store information.
2366 // Don't change this routine unless you understand it.
2367 //------------------------------------------------------------------------------
2368 static bool triPoolInit(Tmemtype pool,
2369  int bytecount,
2370  int itemcount,
2371  int firstitemcount,
2372  int alignment)
2373 {
2374  /* Find alignment to avoid unaligned access *
2375  * Must be at least as large as: *
2376  * -`alignment' *
2377  * - primary word type, *
2378  * - sizeof(int*), to maintain dead item stack */
2379  if (alignment > sizeof(int*))
2380  {
2381  pool->alignbytes = alignment;
2382  }
2383  else
2384  {
2385  pool->alignbytes = sizeof(int*);
2386  }
2387  pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) * pool->alignbytes;
2388  pool->itemsperblock = itemcount;
2389  if (firstitemcount == 0)
2390  {
2391  pool->itemsfirstblock = itemcount;
2392  }
2393  else
2394  {
2395  pool->itemsfirstblock = firstitemcount;
2396  }
2397  /* Allocate block of items. Space for: *
2398  * `itemsperblock' items *
2399  * 1 ptr (to point to next block) *
2400  * space to ensure alignment of the items */
2401  pool->firstblock =
2402  (int**)malloc(pool->itemsfirstblock * pool->itembytes + sizeof(int*) + pool->alignbytes);
2403  if (pool->firstblock == nullptr)
2404  {
2405  std::string s = "malloc failed: ";
2406  s += __FUNCTION__;
2407  XM_LOG(xmlog::error, s);
2408  return false;
2409  }
2410  /* Set the next block pointer to NULL. */
2411  *(pool->firstblock) = nullptr;
2412  /* Initialize the pool */
2413  triPoolRestart(pool);
2414  return true;
2415 } // triPoolInit
2416 //------------------------------------------------------------------------------
2417 // FUNCTION triPoolRestart
2419 // NOTES
2420 // This is a simple linear congruential random number generator. Hence, it
2421 // is a bad random number generator, but good enough for most randomized
2422 // geometric algorithms.
2423 //------------------------------------------------------------------------------
2424 static void triPoolRestart(Tmemtype pool)
2425 {
2426  unsigned long long alignptr;
2427 
2428  pool->items = 0;
2429  pool->maxitems = 0;
2430 
2431  /* Set the currently active block. */
2432  pool->nowblock = pool->firstblock;
2433  /* Find the first item in the pool. Increment by the size of (VOID *). */
2434  alignptr = (unsigned long long)(pool->nowblock + 1);
2435  /* Align the item on an `alignbytes'-byte boundary. */
2436  pool->nextitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2437  (alignptr % (unsigned long long)pool->alignbytes));
2438  /* There are lots of unallocated items left in this block. */
2439  pool->unallocateditems = pool->itemsfirstblock;
2440  /* The stack of deallocated items is empty. */
2441  pool->deaditemstack = nullptr;
2442 
2443 } // triPoolRestart
2444 //------------------------------------------------------------------------------
2445 // FUNCTION triRandomnation
2447 // NOTES
2448 // This is a simple linear congruential random number generator. Hence, it
2449 // is a bad random number generator, but good enough for most randomized
2450 // geometric algorithms.
2451 //------------------------------------------------------------------------------
2452 static unsigned long triRandomnation(unsigned int choices)
2453 {
2454  static unsigned long randomseed = 1;
2455 
2456  if (choices == 0)
2457  return 0;
2458  randomseed = (randomseed * 1366l + 150889l) % 714025l;
2459  return randomseed / (714025l / choices + 1);
2460 } // triRandomnation
2461 //------------------------------------------------------------------------------
2462 // FUNCTION triRemoveGhosts
2464 // NOTES
2465 //------------------------------------------------------------------------------
2466 static void triRemoveGhosts(Tedgetype startghost, TriVars& t)
2467 {
2468  Tedge searchedge, dissolveedge, deadtri;
2469  Tpt markorg;
2470  Ttri ptr; /* temp variable used by sym() */
2471  /* Find a starting edge on the convex hull */
2472  lprev(*startghost, searchedge);
2473  symself(searchedge);
2474  t.m_dummytri[0] = encode(searchedge);
2475  /* Remove bounding box & count convex hull edges */
2476  tedgecopy(*startghost, dissolveedge);
2477  do
2478  {
2479  lnext(dissolveedge, deadtri);
2480  lprevself(dissolveedge);
2481  symself(dissolveedge);
2482  /* If no PSLG is involved, set the boundary markers of all the points */
2483  /* on the convex hull. If a PSLG is used, this step is done later. */
2484  /* Watch out for the all collinear input case */
2485  if (dissolveedge.tri != t.m_dummytri)
2486  {
2487  org(dissolveedge, markorg);
2488  if (pointmark(markorg, t.m_pointmarkindex) == 0)
2489  {
2490  setpointmark(markorg, 1, t.m_pointmarkindex);
2491  }
2492  }
2493  /* Remove a bounding tri from a convex hull tri */
2494  dissolveedge.tri[dissolveedge.orient] = (Ttri)t.m_dummytri;
2495  /* Find the next bounding triangle */
2496  sym(deadtri, dissolveedge);
2497  /* Delete the bounding triangle */
2498  triTriangleDealloc(deadtri.tri, t);
2499  } while (!tedgeequal(dissolveedge, *startghost));
2500 } // triRemoveGhosts
2501 //------------------------------------------------------------------------------
2502 // FUNCTION triScaleExpansionZeroElim
2504 // the output expansion.
2505 // NOTES Sets h = be. See my Robust Predicates paper for details.
2506 //
2507 // Maintains the nonoverlapping property. If round-to-even is used (as
2508 // with IEEE 754), maintains the strongly nonoverlapping and nonadjacent
2509 // properties as well. (That is, if e has one of these properties, so
2510 // will h.) e and h cannot be the same.
2511 //------------------------------------------------------------------------------
2512 static int triScaleExpansionZeroElim(int elen, double* e, double b, double* h, TriVars& t)
2513 {
2514  int eindex, hindex;
2515  double Q, sum;
2516  double hh;
2517  double product1, product0;
2518  double enow;
2519  double bvirt, avirt, bround, around;
2520  double c;
2521  double abig, ahi, alo, bhi, blo;
2522  double err1, err2, err3;
2523 
2524  Split(t.m_splitter, b, bhi, blo);
2525  Two_Product_Presplit(t.m_splitter, e[0], b, bhi, blo, Q, hh);
2526  hindex = 0;
2527  if (hh != 0)
2528  h[hindex++] = hh;
2529 
2530  for (eindex = 1; eindex < elen; eindex++)
2531  {
2532  enow = e[eindex];
2533  Two_Product_Presplit(t.m_splitter, enow, b, bhi, blo, product1, product0);
2534  Two_Sum(Q, product0, sum, hh);
2535  if (hh != 0)
2536  h[hindex++] = hh;
2537  Fast_Two_Sum(product1, sum, Q, hh);
2538  if (hh != 0)
2539  h[hindex++] = hh;
2540  }
2541  if ((Q != 0.0) || (hindex == 0))
2542  h[hindex++] = Q;
2543  return hindex;
2544 } // triScaleExpansionZeroElim
2545 //------------------------------------------------------------------------------
2546 // FUNCTION triTraversalInit
2548 // NOTES This routine is used in conjunction with triTraverse().
2549 //------------------------------------------------------------------------------
2550 static void triTraversalInit(Tmemtype pool)
2551 {
2552  unsigned long long alignptr;
2553  /* Begin the traversal in the first block */
2554  pool->pathblock = pool->firstblock;
2555  /* Find 1st item in block. Inc by sizeof(int*) */
2556  alignptr = (unsigned long long)(pool->pathblock + 1);
2557  /* Align w/item on an `alignbytes'-byte boundary */
2558  pool->pathitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2559  (alignptr % (unsigned long long)pool->alignbytes));
2560  /* Update # of items left in the current block */
2561  pool->pathitemsleft = pool->itemsfirstblock;
2562 } // triTraversalInit
2563 //------------------------------------------------------------------------------
2564 // FUNCTION triTraverse
2566 // NOTES This routine is used in conjunction with triTraversalInit().
2567 // Be forewarned that this routine successively returns all items in
2568 // the list, including deallocated ones on the deaditemqueue. It's up
2569 // to you to figure out which ones are actually dead. Why? I don't
2570 // want to allocate extra space just to demarcate dead items. It can
2571 // usually be done more space-efficiently by a routine that knows
2572 // something about the structure of the item.
2573 //------------------------------------------------------------------------------
2574 static int* triTraverse(Tmemtype pool)
2575 {
2576  int* newitem;
2577  unsigned long long alignptr;
2578  /* Stop upon exhausting the list of items. */
2579  if (pool->pathitem == pool->nextitem)
2580  return nullptr;
2581  /* look for untraversed items in current block */
2582  if (pool->pathitemsleft == 0)
2583  {
2584  /* Find the next block. */
2585  pool->pathblock = (int**)*(pool->pathblock);
2586  /* Find 1st item in block. Inc by sizeof(int*) */
2587  alignptr = (unsigned long long)(pool->pathblock + 1);
2588  /* Align w/item on `alignbytes'-byte boundary */
2589  pool->pathitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2590  (alignptr % (unsigned long long)pool->alignbytes));
2591  /* Update # of items left in the current block */
2592  pool->pathitemsleft = pool->itemsperblock;
2593  }
2594  newitem = pool->pathitem;
2595  /* Find the next item in the block. */
2596 
2597  pool->pathitem = (int*)((char*)pool->pathitem + pool->itembytes);
2598  pool->pathitemsleft--;
2599  return newitem;
2600 } // triTraverse
2601 //------------------------------------------------------------------------------
2602 // FUNCTION triTriangleDealloc
2604 // NOTES Makes it possible to detect dead triangles when traversing
2605 //------------------------------------------------------------------------------
2606 static void triTriangleDealloc(Ttri* dyingtriangle, TriVars& t)
2607 {
2608  /* Set triangle's vertices to NULL */
2609  dyingtriangle[3] = nullptr;
2610  dyingtriangle[4] = nullptr;
2611  dyingtriangle[5] = nullptr;
2612  triPoolDealloc(&t.m_triangles, (int*)dyingtriangle);
2613 } // triTriangleDealloc
2614 //------------------------------------------------------------------------------
2615 // FUNCTION triTriangleTraverse
2617 // NOTES
2618 //------------------------------------------------------------------------------
2619 static Ttri* triTriangleTraverse(TriVars& t)
2620 {
2621  Ttri* newtriangle;
2622  do
2623  {
2624  newtriangle = (Ttri*)triTraverse(&t.m_triangles);
2625  if (newtriangle == nullptr)
2626  return nullptr;
2627  } while (newtriangle[3] == nullptr); /* Skip dead ones */
2628  return newtriangle;
2629 } // triTriangleTraverse
2630 
2631 } // namespace unnamed
2633 
2634 namespace xms
2635 {
2636 //----- Class Definitions ------------------------------------------------------
2637 
2638 //----- Function Definitions ---------------------------------------------------
2639 
2640 //------------------------------------------------------------------------------
2650 //------------------------------------------------------------------------------
2651 bool trTriangulateIt(TrTriangulator& a_Client)
2652 {
2653  TriVars t;
2654  try
2655  {
2656  // initialize counters
2657  t.m_points.maxitems = t.m_triangles.maxitems = 0l;
2658  t.m_points.itembytes = t.m_triangles.itembytes = 0;
2659 
2660  // initialize exact arithmetic constants
2661  triExactInit(t);
2662 
2663  // copy points into pool data
2664  if (!triGetPoints(a_Client, t))
2665  {
2666  throw - 1;
2667  }
2668 
2669  if (t.m_numpoints > 2)
2670  {
2671  // initialize the triangle pool
2672  triInitTrianglePool(t);
2673 
2674  // do the triangulation
2675  bool ok = triDivConqDelaunay(t);
2676  if (ok)
2677  {
2678  triNumberNodes(t);
2679  triFillTriList(a_Client, t);
2680 
2681  // free the memory
2682  triPoolDeinit(&t.m_triangles);
2683  if (t.m_dummytribase)
2684  {
2685  free(t.m_dummytribase);
2686  }
2687  }
2688  }
2689 
2690  // more memory clean up
2691  triPoolDeinit(&t.m_points);
2692 
2693  a_Client.FinalizeTriangulation();
2694  }
2695  catch (...)
2696  {
2697  XM_LOG(xmlog::error, "Error: Unable to triangulate.");
2698  triPoolDeinit(&t.m_triangles);
2699  triPoolDeinit(&t.m_points);
2700  return false;
2701  }
2702  return true;
2703 } // trTriangulateIt
2704 
2705 } // namespace xms
2706 
2707 // eof triangulate.cpp
#define XM_LOG(A, B)
Code that creates a Delauney triangulation from points.
Base class used to derive a class to triangulate points.