xmsgrid  1.0
triangulate.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
7 //------------------------------------------------------------------------------
8 
9 //----- Include Files ----------------------------------------------------------
10 
11 // 1. Precompiled header
12 
13 // 2. My own header
15 
16 // 3. Standard library headers
17 #include <cmath>
18 
19 // 4. External library headers
20 
21 // 5. Shared code headers
22 #include <xmscore/misc/Progress.h>
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  Progress prog("Triangulating Points");
925  // prepare to recieve trianlges
926  a_Client.PrepareToReceiveTriangles();
927  double triCount(0.0);
928  double total = static_cast<double>(a_Client.GetNPoints());
929 
930  triTraversalInit(&t.m_triangles);
931  triangleloop.tri = triTriangleTraverse(t);
932  triangleloop.orient = 0;
933  while (triangleloop.tri != nullptr)
934  {
935  // get the ids
936  org(triangleloop, p1);
937  dest(triangleloop, p2);
938  apex(triangleloop, p3);
939  id1 = pointmark(p1, t.m_pointmarkindex);
940  id2 = pointmark(p2, t.m_pointmarkindex);
941  id3 = pointmark(p3, t.m_pointmarkindex);
942 
943  // recieve the triangle
944  a_Client.ReceiveTriangle(id1, id2, id3);
945  triCount += 2.0;
946  prog.ProgressStatus(std::min(1.0, triCount / total));
947 
948  triangleloop.tri = triTriangleTraverse(t);
949  }
950 } // triFillTriList
951 //------------------------------------------------------------------------------
952 // FUNCTION triGetPoints
954 // NOTES
955 //------------------------------------------------------------------------------
956 static bool triGetPoints(TrTriangulator& a_Client, TriVars& t)
957 {
958 #define POINTPERBLOCK 4092
959 
960  int i, pointsize;
961  Pt3d loc;
962  Tpt pointloop;
963 
964  // number of points allocated at once
965  t.m_pointmarkindex = (3 * sizeof(double) + sizeof(int) - 1) / sizeof(int);
966  pointsize = (t.m_pointmarkindex + 1) * sizeof(int);
967 
968  // initialize the pool of points
969  // get the number of points
970  t.m_numpoints = a_Client.GetNPoints();
971 
972  if (!triPoolInit(&t.m_points, pointsize, POINTPERBLOCK,
973  t.m_numpoints > POINTPERBLOCK ? t.m_numpoints : POINTPERBLOCK, 0))
974  {
975  return false;
976  }
977 
978  // get the points
979  for (i = 0; i < t.m_numpoints; i++)
980  {
981  pointloop = (Tpt)triPoolAlloc(&t.m_points);
982 
983  // set the location
984  loc = a_Client.GetLocation();
985  pointloop[0] = loc.x;
986  pointloop[1] = loc.y;
987 
988  // save id for pt (used after triangulation)
989  pointloop[2] = a_Client.GetID();
990 
991  setpointmark(pointloop, 0, t.m_pointmarkindex);
992 
993  // go to the next point
994  a_Client.IncrementPoint();
995  }
996  return true;
997 } // triGetPoints
998 //------------------------------------------------------------------------------
999 // FUNCTION triInCircle
1001 // NOTES
1002 //------------------------------------------------------------------------------
1003 static double triInCircle(Tpt pa, Tpt pb, Tpt pc, Tpt pd, TriVars& t)
1004 {
1005  double adx, bdx, cdx, ady, bdy, cdy;
1006  double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
1007  double alift, blift, clift;
1008  double det;
1009  double permanent, errbound;
1010 
1011  adx = pa[0] - pd[0];
1012  bdx = pb[0] - pd[0];
1013  cdx = pc[0] - pd[0];
1014  ady = pa[1] - pd[1];
1015  bdy = pb[1] - pd[1];
1016  cdy = pc[1] - pd[1];
1017 
1018  bdxcdy = bdx * cdy;
1019  cdxbdy = cdx * bdy;
1020  alift = adx * adx + ady * ady;
1021 
1022  cdxady = cdx * ady;
1023  adxcdy = adx * cdy;
1024  blift = bdx * bdx + bdy * bdy;
1025 
1026  adxbdy = adx * bdy;
1027  bdxady = bdx * ady;
1028  clift = cdx * cdx + cdy * cdy;
1029 
1030  det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
1031 
1032  permanent = (fabs(bdxcdy) + fabs(cdxbdy)) * alift + (fabs(cdxady) + fabs(adxcdy)) * blift +
1033  (fabs(adxbdy) + fabs(bdxady)) * clift;
1034  errbound = t.m_iccerrboundA * permanent;
1035  if ((det > errbound) || (-det > errbound))
1036  return det;
1037 
1038  return triInCircleAdapt(pa, pb, pc, pd, permanent, t);
1039 } // triInCircle
1040 //------------------------------------------------------------------------------
1041 // FUNCTION triInCircleAdapt
1043 // passing through pa, pb, and pc; a negative value if it lies
1044 // outside; and zero if the four points are cocircular. The points pa,
1045 // pb, and pc must be in counterclockwise order, or the sign of the
1046 // result will be reversed.
1047 // NOTES Uses exact arithmetic if necessary to ensure a correct answer. The
1048 // result returned is the determinant of a matrix. This determinant is
1049 // computed adaptively, in the sense that exact arithmetic is used only to
1050 // the degree it is needed to ensure that the returned value has the
1051 // correct sign. Hence, this function is usually quite fast, but will run
1052 // more slowly when the input points are cocircular or nearly so.
1053 //------------------------------------------------------------------------------
1054 static double triInCircleAdapt(Tpt pa, Tpt pb, Tpt pc, Tpt pd, double permanent, TriVars& t)
1055 {
1056  int axbclen, axxbclen, aybclen, ayybclen, alen;
1057  int bxcalen, bxxcalen, bycalen, byycalen, blen;
1058  int cxablen, cxxablen, cyablen, cyyablen, clen;
1059  int ablen;
1060  int finlength;
1061  double adx, bdx, cdx, ady, bdy, cdy;
1062  double det, errbound;
1063  double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
1064  double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
1065  double bc[4], ca[4], ab[4];
1066  double bc3, ca3, ab3;
1067  double axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
1068  double bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
1069  double cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
1070  double abdet[64];
1071  double fin1[1152], fin2[1152];
1072  double *finnow, *finother, *finswap;
1073 
1074  int temp8len, temp16alen, temp16blen, temp16clen;
1075  int temp32alen, temp32blen, temp48len, temp64len;
1076  int axtbblen, axtcclen, aytbblen, aytcclen;
1077  int bxtaalen, bxtcclen, bytaalen, bytcclen;
1078  int cxtaalen, cxtbblen, cytaalen, cytbblen;
1079  int axtbclen = 0, aytbclen = 0, bxtcalen = 0;
1080  int bytcalen = 0, cxtablen = 0, cytablen = 0;
1081  int axtbctlen, bxtcatlen, cxtabtlen;
1082  int aytbctlen, bytcatlen, cytabtlen;
1083  int axtbcttlen, bxtcattlen, cxtabttlen;
1084  int aytbcttlen, bytcattlen, cytabttlen;
1085  int abtlen, bctlen, catlen;
1086  int abttlen, bcttlen, cattlen;
1087  double adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
1088  double adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
1089  double adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
1090  double aa[4], bb[4], cc[4];
1091  double aa3, bb3, cc3;
1092  double ti1, tj1;
1093  double ti0, tj0;
1094  double u[4], v[4];
1095  double u3, v3;
1096  double temp8[8], temp16a[16], temp16b[16], temp16c[16];
1097  double temp32a[32], temp32b[32], temp48[48], temp64[64];
1098  double axtbb[8], axtcc[8], aytbb[8], aytcc[8];
1099  double bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
1100  double cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
1101  double axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
1102  double axtbct[16], bxtcat[16], cxtabt[16];
1103  double aytbct[16], bytcat[16], cytabt[16];
1104  double axtbctt[8], aytbctt[8], bxtcatt[8];
1105  double bytcatt[8], cxtabtt[8], cytabtt[8];
1106  double abt[8], bct[8], cat[8];
1107  double abtt[4], bctt[4], catt[4];
1108  double abtt3, bctt3, catt3;
1109  double negate;
1110 
1111  double bvirt;
1112  double avirt, bround, around;
1113  double c;
1114  double abig, ahi, alo, bhi, blo;
1115  double err1, err2, err3;
1116  double _i, _j, _0;
1117 
1118  // Initialize all memory
1119  memset(bc, 0, 4 * sizeof(double));
1120  memset(ca, 0, 4 * sizeof(double));
1121  memset(ab, 0, 4 * sizeof(double));
1122 
1123  memset(axbc, 0, 8 * sizeof(double));
1124  memset(axxbc, 0, 16 * sizeof(double));
1125  memset(aybc, 0, 8 * sizeof(double));
1126  memset(ayybc, 0, 16 * sizeof(double));
1127  memset(adet, 0, 32 * sizeof(double));
1128 
1129  memset(bxca, 0, 8 * sizeof(double));
1130  memset(bxxca, 0, 16 * sizeof(double));
1131  memset(byca, 0, 8 * sizeof(double));
1132  memset(byyca, 0, 16 * sizeof(double));
1133  memset(bdet, 0, 32 * sizeof(double));
1134 
1135  memset(cxab, 0, 8 * sizeof(double));
1136  memset(cxxab, 0, 16 * sizeof(double));
1137  memset(cyab, 0, 8 * sizeof(double));
1138  memset(cyyab, 0, 16 * sizeof(double));
1139  memset(cdet, 0, 32 * sizeof(double));
1140 
1141  memset(abdet, 0, 64 * sizeof(double));
1142  memset(fin1, 0, 1152 * sizeof(double));
1143  memset(fin2, 0, 1152 * sizeof(double));
1144 
1145  memset(aa, 0, 4 * sizeof(double));
1146  memset(bb, 0, 4 * sizeof(double));
1147  memset(cc, 0, 4 * sizeof(double));
1148 
1149  memset(u, 0, 4 * sizeof(double));
1150  memset(v, 0, 4 * sizeof(double));
1151 
1152  memset(temp8, 0, 8 * sizeof(double));
1153  memset(temp16a, 0, 16 * sizeof(double));
1154  memset(temp16b, 0, 16 * sizeof(double));
1155  memset(temp16c, 0, 16 * sizeof(double));
1156 
1157  memset(temp32a, 0, 32 * sizeof(double));
1158  memset(temp32b, 0, 32 * sizeof(double));
1159  memset(temp48, 0, 48 * sizeof(double));
1160  memset(temp64, 0, 64 * sizeof(double));
1161 
1162  memset(axtbb, 0, 8 * sizeof(double));
1163  memset(axtcc, 0, 8 * sizeof(double));
1164  memset(aytbb, 0, 8 * sizeof(double));
1165  memset(aytcc, 0, 8 * sizeof(double));
1166 
1167  memset(bxtaa, 0, 8 * sizeof(double));
1168  memset(bxtcc, 0, 8 * sizeof(double));
1169  memset(bytaa, 0, 8 * sizeof(double));
1170  memset(bytcc, 0, 8 * sizeof(double));
1171 
1172  memset(cxtaa, 0, 8 * sizeof(double));
1173  memset(cxtbb, 0, 8 * sizeof(double));
1174  memset(cytaa, 0, 8 * sizeof(double));
1175  memset(cytbb, 0, 8 * sizeof(double));
1176 
1177  memset(axtbc, 0, 8 * sizeof(double));
1178  memset(aytbc, 0, 8 * sizeof(double));
1179  memset(bxtca, 0, 8 * sizeof(double));
1180  memset(bytca, 0, 8 * sizeof(double));
1181  memset(cxtab, 0, 8 * sizeof(double));
1182  memset(cytab, 0, 8 * sizeof(double));
1183 
1184  memset(axtbct, 0, 16 * sizeof(double));
1185  memset(bxtcat, 0, 16 * sizeof(double));
1186  memset(cxtabt, 0, 16 * sizeof(double));
1187 
1188  memset(aytbct, 0, 16 * sizeof(double));
1189  memset(bytcat, 0, 16 * sizeof(double));
1190  memset(cytabt, 0, 16 * sizeof(double));
1191 
1192  memset(axtbctt, 0, 8 * sizeof(double));
1193  memset(aytbctt, 0, 8 * sizeof(double));
1194  memset(bxtcatt, 0, 8 * sizeof(double));
1195 
1196  memset(bytcatt, 0, 8 * sizeof(double));
1197  memset(cxtabtt, 0, 8 * sizeof(double));
1198  memset(cytabtt, 0, 8 * sizeof(double));
1199 
1200  memset(abt, 0, 8 * sizeof(double));
1201  memset(bct, 0, 8 * sizeof(double));
1202  memset(cat, 0, 8 * sizeof(double));
1203 
1204  memset(abtt, 0, 4 * sizeof(double));
1205  memset(bctt, 0, 4 * sizeof(double));
1206  memset(catt, 0, 4 * sizeof(double));
1207 
1208  adx = (double)(pa[0] - pd[0]);
1209  bdx = (double)(pb[0] - pd[0]);
1210  cdx = (double)(pc[0] - pd[0]);
1211  ady = (double)(pa[1] - pd[1]);
1212  bdy = (double)(pb[1] - pd[1]);
1213  cdy = (double)(pc[1] - pd[1]);
1214 
1215  Two_Product(t.m_splitter, bdx, cdy, bdxcdy1, bdxcdy0);
1216  Two_Product(t.m_splitter, cdx, bdy, cdxbdy1, cdxbdy0);
1217  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
1218  bc[3] = bc3;
1219  axbclen = triScaleExpansionZeroElim(4, bc, adx, axbc, t);
1220  axxbclen = triScaleExpansionZeroElim(axbclen, axbc, adx, axxbc, t);
1221  aybclen = triScaleExpansionZeroElim(4, bc, ady, aybc, t);
1222  ayybclen = triScaleExpansionZeroElim(aybclen, aybc, ady, ayybc, t);
1223  alen = triFastExpansionSumZeroElim(axxbclen, axxbc, ayybclen, ayybc, adet);
1224 
1225  Two_Product(t.m_splitter, cdx, ady, cdxady1, cdxady0);
1226  Two_Product(t.m_splitter, adx, cdy, adxcdy1, adxcdy0);
1227  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
1228  ca[3] = ca3;
1229  bxcalen = triScaleExpansionZeroElim(4, ca, bdx, bxca, t);
1230  bxxcalen = triScaleExpansionZeroElim(bxcalen, bxca, bdx, bxxca, t);
1231  bycalen = triScaleExpansionZeroElim(4, ca, bdy, byca, t);
1232  byycalen = triScaleExpansionZeroElim(bycalen, byca, bdy, byyca, t);
1233  blen = triFastExpansionSumZeroElim(bxxcalen, bxxca, byycalen, byyca, bdet);
1234 
1235  Two_Product(t.m_splitter, adx, bdy, adxbdy1, adxbdy0);
1236  Two_Product(t.m_splitter, bdx, ady, bdxady1, bdxady0);
1237  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
1238  ab[3] = ab3;
1239  cxablen = triScaleExpansionZeroElim(4, ab, cdx, cxab, t);
1240  cxxablen = triScaleExpansionZeroElim(cxablen, cxab, cdx, cxxab, t);
1241  cyablen = triScaleExpansionZeroElim(4, ab, cdy, cyab, t);
1242  cyyablen = triScaleExpansionZeroElim(cyablen, cyab, cdy, cyyab, t);
1243  clen = triFastExpansionSumZeroElim(cxxablen, cxxab, cyyablen, cyyab, cdet);
1244 
1245  ablen = triFastExpansionSumZeroElim(alen, adet, blen, bdet, abdet);
1246  finlength = triFastExpansionSumZeroElim(ablen, abdet, clen, cdet, fin1);
1247 
1248  det = triEstimate(finlength, fin1);
1249  errbound = t.m_iccerrboundB * permanent;
1250  if ((det >= errbound) || (-det >= errbound))
1251  return det;
1252 
1253  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
1254  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
1255  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
1256  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
1257  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
1258  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
1259  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) && (adytail == 0.0) &&
1260  (bdytail == 0.0) && (cdytail == 0.0))
1261  {
1262  return det;
1263  }
1264 
1265  errbound = t.m_iccerrboundC * permanent + t.m_resulterrbound * fabs(det);
1266  det +=
1267  ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail)) +
1268  2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +
1269  ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail)) +
1270  2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +
1271  ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail)) +
1272  2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
1273  if ((det >= errbound) || (-det >= errbound))
1274  return det;
1275 
1276  finnow = fin1;
1277  finother = fin2;
1278 
1279  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) || (cdytail != 0.0))
1280  {
1281  Square(t.m_splitter, adx, adxadx1, adxadx0);
1282  Square(t.m_splitter, ady, adyady1, adyady0);
1283  Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
1284  aa[3] = aa3;
1285  }
1286  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) || (adytail != 0.0))
1287  {
1288  Square(t.m_splitter, bdx, bdxbdx1, bdxbdx0);
1289  Square(t.m_splitter, bdy, bdybdy1, bdybdy0);
1290  Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
1291  bb[3] = bb3;
1292  }
1293  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) || (bdytail != 0.0))
1294  {
1295  Square(t.m_splitter, cdx, cdxcdx1, cdxcdx0);
1296  Square(t.m_splitter, cdy, cdycdy1, cdycdy0);
1297  Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
1298  cc[3] = cc3;
1299  }
1300 
1301  if (adxtail != 0.0)
1302  {
1303  axtbclen = triScaleExpansionZeroElim(4, bc, adxtail, axtbc, t);
1304  temp16alen = triScaleExpansionZeroElim(axtbclen, axtbc, 2.0 * adx, temp16a, t);
1305 
1306  axtcclen = triScaleExpansionZeroElim(4, cc, adxtail, axtcc, t);
1307  temp16blen = triScaleExpansionZeroElim(axtcclen, axtcc, bdy, temp16b, t);
1308 
1309  axtbblen = triScaleExpansionZeroElim(4, bb, adxtail, axtbb, t);
1310  temp16clen = triScaleExpansionZeroElim(axtbblen, axtbb, -cdy, temp16c, t);
1311 
1312  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1313  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1314  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1315  finswap = finnow;
1316  finnow = finother;
1317  finother = finswap;
1318  }
1319  if (adytail != 0.0)
1320  {
1321  aytbclen = triScaleExpansionZeroElim(4, bc, adytail, aytbc, t);
1322  temp16alen = triScaleExpansionZeroElim(aytbclen, aytbc, 2.0 * ady, temp16a, t);
1323 
1324  aytbblen = triScaleExpansionZeroElim(4, bb, adytail, aytbb, t);
1325  temp16blen = triScaleExpansionZeroElim(aytbblen, aytbb, cdx, temp16b, t);
1326 
1327  aytcclen = triScaleExpansionZeroElim(4, cc, adytail, aytcc, t);
1328  temp16clen = triScaleExpansionZeroElim(aytcclen, aytcc, -bdx, temp16c, t);
1329 
1330  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1331  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1332  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1333  finswap = finnow;
1334  finnow = finother;
1335  finother = finswap;
1336  }
1337  if (bdxtail != 0.0)
1338  {
1339  bxtcalen = triScaleExpansionZeroElim(4, ca, bdxtail, bxtca, t);
1340  temp16alen = triScaleExpansionZeroElim(bxtcalen, bxtca, 2.0 * bdx, temp16a, t);
1341 
1342  bxtaalen = triScaleExpansionZeroElim(4, aa, bdxtail, bxtaa, t);
1343  temp16blen = triScaleExpansionZeroElim(bxtaalen, bxtaa, cdy, temp16b, t);
1344 
1345  bxtcclen = triScaleExpansionZeroElim(4, cc, bdxtail, bxtcc, t);
1346  temp16clen = triScaleExpansionZeroElim(bxtcclen, bxtcc, -ady, temp16c, t);
1347 
1348  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1349  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1350  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1351  finswap = finnow;
1352  finnow = finother;
1353  finother = finswap;
1354  }
1355  if (bdytail != 0.0)
1356  {
1357  bytcalen = triScaleExpansionZeroElim(4, ca, bdytail, bytca, t);
1358  temp16alen = triScaleExpansionZeroElim(bytcalen, bytca, 2.0 * bdy, temp16a, t);
1359 
1360  bytcclen = triScaleExpansionZeroElim(4, cc, bdytail, bytcc, t);
1361  temp16blen = triScaleExpansionZeroElim(bytcclen, bytcc, adx, temp16b, t);
1362 
1363  bytaalen = triScaleExpansionZeroElim(4, aa, bdytail, bytaa, t);
1364  temp16clen = triScaleExpansionZeroElim(bytaalen, bytaa, -cdx, temp16c, t);
1365 
1366  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1367  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1368  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1369  finswap = finnow;
1370  finnow = finother;
1371  finother = finswap;
1372  }
1373  if (cdxtail != 0.0)
1374  {
1375  cxtablen = triScaleExpansionZeroElim(4, ab, cdxtail, cxtab, t);
1376  temp16alen = triScaleExpansionZeroElim(cxtablen, cxtab, 2.0 * cdx, temp16a, t);
1377 
1378  cxtbblen = triScaleExpansionZeroElim(4, bb, cdxtail, cxtbb, t);
1379  temp16blen = triScaleExpansionZeroElim(cxtbblen, cxtbb, ady, temp16b, t);
1380 
1381  cxtaalen = triScaleExpansionZeroElim(4, aa, cdxtail, cxtaa, t);
1382  temp16clen = triScaleExpansionZeroElim(cxtaalen, cxtaa, -bdy, temp16c, t);
1383 
1384  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1385  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1386  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1387  finswap = finnow;
1388  finnow = finother;
1389  finother = finswap;
1390  }
1391  if (cdytail != 0.0)
1392  {
1393  cytablen = triScaleExpansionZeroElim(4, ab, cdytail, cytab, t);
1394  temp16alen = triScaleExpansionZeroElim(cytablen, cytab, 2.0 * cdy, temp16a, t);
1395 
1396  cytaalen = triScaleExpansionZeroElim(4, aa, cdytail, cytaa, t);
1397  temp16blen = triScaleExpansionZeroElim(cytaalen, cytaa, bdx, temp16b, t);
1398 
1399  cytbblen = triScaleExpansionZeroElim(4, bb, cdytail, cytbb, t);
1400  temp16clen = triScaleExpansionZeroElim(cytbblen, cytbb, -adx, temp16c, t);
1401 
1402  temp32alen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
1403  temp48len = triFastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
1404  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1405  finswap = finnow;
1406  finnow = finother;
1407  finother = finswap;
1408  }
1409 
1410  if ((adxtail != 0.0) || (adytail != 0.0))
1411  {
1412  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) || (cdytail != 0.0))
1413  {
1414  Two_Product(t.m_splitter, bdxtail, cdy, ti1, ti0);
1415  Two_Product(t.m_splitter, bdx, cdytail, tj1, tj0);
1416  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1417  u[3] = u3;
1418  negate = -bdy;
1419  Two_Product(t.m_splitter, cdxtail, negate, ti1, ti0);
1420  negate = -bdytail;
1421  Two_Product(t.m_splitter, cdx, negate, tj1, tj0);
1422  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1423  v[3] = v3;
1424  bctlen = triFastExpansionSumZeroElim(4, u, 4, v, bct);
1425 
1426  Two_Product(t.m_splitter, bdxtail, cdytail, ti1, ti0);
1427  Two_Product(t.m_splitter, cdxtail, bdytail, tj1, tj0);
1428  Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
1429  bctt[3] = bctt3;
1430  bcttlen = 4;
1431  }
1432  else
1433  {
1434  bct[0] = 0.0;
1435  bctlen = 1;
1436  bctt[0] = 0.0;
1437  bcttlen = 1;
1438  }
1439 
1440  if (adxtail != 0.0)
1441  {
1442  temp16alen = triScaleExpansionZeroElim(axtbclen, axtbc, adxtail, temp16a, t);
1443  axtbctlen = triScaleExpansionZeroElim(bctlen, bct, adxtail, axtbct, t);
1444  temp32alen = triScaleExpansionZeroElim(axtbctlen, axtbct, 2.0 * adx, temp32a, t);
1445  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1446  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1447  finswap = finnow;
1448  finnow = finother;
1449  finother = finswap;
1450  if (bdytail != 0.0)
1451  {
1452  temp8len = triScaleExpansionZeroElim(4, cc, adxtail, temp8, t);
1453  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a, t);
1454  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1455  finswap = finnow;
1456  finnow = finother;
1457  finother = finswap;
1458  }
1459  if (cdytail != 0.0)
1460  {
1461  temp8len = triScaleExpansionZeroElim(4, bb, -adxtail, temp8, t);
1462  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a, t);
1463  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1464  finswap = finnow;
1465  finnow = finother;
1466  finother = finswap;
1467  }
1468 
1469  temp32alen = triScaleExpansionZeroElim(axtbctlen, axtbct, adxtail, temp32a, t);
1470  axtbcttlen = triScaleExpansionZeroElim(bcttlen, bctt, adxtail, axtbctt, t);
1471  temp16alen = triScaleExpansionZeroElim(axtbcttlen, axtbctt, 2.0 * adx, temp16a, t);
1472  temp16blen = triScaleExpansionZeroElim(axtbcttlen, axtbctt, adxtail, temp16b, t);
1473  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1474  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1475  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1476  finswap = finnow;
1477  finnow = finother;
1478  finother = finswap;
1479  }
1480  if (adytail != 0.0)
1481  {
1482  temp16alen = triScaleExpansionZeroElim(aytbclen, aytbc, adytail, temp16a, t);
1483  aytbctlen = triScaleExpansionZeroElim(bctlen, bct, adytail, aytbct, t);
1484  temp32alen = triScaleExpansionZeroElim(aytbctlen, aytbct, 2.0 * ady, temp32a, t);
1485  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1486  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1487  finswap = finnow;
1488  finnow = finother;
1489  finother = finswap;
1490 
1491  temp32alen = triScaleExpansionZeroElim(aytbctlen, aytbct, adytail, temp32a, t);
1492  aytbcttlen = triScaleExpansionZeroElim(bcttlen, bctt, adytail, aytbctt, t);
1493  temp16alen = triScaleExpansionZeroElim(aytbcttlen, aytbctt, 2.0 * ady, temp16a, t);
1494  temp16blen = triScaleExpansionZeroElim(aytbcttlen, aytbctt, adytail, temp16b, t);
1495  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1496  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1497  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1498  finswap = finnow;
1499  finnow = finother;
1500  finother = finswap;
1501  }
1502  }
1503  if ((bdxtail != 0.0) || (bdytail != 0.0))
1504  {
1505  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) || (adytail != 0.0))
1506  {
1507  Two_Product(t.m_splitter, cdxtail, ady, ti1, ti0);
1508  Two_Product(t.m_splitter, cdx, adytail, tj1, tj0);
1509  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1510  u[3] = u3;
1511  negate = -cdy;
1512  Two_Product(t.m_splitter, adxtail, negate, ti1, ti0);
1513  negate = -cdytail;
1514  Two_Product(t.m_splitter, adx, negate, tj1, tj0);
1515  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1516  v[3] = v3;
1517  catlen = triFastExpansionSumZeroElim(4, u, 4, v, cat);
1518 
1519  Two_Product(t.m_splitter, cdxtail, adytail, ti1, ti0);
1520  Two_Product(t.m_splitter, adxtail, cdytail, tj1, tj0);
1521  Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
1522  catt[3] = catt3;
1523  cattlen = 4;
1524  }
1525  else
1526  {
1527  cat[0] = 0.0;
1528  catlen = 1;
1529  catt[0] = 0.0;
1530  cattlen = 1;
1531  }
1532 
1533  if (bdxtail != 0.0)
1534  {
1535  temp16alen = triScaleExpansionZeroElim(bxtcalen, bxtca, bdxtail, temp16a, t);
1536  bxtcatlen = triScaleExpansionZeroElim(catlen, cat, bdxtail, bxtcat, t);
1537  temp32alen = triScaleExpansionZeroElim(bxtcatlen, bxtcat, 2.0 * bdx, temp32a, t);
1538  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1539  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1540  finswap = finnow;
1541  finnow = finother;
1542  finother = finswap;
1543  if (cdytail != 0.0)
1544  {
1545  temp8len = triScaleExpansionZeroElim(4, aa, bdxtail, temp8, t);
1546  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a, t);
1547  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1548  finswap = finnow;
1549  finnow = finother;
1550  finother = finswap;
1551  }
1552  if (adytail != 0.0)
1553  {
1554  temp8len = triScaleExpansionZeroElim(4, cc, -bdxtail, temp8, t);
1555  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a, t);
1556  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1557  finswap = finnow;
1558  finnow = finother;
1559  finother = finswap;
1560  }
1561 
1562  temp32alen = triScaleExpansionZeroElim(bxtcatlen, bxtcat, bdxtail, temp32a, t);
1563  bxtcattlen = triScaleExpansionZeroElim(cattlen, catt, bdxtail, bxtcatt, t);
1564  temp16alen = triScaleExpansionZeroElim(bxtcattlen, bxtcatt, 2.0 * bdx, temp16a, t);
1565  temp16blen = triScaleExpansionZeroElim(bxtcattlen, bxtcatt, bdxtail, temp16b, t);
1566  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1567  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1568  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1569  finswap = finnow;
1570  finnow = finother;
1571  finother = finswap;
1572  }
1573  if (bdytail != 0.0)
1574  {
1575  temp16alen = triScaleExpansionZeroElim(bytcalen, bytca, bdytail, temp16a, t);
1576  bytcatlen = triScaleExpansionZeroElim(catlen, cat, bdytail, bytcat, t);
1577  temp32alen = triScaleExpansionZeroElim(bytcatlen, bytcat, 2.0 * bdy, temp32a, t);
1578  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1579  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1580  finswap = finnow;
1581  finnow = finother;
1582  finother = finswap;
1583 
1584  temp32alen = triScaleExpansionZeroElim(bytcatlen, bytcat, bdytail, temp32a, t);
1585  bytcattlen = triScaleExpansionZeroElim(cattlen, catt, bdytail, bytcatt, t);
1586  temp16alen = triScaleExpansionZeroElim(bytcattlen, bytcatt, 2.0 * bdy, temp16a, t);
1587  temp16blen = triScaleExpansionZeroElim(bytcattlen, bytcatt, bdytail, temp16b, t);
1588  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1589  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1590  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1591  finswap = finnow;
1592  finnow = finother;
1593  finother = finswap;
1594  }
1595  }
1596  if ((cdxtail != 0.0) || (cdytail != 0.0))
1597  {
1598  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) || (bdytail != 0.0))
1599  {
1600  Two_Product(t.m_splitter, adxtail, bdy, ti1, ti0);
1601  Two_Product(t.m_splitter, adx, bdytail, tj1, tj0);
1602  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
1603  u[3] = u3;
1604  negate = -ady;
1605  Two_Product(t.m_splitter, bdxtail, negate, ti1, ti0);
1606  negate = -adytail;
1607  Two_Product(t.m_splitter, bdx, negate, tj1, tj0);
1608  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
1609  v[3] = v3;
1610  abtlen = triFastExpansionSumZeroElim(4, u, 4, v, abt);
1611 
1612  Two_Product(t.m_splitter, adxtail, bdytail, ti1, ti0);
1613  Two_Product(t.m_splitter, bdxtail, adytail, tj1, tj0);
1614  Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
1615  abtt[3] = abtt3;
1616  abttlen = 4;
1617  }
1618  else
1619  {
1620  abt[0] = 0.0;
1621  abtlen = 1;
1622  abtt[0] = 0.0;
1623  abttlen = 1;
1624  }
1625 
1626  if (cdxtail != 0.0)
1627  {
1628  temp16alen = triScaleExpansionZeroElim(cxtablen, cxtab, cdxtail, temp16a, t);
1629  cxtabtlen = triScaleExpansionZeroElim(abtlen, abt, cdxtail, cxtabt, t);
1630  temp32alen = triScaleExpansionZeroElim(cxtabtlen, cxtabt, 2.0 * cdx, temp32a, t);
1631  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1632  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1633  finswap = finnow;
1634  finnow = finother;
1635  finother = finswap;
1636  if (adytail != 0.0)
1637  {
1638  temp8len = triScaleExpansionZeroElim(4, bb, cdxtail, temp8, t);
1639  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a, t);
1640  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1641  finswap = finnow;
1642  finnow = finother;
1643  finother = finswap;
1644  }
1645  if (bdytail != 0.0)
1646  {
1647  temp8len = triScaleExpansionZeroElim(4, aa, -cdxtail, temp8, t);
1648  temp16alen = triScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a, t);
1649  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
1650  finswap = finnow;
1651  finnow = finother;
1652  finother = finswap;
1653  }
1654 
1655  temp32alen = triScaleExpansionZeroElim(cxtabtlen, cxtabt, cdxtail, temp32a, t);
1656  cxtabttlen = triScaleExpansionZeroElim(abttlen, abtt, cdxtail, cxtabtt, t);
1657  temp16alen = triScaleExpansionZeroElim(cxtabttlen, cxtabtt, 2.0 * cdx, temp16a, t);
1658  temp16blen = triScaleExpansionZeroElim(cxtabttlen, cxtabtt, cdxtail, temp16b, t);
1659  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1660  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1661  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1662  finswap = finnow;
1663  finnow = finother;
1664  finother = finswap;
1665  }
1666  if (cdytail != 0.0)
1667  {
1668  temp16alen = triScaleExpansionZeroElim(cytablen, cytab, cdytail, temp16a, t);
1669  cytabtlen = triScaleExpansionZeroElim(abtlen, abt, cdytail, cytabt, t);
1670  temp32alen = triScaleExpansionZeroElim(cytabtlen, cytabt, 2.0 * cdy, temp32a, t);
1671  temp48len = triFastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
1672  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
1673  finswap = finnow;
1674  finnow = finother;
1675  finother = finswap;
1676 
1677  temp32alen = triScaleExpansionZeroElim(cytabtlen, cytabt, cdytail, temp32a, t);
1678  cytabttlen = triScaleExpansionZeroElim(abttlen, abtt, cdytail, cytabtt, t);
1679  temp16alen = triScaleExpansionZeroElim(cytabttlen, cytabtt, 2.0 * cdy, temp16a, t);
1680  temp16blen = triScaleExpansionZeroElim(cytabttlen, cytabtt, cdytail, temp16b, t);
1681  temp32blen = triFastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
1682  temp64len = triFastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
1683  finlength = triFastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
1684  finswap = finnow;
1685  finnow = finother;
1686  finother = finswap;
1687  }
1688  }
1689 
1690  return finnow[finlength - 1];
1691 } // triInCircleAdapt
1692 //------------------------------------------------------------------------------
1693 // FUNCTION triInitTrianglePool
1695 // and initialize their memory pools.
1696 // NOTES This routine also computes the `highorderid', `elemattid',
1697 // indices used to find values within each triangle.
1698 // highorderid: index in each tri for extra nodes (above three)
1699 // associated with high order elements are found
1700 // There are 3 ptrs to other tris, 3 pts to corners,
1701 // & maybe 3 ptrs to shell edges before the extra nodes
1702 // elemattid: index in each tri for its attributes
1703 // where the index is measured in double
1704 //------------------------------------------------------------------------------
1705 static void triInitTrianglePool(TriVars& t)
1706 {
1707 #define TRIPERBLOCK 4092 /* # of tris allocated at once */
1708  int trisize, highorderid, elemattid;
1709  /* AKZ - we may be able to hack this based on no high order elements */
1710  highorderid = 6;
1711  /* # of bytes occupied by a triangle */
1712  trisize = (3 + (highorderid - 3)) * sizeof(Ttri);
1713  elemattid = (trisize + sizeof(double) - 1) / sizeof(double);
1714  /* Initialize triangle pool */
1715  triPoolInit(&t.m_triangles, trisize, TRIPERBLOCK, TRIPERBLOCK, 4);
1716  /* Initialize the "outer space" triangle */
1717  triDummyInit(t.m_triangles.itembytes, t);
1718 } // triInitTrianglePool
1719 //------------------------------------------------------------------------------
1720 // FUNCTION triMakeTriangle
1722 // NOTES
1723 //------------------------------------------------------------------------------
1724 static bool triMakeTriangle(Tedgetype newtedge, TriVars& t)
1725 {
1726  newtedge->tri = (Ttri*)triPoolAlloc(&t.m_triangles);
1727 
1728  /* Init the adjoining tris to be "outer space" */
1729  newtedge->tri[0] = (Ttri)t.m_dummytri;
1730  newtedge->tri[1] = (Ttri)t.m_dummytri;
1731  newtedge->tri[2] = (Ttri)t.m_dummytri;
1732  /* Three NULL vertex points. */
1733  newtedge->tri[3] = nullptr;
1734  newtedge->tri[4] = nullptr;
1735  newtedge->tri[5] = nullptr;
1736  newtedge->orient = 0;
1737  return true;
1738 } // triMakeNewTriangle
1739 //------------------------------------------------------------------------------
1740 // FUNCTION triMergeHulls
1742 // single Delaunay triangulation.
1743 // NOTES
1744 // This is similar to the algorithm given by Guibas and Stolfi, but uses
1745 // a triangle-based, rather than edge-based, data structure.
1746 //
1747 // The algorithm walks up the gap between the two triangulations, knitting
1748 // them together. As they are merged, some of their bounding triangles
1749 // are converted into real triangles of the triangulation. The procedure
1750 // pulls each hull's bounding triangles apart, then knits them together
1751 // like the teeth of two gears. The Delaunay property determines, at each
1752 // step, whether the next "tooth" is a bounding triangle of the left hull
1753 // or the right. When a bounding triangle becomes real, its apex is
1754 // changed from NULL to a real point.
1755 //
1756 // Only two new triangles need to be allocated. These become new bounding
1757 // triangles at the top and bottom of the seam. They are used to connect
1758 // the remaining bounding triangles (those that have not been converted
1759 // into real triangles) into a single fan.
1760 //
1761 // On entry, `farleft' and `innerleft' are bounding triangles of the left
1762 // triangulation. The origin of `farleft' is the leftmost vertex, and
1763 // the destination of `innerleft' is the rightmost vertex of the
1764 // triangulation. Similarly, `innerright' and `farright' are bounding
1765 // triangles of the right triangulation. The origin of `innerright' and
1766 // destination of `farright' are the leftmost and rightmost vertices.
1767 //
1768 // On completion, the origin of `farleft' is the leftmost vertex of the
1769 // merged triangulation, and the destination of `farright' is the rightmost
1770 // vertex.
1771 //------------------------------------------------------------------------------
1772 static bool triMergeHulls(Tedgetype farleft,
1773  Tedgetype innerleft,
1774  Tedgetype innerright,
1775  Tedgetype farright,
1776  int axis,
1777  TriVars& t)
1778 {
1779  int changemade, badedge, leftfinished, rightfinished;
1780  Tedge leftcand, rightcand, baseedge, nextedge;
1781  Tedge sidecasing, topcasing, outercasing, checkedge;
1782  Tpt innerleftdest, innerrightorg;
1783  Tpt innerleftapex, innerrightapex;
1784  Tpt farleftpt, farrightpt;
1785  Tpt farleftapex, farrightapex;
1786  Tpt lowerleft, lowerright;
1787  Tpt upperleft, upperright;
1788  Tpt nextapex, checkvertex;
1789  Ttri ptr; /* Temporary variable used by sym() */
1790  bool canMakeTriangles = true;
1791 
1792  dest(*innerleft, innerleftdest);
1793  apex(*innerleft, innerleftapex);
1794  org(*innerright, innerrightorg);
1795  apex(*innerright, innerrightapex);
1796  /* Special treatment for horizontal cuts */
1797  if (axis == 1)
1798  {
1799  org(*farleft, farleftpt);
1800  apex(*farleft, farleftapex);
1801  dest(*farright, farrightpt);
1802  apex(*farright, farrightapex);
1803  /* The pointers to the extremal points are shifted to point to the */
1804  /* topmost and bottommost point of each hull, rather than the */
1805  /* leftmost and rightmost points. */
1806  while (farleftapex[1] < farleftpt[1])
1807  {
1808  lnextself(*farleft);
1809  symself(*farleft);
1810  farleftpt = farleftapex;
1811  apex(*farleft, farleftapex);
1812  }
1813  sym(*innerleft, checkedge);
1814  apex(checkedge, checkvertex);
1815  while (checkvertex[1] > innerleftdest[1])
1816  {
1817  lnext(checkedge, *innerleft);
1818  innerleftapex = innerleftdest;
1819  innerleftdest = checkvertex;
1820  sym(*innerleft, checkedge);
1821  apex(checkedge, checkvertex);
1822  }
1823  while (innerrightapex[1] < innerrightorg[1])
1824  {
1825  lnextself(*innerright);
1826  symself(*innerright);
1827  innerrightorg = innerrightapex;
1828  apex(*innerright, innerrightapex);
1829  }
1830  sym(*farright, checkedge);
1831  apex(checkedge, checkvertex);
1832  while (checkvertex[1] > farrightpt[1])
1833  {
1834  lnext(checkedge, *farright);
1835  farrightapex = farrightpt;
1836  farrightpt = checkvertex;
1837  sym(*farright, checkedge);
1838  apex(checkedge, checkvertex);
1839  }
1840  }
1841  /* Find a line tangent to and below both hulls. */
1842  do
1843  {
1844  changemade = 0;
1845  /* Make innerleftdest the "bottommost" point
1846  * of the left hull. */
1847  if (triCounterClockwise(innerleftdest, innerleftapex, innerrightorg, t) > 0.0)
1848  {
1849  lprevself(*innerleft);
1850  symself(*innerleft);
1851  innerleftdest = innerleftapex;
1852  apex(*innerleft, innerleftapex);
1853  changemade = 1;
1854  }
1855  /* Make innerrightorg the "bottommost" point
1856  * of the right hull. */
1857  if (triCounterClockwise(innerrightapex, innerrightorg, innerleftdest, t) > 0.0)
1858  {
1859  lnextself(*innerright);
1860  symself(*innerright);
1861  innerrightorg = innerrightapex;
1862  apex(*innerright, innerrightapex);
1863  changemade = 1;
1864  }
1865  } while (changemade);
1866  /* Find the 2 candidates to be next "gear tooth" */
1867  sym(*innerleft, leftcand);
1868  sym(*innerright, rightcand);
1869  /* Create the bottom new bounding triangle. */
1870  canMakeTriangles = triMakeTriangle(&baseedge, t);
1871  if (!canMakeTriangles)
1872  {
1873  return false;
1874  }
1875  /* Connect it to the bounding boxes of the left
1876  * and right triangulations. */
1877  bond(baseedge, *innerleft);
1878  lnextself(baseedge);
1879  bond(baseedge, *innerright);
1880  lnextself(baseedge);
1881  setorg(baseedge, innerrightorg);
1882  setdest(baseedge, innerleftdest);
1883  /* Apex is intentionally left NULL. */
1884  /* Fix the extreme triangles if necessary. */
1885  org(*farleft, farleftpt);
1886  if (innerleftdest == farleftpt)
1887  {
1888  lnext(baseedge, *farleft);
1889  }
1890  dest(*farright, farrightpt);
1891  if (innerrightorg == farrightpt)
1892  {
1893  lprev(baseedge, *farright);
1894  }
1895  /* The vertices of the current knitting edge. */
1896  lowerleft = innerleftdest;
1897  lowerright = innerrightorg;
1898  /* The candidate vertices for knitting. */
1899  apex(leftcand, upperleft);
1900  apex(rightcand, upperright);
1901  /* Walk up the gap between the two triangulations,
1902  * knitting them together. */
1903  for (;;)
1904  {
1905  /* Have we reached the top? (This isn't quite the right question, */
1906  /* because even though the left triangulation might seem finished now, */
1907  /* moving up on the right triangulation might reveal a new point of */
1908  /* the left triangulation. And vice-versa.) */
1909  leftfinished = triCounterClockwise(upperleft, lowerleft, lowerright, t) <= 0.0;
1910  rightfinished = triCounterClockwise(upperright, lowerleft, lowerright, t) <= 0.0;
1911  if (leftfinished && rightfinished)
1912  {
1913  /* Create the top new bounding triangle. */
1914  canMakeTriangles = triMakeTriangle(&nextedge, t);
1915  if (!canMakeTriangles)
1916  {
1917  return false;
1918  }
1919  setorg(nextedge, lowerleft);
1920  setdest(nextedge, lowerright);
1921  /* Apex is intentionally left NULL. */
1922  /* Connect it to the bounding boxes of the
1923  * two triangulations. */
1924  bond(nextedge, baseedge);
1925  lnextself(nextedge);
1926  bond(nextedge, rightcand);
1927  lnextself(nextedge);
1928  bond(nextedge, leftcand);
1929  /* Special treatment for horizontal cuts. */
1930  if (axis == 1)
1931  {
1932  org(*farleft, farleftpt);
1933  apex(*farleft, farleftapex);
1934  dest(*farright, farrightpt);
1935  apex(*farright, farrightapex);
1936  sym(*farleft, checkedge);
1937  apex(checkedge, checkvertex);
1938  /* The pointers to the extremal points are restored to the leftmost */
1939  /* and rightmost points (rather than topmost and bottommost). */
1940  while (checkvertex[0] < farleftpt[0])
1941  {
1942  lprev(checkedge, *farleft);
1943  farleftapex = farleftpt;
1944  farleftpt = checkvertex;
1945  sym(*farleft, checkedge);
1946  apex(checkedge, checkvertex);
1947  }
1948  while (farrightapex[0] > farrightpt[0])
1949  {
1950  lprevself(*farright);
1951  symself(*farright);
1952  farrightpt = farrightapex;
1953  apex(*farright, farrightapex);
1954  }
1955  }
1956  return true;
1957  }
1958  /* Consider eliminating edges from the left
1959  * triangulation. */
1960  if (!leftfinished)
1961  {
1962  /* What vertex would be exposed if an edge
1963  * were deleted? */
1964  lprev(leftcand, nextedge);
1965  symself(nextedge);
1966  apex(nextedge, nextapex);
1967  /* If nextapex is NULL, then no vertex would be exposed; the */
1968  /* triangulation would have been eaten right through. */
1969  if (nextapex != nullptr)
1970  {
1971  /* Check whether the edge is Delaunay. */
1972  badedge = triInCircle(lowerleft, lowerright, upperleft, nextapex, t) > 0.0;
1973  while (badedge)
1974  {
1975  /* Eliminate the edge with an edge flip. As a result, the */
1976  /* left triangulation will have one more boundary triangle. */
1977  lnextself(nextedge);
1978  sym(nextedge, topcasing);
1979  lnextself(nextedge);
1980  sym(nextedge, sidecasing);
1981  bond(nextedge, topcasing);
1982  bond(leftcand, sidecasing);
1983  lnextself(leftcand);
1984  sym(leftcand, outercasing);
1985  lprevself(nextedge);
1986  bond(nextedge, outercasing);
1987  /* Correct vertices to reflect the edge flip. */
1988  setorg(leftcand, lowerleft);
1989  setdest(leftcand, nullptr);
1990  setapex(leftcand, nextapex);
1991  setorg(nextedge, nullptr);
1992  setdest(nextedge, upperleft);
1993  setapex(nextedge, nextapex);
1994  /* Consider the newly exposed vertex. */
1995  upperleft = nextapex;
1996  /* What vertex would be exposed if another
1997  * edge were deleted? */
1998  tedgecopy(sidecasing, nextedge);
1999  apex(nextedge, nextapex);
2000  if (nextapex != nullptr)
2001  {
2002  /* Check whether the edge is Delaunay. */
2003  badedge = triInCircle(lowerleft, lowerright, upperleft, nextapex, t) > 0.0;
2004  }
2005  else
2006  {
2007  /* Avoid eating right through the triangulation */
2008  badedge = 0;
2009  }
2010  }
2011  }
2012  }
2013  /* Consider eliminating edges from the
2014  * right triangulation. */
2015  if (!rightfinished)
2016  {
2017  /* What vertex would be exposed if an edge
2018  * were deleted? */
2019  lnext(rightcand, nextedge);
2020  symself(nextedge);
2021  apex(nextedge, nextapex);
2022  /* If nextapex is NULL, then no vertex would
2023  * be exposed; the triangulation would have been
2024  * eaten right through. */
2025  if (nextapex != nullptr)
2026  {
2027  /* Check whether the edge is Delaunay. */
2028  badedge = triInCircle(lowerleft, lowerright, upperright, nextapex, t) > 0.0;
2029  while (badedge)
2030  {
2031  /* Eliminate the edge with an edge flip.
2032  * As a result, the right triangulation will
2033  * have one more boundary triangle. */
2034  lprevself(nextedge);
2035  sym(nextedge, topcasing);
2036  lprevself(nextedge);
2037  sym(nextedge, sidecasing);
2038  bond(nextedge, topcasing);
2039  bond(rightcand, sidecasing);
2040  lprevself(rightcand);
2041  sym(rightcand, outercasing);
2042  lnextself(nextedge);
2043  bond(nextedge, outercasing);
2044  /* Correct vertices to reflect the edge flip. */
2045  setorg(rightcand, nullptr);
2046  setdest(rightcand, lowerright);
2047  setapex(rightcand, nextapex);
2048  setorg(nextedge, upperright);
2049  setdest(nextedge, nullptr);
2050  setapex(nextedge, nextapex);
2051  /* Consider the newly exposed vertex. */
2052  upperright = nextapex;
2053  /* What vertex would be exposed if another
2054  * edge were deleted? */
2055  tedgecopy(sidecasing, nextedge);
2056  apex(nextedge, nextapex);
2057  if (nextapex != nullptr)
2058  {
2059  /* Check whether the edge is Delaunay. */
2060  badedge = triInCircle(lowerleft, lowerright, upperright, nextapex, t) > 0.0;
2061  }
2062  else
2063  {
2064  /* Avoid eating right through the triangulation. */
2065  badedge = 0;
2066  }
2067  }
2068  }
2069  }
2070  if (leftfinished ||
2071  (!rightfinished && (triInCircle(upperleft, lowerleft, lowerright, upperright, t) > 0.0)))
2072  {
2073  /* Knit the triangulations, adding an edge
2074  * from `lowerleft' to `upperright' */
2075  bond(baseedge, rightcand);
2076  lprev(rightcand, baseedge);
2077  setdest(baseedge, lowerleft);
2078  lowerright = upperright;
2079  sym(baseedge, rightcand);
2080  apex(rightcand, upperright);
2081  }
2082  else
2083  {
2084  /* Knit the triangulations, adding an edge
2085  * from `upperleft' to `lowerright' */
2086  bond(baseedge, leftcand);
2087  lnext(leftcand, baseedge);
2088  setorg(baseedge, lowerright);
2089  lowerleft = upperleft;
2090  sym(baseedge, leftcand);
2091  apex(leftcand, upperleft);
2092  }
2093  }
2094 } // triMergeHulls
2095 //------------------------------------------------------------------------------
2096 // FUNCTION triNumberNodes
2098 // NOTES Each point is assigned a marker equal to its number.
2099 //------------------------------------------------------------------------------
2100 static void triNumberNodes(TriVars& t)
2101 {
2102  int pointnumber;
2103  Tpt pointloop;
2104 
2105  triTraversalInit(&t.m_points);
2106  pointloop = triPointTraverse(t);
2107  pointnumber = 1;
2108  while (pointloop != nullptr)
2109  {
2110  setpointmark(pointloop, pointnumber, t.m_pointmarkindex);
2111  pointloop = triPointTraverse(t);
2112  pointnumber++;
2113  }
2114 } // triNumberNodes
2115 //------------------------------------------------------------------------------
2116 // FUNCTION triPointMedian
2118 // of points so that the first `median' points occur
2119 // lexicographically before the remaining points.
2120 // NOTES
2121 // Uses the x-coordinate as the primary key if axis == 0; the y-coordinate
2122 // if axis == 1. Very similar to the triPointSort() procedure, but runs in
2123 // randomized linear time.
2124 //------------------------------------------------------------------------------
2125 static void triPointMedian(Tpt* sortarray, int arraysize, int median, int axis)
2126 {
2127  int left, right, pivot;
2128  double pivot1, pivot2;
2129  Tpt temp;
2130  /* Recursive base case. */
2131  if (arraysize == 2)
2132  {
2133  if ((sortarray[0][axis] > sortarray[1][axis]) ||
2134  ((sortarray[0][axis] == sortarray[1][axis]) &&
2135  (sortarray[0][1 - axis] > sortarray[1][1 - axis])))
2136  {
2137  temp = sortarray[1];
2138  sortarray[1] = sortarray[0];
2139  sortarray[0] = temp;
2140  }
2141  return;
2142  }
2143  else if (arraysize == 0)
2144  return;
2145  /* Choose a random pivot to split the array. */
2146  pivot = (int)triRandomnation((unsigned int)arraysize);
2147  pivot1 = sortarray[pivot][axis];
2148  pivot2 = sortarray[pivot][1 - axis];
2149  /* Split the array. */
2150  left = -1;
2151  right = arraysize;
2152  while (left < right)
2153  {
2154  /* Find a pt whose 'x' is > left */
2155  do
2156  {
2157  left++;
2158  } while ((left <= right) &&
2159  ((sortarray[left][axis] < pivot1) ||
2160  ((sortarray[left][axis] == pivot1) && (sortarray[left][1 - axis] < pivot2))));
2161  /* Find a pt whose 'x' is < right */
2162  do
2163  {
2164  right--;
2165  } while ((left <= right) &&
2166  ((sortarray[right][axis] > pivot1) ||
2167  ((sortarray[right][axis] == pivot1) && (sortarray[right][1 - axis] > pivot2))));
2168  if (left < right)
2169  {
2170  /* Swap the left and right points. */
2171  temp = sortarray[left];
2172  sortarray[left] = sortarray[right];
2173  sortarray[right] = temp;
2174  }
2175  }
2176  /* Recurse - only one condition can be true */
2177  if (left > median)
2178  {
2179  /* Recursively shuffle the left subset. */
2180  triPointMedian(sortarray, left, median, axis);
2181  }
2182  if (right < median - 1)
2183  {
2184  /* Recursively shuffle the right subset. */
2185  triPointMedian(&sortarray[right + 1], arraysize - right - 1, median - right - 1, axis);
2186  }
2187 } // triPointMedian
2188 //------------------------------------------------------------------------------
2189 // FUNCTION triPointSort
2191 // a secondary key.
2192 // NOTES
2193 // Uses quicksort. Randomized O(n log n) time. No, I did not make any of
2194 // the usual quicksort mistakes.
2195 //------------------------------------------------------------------------------
2196 static void triPointSort(Tpt* sortarray, int arraysize)
2197 {
2198  int left, right, pivot;
2199  double pivotx, pivoty;
2200  Tpt temp;
2201  /* Recursive base case. */
2202  if (arraysize == 2)
2203  {
2204  if ((sortarray[0][0] > sortarray[1][0]) ||
2205  ((sortarray[0][0] == sortarray[1][0]) && (sortarray[0][1] > sortarray[1][1])))
2206  {
2207  temp = sortarray[1];
2208  sortarray[1] = sortarray[0];
2209  sortarray[0] = temp;
2210  }
2211  return;
2212  }
2213  else if (arraysize == 0)
2214  return;
2215  /* Choose a random pivot to split the array. */
2216  pivot = (int)triRandomnation((unsigned int)arraysize);
2217  pivotx = sortarray[pivot][0];
2218  pivoty = sortarray[pivot][1];
2219  /* Split the array. */
2220  left = -1;
2221  right = arraysize;
2222  while (left < right)
2223  {
2224  /* Find a pt whose 'x' is > left */
2225  do
2226  {
2227  left++;
2228  } while ((left <= right) && ((sortarray[left][0] < pivotx) || ((sortarray[left][0] == pivotx) &&
2229  (sortarray[left][1] < pivoty))));
2230  /* Find a pt whose 'x' is < right */
2231  do
2232  {
2233  right--;
2234  } while ((left <= right) &&
2235  ((sortarray[right][0] > pivotx) ||
2236  ((sortarray[right][0] == pivotx) && (sortarray[right][1] > pivoty))));
2237  if (left < right)
2238  {
2239  /* Swap the left and right points. */
2240  temp = sortarray[left];
2241  sortarray[left] = sortarray[right];
2242  sortarray[right] = temp;
2243  }
2244  }
2245  if (left > 1)
2246  {
2247  /* Recursively sort the left subset. */
2248  triPointSort(sortarray, left);
2249  }
2250  if (right < arraysize - 2)
2251  {
2252  /* Recursively sort the right subset. */
2253  triPointSort(&sortarray[right + 1], arraysize - right - 1);
2254  }
2255 } // triPointSort
2256 //------------------------------------------------------------------------------
2257 // FUNCTION triPointTraverse
2259 // NOTES
2260 //------------------------------------------------------------------------------
2261 static Tpt triPointTraverse(TriVars& t)
2262 {
2263  Tpt newpoint;
2264 
2265  do
2266  {
2267  newpoint = (Tpt)triTraverse(&t.m_points);
2268  if (newpoint == nullptr)
2269  return nullptr;
2270  } while (pointmark(newpoint, t.m_pointmarkindex) == -999); // Skip dead ones.
2271  return newpoint;
2272 } // triPointTraverse
2273 //------------------------------------------------------------------------------
2274 // FUNCTION triPoolAlloc
2276 // NOTES
2277 //------------------------------------------------------------------------------
2278 static int* triPoolAlloc(Tmemtype pool)
2279 {
2280  int *newitem, **newblock;
2281  unsigned long long alignptr;
2282  /* use dead item before allocating a fresh one */
2283  if (pool->deaditemstack != nullptr)
2284  {
2285  newitem = pool->deaditemstack; /* Take first item in list */
2286  pool->deaditemstack = *(int**)pool->deaditemstack;
2287  }
2288  else
2289  {
2290  /* see if a new block must be allocated */
2291  if (pool->unallocateditems == 0)
2292  {
2293  if (*(pool->nowblock) == nullptr)
2294  {
2295  /* get a new block, add to linked list of blocks */
2296  newblock =
2297  (int**)malloc(pool->itemsperblock * pool->itembytes + sizeof(int*) + pool->alignbytes);
2298  if (newblock == nullptr)
2299  {
2300  std::string s = "malloc failed: ";
2301  s += __FUNCTION__;
2302  XM_LOG(xmlog::error, s);
2303  return nullptr;
2304  }
2305  *(pool->nowblock) = (int*)newblock;
2306  /* next block pointer is NULL. */
2307  *newblock = nullptr;
2308  }
2309  /* Move to the new block. */
2310  pool->nowblock = (int**)*(pool->nowblock);
2311  /* Find 1st item in pool. Inc by sizeof(int*) */
2312  alignptr = (unsigned long long)(pool->nowblock + 1);
2313  /* Align item on an `alignbytes'-byte boundary */
2314  pool->nextitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2315  (alignptr % (unsigned long long)pool->alignbytes));
2316  /* all items in block are unallocated */
2317  pool->unallocateditems = pool->itemsperblock;
2318  }
2319  /* Allocate a new item */
2320  newitem = pool->nextitem;
2321  /* Advance `nextitem' ptr to next item in block */
2322  pool->nextitem = (int*)((char*)pool->nextitem + pool->itembytes);
2323 
2324  pool->unallocateditems--;
2325  pool->maxitems++;
2326  }
2327  pool->items++;
2328  return newitem;
2329 } // triPoolAlloc
2330 //------------------------------------------------------------------------------
2331 // FUNCTION triPoolDealloc
2333 // NOTES The deallocated space is stored in a queue for later reuse.
2334 //------------------------------------------------------------------------------
2335 static void triPoolDealloc(Tmemtype pool, int* dyingitem)
2336 {
2337  /* Push freshly killed item onto stack. */
2338  *((int**)dyingitem) = pool->deaditemstack;
2339  pool->deaditemstack = dyingitem;
2340  pool->items--;
2341 } // triPoolDealloc
2342 //------------------------------------------------------------------------------
2343 // FUNCTION triPoolDeinit
2345 // NOTES
2346 //------------------------------------------------------------------------------
2347 static void triPoolDeinit(Tmemtype pool)
2348 {
2349  while (pool && pool->firstblock != nullptr)
2350  {
2351  pool->nowblock = (int**)*(pool->firstblock);
2352  free(pool->firstblock);
2353  pool->firstblock = pool->nowblock;
2354  }
2355 } // triPoolDeinit
2356 //------------------------------------------------------------------------------
2357 // FUNCTION triPoolInit
2359 // NOTES This routine initializes machinery for allocating items.
2360 // A `pool' is created with records of at least `bytecount' bytes.
2361 // Items will be allocated in `itemcount'- blocks.
2362 // Each item is assumed to be a collection of words, and either
2363 // pointers or floating-point values are assumed to be the
2364 // "primary" word type. (The "primary" word type is used
2365 // to determine alignment of items.)
2366 // If `alignment' isn't zero, all items will be `alignment'-byte
2367 // aligned in memory. `alignment' must be either a multiple or
2368 // a factor of the primary word size; powers of two are safe.
2369 // `alignment' is normally used to create a few unused bits at the
2370 // bottom of each item's pointer to store information.
2371 // Don't change this routine unless you understand it.
2372 //------------------------------------------------------------------------------
2373 static bool triPoolInit(Tmemtype pool,
2374  int bytecount,
2375  int itemcount,
2376  int firstitemcount,
2377  int alignment)
2378 {
2379  /* Find alignment to avoid unaligned access *
2380  * Must be at least as large as: *
2381  * -`alignment' *
2382  * - primary word type, *
2383  * - sizeof(int*), to maintain dead item stack */
2384  if (alignment > sizeof(int*))
2385  {
2386  pool->alignbytes = alignment;
2387  }
2388  else
2389  {
2390  pool->alignbytes = sizeof(int*);
2391  }
2392  pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) * pool->alignbytes;
2393  pool->itemsperblock = itemcount;
2394  if (firstitemcount == 0)
2395  {
2396  pool->itemsfirstblock = itemcount;
2397  }
2398  else
2399  {
2400  pool->itemsfirstblock = firstitemcount;
2401  }
2402  /* Allocate block of items. Space for: *
2403  * `itemsperblock' items *
2404  * 1 ptr (to point to next block) *
2405  * space to ensure alignment of the items */
2406  pool->firstblock =
2407  (int**)malloc(pool->itemsfirstblock * pool->itembytes + sizeof(int*) + pool->alignbytes);
2408  if (pool->firstblock == nullptr)
2409  {
2410  std::string s = "malloc failed: ";
2411  s += __FUNCTION__;
2412  XM_LOG(xmlog::error, s);
2413  return false;
2414  }
2415  /* Set the next block pointer to NULL. */
2416  *(pool->firstblock) = nullptr;
2417  /* Initialize the pool */
2418  triPoolRestart(pool);
2419  return true;
2420 } // triPoolInit
2421 //------------------------------------------------------------------------------
2422 // FUNCTION triPoolRestart
2424 // NOTES
2425 // This is a simple linear congruential random number generator. Hence, it
2426 // is a bad random number generator, but good enough for most randomized
2427 // geometric algorithms.
2428 //------------------------------------------------------------------------------
2429 static void triPoolRestart(Tmemtype pool)
2430 {
2431  unsigned long long alignptr;
2432 
2433  pool->items = 0;
2434  pool->maxitems = 0;
2435 
2436  /* Set the currently active block. */
2437  pool->nowblock = pool->firstblock;
2438  /* Find the first item in the pool. Increment by the size of (VOID *). */
2439  alignptr = (unsigned long long)(pool->nowblock + 1);
2440  /* Align the item on an `alignbytes'-byte boundary. */
2441  pool->nextitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2442  (alignptr % (unsigned long long)pool->alignbytes));
2443  /* There are lots of unallocated items left in this block. */
2444  pool->unallocateditems = pool->itemsfirstblock;
2445  /* The stack of deallocated items is empty. */
2446  pool->deaditemstack = nullptr;
2447 
2448 } // triPoolRestart
2449 //------------------------------------------------------------------------------
2450 // FUNCTION triRandomnation
2452 // NOTES
2453 // This is a simple linear congruential random number generator. Hence, it
2454 // is a bad random number generator, but good enough for most randomized
2455 // geometric algorithms.
2456 //------------------------------------------------------------------------------
2457 static unsigned long triRandomnation(unsigned int choices)
2458 {
2459  static unsigned long randomseed = 1;
2460 
2461  if (choices == 0)
2462  return 0;
2463  randomseed = (randomseed * 1366l + 150889l) % 714025l;
2464  return randomseed / (714025l / choices + 1);
2465 } // triRandomnation
2466 //------------------------------------------------------------------------------
2467 // FUNCTION triRemoveGhosts
2469 // NOTES
2470 //------------------------------------------------------------------------------
2471 static void triRemoveGhosts(Tedgetype startghost, TriVars& t)
2472 {
2473  Tedge searchedge, dissolveedge, deadtri;
2474  Tpt markorg;
2475  Ttri ptr; /* temp variable used by sym() */
2476  /* Find a starting edge on the convex hull */
2477  lprev(*startghost, searchedge);
2478  symself(searchedge);
2479  t.m_dummytri[0] = encode(searchedge);
2480  /* Remove bounding box & count convex hull edges */
2481  tedgecopy(*startghost, dissolveedge);
2482  do
2483  {
2484  lnext(dissolveedge, deadtri);
2485  lprevself(dissolveedge);
2486  symself(dissolveedge);
2487  /* If no PSLG is involved, set the boundary markers of all the points */
2488  /* on the convex hull. If a PSLG is used, this step is done later. */
2489  /* Watch out for the all collinear input case */
2490  if (dissolveedge.tri != t.m_dummytri)
2491  {
2492  org(dissolveedge, markorg);
2493  if (pointmark(markorg, t.m_pointmarkindex) == 0)
2494  {
2495  setpointmark(markorg, 1, t.m_pointmarkindex);
2496  }
2497  }
2498  /* Remove a bounding tri from a convex hull tri */
2499  dissolveedge.tri[dissolveedge.orient] = (Ttri)t.m_dummytri;
2500  /* Find the next bounding triangle */
2501  sym(deadtri, dissolveedge);
2502  /* Delete the bounding triangle */
2503  triTriangleDealloc(deadtri.tri, t);
2504  } while (!tedgeequal(dissolveedge, *startghost));
2505 } // triRemoveGhosts
2506 //------------------------------------------------------------------------------
2507 // FUNCTION triScaleExpansionZeroElim
2509 // the output expansion.
2510 // NOTES Sets h = be. See my Robust Predicates paper for details.
2511 //
2512 // Maintains the nonoverlapping property. If round-to-even is used (as
2513 // with IEEE 754), maintains the strongly nonoverlapping and nonadjacent
2514 // properties as well. (That is, if e has one of these properties, so
2515 // will h.) e and h cannot be the same.
2516 //------------------------------------------------------------------------------
2517 static int triScaleExpansionZeroElim(int elen, double* e, double b, double* h, TriVars& t)
2518 {
2519  int eindex, hindex;
2520  double Q, sum;
2521  double hh;
2522  double product1, product0;
2523  double enow;
2524  double bvirt, avirt, bround, around;
2525  double c;
2526  double abig, ahi, alo, bhi, blo;
2527  double err1, err2, err3;
2528 
2529  Split(t.m_splitter, b, bhi, blo);
2530  Two_Product_Presplit(t.m_splitter, e[0], b, bhi, blo, Q, hh);
2531  hindex = 0;
2532  if (hh != 0)
2533  h[hindex++] = hh;
2534 
2535  for (eindex = 1; eindex < elen; eindex++)
2536  {
2537  enow = e[eindex];
2538  Two_Product_Presplit(t.m_splitter, enow, b, bhi, blo, product1, product0);
2539  Two_Sum(Q, product0, sum, hh);
2540  if (hh != 0)
2541  h[hindex++] = hh;
2542  Fast_Two_Sum(product1, sum, Q, hh);
2543  if (hh != 0)
2544  h[hindex++] = hh;
2545  }
2546  if ((Q != 0.0) || (hindex == 0))
2547  h[hindex++] = Q;
2548  return hindex;
2549 } // triScaleExpansionZeroElim
2550 //------------------------------------------------------------------------------
2551 // FUNCTION triTraversalInit
2553 // NOTES This routine is used in conjunction with triTraverse().
2554 //------------------------------------------------------------------------------
2555 static void triTraversalInit(Tmemtype pool)
2556 {
2557  unsigned long long alignptr;
2558  /* Begin the traversal in the first block */
2559  pool->pathblock = pool->firstblock;
2560  /* Find 1st item in block. Inc by sizeof(int*) */
2561  alignptr = (unsigned long long)(pool->pathblock + 1);
2562  /* Align w/item on an `alignbytes'-byte boundary */
2563  pool->pathitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2564  (alignptr % (unsigned long long)pool->alignbytes));
2565  /* Update # of items left in the current block */
2566  pool->pathitemsleft = pool->itemsfirstblock;
2567 } // triTraversalInit
2568 //------------------------------------------------------------------------------
2569 // FUNCTION triTraverse
2571 // NOTES This routine is used in conjunction with triTraversalInit().
2572 // Be forewarned that this routine successively returns all items in
2573 // the list, including deallocated ones on the deaditemqueue. It's up
2574 // to you to figure out which ones are actually dead. Why? I don't
2575 // want to allocate extra space just to demarcate dead items. It can
2576 // usually be done more space-efficiently by a routine that knows
2577 // something about the structure of the item.
2578 //------------------------------------------------------------------------------
2579 static int* triTraverse(Tmemtype pool)
2580 {
2581  int* newitem;
2582  unsigned long long alignptr;
2583  /* Stop upon exhausting the list of items. */
2584  if (pool->pathitem == pool->nextitem)
2585  return nullptr;
2586  /* look for untraversed items in current block */
2587  if (pool->pathitemsleft == 0)
2588  {
2589  /* Find the next block. */
2590  pool->pathblock = (int**)*(pool->pathblock);
2591  /* Find 1st item in block. Inc by sizeof(int*) */
2592  alignptr = (unsigned long long)(pool->pathblock + 1);
2593  /* Align w/item on `alignbytes'-byte boundary */
2594  pool->pathitem = (int*)(alignptr + (unsigned long long)pool->alignbytes -
2595  (alignptr % (unsigned long long)pool->alignbytes));
2596  /* Update # of items left in the current block */
2597  pool->pathitemsleft = pool->itemsperblock;
2598  }
2599  newitem = pool->pathitem;
2600  /* Find the next item in the block. */
2601 
2602  pool->pathitem = (int*)((char*)pool->pathitem + pool->itembytes);
2603  pool->pathitemsleft--;
2604  return newitem;
2605 } // triTraverse
2606 //------------------------------------------------------------------------------
2607 // FUNCTION triTriangleDealloc
2609 // NOTES Makes it possible to detect dead triangles when traversing
2610 //------------------------------------------------------------------------------
2611 static void triTriangleDealloc(Ttri* dyingtriangle, TriVars& t)
2612 {
2613  /* Set triangle's vertices to NULL */
2614  dyingtriangle[3] = nullptr;
2615  dyingtriangle[4] = nullptr;
2616  dyingtriangle[5] = nullptr;
2617  triPoolDealloc(&t.m_triangles, (int*)dyingtriangle);
2618 } // triTriangleDealloc
2619 //------------------------------------------------------------------------------
2620 // FUNCTION triTriangleTraverse
2622 // NOTES
2623 //------------------------------------------------------------------------------
2624 static Ttri* triTriangleTraverse(TriVars& t)
2625 {
2626  Ttri* newtriangle;
2627  do
2628  {
2629  newtriangle = (Ttri*)triTraverse(&t.m_triangles);
2630  if (newtriangle == nullptr)
2631  return nullptr;
2632  } while (newtriangle[3] == nullptr); /* Skip dead ones */
2633  return newtriangle;
2634 } // triTriangleTraverse
2635 
2636 } // namespace unnamed
2638 
2639 namespace xms
2640 {
2641 //----- Class Definitions ------------------------------------------------------
2642 
2643 //----- Function Definitions ---------------------------------------------------
2644 
2645 //------------------------------------------------------------------------------
2655 //------------------------------------------------------------------------------
2657 {
2658  TriVars t;
2659  try
2660  {
2661  // initialize counters
2662  t.m_points.maxitems = t.m_triangles.maxitems = 0l;
2663  t.m_points.itembytes = t.m_triangles.itembytes = 0;
2664 
2665  // initialize exact arithmetic constants
2666  triExactInit(t);
2667 
2668  // copy points into pool data
2669  if (!triGetPoints(a_Client, t))
2670  {
2671  throw - 1;
2672  }
2673 
2674  if (t.m_numpoints > 2)
2675  {
2676  // initialize the triangle pool
2677  triInitTrianglePool(t);
2678 
2679  // do the triangulation
2680  bool ok = triDivConqDelaunay(t);
2681  if (ok)
2682  {
2683  triNumberNodes(t);
2684  triFillTriList(a_Client, t);
2685 
2686  // free the memory
2687  triPoolDeinit(&t.m_triangles);
2688  if (t.m_dummytribase)
2689  {
2690  free(t.m_dummytribase);
2691  }
2692  }
2693  }
2694 
2695  // more memory clean up
2696  triPoolDeinit(&t.m_points);
2697 
2698  a_Client.FinalizeTriangulation();
2699  }
2700  catch (...)
2701  {
2702  XM_LOG(xmlog::error, "Error: Unable to triangulate.");
2703  triPoolDeinit(&t.m_triangles);
2704  triPoolDeinit(&t.m_points);
2705  return false;
2706  }
2707  return true;
2708 } // trTriangulateIt
2709 
2710 } // namespace xms
2711 
2712 // eof triangulate.cpp
#define XM_LOG(A, B)
Code that creates a Delauney triangulation from points.
bool trTriangulateIt(TrTriangulator &a_Client)
Do delaunay divide-and-conquer triangulation.
Base class used to derive a class to triangulate points.
XMS Namespace.
Definition: geoms.cpp:34