Seamly2D
Code documentation
delaunay.cpp
Go to the documentation of this file.
1 /*
2 ** delaunay.c : compute 2D delaunay triangulation in the plane.
3 ** Copyright (C) 2005 Wael El Oraiby <wael.eloraiby@gmail.com>
4 **
5 **
6 ** This program is free software: you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation, either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <QtGlobal>
25 
26 #include "../vmisc/diagnostic.h"
27 #include "delaunay.h"
28 
29 QT_WARNING_PUSH
30 QT_WARNING_DISABLE_GCC("-Wold-style-cast")
31 QT_WARNING_DISABLE_CLANG("-Wold-style-cast")
32 QT_WARNING_DISABLE_GCC("-Wcast-qual")
33 
34 #if PREDICATE == EXACT_PREDICATE
35 extern void exactinit();
36 extern real incircle(real* pa, real* pb, real* pc, real* pd);
37 #endif
38 
39 #define ON_RIGHT 1
40 #define ON_SEG 0
41 #define ON_LEFT -1
42 
43 #define OUTSIDE -1
44 #define ON_CIRCLE 0
45 #define INSIDE 1
46 
47 struct delaunay_s;
48 struct face_s;
49 struct halfedge_s;
50 struct point2d_s;
51 
52 
53 #ifdef USE_DOUBLE
54 # define REAL_ZERO 0.0
55 # define REAL_ONE 1.0
56 # define REAL_TWO 2.0
57 # define REAL_FOUR 4.0
58 # define TOLERANCE (1024.0 * 1024.0)
59 #else
60 # define REAL_ZERO 0.0f
61 # define REAL_ONE 1.0f
62 # define REAL_TWO 2.0f
63 # define REAL_FOUR 4.0f
64 # define TOLERANCE (16.0f )
65 #endif
66 
67 #define EPSILON (REAL_ONE / TOLERANCE)
68 
69 typedef struct point2d_s point2d_t;
70 typedef struct face_s face_t;
71 typedef struct halfedge_s halfedge_t;
72 typedef struct delaunay_s delaunay_t;
73 typedef real mat3_t[3][3];
74 
75 struct point2d_s
76 {
77  real x, y; /* point coordinates */
78  halfedge_t* he; /* point halfedge */
79  quint32 idx; /* point index in input buffer */
80 };
81 
82 struct face_s
83 {
84 /* real radius;
85  real cx, cy;
86  point2d_t* p[3];
87 */
88  halfedge_t* he; /* a pointing half edge */
89  quint32 num_verts; /* number of vertices on this face */
90 };
91 
92 struct halfedge_s
93 {
94  point2d_t* vertex; /* vertex */
95  halfedge_t* pair; /* pair */
96  halfedge_t* next; /* next */
97  halfedge_t* prev; /* next^-1 */
98  face_t* face; /* halfedge face */
99 };
100 
102 {
103  halfedge_t* rightmost_he; /* right most halfedge */
104  halfedge_t* leftmost_he; /* left most halfedge */
105  point2d_t** points; /* pointer to points */
106  face_t* faces; /* faces of delaunay */
107  quint32 num_faces; /* face count */
108  quint32 start_point; /* start point index */
109  quint32 end_point; /* end point index */
110 };
111 
112 
113 /*
114 * 3x3 matrix determinant
115 */
116 //static real det3( mat3_t *m )
117 //{
118 // real res;
119 
120 // res = ((*m)[0][0]) * (((*m)[1][1]) * ((*m)[2][2]) - ((*m)[1][2]) * ((*m)[2][1]))
121 // - ((*m)[0][1]) * (((*m)[1][0]) * ((*m)[2][2]) - ((*m)[1][2]) * ((*m)[2][0]))
122 // + ((*m)[0][2]) * (((*m)[1][0]) * ((*m)[2][1]) - ((*m)[1][1]) * ((*m)[2][0]));
123 
124 // return res;
125 //}
126 
127 /*
128 * allocate a point
129 */
131 {
132  point2d_t* p;
133 
134  p = (point2d_t*)malloc(sizeof(point2d_t));
135  assert( p != nullptr );
136 // cppcheck-suppress memsetClassFloat
137  memset(p, 0, sizeof(point2d_t));
138 
139  return p;
140 }
141 
142 /*
143 * free a point
144 */
145 static void point_free( point2d_t* p )
146 {
147  assert( p != nullptr );
148  free(p);
149 }
150 
151 /*
152 * allocate a halfedge
153 */
155 {
156  halfedge_t* d;
157 
158  d = (halfedge_t*)malloc(sizeof(halfedge_t));
159  assert( d != nullptr );
160  memset(d, 0, sizeof(halfedge_t));
161 
162  return d;
163 }
164 
165 /*
166 * free a halfedge
167 */
168 static void halfedge_free( halfedge_t* d )
169 {
170  assert( d != nullptr );
171  memset(d, 0, sizeof(halfedge_t));
172  free(d);
173 }
174 
175 /*
176 * free all delaunay halfedges
177 */
178 void del_free_halfedges( delaunay_t *del );
180 {
181  quint32 i;
182  halfedge_t *d, *sig;
183 
184  /* if there is nothing to do */
185  if( del->points == nullptr )
186  return;
187 
188  for( i = 0; i <= (del->end_point - del->start_point); i++ )
189  {
190  /* free all the halfedges around the point */
191  d = del->points[i]->he;
192  if( d != nullptr )
193  {
194  do {
195  sig = d->next;
196  halfedge_free( d );
197  d = sig;
198  } while( d != del->points[i]->he );
199  del->points[i]->he = nullptr;
200  }
201  }
202 }
203 
204 /*
205  * allocate memory for a face
206  */
207 //static face_t* face_alloc()
208 //{
209 // face_t *f = (face_t*)malloc(sizeof(face_t));
210 // assert( f != nullptr );
211 // memset(f, 0, sizeof(face_t));
212 // return f;
213 //}
214 
215 /*
216  * free a face
217  */
218 //static void face_free(face_t *f)
219 //{
220 // assert( f != nullptr );
221 // free(f);
222 //}
223 
224 /*
225 * compare 2 points when sorting
226 */
227 static int cmp_points( const void *_pt0, const void *_pt1 )
228 {
229  point2d_t *pt0, *pt1;
230 
231  pt0 = (point2d_t*)(*((point2d_t**)_pt0));
232  pt1 = (point2d_t*)(*((point2d_t**)_pt1));
233 
234  if( pt0->x < pt1->x )
235  return -1;
236  else if( pt0->x > pt1->x )
237  return 1;
238  else if( pt0->y < pt1->y )
239  return -1;
240  else if( pt0->y > pt1->y )
241  return 1;
242  assert(0 && "2 or more points share the same exact coordinate");
243  return 0; /* Should not be given! */
244 }
245 
246 /*
247 * classify a point relative to a segment
248 */
250 {
251  point2d_t se, spt;
252  real res;
253 
254  se.x = e->x - s->x;
255  se.y = e->y - s->y;
256 
257  spt.x = pt->x - s->x;
258  spt.y = pt->y - s->y;
259 
260  res = (( se.x * spt.y ) - ( se.y * spt.x ));
261  if( res < REAL_ZERO )
262  return ON_RIGHT;
263  else if( res > REAL_ZERO )
264  return ON_LEFT;
265 
266  return ON_SEG;
267 }
268 
269 /*
270 * classify a point relative to a halfedge, -1 is left, 0 is on, 1 is right
271 */
273 {
274  point2d_t *s, *e;
275 
276  s = d->vertex;
277  e = d->pair->vertex;
278 
279  return classify_point_seg(s, e, pt);
280 }
281 
282 /*
283 * return the absolute value
284 */
285 //static real dabs( real a )
286 //{
287 // if( a < REAL_ZERO )
288 // return (-a);
289 // return a;
290 //}
291 
292 /*
293 * compute the circle given 3 points
294 */
295 #if PREDICATE == LOOSE_PREDICATE
296 static void compute_circle( point2d_t *pt0, point2d_t *pt1, point2d_t *pt2, real *cx, real *cy, real *radius )
297 {
298  mat3_t ma, mbx, mby, mc;
299  real x0y0, x1y1, x2y2;
300  real a, bx, by, c;
301 
302  /* calculate x0y0, .... */
303  x0y0 = pt0->x * pt0->x + pt0->y * pt0->y;
304  x1y1 = pt1->x * pt1->x + pt1->y * pt1->y;
305  x2y2 = pt2->x * pt2->x + pt2->y * pt2->y;
306 
307  /* setup A matrix */
308  ma[0][0] = pt0->x;
309  ma[0][1] = pt0->y;
310  ma[1][0] = pt1->x;
311  ma[1][1] = pt1->y;
312  ma[2][0] = pt2->x;
313  ma[2][1] = pt2->y;
314  ma[0][2] = ma[1][2] = ma[2][2] = REAL_ONE;
315 
316  /* setup Bx matrix */
317  mbx[0][0] = x0y0;
318  mbx[1][0] = x1y1;
319  mbx[2][0] = x2y2;
320  mbx[0][1] = pt0->y;
321  mbx[1][1] = pt1->y;
322  mbx[2][1] = pt2->y;
323  mbx[0][2] = mbx[1][2] = mbx[2][2] = REAL_ONE;
324 
325  /* setup By matrix */
326  mby[0][0] = x0y0;
327  mby[1][0] = x1y1;
328  mby[2][0] = x2y2;
329  mby[0][1] = pt0->x;
330  mby[1][1] = pt1->x;
331  mby[2][1] = pt2->x;
332  mby[0][2] = mby[1][2] = mby[2][2] = REAL_ONE;
333 
334  /* setup C matrix */
335  mc[0][0] = x0y0;
336  mc[1][0] = x1y1;
337  mc[2][0] = x2y2;
338  mc[0][1] = pt0->x;
339  mc[1][1] = pt1->x;
340  mc[2][1] = pt2->x;
341  mc[0][2] = pt0->y;
342  mc[1][2] = pt1->y;
343  mc[2][2] = pt2->y;
344 
345  /* compute a, bx, by and c */
346  a = det3(&ma);
347  bx = det3(&mbx);
348  by = -det3(&mby);
349  c = -det3(&mc);
350 
351  *cx = bx / (REAL_TWO * a);
352  *cy = by / (REAL_TWO * a);
353  *radius = sqrt(bx * bx + by * by - REAL_FOUR * a * c) / (REAL_TWO * dabs(a));
354 }
355 #endif
356 
357 /*
358 * test if a point is inside a circle given by 3 points, 1 if inside, 0 if outside
359 */
360 static int in_circle( point2d_t *pt0, point2d_t *pt1, point2d_t *pt2, point2d_t *p )
361 {
362 #if PREDICATE == EXACT_PREDICATE
363  real res = incircle(&(pt0->x), &(pt1->x), &(pt2->x), &(p->x));
364  if( res > REAL_ZERO )
365  return INSIDE;
366  else if( res < REAL_ZERO )
367  return OUTSIDE;
368 
369  return ON_CIRCLE;
370 #endif
371 #if PREDICATE == LOOSE_PREDICATE
372  real cx, cy, radius;
373  compute_circle(pt0, pt1, pt2, &cx, &cy, &radius);
374 
375  real distance = sqrt((p->x - cx) * (p->x - cx) + (p->y - cy) * (p->y - cy));
376  if( distance < radius - EPSILON )
377  return INSIDE;
378  else if(distance > radius + EPSILON )
379  return OUTSIDE;
380  return ON_CIRCLE;
381 #endif
382 #if PREDICATE == FAST_PREDICATE
383  mat3_t ma, mbx, mby, mc;
384  real x0y0, x1y1, x2y2;
385  real a, bx, by, c, res;
386 
387  /* calculate x0y0, .... */
388  x0y0 = pt0->x * pt0->x + pt0->y * pt0->y;
389  x1y1 = pt1->x * pt1->x + pt1->y * pt1->y;
390  x2y2 = pt2->x * pt2->x + pt2->y * pt2->y;
391 
392  /* setup A matrix */
393  ma[0][0] = pt0->x;
394  ma[0][1] = pt0->y;
395  ma[1][0] = pt1->x;
396  ma[1][1] = pt1->y;
397  ma[2][0] = pt2->x;
398  ma[2][1] = pt2->y;
399  ma[0][2] = ma[1][2] = ma[2][2] = REAL_ONE;
400 
401  /* setup Bx matrix */
402  mbx[0][0] = x0y0;
403  mbx[1][0] = x1y1;
404  mbx[2][0] = x2y2;
405  mbx[0][1] = pt0->y;
406  mbx[1][1] = pt1->y;
407  mbx[2][1] = pt2->y;
408  mbx[0][2] = mbx[1][2] = mbx[2][2] = REAL_ONE;
409 
410  /* setup By matrix */
411  mby[0][0] = x0y0;
412  mby[1][0] = x1y1;
413  mby[2][0] = x2y2;
414  mby[0][1] = pt0->x;
415  mby[1][1] = pt1->x;
416  mby[2][1] = pt2->x;
417  mby[0][2] = mby[1][2] = mby[2][2] = REAL_ONE;
418 
419  /* setup C matrix */
420  mc[0][0] = x0y0;
421  mc[1][0] = x1y1;
422  mc[2][0] = x2y2;
423  mc[0][1] = pt0->x;
424  mc[1][1] = pt1->x;
425  mc[2][1] = pt2->x;
426  mc[0][2] = pt0->y;
427  mc[1][2] = pt1->y;
428  mc[2][2] = pt2->y;
429 
430  /* compute a, bx, by and c */
431  a = det3(&ma);
432  bx = det3(&mbx);
433  by = -det3(&mby);
434  c = -det3(&mc);
435 
436  res = a * (p->x * p->x + p->y * p->y ) - bx * p->x - by * p->y + c;
437 
438 
439  if( res < REAL_ZERO )
440  return INSIDE;
441  else if( res > REAL_ZERO )
442  return OUTSIDE;
443 
444  return ON_CIRCLE;
445 #endif
446 }
447 
448 /*
449 * initialize delaunay segment
450 */
451 static int del_init_seg( delaunay_t *del, int start )
452 {
453  halfedge_t *d0, *d1;
454  point2d_t *pt0, *pt1;
455 
456  /* init delaunay */
457  del->start_point = static_cast<quint32>(start);
458  del->end_point = static_cast<quint32>(start + 1);
459 
460  /* setup pt0 and pt1 */
461  pt0 = del->points[start];
462  pt1 = del->points[start + 1];
463 
464  /* allocate the halfedges and setup them */
465  d0 = halfedge_alloc();
466  d1 = halfedge_alloc();
467 
468  d0->vertex = pt0;
469  d1->vertex = pt1;
470 
471  d0->next = d0->prev = d0;
472  d1->next = d1->prev = d1;
473 
474  d0->pair = d1;
475  d1->pair = d0;
476 
477  pt0->he = d0;
478  pt1->he = d1;
479 
480  del->rightmost_he = d1;
481  del->leftmost_he = d0;
482 
483 
484  return 0;
485 }
486 
487 /*
488 * initialize delaunay triangle
489 */
490 static int del_init_tri( delaunay_t *del, int start )
491 {
492  halfedge_t *d0, *d1, *d2, *d3, *d4, *d5;
493  point2d_t *pt0, *pt1, *pt2;
494 
495  /* initiate delaunay */
496  del->start_point = static_cast<quint32>(start);
497  del->end_point = static_cast<quint32>(start + 2);
498 
499  /* setup the points */
500  pt0 = del->points[start];
501  pt1 = del->points[start + 1];
502  pt2 = del->points[start + 2];
503 
504  /* allocate the 6 halfedges */
505  d0 = halfedge_alloc();
506  d1 = halfedge_alloc();
507  d2 = halfedge_alloc();
508  d3 = halfedge_alloc();
509  d4 = halfedge_alloc();
510  d5 = halfedge_alloc();
511 
512  if( classify_point_seg(pt0, pt2, pt1) == ON_LEFT ) /* first case */
513  {
514  /* set halfedges points */
515  d0->vertex = pt0;
516  d1->vertex = pt2;
517  d2->vertex = pt1;
518 
519  d3->vertex = pt2;
520  d4->vertex = pt1;
521  d5->vertex = pt0;
522 
523  /* set points halfedges */
524  pt0->he = d0;
525  pt1->he = d2;
526  pt2->he = d1;
527 
528  /* next and next -1 setup */
529  d0->next = d5;
530  d0->prev = d5;
531 
532  d1->next = d3;
533  d1->prev = d3;
534 
535  d2->next = d4;
536  d2->prev = d4;
537 
538  d3->next = d1;
539  d3->prev = d1;
540 
541  d4->next = d2;
542  d4->prev = d2;
543 
544  d5->next = d0;
545  d5->prev = d0;
546 
547  /* set halfedges pair */
548  d0->pair = d3;
549  d3->pair = d0;
550 
551  d1->pair = d4;
552  d4->pair = d1;
553 
554  d2->pair = d5;
555  d5->pair = d2;
556 
557  del->rightmost_he = d1;
558  del->leftmost_he = d0;
559 
560  } else /* 2nd case */
561  {
562  /* set halfedges points */
563  d0->vertex = pt0;
564  d1->vertex = pt1;
565  d2->vertex = pt2;
566 
567  d3->vertex = pt1;
568  d4->vertex = pt2;
569  d5->vertex = pt0;
570 
571  /* set points halfedges */
572  pt0->he = d0;
573  pt1->he = d1;
574  pt2->he = d2;
575 
576  /* next and next -1 setup */
577  d0->next = d5;
578  d0->prev = d5;
579 
580  d1->next = d3;
581  d1->prev = d3;
582 
583  d2->next = d4;
584  d2->prev = d4;
585 
586  d3->next = d1;
587  d3->prev = d1;
588 
589  d4->next = d2;
590  d4->prev = d2;
591 
592  d5->next = d0;
593  d5->prev = d0;
594 
595  /* set halfedges pair */
596  d0->pair = d3;
597  d3->pair = d0;
598 
599  d1->pair = d4;
600  d4->pair = d1;
601 
602  d2->pair = d5;
603  d5->pair = d2;
604 
605  del->rightmost_he = d2;
606  del->leftmost_he = d0;
607  }
608 
609  return 0;
610 }
611 
612 /*
613 * remove an edge given a halfedge
614 */
615 static void del_remove_edge( halfedge_t *d )
616 {
617  halfedge_t *next, *prev, *pair, *orig_pair;
618 
619  orig_pair = d->pair;
620 
621  next = d->next;
622  prev = d->prev;
623  pair = d->pair;
624 
625  assert(next != nullptr);
626  assert(prev != nullptr);
627 
628  next->prev = prev;
629  prev->next = next;
630 
631 
632  /* check to see if we have already removed pair */
633  if( pair )
634  pair->pair = nullptr;
635 
636  /* check to see if the vertex points to this halfedge */
637  if( d->vertex->he == d )
638  d->vertex->he = next;
639 
640  d->vertex = nullptr;
641  d->next = nullptr;
642  d->prev = nullptr;
643  d->pair = nullptr;
644 
645  next = orig_pair->next;
646  prev = orig_pair->prev;
647  pair = orig_pair->pair;
648 
649  assert(next != nullptr);
650  assert(prev != nullptr);
651 
652  next->prev = prev;
653  prev->next = next;
654 
655 
656  /* check to see if we have already removed pair */
657  if( pair )
658  pair->pair = nullptr;
659 
660  /* check to see if the vertex points to this halfedge */
661  if( orig_pair->vertex->he == orig_pair )
662  orig_pair->vertex->he = next;
663 
664  orig_pair->vertex = nullptr;
665  orig_pair->next = nullptr;
666  orig_pair->prev = nullptr;
667  orig_pair->pair = nullptr;
668 
669 
670  /* finally free the halfedges */
671  halfedge_free(d);
672  halfedge_free(orig_pair);
673 }
674 
675 /*
676 * pass through all the halfedges on the left side and validate them
677 */
679 {
680  point2d_t *g, *d, *u, *v;
681  halfedge_t *c, *du, *dg;
682 
683  g = b->vertex; /* base halfedge point */
684  dg = b;
685 
686  d = b->pair->vertex; /* pair(halfedge) point */
687  b = b->next;
688 
689  u = b->pair->vertex; /* next(pair(halfedge)) point */
690  du = b->pair;
691 
692  v = b->next->pair->vertex; /* pair(next(next(halfedge)) point */
693 
694  if( classify_point_seg(g, d, u) == ON_LEFT )
695  {
696  /* 3 points aren't colinear */
697  /* as long as the 4 points belong to the same circle, do the cleaning */
698  assert( v != u && "1: floating point precision error");
699  while( v != d && v != g && in_circle(g, d, u, v) == INSIDE )
700  {
701  c = b->next;
702  du = b->next->pair;
703  del_remove_edge(b);
704  b = c;
705  u = du->vertex;
706  v = b->next->pair->vertex;
707  }
708 
709  assert( v != u && "2: floating point precision error");
710  if( v != d && v != g && in_circle(g, d, u, v) == ON_CIRCLE )
711  {
712  du = du->prev;
713  del_remove_edge(b);
714  }
715  } else /* treat the case where the 3 points are colinear */
716  du = dg;
717 
718  assert(du->pair);
719  return du;
720 }
721 
722 /*
723 * pass through all the halfedges on the right side and validate them
724 */
726 {
727  point2d_t *rv, *lv, *u, *v;
728  halfedge_t *c, *dd, *du;
729 
730  b = b->pair;
731  rv = b->vertex;
732  dd = b;
733  lv = b->pair->vertex;
734  b = b->prev;
735  u = b->pair->vertex;
736  du = b->pair;
737 
738  v = b->prev->pair->vertex;
739 
740  if( classify_point_seg(lv, rv, u) == ON_LEFT )
741  {
742  assert( v != u && "1: floating point precision error");
743  while( v != lv && v != rv && in_circle(lv, rv, u, v) == INSIDE )
744  {
745  c = b->prev;
746  du = c->pair;
747  del_remove_edge(b);
748  b = c;
749  u = du->vertex;
750  v = b->prev->pair->vertex;
751  }
752 
753  assert( v != u && "1: floating point precision error");
754  if( v != lv && v != rv && in_circle(lv, rv, u, v) == ON_CIRCLE )
755  {
756  du = du->next;
757  del_remove_edge(b);
758  }
759  } else
760  du = dd;
761 
762  assert(du->pair);
763  return du;
764 }
765 
766 
767 /*
768 * validate a link
769 */
771 {
772  point2d_t *g, *g_p, *d, *d_p;
773  halfedge_t *gd, *dd, *new_gd, *new_dd;
774 
775  g = b->vertex;
776  gd = del_valid_left(b);
777  g_p = gd->vertex;
778 
779  assert(b->pair);
780  d = b->pair->vertex;
781  dd = del_valid_right(b);
782  d_p = dd->vertex;
783  assert(b->pair);
784 
785  if( g != g_p && d != d_p )
786  {
787  int a = in_circle(g, d, g_p, d_p);
788 
789  if( a != ON_CIRCLE )
790  {
791  if( a == INSIDE )
792  {
793  g_p = g;
794  gd = b;
795  }
796  else
797  {
798  d_p = d;
799  dd = b->pair;
800  }
801  }
802  }
803 
804  /* create the 2 halfedges */
805  new_gd = halfedge_alloc();
806  new_dd = halfedge_alloc();
807 
808  /* setup new_gd and new_dd */
809 
810  new_gd->vertex = gd->vertex;
811  new_gd->pair = new_dd;
812  new_gd->prev = gd;
813  new_gd->next = gd->next;
814  gd->next->prev = new_gd;
815  gd->next = new_gd;
816 
817  new_dd->vertex = dd->vertex;
818  new_dd->pair = new_gd;
819  new_dd->prev = dd->prev;
820  dd->prev->next = new_dd;
821  new_dd->next = dd;
822  dd->prev = new_dd;
823 
824  return new_gd;
825 }
826 
827 /*
828 * find the lower tangent between the two delaunay, going from left to right (returns the left half edge)
829 */
831 {
832  halfedge_t *right_d, *left_d, *new_ld, *new_rd;
833  int sl, sr;
834 
835  left_d = left->rightmost_he;
836  right_d = right->leftmost_he;
837 
838  do {
839  point2d_t *pl = left_d->prev->pair->vertex;
840  point2d_t *pr = right_d->pair->vertex;
841 
842  if( (sl = classify_point_seg(left_d->vertex, right_d->vertex, pl)) == ON_RIGHT ) {
843  left_d = left_d->prev->pair;
844  }
845 
846  if( (sr = classify_point_seg(left_d->vertex, right_d->vertex, pr)) == ON_RIGHT ) {
847  right_d = right_d->pair->next;
848  }
849 
850  } while( sl == ON_RIGHT || sr == ON_RIGHT );
851 
852  /* create the 2 halfedges */
853  new_ld = halfedge_alloc();
854  new_rd = halfedge_alloc();
855 
856  /* setup new_gd and new_dd */
857  new_ld->vertex = left_d->vertex;
858  new_ld->pair = new_rd;
859  new_ld->prev = left_d->prev;
860  left_d->prev->next = new_ld;
861  new_ld->next = left_d;
862  left_d->prev = new_ld;
863 
864  new_rd->vertex = right_d->vertex;
865  new_rd->pair = new_ld;
866  new_rd->prev = right_d->prev;
867  right_d->prev->next = new_rd;
868  new_rd->next = right_d;
869  right_d->prev = new_rd;
870 
871  return new_ld;
872 }
873 
874 /*
875 * link the 2 delaunay together
876 */
877 static void del_link( delaunay_t *result, delaunay_t *left, delaunay_t *right )
878 {
879  point2d_t *u, *v, *ml, *mr;
880  halfedge_t *base;
881 
882  assert( left->points == right->points );
883 
884  /* save the most right point and the most left point */
885  ml = left->leftmost_he->vertex;
886  mr = right->rightmost_he->vertex;
887 
888  base = del_get_lower_tangent(left, right);
889 
890  u = base->next->pair->vertex;
891  v = base->pair->prev->pair->vertex;
892 
893  while( del_classify_point(base, u) == ON_LEFT ||
894  del_classify_point(base, v) == ON_LEFT )
895  {
896  base = del_valid_link(base);
897  u = base->next->pair->vertex;
898  v = base->pair->prev->pair->vertex;
899  }
900 
901  right->rightmost_he = mr->he;
902  left->leftmost_he = ml->he;
903 
904  /* TODO: this part is not needed, and can be optimized */
905  while( del_classify_point( right->rightmost_he, right->rightmost_he->prev->pair->vertex ) == ON_RIGHT )
906  right->rightmost_he = right->rightmost_he->prev;
907 
908  while( del_classify_point( left->leftmost_he, left->leftmost_he->prev->pair->vertex ) == ON_RIGHT )
909  left->leftmost_he = left->leftmost_he->prev;
910 
911  result->leftmost_he = left->leftmost_he;
912  result->rightmost_he = right->rightmost_he;
913  result->points = left->points;
914  result->start_point = left->start_point;
915  result->end_point = right->end_point;
916 }
917 
918 /*
919 * divide and conquer delaunay
920 */
921 void del_divide_and_conquer( delaunay_t *del, int start, int end );
922 void del_divide_and_conquer( delaunay_t *del, int start, int end )
923 {
924  delaunay_t left, right;
925 
926  int n = (end - start + 1);
927 
928  if( n > 3 )
929  {
930  int i = (n / 2) + (n & 1);
931  left.points = del->points;
932  right.points = del->points;
933  del_divide_and_conquer( &left, start, start + i - 1 );
934  del_divide_and_conquer( &right, start + i, end );
935  del_link( del, &left, &right );
936  } else
937  if( n == 3 )
938  del_init_tri( del, start );
939  else
940  if( n == 2 )
941  del_init_seg( del, start );
942 }
943 
945 {
946  halfedge_t *curr;
947 
948  /* test if the halfedge has already a pointing face */
949  if( d->face != nullptr )
950  return;
951 
952  del->faces = (face_t*)realloc(del->faces, (del->num_faces + 1) * sizeof(face_t));
953 
954  face_t *f = &(del->faces[del->num_faces]);
955  curr = d;
956  f->he = d;
957  f->num_verts = 0;
958  do {
959  curr->face = f;
960  (f->num_verts)++;
961  curr = curr->pair->prev;
962  } while( curr != d );
963 
964  (del->num_faces)++;
965 
966 /* if( d->face.radius < 0.0 )
967  {
968  d->face.p[0] = d->vertex;
969  d->face.p[1] = d->pair->vertex;
970  d->face.p[2] = d->pair->prev->pair->vertex;
971 
972  if( classify_point_seg( d->face.p[0], d->face.p[1], d->face.p[2] ) == ON_LEFT )
973  {
974  compute_circle(d->face.p[0], d->face.p[1], d->face.p[2], &(d->face.cx), &(d->face.cy), &(d->face.radius));
975  }
976  }
977 */
978 }
979 
980 /*
981 * build the faces for all the halfedge
982 */
983 void del_build_faces( delaunay_t *del );
985 {
986  quint32 i;
987  halfedge_t *curr;
988 
989  del->num_faces = 0;
990  del->faces = nullptr;
991 
992  /* build external face first */
994 
995  for( i = del->start_point; i <= del->end_point; i++ )
996  {
997  curr = del->points[i]->he;
998 
999  do {
1000  build_halfedge_face( del, curr );
1001  curr = curr->next;
1002  } while( curr != del->points[i]->he );
1003  }
1004 }
1005 
1006 /*
1007 */
1008 delaunay2d_t* delaunay2d_from(del_point2d_t *points, quint32 num_points) {
1009  delaunay2d_t* res = nullptr;
1010  delaunay_t del;
1011  quint32 i;
1012  quint32* faces = nullptr;
1013 
1014  del.num_faces = 0; //Warning using uninitialized value
1015 
1016 #if PREDICATE == EXACT_PREDICATE
1017  exactinit();
1018 #endif
1019 
1020  /* allocate the points */
1021  del.points = (point2d_t**)malloc(num_points * sizeof(point2d_t*));
1022  assert( del.points != nullptr );
1023  memset(del.points, 0, num_points * sizeof(point2d_t*));
1024 
1025  /* copy the points */
1026  for( i = 0; i < num_points; i++ )
1027  {
1028  del.points[i] = point_alloc();
1029  del.points[i]->idx = i;
1030  del.points[i]->x = points[i].x;
1031  del.points[i]->y = points[i].y;
1032  }
1033 
1034  qsort(del.points, num_points, sizeof(point2d_t*), cmp_points);
1035 
1036  if( num_points >= 3 ) {
1037  quint32 fbuff_size = 0;
1038  quint32 j = 0;
1039 
1040  del_divide_and_conquer( &del, 0, static_cast<int>(num_points - 1) );
1041  del_build_faces( &del );
1042 
1043  for( i = 0; i < del.num_faces; i++ )
1044  fbuff_size += del.faces[i].num_verts + 1;
1045 
1046  faces = (quint32*)malloc(sizeof(quint32) * fbuff_size);
1047 
1048  for( i = 0; i < del.num_faces; i++ )
1049  {
1050  halfedge_t *curr;
1051 
1052  faces[j] = del.faces[i].num_verts;
1053  j++;
1054 
1055  curr = del.faces[i].he;
1056  do {
1057  faces[j] = curr->vertex->idx;
1058  j++;
1059  curr = curr->pair->prev;
1060  } while( curr != del.faces[i].he );
1061  }
1062 
1063  del_free_halfedges( &del );
1064 
1065  free(del.faces);
1066  for( i = 0; i < num_points; i++ )
1067  point_free(del.points[i]);
1068 
1069  free(del.points);
1070  }
1071 
1072  res = (delaunay2d_t*)malloc(sizeof(delaunay2d_t));
1073  res->num_points = num_points;
1074  res->points = (del_point2d_t*)malloc(sizeof(del_point2d_t) * num_points);
1075  memcpy(res->points, points, sizeof(del_point2d_t) * num_points);
1076  res->num_faces = del.num_faces;
1077  res->faces = faces;
1078 
1079  return res;
1080 }
1081 
1083  free(del->faces);
1084  free(del->points);
1085  free(del);
1086 }
1087 
#define EPSILON
Definition: delaunay.cpp:67
void del_free_halfedges(delaunay_t *del)
Definition: delaunay.cpp:179
real incircle(real *pa, real *pb, real *pc, real *pd)
#define INSIDE
Definition: delaunay.cpp:45
#define ON_CIRCLE
Definition: delaunay.cpp:44
void delaunay2d_release(delaunay2d_t *del)
Definition: delaunay.cpp:1082
#define ON_SEG
Definition: delaunay.cpp:40
#define REAL_TWO
Definition: delaunay.cpp:56
static halfedge_t * del_valid_link(halfedge_t *b)
Definition: delaunay.cpp:770
struct face_s face_t
Definition: delaunay.cpp:70
static int del_classify_point(halfedge_t *d, point2d_t *pt)
Definition: delaunay.cpp:272
static halfedge_t * halfedge_alloc()
Definition: delaunay.cpp:154
static int in_circle(point2d_t *pt0, point2d_t *pt1, point2d_t *pt2, point2d_t *p)
Definition: delaunay.cpp:360
static void del_remove_edge(halfedge_t *d)
Definition: delaunay.cpp:615
static halfedge_t * del_valid_right(halfedge_t *b)
Definition: delaunay.cpp:725
static int classify_point_seg(point2d_t *s, point2d_t *e, point2d_t *pt)
Definition: delaunay.cpp:249
#define OUTSIDE
Definition: delaunay.cpp:43
static void point_free(point2d_t *p)
Definition: delaunay.cpp:145
static halfedge_t * del_valid_left(halfedge_t *b)
Definition: delaunay.cpp:678
static void halfedge_free(halfedge_t *d)
Definition: delaunay.cpp:168
static int del_init_seg(delaunay_t *del, int start)
Definition: delaunay.cpp:451
static void del_link(delaunay_t *result, delaunay_t *left, delaunay_t *right)
Definition: delaunay.cpp:877
#define REAL_FOUR
Definition: delaunay.cpp:57
#define REAL_ZERO
Definition: delaunay.cpp:54
delaunay2d_t * delaunay2d_from(del_point2d_t *points, quint32 num_points)
Definition: delaunay.cpp:1008
#define ON_LEFT
Definition: delaunay.cpp:41
#define REAL_ONE
Definition: delaunay.cpp:55
void del_divide_and_conquer(delaunay_t *del, int start, int end)
Definition: delaunay.cpp:922
void del_build_faces(delaunay_t *del)
Definition: delaunay.cpp:984
static int cmp_points(const void *_pt0, const void *_pt1)
Definition: delaunay.cpp:227
static halfedge_t * del_get_lower_tangent(delaunay_t *left, delaunay_t *right)
Definition: delaunay.cpp:830
static int del_init_tri(delaunay_t *del, int start)
Definition: delaunay.cpp:490
static void build_halfedge_face(delaunay_t *del, halfedge_t *d)
Definition: delaunay.cpp:944
#define ON_RIGHT
Definition: delaunay.cpp:39
QT_WARNING_PUSH void exactinit()
Definition: predicates.cpp:285
static point2d_t * point_alloc()
Definition: delaunay.cpp:130
real mat3_t[3][3]
Definition: delaunay.cpp:73
double real
Definition: delaunay.h:45
quint32 * faces
Definition: delaunay.h:65
quint32 num_points
Definition: delaunay.h:56
quint32 num_faces
Definition: delaunay.h:62
del_point2d_t * points
Definition: delaunay.h:59
point2d_t ** points
Definition: delaunay.cpp:105
face_t * faces
Definition: delaunay.cpp:106
halfedge_t * leftmost_he
Definition: delaunay.cpp:104
quint32 start_point
Definition: delaunay.cpp:108
halfedge_t * rightmost_he
Definition: delaunay.cpp:103
quint32 end_point
Definition: delaunay.cpp:109
quint32 num_faces
Definition: delaunay.cpp:107
quint32 num_verts
Definition: delaunay.cpp:89
halfedge_t * he
Definition: delaunay.cpp:88
face_t * face
Definition: delaunay.cpp:98
halfedge_t * prev
Definition: delaunay.cpp:97
halfedge_t * next
Definition: delaunay.cpp:96
point2d_t * vertex
Definition: delaunay.cpp:94
halfedge_t * pair
Definition: delaunay.cpp:95
real y
Definition: delaunay.cpp:77
halfedge_t * he
Definition: delaunay.cpp:78
real x
Definition: delaunay.cpp:77
quint32 idx
Definition: delaunay.cpp:79