Blender  V2.93
delaunay_2d.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <algorithm>
22 #include <fstream>
23 #include <iostream>
24 #include <sstream>
25 
26 #include "BLI_array.hh"
27 #include "BLI_double2.hh"
28 #include "BLI_linklist.h"
29 #include "BLI_math_boolean.hh"
30 #include "BLI_math_mpq.hh"
31 #include "BLI_mpq2.hh"
32 #include "BLI_vector.hh"
33 
34 #include "BLI_delaunay_2d.h"
35 
36 namespace blender::meshintersect {
37 
38 /* Throughout this file, template argument T will be an
39  * arithmetic-like type, like float, double, or mpq_class. */
40 
41 template<typename T> T math_abs(const T v)
42 {
43  return (v < 0) ? -v : v;
44 }
45 
46 #ifdef WITH_GMP
47 template<> mpq_class math_abs<mpq_class>(const mpq_class v)
48 {
49  return abs(v);
50 }
51 #endif
52 
53 template<> double math_abs<double>(const double v)
54 {
55  return fabs(v);
56 }
57 
58 template<typename T> double math_to_double(const T UNUSED(v))
59 {
60  BLI_assert(false); /* Need implementation for other type. */
61  return 0.0;
62 }
63 
64 #ifdef WITH_GMP
65 template<> double math_to_double<mpq_class>(const mpq_class v)
66 {
67  return v.get_d();
68 }
69 #endif
70 
71 template<> double math_to_double<double>(const double v)
72 {
73  return v;
74 }
75 
87 template<typename Arith_t> struct CDTVert;
88 template<typename Arith_t> struct CDTEdge;
89 template<typename Arith_t> struct CDTFace;
90 
91 template<typename Arith_t> struct SymEdge {
93  SymEdge<Arith_t> *next{nullptr};
95  SymEdge<Arith_t> *rot{nullptr};
97  CDTVert<Arith_t> *vert{nullptr};
99  CDTEdge<Arith_t> *edge{nullptr};
101  CDTFace<Arith_t> *face{nullptr};
102 
103  SymEdge() = default;
104 };
105 
109 template<typename T> inline SymEdge<T> *sym(const SymEdge<T> *se)
110 {
111  return se->next->rot;
112 }
113 
115 template<typename T> inline SymEdge<T> *prev(const SymEdge<T> *se)
116 {
117  return se->rot->next->rot;
118 }
119 
122 template<typename T> struct FatCo {
123  vec2<T> exact;
124  vec2<double> approx;
125  vec2<double> abs_approx;
126 
127  FatCo();
128 #ifdef WITH_GMP
129  FatCo(const vec2<mpq_class> &v);
130 #endif
131  FatCo(const vec2<double> &v);
132 };
133 
134 #ifdef WITH_GMP
135 template<> struct FatCo<mpq_class> {
136  vec2<mpq_class> exact;
137  vec2<double> approx;
138  vec2<double> abs_approx;
139 
140  FatCo()
141  : exact(vec2<mpq_class>(0, 0)), approx(vec2<double>(0, 0)), abs_approx(vec2<double>(0, 0))
142  {
143  }
144 
145  FatCo(const vec2<mpq_class> &v)
146  {
147  exact = v;
148  approx = vec2<double>(v.x.get_d(), v.y.get_d());
149  abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
150  }
151 
152  FatCo(const vec2<double> &v)
153  {
154  exact = vec2<mpq_class>(v.x, v.y);
155  approx = v;
156  abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
157  }
158 };
159 #endif
160 
161 template<> struct FatCo<double> {
162  vec2<double> exact;
163  vec2<double> approx;
164  vec2<double> abs_approx;
165 
166  FatCo() : exact(vec2<double>(0, 0)), approx(vec2<double>(0, 0)), abs_approx(vec2<double>(0, 0))
167  {
168  }
169 
170 #ifdef WITH_GMP
171  FatCo(const vec2<mpq_class> &v)
172  {
173  exact = vec2<double>(v.x.get_d(), v.y.get_d());
174  approx = exact;
175  abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
176  }
177 #endif
178 
179  FatCo(const vec2<double> &v)
180  {
181  exact = v;
182  approx = v;
183  abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
184  }
185 };
186 
187 template<typename T> std::ostream &operator<<(std::ostream &stream, const FatCo<T> &co)
188 {
189  stream << "(" << co.approx.x << ", " << co.approx.y << ")";
190  return stream;
191 }
192 
193 template<typename T> struct CDTVert {
195  FatCo<T> co;
197  SymEdge<T> *symedge{nullptr};
199  LinkNode *input_ids{nullptr};
201  int index{-1};
203  int merge_to_index{-1};
205  int visit_index{0};
206 
207  CDTVert() = default;
208  explicit CDTVert(const vec2<T> &pt);
209 };
210 
211 template<typename Arith_t> struct CDTEdge {
213  LinkNode *input_ids{nullptr};
215  SymEdge<Arith_t> symedges[2]{SymEdge<Arith_t>(), SymEdge<Arith_t>()};
216 
217  CDTEdge() = default;
218 };
219 
220 template<typename Arith_t> struct CDTFace {
222  SymEdge<Arith_t> *symedge{nullptr};
224  LinkNode *input_ids{nullptr};
226  int visit_index{0};
228  bool deleted{false};
229 
230  CDTFace() = default;
231 };
232 
233 template<typename Arith_t> struct CDTArrangement {
234  /* The arrangement owns the memory pointed to by the pointers in these vectors.
235  * They are pointers instead of actual structures because these vectors may be resized and
236  * other elements refer to the elements by pointer. */
237 
239  Vector<CDTVert<Arith_t> *> verts;
241  Vector<CDTEdge<Arith_t> *> edges;
243  Vector<CDTFace<Arith_t> *> faces;
245  CDTFace<Arith_t> *outer_face{nullptr};
246 
247  CDTArrangement() = default;
248  ~CDTArrangement();
249 
252  void reserve(int num_verts, int num_edges, int num_faces);
253 
258  CDTVert<Arith_t> *add_vert(const vec2<Arith_t> &pt);
259 
266  CDTEdge<Arith_t> *add_edge(CDTVert<Arith_t> *v1,
267  CDTVert<Arith_t> *v2,
268  CDTFace<Arith_t> *fleft,
269  CDTFace<Arith_t> *fright);
270 
275  CDTFace<Arith_t> *add_face();
276 
278  CDTEdge<Arith_t> *add_vert_to_symedge_edge(CDTVert<Arith_t> *v, SymEdge<Arith_t> *se);
279 
286  CDTEdge<Arith_t> *add_diagonal(SymEdge<Arith_t> *s1, SymEdge<Arith_t> *s2);
287 
292  CDTEdge<Arith_t> *connect_separate_parts(SymEdge<Arith_t> *se1, SymEdge<Arith_t> *se2);
293 
298  CDTEdge<Arith_t> *split_edge(SymEdge<Arith_t> *se, Arith_t lambda);
299 
305  void delete_edge(SymEdge<Arith_t> *se);
306 
311  CDTVert<Arith_t> *get_vert_resolve_merge(int i)
312  {
313  CDTVert<Arith_t> *v = this->verts[i];
314  if (v->merge_to_index != -1) {
315  v = this->verts[v->merge_to_index];
316  }
317  return v;
318  }
319 };
320 
321 template<typename T> class CDT_state {
322  public:
323  CDTArrangement<T> cdt;
325  int input_vert_tot;
327  int visit_count;
332  int face_edge_offset;
334  T epsilon;
335 
336  explicit CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon);
337 };
338 
339 template<typename T> CDTArrangement<T>::~CDTArrangement()
340 {
341  for (int i : this->verts.index_range()) {
342  CDTVert<T> *v = this->verts[i];
343  BLI_linklist_free(v->input_ids, nullptr);
344  delete v;
345  this->verts[i] = nullptr;
346  }
347  for (int i : this->edges.index_range()) {
348  CDTEdge<T> *e = this->edges[i];
349  BLI_linklist_free(e->input_ids, nullptr);
350  delete e;
351  this->edges[i] = nullptr;
352  }
353  for (int i : this->faces.index_range()) {
354  CDTFace<T> *f = this->faces[i];
355  BLI_linklist_free(f->input_ids, nullptr);
356  delete f;
357  this->faces[i] = nullptr;
358  }
359 }
360 
361 #define DEBUG_CDT
362 #ifdef DEBUG_CDT
363 /* Some functions to aid in debugging. */
364 template<typename T> std::string vertname(const CDTVert<T> *v)
365 {
366  std::stringstream ss;
367  ss << "[" << v->index << "]";
368  return ss.str();
369 }
370 
371 /* Abbreviated pointer value is easier to read in dumps. */
372 static std::string trunc_ptr(const void *p)
373 {
374  constexpr int TRUNC_PTR_MASK = 0xFFFF;
375  std::stringstream ss;
376  ss << std::hex << (POINTER_AS_INT(p) & TRUNC_PTR_MASK);
377  return ss.str();
378 }
379 
380 template<typename T> std::string sename(const SymEdge<T> *se)
381 {
382  std::stringstream ss;
383  ss << "{" << trunc_ptr(se) << "}";
384  return ss.str();
385 }
386 
387 template<typename T> std::ostream &operator<<(std::ostream &os, const SymEdge<T> &se)
388 {
389  if (se.next) {
390  os << vertname(se.vert) << "(" << se.vert->co << "->" << se.next->vert->co << ")"
391  << vertname(se.next->vert);
392  }
393  else {
394  os << vertname(se.vert) << "(" << se.vert->co << "->NULL)";
395  }
396  return os;
397 }
398 
399 template<typename T> std::ostream &operator<<(std::ostream &os, const SymEdge<T> *se)
400 {
401  os << *se;
402  return os;
403 }
404 
405 template<typename T> std::string short_se_dump(const SymEdge<T> *se)
406 {
407  if (se == nullptr) {
408  return std::string("NULL");
409  }
410  return vertname(se->vert) +
411  (se->next == nullptr ? std::string("[NULL]") : vertname(se->next->vert));
412 }
413 
414 template<typename T> std::ostream &operator<<(std::ostream &os, const CDT_state<T> &cdt_state)
415 {
416  os << "\nCDT\n\nVERTS\n";
417  for (const CDTVert<T> *v : cdt_state.cdt.verts) {
418  os << vertname(v) << " " << trunc_ptr(v) << ": " << v->co
419  << " symedge=" << trunc_ptr(v->symedge);
420  if (v->merge_to_index == -1) {
421  os << "\n";
422  }
423  else {
424  os << " merge to " << vertname(cdt_state.cdt.verts[v->merge_to_index]) << "\n";
425  }
426  const SymEdge<T> *se = v->symedge;
427  int cnt = 0;
428  constexpr int print_count_limit = 25;
429  if (se) {
430  os << " edges out:\n";
431  do {
432  if (se->next == NULL) {
433  os << " [NULL] next/rot symedge, se=" << trunc_ptr(se) << "\n";
434  break;
435  }
436  if (se->next->next == NULL) {
437  os << " [NULL] next-next/rot symedge, se=" << trunc_ptr(se) << "\n";
438  break;
439  }
440  const CDTVert<T> *vother = sym(se)->vert;
441  os << " " << vertname(vother) << "(e=" << trunc_ptr(se->edge)
442  << ", se=" << trunc_ptr(se) << ")\n";
443  se = se->rot;
444  cnt++;
445  } while (se != v->symedge && cnt < print_count_limit);
446  os << "\n";
447  }
448  }
449  os << "\nEDGES\n";
450  for (const CDTEdge<T> *e : cdt_state.cdt.edges) {
451  if (e->symedges[0].next == nullptr) {
452  continue;
453  }
454  os << trunc_ptr(&e) << ":\n";
455  for (int i = 0; i < 2; ++i) {
456  const SymEdge<T> *se = &e->symedges[i];
457  os << " se[" << i << "] @" << trunc_ptr(se) << " next=" << trunc_ptr(se->next)
458  << ", rot=" << trunc_ptr(se->rot) << ", vert=" << trunc_ptr(se->vert) << " "
459  << vertname(se->vert) << " " << se->vert->co << ", edge=" << trunc_ptr(se->edge)
460  << ", face=" << trunc_ptr(se->face) << "\n";
461  }
462  }
463  os << "\nFACES\n";
464  os << "outer_face=" << trunc_ptr(cdt_state.cdt.outer_face) << "\n";
465  /* Only after prepare_output do faces have non-null symedges. */
466  if (cdt_state.cdt.outer_face->symedge != nullptr) {
467  for (const CDTFace<T> *f : cdt_state.cdt.faces) {
468  if (!f->deleted) {
469  os << trunc_ptr(f) << " symedge=" << trunc_ptr(f->symedge) << "\n";
470  }
471  }
472  }
473  return os;
474 }
475 
476 template<typename T> void cdt_draw(const std::string &label, const CDTArrangement<T> &cdt)
477 {
478  static bool append = false; /* Will be set to true after first call. */
479 
480 /* Would like to use #BKE_tempdir_base() here, but that brings in dependence on kernel library.
481  * This is just for developer debugging anyway, and should never be called in production Blender.
482  */
483 # ifdef _WIN32
484  const char *drawfile = "./debug_draw.html";
485 # else
486  const char *drawfile = "/tmp/debug_draw.html";
487 # endif
488  constexpr int max_draw_width = 1800;
489  constexpr int max_draw_height = 1600;
490  constexpr double margin_expand = 0.05;
491  constexpr int thin_line = 1;
492  constexpr int thick_line = 4;
493  constexpr int vert_radius = 3;
494  constexpr bool draw_vert_labels = true;
495  constexpr bool draw_edge_labels = false;
496 
497  if (cdt.verts.size() == 0) {
498  return;
499  }
500  vec2<double> vmin(DBL_MAX, DBL_MAX);
501  vec2<double> vmax(-DBL_MAX, -DBL_MAX);
502  for (const CDTVert<T> *v : cdt.verts) {
503  for (int i = 0; i < 2; ++i) {
504  double dvi = v->co.approx[i];
505  if (dvi < vmin[i]) {
506  vmin[i] = dvi;
507  }
508  if (dvi > vmax[i]) {
509  vmax[i] = dvi;
510  }
511  }
512  }
513  double draw_margin = ((vmax.x - vmin.x) + (vmax.y - vmin.y)) * margin_expand;
514  double minx = vmin.x - draw_margin;
515  double maxx = vmax.x + draw_margin;
516  double miny = vmin.y - draw_margin;
517  double maxy = vmax.y + draw_margin;
518 
519  double width = maxx - minx;
520  double height = maxy - miny;
521  double aspect = height / width;
522  int view_width = max_draw_width;
523  int view_height = static_cast<int>(view_width * aspect);
524  if (view_height > max_draw_height) {
525  view_height = max_draw_height;
526  view_width = static_cast<int>(view_height / aspect);
527  }
528  double scale = view_width / width;
529 
530 # define SX(x) (((x)-minx) * scale)
531 # define SY(y) ((maxy - (y)) * scale)
532 
533  std::ofstream f;
534  if (append) {
535  f.open(drawfile, std::ios_base::app);
536  }
537  else {
538  f.open(drawfile);
539  }
540  if (!f) {
541  std::cout << "Could not open file " << drawfile << "\n";
542  return;
543  }
544 
545  f << "<div>" << label << "</div>\n<div>\n"
546  << "<svg version=\"1.1\" "
547  "xmlns=\"http://www.w3.org/2000/svg\" "
548  "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
549  "xml:space=\"preserve\"\n"
550  << "width=\"" << view_width << "\" height=\"" << view_height << "\">n";
551 
552  for (const CDTEdge<T> *e : cdt.edges) {
553  if (e->symedges[0].next == nullptr) {
554  continue;
555  }
556  const CDTVert<T> *u = e->symedges[0].vert;
557  const CDTVert<T> *v = e->symedges[1].vert;
558  const vec2<double> &uco = u->co.approx;
559  const vec2<double> &vco = v->co.approx;
560  int strokew = e->input_ids == nullptr ? thin_line : thick_line;
561  f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
562  << SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\""
563  << SY(vco[1]) << "\">\n";
564  f << " <title>" << vertname(u) << vertname(v) << "</title>\n";
565  f << "</line>\n";
566  if (draw_edge_labels) {
567  f << "<text x=\"" << SX((uco[0] + vco[0]) / 2) << "\" y=\"" << SY((uco[1] + vco[1]) / 2)
568  << R"(" font-size="small">)";
569  f << vertname(u) << vertname(v) << sename(&e->symedges[0]) << sename(&e->symedges[1])
570  << "</text>\n";
571  }
572  }
573 
574  int i = 0;
575  for (const CDTVert<T> *v : cdt.verts) {
576  f << R"(<circle fill="black" cx=")" << SX(v->co.approx[0]) << "\" cy=\"" << SY(v->co.approx[1])
577  << "\" r=\"" << vert_radius << "\">\n";
578  f << " <title>[" << i << "]" << v->co.approx << "</title>\n";
579  f << "</circle>\n";
580  if (draw_vert_labels) {
581  f << "<text x=\"" << SX(v->co.approx[0]) + vert_radius << "\" y=\""
582  << SY(v->co.approx[1]) - vert_radius << R"(" font-size="small">[)" << i << "]</text>\n";
583  }
584  ++i;
585  }
586 
587  append = true;
588 # undef SX
589 # undef SY
590 }
591 #endif
592 
597 template<typename T>
598 static int filtered_orient2d(const FatCo<T> &a, const FatCo<T> &b, const FatCo<T> &c);
599 
600 #ifdef WITH_GMP
601 template<>
602 int filtered_orient2d<mpq_class>(const FatCo<mpq_class> &a,
603  const FatCo<mpq_class> &b,
604  const FatCo<mpq_class> &c)
605 {
606  double det = (a.approx[0] - c.approx[0]) * (b.approx[1] - c.approx[1]) -
607  (a.approx[1] - c.approx[1]) * (b.approx[0] - c.approx[0]);
608  double supremum = (a.abs_approx[0] + c.abs_approx[0]) * (b.abs_approx[1] + c.abs_approx[1]) +
609  (a.abs_approx[1] + c.abs_approx[1]) * (b.abs_approx[0] + c.abs_approx[0]);
610  constexpr double index_orient2d = 6;
611  double err_bound = supremum * index_orient2d * DBL_EPSILON;
612  if (fabs(det) > err_bound) {
613  return det > 0 ? 1 : -1;
614  }
615  return orient2d(a.exact, b.exact, c.exact);
616 }
617 #endif
618 
619 template<>
620 int filtered_orient2d<double>(const FatCo<double> &a,
621  const FatCo<double> &b,
622  const FatCo<double> &c)
623 {
624  return orient2d(a.approx, b.approx, c.approx);
625 }
626 
630 template<typename T>
631 static int filtered_incircle(const FatCo<T> &a,
632  const FatCo<T> &b,
633  const FatCo<T> &c,
634  const FatCo<T> &d);
635 
636 #ifdef WITH_GMP
637 template<>
638 int filtered_incircle<mpq_class>(const FatCo<mpq_class> &a,
639  const FatCo<mpq_class> &b,
640  const FatCo<mpq_class> &c,
641  const FatCo<mpq_class> &d)
642 {
643  double adx = a.approx[0] - d.approx[0];
644  double bdx = b.approx[0] - d.approx[0];
645  double cdx = c.approx[0] - d.approx[0];
646  double ady = a.approx[1] - d.approx[1];
647  double bdy = b.approx[1] - d.approx[1];
648  double cdy = c.approx[1] - d.approx[1];
649  double bdxcdy = bdx * cdy;
650  double cdxbdy = cdx * bdy;
651  double alift = adx * adx + ady * ady;
652  double cdxady = cdx * ady;
653  double adxcdy = adx * cdy;
654  double blift = bdx * bdx + bdy * bdy;
655  double adxbdy = adx * bdy;
656  double bdxady = bdx * ady;
657  double clift = cdx * cdx + cdy * cdy;
658  double det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
659 
660  double sup_adx = a.abs_approx[0] + d.abs_approx[0]; /* index 2. */
661  double sup_bdx = b.abs_approx[0] + d.abs_approx[0];
662  double sup_cdx = c.abs_approx[0] + d.abs_approx[0];
663  double sup_ady = a.abs_approx[1] + d.abs_approx[1];
664  double sup_bdy = b.abs_approx[1] + d.abs_approx[1];
665  double sup_cdy = c.abs_approx[1] + d.abs_approx[1];
666  double sup_bdxcdy = sup_bdx * sup_cdy; /* index 5. */
667  double sup_cdxbdy = sup_cdx * sup_bdy;
668  double sup_alift = sup_adx * sup_adx + sup_ady * sup_ady; /* index 6. */
669  double sup_cdxady = sup_cdx * sup_ady;
670  double sup_adxcdy = sup_adx * sup_cdy;
671  double sup_blift = sup_bdx * sup_bdx + sup_bdy * sup_bdy;
672  double sup_adxbdy = sup_adx * sup_bdy;
673  double sup_bdxady = sup_bdx * sup_ady;
674  double sup_clift = sup_cdx * sup_cdx + sup_cdy * sup_cdy;
675  double sup_det = sup_alift * (sup_bdxcdy + sup_cdxbdy) + sup_blift * (sup_cdxady + sup_adxcdy) +
676  sup_clift * (sup_adxbdy + sup_bdxady);
677  int index = 14;
678  double err_bound = sup_det * index * DBL_EPSILON;
679  if (fabs(det) > err_bound) {
680  return det < 0.0 ? -1 : (det > 0.0 ? 1 : 0);
681  }
682  return incircle(a.exact, b.exact, c.exact, d.exact);
683 }
684 #endif
685 
686 template<>
687 int filtered_incircle<double>(const FatCo<double> &a,
688  const FatCo<double> &b,
689  const FatCo<double> &c,
690  const FatCo<double> &d)
691 {
692  return incircle(a.approx, b.approx, c.approx, d.approx);
693 }
694 
701 template<typename T> static bool in_line(const FatCo<T> &a, const FatCo<T> &b, const FatCo<T> &c);
702 
703 #ifdef WITH_GMP
704 template<>
705 bool in_line<mpq_class>(const FatCo<mpq_class> &a,
706  const FatCo<mpq_class> &b,
707  const FatCo<mpq_class> &c)
708 {
709  vec2<double> ab = b.approx - a.approx;
710  vec2<double> bc = c.approx - b.approx;
711  vec2<double> ac = c.approx - a.approx;
712  vec2<double> supremum_ab = b.abs_approx + a.abs_approx;
713  vec2<double> supremum_bc = c.abs_approx + b.abs_approx;
714  vec2<double> supremum_ac = c.abs_approx + a.abs_approx;
715  double dot_ab_ac = ab.x * ac.x + ab.y * ac.y;
716  double supremum_dot_ab_ac = supremum_ab.x * supremum_ac.x + supremum_ab.y * supremum_ac.y;
717  constexpr double index = 6;
718  double err_bound = supremum_dot_ab_ac * index * DBL_EPSILON;
719  if (dot_ab_ac < -err_bound) {
720  return false;
721  }
722  double dot_bc_ac = bc.x * ac.x + bc.y * ac.y;
723  double supremum_dot_bc_ac = supremum_bc.x * supremum_ac.x + supremum_bc.y * supremum_ac.y;
724  err_bound = supremum_dot_bc_ac * index * DBL_EPSILON;
725  if (dot_bc_ac < -err_bound) {
726  return false;
727  }
728  vec2<mpq_class> exact_ab = b.exact - a.exact;
729  vec2<mpq_class> exact_ac = c.exact - a.exact;
730  if (vec2<mpq_class>::dot(exact_ab, exact_ac) < 0) {
731  return false;
732  }
733  vec2<mpq_class> exact_bc = c.exact - b.exact;
734  return vec2<mpq_class>::dot(exact_bc, exact_ac) >= 0;
735 }
736 #endif
737 
738 template<>
739 bool in_line<double>(const FatCo<double> &a, const FatCo<double> &b, const FatCo<double> &c)
740 {
741  vec2<double> ab = b.approx - a.approx;
742  vec2<double> ac = c.approx - a.approx;
743  if (vec2<double>::dot(ab, ac) < 0) {
744  return false;
745  }
746  vec2<double> bc = c.approx - b.approx;
747  return vec2<double>::dot(bc, ac) >= 0;
748 }
749 
750 template<> CDTVert<double>::CDTVert(const vec2<double> &pt)
751 {
752  this->co.exact = pt;
753  this->co.approx = pt;
754  this->co.abs_approx = pt; /* Not used, so doesn't matter. */
755  this->input_ids = nullptr;
756  this->symedge = nullptr;
757  this->index = -1;
758  this->merge_to_index = -1;
759  this->visit_index = 0;
760 }
761 
762 #ifdef WITH_GMP
763 template<> CDTVert<mpq_class>::CDTVert(const vec2<mpq_class> &pt)
764 {
765  this->co.exact = pt;
766  this->co.approx = double2(pt.x.get_d(), pt.y.get_d());
767  this->co.abs_approx = double2(fabs(this->co.approx.x), fabs(this->co.approx.y));
768  this->input_ids = nullptr;
769  this->symedge = nullptr;
770  this->index = -1;
771  this->merge_to_index = -1;
772  this->visit_index = 0;
773 }
774 #endif
775 
776 template<typename T> CDTVert<T> *CDTArrangement<T>::add_vert(const vec2<T> &pt)
777 {
778  CDTVert<T> *v = new CDTVert<T>(pt);
779  int index = this->verts.append_and_get_index(v);
780  v->index = index;
781  return v;
782 }
783 
784 template<typename T>
785 CDTEdge<T> *CDTArrangement<T>::add_edge(CDTVert<T> *v1,
786  CDTVert<T> *v2,
787  CDTFace<T> *fleft,
788  CDTFace<T> *fright)
789 {
790  CDTEdge<T> *e = new CDTEdge<T>();
791  this->edges.append(e);
792  SymEdge<T> *se = &e->symedges[0];
793  SymEdge<T> *sesym = &e->symedges[1];
794  se->edge = sesym->edge = e;
795  se->face = fleft;
796  sesym->face = fright;
797  se->vert = v1;
798  if (v1->symedge == nullptr) {
799  v1->symedge = se;
800  }
801  sesym->vert = v2;
802  if (v2->symedge == nullptr) {
803  v2->symedge = sesym;
804  }
805  se->next = sesym->next = se->rot = sesym->rot = nullptr;
806  return e;
807 }
808 
809 template<typename T> CDTFace<T> *CDTArrangement<T>::add_face()
810 {
811  CDTFace<T> *f = new CDTFace<T>();
812  this->faces.append(f);
813  return f;
814 }
815 
816 template<typename T> void CDTArrangement<T>::reserve(int num_verts, int num_edges, int num_faces)
817 {
818  /* These reserves are just guesses; OK if they aren't exactly right since vectors will resize. */
819  this->verts.reserve(2 * num_verts);
820  this->edges.reserve(3 * num_verts + 2 * num_edges + 3 * 2 * num_faces);
821  this->faces.reserve(2 * num_verts + 2 * num_edges + 2 * num_faces);
822 }
823 
824 template<typename T>
825 CDT_state<T>::CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon)
826 {
827  this->input_vert_tot = num_input_verts;
828  this->cdt.reserve(num_input_verts, num_input_edges, num_input_faces);
829  this->cdt.outer_face = this->cdt.add_face();
830  this->epsilon = epsilon;
831  this->visit_count = 0;
832 }
833 
834 static bool id_in_list(const LinkNode *id_list, int id)
835 {
836  const LinkNode *ln;
837 
838  for (ln = id_list; ln != nullptr; ln = ln->next) {
839  if (POINTER_AS_INT(ln->link) == id) {
840  return true;
841  }
842  }
843  return false;
844 }
845 
846 /* Is any id in (range_start, range_start+1, ... , range_end) in id_list? */
847 static bool id_range_in_list(const LinkNode *id_list, int range_start, int range_end)
848 {
849  const LinkNode *ln;
850  int id;
851 
852  for (ln = id_list; ln != nullptr; ln = ln->next) {
853  id = POINTER_AS_INT(ln->link);
854  if (id >= range_start && id <= range_end) {
855  return true;
856  }
857  }
858  return false;
859 }
860 
861 static void add_to_input_ids(LinkNode **dst, int input_id)
862 {
863  if (!id_in_list(*dst, input_id)) {
864  BLI_linklist_prepend(dst, POINTER_FROM_INT(input_id));
865  }
866 }
867 
868 static void add_list_to_input_ids(LinkNode **dst, const LinkNode *src)
869 {
870  const LinkNode *ln;
871 
872  for (ln = src; ln != nullptr; ln = ln->next) {
873  add_to_input_ids(dst, POINTER_AS_INT(ln->link));
874  }
875 }
876 
877 template<typename T> inline bool is_border_edge(const CDTEdge<T> *e, const CDT_state<T> *cdt)
878 {
879  return e->symedges[0].face == cdt->outer_face || e->symedges[1].face == cdt->outer_face;
880 }
881 
882 template<typename T> inline bool is_constrained_edge(const CDTEdge<T> *e)
883 {
884  return e->input_ids != nullptr;
885 }
886 
887 template<typename T> inline bool is_deleted_edge(const CDTEdge<T> *e)
888 {
889  return e->symedges[0].next == nullptr;
890 }
891 
892 template<typename T> inline bool is_original_vert(const CDTVert<T> *v, CDT_state<T> *cdt)
893 {
894  return (v->index < cdt->input_vert_tot);
895 }
896 
897 /* Return the Symedge that goes from v1 to v2, if it exists, else return nullptr. */
898 template<typename T>
899 SymEdge<T> *find_symedge_between_verts(const CDTVert<T> *v1, const CDTVert<T> *v2)
900 {
901  SymEdge<T> *t = v1->symedge;
902  SymEdge<T> *tstart = t;
903  do {
904  if (t->next->vert == v2) {
905  return t;
906  }
907  } while ((t = t->rot) != tstart);
908  return nullptr;
909 }
910 
914 template<typename T> SymEdge<T> *find_symedge_with_face(const CDTVert<T> *v, const CDTFace<T> *f)
915 {
916  SymEdge<T> *t = v->symedge;
917  SymEdge<T> *tstart = t;
918  do {
919  if (t->face == f) {
920  return t;
921  }
922  } while ((t = t->rot) != tstart);
923  return nullptr;
924 }
925 
929 template<typename T> inline bool exists_edge(const CDTVert<T> *v1, const CDTVert<T> *v2)
930 {
931  return find_symedge_between_verts(v1, v2) != nullptr;
932 }
933 
937 template<typename T> bool vert_touches_face(const CDTVert<T> *v, const CDTFace<T> *f)
938 {
939  SymEdge<T> *se = v->symedge;
940  do {
941  if (se->face == f) {
942  return true;
943  }
944  } while ((se = se->rot) != v->symedge);
945  return false;
946 }
947 
956 template<typename T> CDTEdge<T> *CDTArrangement<T>::add_diagonal(SymEdge<T> *s1, SymEdge<T> *s2)
957 {
958  CDTFace<T> *fold = s1->face;
959  CDTFace<T> *fnew = this->add_face();
960  SymEdge<T> *s1prev = prev(s1);
961  SymEdge<T> *s1prevsym = sym(s1prev);
962  SymEdge<T> *s2prev = prev(s2);
963  SymEdge<T> *s2prevsym = sym(s2prev);
964  CDTEdge<T> *ediag = this->add_edge(s1->vert, s2->vert, fnew, fold);
965  SymEdge<T> *sdiag = &ediag->symedges[0];
966  SymEdge<T> *sdiagsym = &ediag->symedges[1];
967  sdiag->next = s2;
968  sdiagsym->next = s1;
969  s2prev->next = sdiagsym;
970  s1prev->next = sdiag;
971  s1->rot = sdiag;
972  sdiag->rot = s1prevsym;
973  s2->rot = sdiagsym;
974  sdiagsym->rot = s2prevsym;
975  for (SymEdge<T> *se = s2; se != sdiag; se = se->next) {
976  se->face = fnew;
977  }
978  add_list_to_input_ids(&fnew->input_ids, fold->input_ids);
979  return ediag;
980 }
981 
982 template<typename T>
983 CDTEdge<T> *CDTArrangement<T>::add_vert_to_symedge_edge(CDTVert<T> *v, SymEdge<T> *se)
984 {
985  SymEdge<T> *se_rot = se->rot;
986  SymEdge<T> *se_rotsym = sym(se_rot);
987  /* TODO: check: I think last arg in next should be sym(se)->face. */
988  CDTEdge<T> *e = this->add_edge(v, se->vert, se->face, se->face);
989  SymEdge<T> *new_se = &e->symedges[0];
990  SymEdge<T> *new_se_sym = &e->symedges[1];
991  new_se->next = se;
992  new_se_sym->next = new_se;
993  new_se->rot = new_se;
994  new_se_sym->rot = se_rot;
995  se->rot = new_se_sym;
996  se_rotsym->next = new_se_sym;
997  return e;
998 }
999 
1005 template<typename T>
1006 CDTEdge<T> *CDTArrangement<T>::connect_separate_parts(SymEdge<T> *se1, SymEdge<T> *se2)
1007 {
1008  BLI_assert(se1->face == this->outer_face && se2->face == this->outer_face);
1009  SymEdge<T> *se1_rot = se1->rot;
1010  SymEdge<T> *se1_rotsym = sym(se1_rot);
1011  SymEdge<T> *se2_rot = se2->rot;
1012  SymEdge<T> *se2_rotsym = sym(se2_rot);
1013  CDTEdge<T> *e = this->add_edge(se1->vert, se2->vert, this->outer_face, this->outer_face);
1014  SymEdge<T> *new_se = &e->symedges[0];
1015  SymEdge<T> *new_se_sym = &e->symedges[1];
1016  new_se->next = se2;
1017  new_se_sym->next = se1;
1018  new_se->rot = se1_rot;
1019  new_se_sym->rot = se2_rot;
1020  se1->rot = new_se;
1021  se2->rot = new_se_sym;
1022  se1_rotsym->next = new_se;
1023  se2_rotsym->next = new_se_sym;
1024  return e;
1025 }
1026 
1032 template<typename T> CDTEdge<T> *CDTArrangement<T>::split_edge(SymEdge<T> *se, T lambda)
1033 {
1034  /* Split e at lambda. */
1035  const vec2<T> *a = &se->vert->co.exact;
1036  const vec2<T> *b = &se->next->vert->co.exact;
1037  SymEdge<T> *sesym = sym(se);
1038  SymEdge<T> *sesymprev = prev(sesym);
1039  SymEdge<T> *sesymprevsym = sym(sesymprev);
1040  SymEdge<T> *senext = se->next;
1041  CDTVert<T> *v = this->add_vert(vec2<T>::interpolate(*a, *b, lambda));
1042  CDTEdge<T> *e = this->add_edge(v, se->next->vert, se->face, sesym->face);
1043  sesym->vert = v;
1044  SymEdge<T> *newse = &e->symedges[0];
1045  SymEdge<T> *newsesym = &e->symedges[1];
1046  se->next = newse;
1047  newsesym->next = sesym;
1048  newse->next = senext;
1049  newse->rot = sesym;
1050  sesym->rot = newse;
1051  senext->rot = newsesym;
1052  newsesym->rot = sesymprevsym;
1053  sesymprev->next = newsesym;
1054  if (newsesym->vert->symedge == sesym) {
1055  newsesym->vert->symedge = newsesym;
1056  }
1057  add_list_to_input_ids(&e->input_ids, se->edge->input_ids);
1058  return e;
1059 }
1060 
1082 template<typename T> void CDTArrangement<T>::delete_edge(SymEdge<T> *se)
1083 {
1084  SymEdge<T> *sesym = sym(se);
1085  CDTVert<T> *v1 = se->vert;
1086  CDTVert<T> *v2 = sesym->vert;
1087  CDTFace<T> *aface = se->face;
1088  CDTFace<T> *bface = sesym->face;
1089  SymEdge<T> *f = se->next;
1090  SymEdge<T> *h = prev(se);
1091  SymEdge<T> *i = sesym->next;
1092  SymEdge<T> *j = prev(sesym);
1093  SymEdge<T> *jsym = sym(j);
1094  SymEdge<T> *hsym = sym(h);
1095  bool v1_isolated = (i == se);
1096  bool v2_isolated = (f == sesym);
1097 
1098  if (!v1_isolated) {
1099  h->next = i;
1100  i->rot = hsym;
1101  }
1102  if (!v2_isolated) {
1103  j->next = f;
1104  f->rot = jsym;
1105  }
1106  if (!v1_isolated && !v2_isolated && aface != bface) {
1107  for (SymEdge<T> *k = i; k != f; k = k->next) {
1108  k->face = aface;
1109  }
1110  }
1111 
1112  /* If e was representative symedge for v1 or v2, fix that. */
1113  if (v1_isolated) {
1114  v1->symedge = nullptr;
1115  }
1116  else if (v1->symedge == se) {
1117  v1->symedge = i;
1118  }
1119  if (v2_isolated) {
1120  v2->symedge = nullptr;
1121  }
1122  else if (v2->symedge == sesym) {
1123  v2->symedge = f;
1124  }
1125 
1126  /* Mark SymEdge as deleted by setting all its pointers to NULL. */
1127  se->next = se->rot = nullptr;
1128  sesym->next = sesym->rot = nullptr;
1129  if (!v1_isolated && !v2_isolated && aface != bface) {
1130  bface->deleted = true;
1131  if (this->outer_face == bface) {
1132  this->outer_face = aface;
1133  }
1134  }
1135 }
1136 
1137 template<typename T> class SiteInfo {
1138  public:
1139  CDTVert<T> *v;
1140  int orig_index;
1141 };
1142 
1146 template<typename T> bool site_lexicographic_sort(const SiteInfo<T> &a, const SiteInfo<T> &b)
1147 {
1148  const vec2<T> &co_a = a.v->co.exact;
1149  const vec2<T> &co_b = b.v->co.exact;
1150  if (co_a[0] < co_b[0]) {
1151  return true;
1152  }
1153  if (co_a[0] > co_b[0]) {
1154  return false;
1155  }
1156  if (co_a[1] < co_b[1]) {
1157  return true;
1158  }
1159  if (co_a[1] > co_b[1]) {
1160  return false;
1161  }
1162  return a.orig_index < b.orig_index;
1163 }
1164 
1170 template<typename T> void find_site_merges(Array<SiteInfo<T>> &sites)
1171 {
1172  int n = sites.size();
1173  for (int i = 0; i < n - 1; ++i) {
1174  int j = i + 1;
1175  while (j < n && sites[j].v->co.exact == sites[i].v->co.exact) {
1176  sites[j].v->merge_to_index = sites[i].orig_index;
1177  ++j;
1178  }
1179  if (j - i > 1) {
1180  i = j - 1; /* j-1 because loop head will add another 1. */
1181  }
1182  }
1183 }
1184 
1185 template<typename T> inline bool vert_left_of_symedge(CDTVert<T> *v, SymEdge<T> *se)
1186 {
1187  return filtered_orient2d(v->co, se->vert->co, se->next->vert->co) > 0;
1188 }
1189 
1190 template<typename T> inline bool vert_right_of_symedge(CDTVert<T> *v, SymEdge<T> *se)
1191 {
1192  return filtered_orient2d(v->co, se->next->vert->co, se->vert->co) > 0;
1193 }
1194 
1195 /* Is se above basel? */
1196 template<typename T>
1197 inline bool dc_tri_valid(SymEdge<T> *se, SymEdge<T> *basel, SymEdge<T> *basel_sym)
1198 {
1199  return filtered_orient2d(se->next->vert->co, basel_sym->vert->co, basel->vert->co) > 0;
1200 }
1201 
1208 template<typename T>
1209 void dc_tri(CDTArrangement<T> *cdt,
1210  Array<SiteInfo<T>> &sites,
1211  int start,
1212  int end,
1213  SymEdge<T> **r_le,
1214  SymEdge<T> **r_re)
1215 {
1216  constexpr int dbg_level = 0;
1217  if (dbg_level > 0) {
1218  std::cout << "DC_TRI start=" << start << " end=" << end << "\n";
1219  }
1220  int n = end - start;
1221  if (n <= 1) {
1222  *r_le = nullptr;
1223  *r_re = nullptr;
1224  return;
1225  }
1226 
1227  /* Base case: if n <= 3, triangulate directly. */
1228  if (n <= 3) {
1229  CDTVert<T> *v1 = sites[start].v;
1230  CDTVert<T> *v2 = sites[start + 1].v;
1231  CDTEdge<T> *ea = cdt->add_edge(v1, v2, cdt->outer_face, cdt->outer_face);
1232  ea->symedges[0].next = &ea->symedges[1];
1233  ea->symedges[1].next = &ea->symedges[0];
1234  ea->symedges[0].rot = &ea->symedges[0];
1235  ea->symedges[1].rot = &ea->symedges[1];
1236  if (n == 2) {
1237  *r_le = &ea->symedges[0];
1238  *r_re = &ea->symedges[1];
1239  return;
1240  }
1241  CDTVert<T> *v3 = sites[start + 2].v;
1242  CDTEdge<T> *eb = cdt->add_vert_to_symedge_edge(v3, &ea->symedges[1]);
1243  int orient = filtered_orient2d(v1->co, v2->co, v3->co);
1244  if (orient > 0) {
1245  cdt->add_diagonal(&eb->symedges[0], &ea->symedges[0]);
1246  *r_le = &ea->symedges[0];
1247  *r_re = &eb->symedges[0];
1248  }
1249  else if (orient < 0) {
1250  cdt->add_diagonal(&ea->symedges[0], &eb->symedges[0]);
1251  *r_le = ea->symedges[0].rot;
1252  *r_re = eb->symedges[0].rot;
1253  }
1254  else {
1255  /* Collinear points. Just return a line. */
1256  *r_le = &ea->symedges[0];
1257  *r_re = &eb->symedges[0];
1258  }
1259  return;
1260  }
1261  /* Recursive case. Do left (L) and right (R) halves separately, then join. */
1262  int n2 = n / 2;
1263  BLI_assert(n2 >= 2 && end - (start + n2) >= 2);
1264  SymEdge<T> *ldo;
1265  SymEdge<T> *ldi;
1266  SymEdge<T> *rdi;
1267  SymEdge<T> *rdo;
1268  dc_tri(cdt, sites, start, start + n2, &ldo, &ldi);
1269  dc_tri(cdt, sites, start + n2, end, &rdi, &rdo);
1270  if (dbg_level > 0) {
1271  std::cout << "\nDC_TRI merge step for start=" << start << ", end=" << end << "\n";
1272  std::cout << "ldo " << ldo << "\n"
1273  << "ldi " << ldi << "\n"
1274  << "rdi " << rdi << "\n"
1275  << "rdo " << rdo << "\n";
1276  if (dbg_level > 1) {
1277  std::string lab = "dc_tri (" + std::to_string(start) + "," + std::to_string(start + n2) +
1278  ")(" + std::to_string(start + n2) + "," + std::to_string(end) + ")";
1279  cdt_draw(lab, *cdt);
1280  }
1281  }
1282  /* Find lower common tangent of L and R. */
1283  for (;;) {
1284  if (vert_left_of_symedge(rdi->vert, ldi)) {
1285  ldi = ldi->next;
1286  }
1287  else if (vert_right_of_symedge(ldi->vert, rdi)) {
1288  rdi = sym(rdi)->rot; /* Previous edge to rdi with same right face. */
1289  }
1290  else {
1291  break;
1292  }
1293  }
1294  if (dbg_level > 0) {
1295  std::cout << "common lower tangent in between\n"
1296  << "rdi " << rdi << "\n"
1297  << "ldi" << ldi << "\n";
1298  }
1299 
1300  CDTEdge<T> *ebasel = cdt->connect_separate_parts(sym(rdi)->next, ldi);
1301  SymEdge<T> *basel = &ebasel->symedges[0];
1302  SymEdge<T> *basel_sym = &ebasel->symedges[1];
1303  if (dbg_level > 1) {
1304  std::cout << "basel " << basel;
1305  cdt_draw("after basel made", *cdt);
1306  }
1307  if (ldi->vert == ldo->vert) {
1308  ldo = basel_sym;
1309  }
1310  if (rdi->vert == rdo->vert) {
1311  rdo = basel;
1312  }
1313 
1314  /* Merge loop. */
1315  for (;;) {
1316  /* Locate the first point lcand->next->vert encountered by rising bubble,
1317  * and delete L edges out of basel->next->vert that fail the circle test. */
1318  SymEdge<T> *lcand = basel_sym->rot;
1319  SymEdge<T> *rcand = basel_sym->next;
1320  if (dbg_level > 1) {
1321  std::cout << "\ntop of merge loop\n";
1322  std::cout << "lcand " << lcand << "\n"
1323  << "rcand " << rcand << "\n"
1324  << "basel " << basel << "\n";
1325  }
1326  if (dc_tri_valid(lcand, basel, basel_sym)) {
1327  if (dbg_level > 1) {
1328  std::cout << "found valid lcand\n";
1329  std::cout << " lcand" << lcand << "\n";
1330  }
1331  while (filtered_incircle(basel_sym->vert->co,
1332  basel->vert->co,
1333  lcand->next->vert->co,
1334  lcand->rot->next->vert->co) > 0.0) {
1335  if (dbg_level > 1) {
1336  std::cout << "incircle says to remove lcand\n";
1337  std::cout << " lcand" << lcand << "\n";
1338  }
1339  SymEdge<T> *t = lcand->rot;
1340  cdt->delete_edge(sym(lcand));
1341  lcand = t;
1342  }
1343  }
1344  /* Symmetrically, locate first R point to be hit and delete R edges. */
1345  if (dc_tri_valid(rcand, basel, basel_sym)) {
1346  if (dbg_level > 1) {
1347  std::cout << "found valid rcand\n";
1348  std::cout << " rcand" << rcand << "\n";
1349  }
1350  while (filtered_incircle(basel_sym->vert->co,
1351  basel->vert->co,
1352  rcand->next->vert->co,
1353  sym(rcand)->next->next->vert->co) > 0.0) {
1354  if (dbg_level > 0) {
1355  std::cout << "incircle says to remove rcand\n";
1356  std::cout << " rcand" << rcand << "\n";
1357  }
1358  SymEdge<T> *t = sym(rcand)->next;
1359  cdt->delete_edge(rcand);
1360  rcand = t;
1361  }
1362  }
1363  /* If both lcand and rcand are invalid, then basel is the common upper tangent. */
1364  bool valid_lcand = dc_tri_valid(lcand, basel, basel_sym);
1365  bool valid_rcand = dc_tri_valid(rcand, basel, basel_sym);
1366  if (dbg_level > 0) {
1367  std::cout << "after bubbling up, valid_lcand=" << valid_lcand
1368  << ", valid_rand=" << valid_rcand << "\n";
1369  std::cout << "lcand" << lcand << "\n"
1370  << "rcand" << rcand << "\n";
1371  }
1372  if (!valid_lcand && !valid_rcand) {
1373  break;
1374  }
1375  /* The next cross edge to be connected is to either `lcand->next->vert` or `rcand->next->vert`;
1376  * if both are valid, choose the appropriate one using the #incircle test. */
1377  if (!valid_lcand || (valid_rcand && filtered_incircle(lcand->next->vert->co,
1378  lcand->vert->co,
1379  rcand->vert->co,
1380  rcand->next->vert->co) > 0)) {
1381  if (dbg_level > 0) {
1382  std::cout << "connecting rcand\n";
1383  std::cout << " se1=basel_sym" << basel_sym << "\n";
1384  std::cout << " se2=rcand->next" << rcand->next << "\n";
1385  }
1386  ebasel = cdt->add_diagonal(rcand->next, basel_sym);
1387  }
1388  else {
1389  if (dbg_level > 0) {
1390  std::cout << "connecting lcand\n";
1391  std::cout << " se1=sym(lcand)" << sym(lcand) << "\n";
1392  std::cout << " se2=basel_sym->next" << basel_sym->next << "\n";
1393  }
1394  ebasel = cdt->add_diagonal(basel_sym->next, sym(lcand));
1395  }
1396  basel = &ebasel->symedges[0];
1397  basel_sym = &ebasel->symedges[1];
1398  BLI_assert(basel_sym->face == cdt->outer_face);
1399  if (dbg_level > 2) {
1400  cdt_draw("after adding new crossedge", *cdt);
1401  }
1402  }
1403  *r_le = ldo;
1404  *r_re = rdo;
1405  BLI_assert(sym(ldo)->face == cdt->outer_face && rdo->face == cdt->outer_face);
1406 }
1407 
1408 /* Guibas-Stolfi Divide-and_Conquer algorithm. */
1409 template<typename T> void dc_triangulate(CDTArrangement<T> *cdt, Array<SiteInfo<T>> &sites)
1410 {
1411  /* Compress sites in place to eliminated verts that merge to others. */
1412  int i = 0;
1413  int j = 0;
1414  int nsites = sites.size();
1415  while (j < nsites) {
1416  /* Invariant: `sites[0..i-1]` have non-merged verts from `0..(j-1)` in them. */
1417  sites[i] = sites[j++];
1418  if (sites[i].v->merge_to_index < 0) {
1419  i++;
1420  }
1421  }
1422  int n = i;
1423  if (n == 0) {
1424  return;
1425  }
1426  SymEdge<T> *le;
1427  SymEdge<T> *re;
1428  dc_tri(cdt, sites, 0, n, &le, &re);
1429 }
1430 
1449 template<typename T> void initial_triangulation(CDTArrangement<T> *cdt)
1450 {
1451  int n = cdt->verts.size();
1452  if (n <= 1) {
1453  return;
1454  }
1455  Array<SiteInfo<T>> sites(n);
1456  for (int i = 0; i < n; ++i) {
1457  sites[i].v = cdt->verts[i];
1458  sites[i].orig_index = i;
1459  }
1460  std::sort(sites.begin(), sites.end(), site_lexicographic_sort<T>);
1461  find_site_merges(sites);
1462  dc_triangulate(cdt, sites);
1463 }
1464 
1472 template<typename T> static void re_delaunay_triangulate(CDTArrangement<T> *cdt, SymEdge<T> *se)
1473 {
1474  if (se->face == cdt->outer_face || sym(se)->face == cdt->outer_face) {
1475  return;
1476  }
1477  /* 'se' is a diagonal just added, and it is base of area to retriangulate (face on its left) */
1478  int count = 1;
1479  for (SymEdge<T> *ss = se->next; ss != se; ss = ss->next) {
1480  count++;
1481  }
1482  if (count <= 3) {
1483  return;
1484  }
1485  /* First and last are the SymEdges whose verts are first and last off of base,
1486  * continuing from 'se'. */
1487  SymEdge<T> *first = se->next->next;
1488  /* We want to make a triangle with 'se' as base and some other c as 3rd vertex. */
1489  CDTVert<T> *a = se->vert;
1490  CDTVert<T> *b = se->next->vert;
1491  CDTVert<T> *c = first->vert;
1492  SymEdge<T> *cse = first;
1493  for (SymEdge<T> *ss = first->next; ss != se; ss = ss->next) {
1494  CDTVert<T> *v = ss->vert;
1495  if (filtered_incircle(a->co, b->co, c->co, v->co) > 0) {
1496  c = v;
1497  cse = ss;
1498  }
1499  }
1500  /* Add diagonals necessary to make `abc` a triangle. */
1501  CDTEdge<T> *ebc = nullptr;
1502  CDTEdge<T> *eca = nullptr;
1503  if (!exists_edge(b, c)) {
1504  ebc = cdt->add_diagonal(se->next, cse);
1505  }
1506  if (!exists_edge(c, a)) {
1507  eca = cdt->add_diagonal(cse, se);
1508  }
1509  /* Now recurse. */
1510  if (ebc) {
1511  re_delaunay_triangulate(cdt, &ebc->symedges[1]);
1512  }
1513  if (eca) {
1514  re_delaunay_triangulate(cdt, &eca->symedges[1]);
1515  }
1516 }
1517 
1518 template<typename T> inline int tri_orient(const SymEdge<T> *t)
1519 {
1520  return filtered_orient2d(t->vert->co, t->next->vert->co, t->next->next->vert->co);
1521 }
1522 
1548 template<typename T> class CrossData {
1549  public:
1550  T lambda = T(0);
1551  CDTVert<T> *vert;
1552  SymEdge<T> *in;
1553  SymEdge<T> *out;
1554 
1555  CrossData() : lambda(T(0)), vert(nullptr), in(nullptr), out(nullptr)
1556  {
1557  }
1558  CrossData(T l, CDTVert<T> *v, SymEdge<T> *i, SymEdge<T> *o) : lambda(l), vert(v), in(i), out(o)
1559  {
1560  }
1561  CrossData(const CrossData &other)
1562  : lambda(other.lambda), vert(other.vert), in(other.in), out(other.out)
1563  {
1564  }
1565  CrossData(CrossData &&other) noexcept
1566  : lambda(std::move(other.lambda)),
1567  vert(std::move(other.vert)),
1568  in(std::move(other.in)),
1569  out(std::move(other.out))
1570  {
1571  }
1572  ~CrossData() = default;
1573  CrossData &operator=(const CrossData &other)
1574  {
1575  if (this != &other) {
1576  lambda = other.lambda;
1577  vert = other.vert;
1578  in = other.in;
1579  out = other.out;
1580  }
1581  return *this;
1582  }
1583  CrossData &operator=(CrossData &&other) noexcept
1584  {
1585  lambda = std::move(other.lambda);
1586  vert = std::move(other.vert);
1587  in = std::move(other.in);
1588  out = std::move(other.out);
1589  return *this;
1590  }
1591 };
1592 
1593 template<typename T>
1594 bool get_next_crossing_from_vert(CDT_state<T> *cdt_state,
1595  CrossData<T> *cd,
1596  CrossData<T> *cd_next,
1597  const CDTVert<T> *v2);
1598 
1606 template<typename T>
1607 void fill_crossdata_for_through_vert(CDTVert<T> *v,
1608  SymEdge<T> *cd_out,
1609  CrossData<T> *cd,
1610  CrossData<T> *cd_next)
1611 {
1612  SymEdge<T> *se;
1613 
1614  cd_next->lambda = T(0);
1615  cd_next->vert = v;
1616  cd_next->in = nullptr;
1617  cd_next->out = nullptr;
1618  if (cd->lambda == 0) {
1619  cd->out = cd_out;
1620  }
1621  else {
1622  /* One of the edges in the triangle with edge sym(cd->in) contains v. */
1623  se = sym(cd->in);
1624  if (se->vert != v) {
1625  se = se->next;
1626  if (se->vert != v) {
1627  se = se->next;
1628  }
1629  }
1630  BLI_assert(se->vert == v);
1631  cd_next->in = se;
1632  }
1633 }
1634 
1648 template<typename T>
1649 void fill_crossdata_for_intersect(const FatCo<T> &curco,
1650  const CDTVert<T> *v2,
1651  SymEdge<T> *t,
1652  CrossData<T> *cd,
1653  CrossData<T> *cd_next,
1654  const T epsilon)
1655 {
1656  CDTVert<T> *va = t->vert;
1657  CDTVert<T> *vb = t->next->vert;
1658  CDTVert<T> *vc = t->next->next->vert;
1659  SymEdge<T> *se_vcvb = sym(t->next);
1660  SymEdge<T> *se_vcva = t->next->next;
1661  BLI_assert(se_vcva->vert == vc && se_vcva->next->vert == va);
1662  BLI_assert(se_vcvb->vert == vc && se_vcvb->next->vert == vb);
1663  UNUSED_VARS_NDEBUG(vc);
1664  auto isect = vec2<T>::isect_seg_seg(va->co.exact, vb->co.exact, curco.exact, v2->co.exact);
1665  T &lambda = isect.lambda;
1666  switch (isect.kind) {
1667  case vec2<T>::isect_result::LINE_LINE_CROSS: {
1668 #ifdef WITH_GMP
1669  if (!std::is_same<T, mpq_class>::value) {
1670 #else
1671  if (true) {
1672 #endif
1673  double len_ab = vec2<double>::distance(va->co.approx, vb->co.approx);
1674  if (lambda * len_ab <= epsilon) {
1675  fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1676  }
1677  else if ((1 - lambda) * len_ab <= epsilon) {
1678  fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1679  }
1680  else {
1681  *cd_next = CrossData<T>(lambda, nullptr, t, nullptr);
1682  if (cd->lambda == 0) {
1683  cd->out = se_vcva;
1684  }
1685  }
1686  }
1687  else {
1688  *cd_next = CrossData<T>(lambda, nullptr, t, nullptr);
1689  if (cd->lambda == 0) {
1690  cd->out = se_vcva;
1691  }
1692  }
1693  break;
1694  }
1695  case vec2<T>::isect_result::LINE_LINE_EXACT: {
1696  if (lambda == 0) {
1697  fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1698  }
1699  else if (lambda == 1) {
1700  fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1701  }
1702  else {
1703  *cd_next = CrossData<T>(lambda, nullptr, t, nullptr);
1704  if (cd->lambda == 0) {
1705  cd->out = se_vcva;
1706  }
1707  }
1708  break;
1709  }
1710  case vec2<T>::isect_result::LINE_LINE_NONE: {
1711 #ifdef WITH_GMP
1712  if (std::is_same<T, mpq_class>::value) {
1713  BLI_assert(false);
1714  }
1715 #endif
1716  /* It should be very near one end or other of segment. */
1717  const T middle_lambda = 0.5;
1718  if (lambda <= middle_lambda) {
1719  fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1720  }
1721  else {
1722  fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1723  }
1724  break;
1725  }
1726  case vec2<T>::isect_result::LINE_LINE_COLINEAR: {
1727  if (vec2<double>::distance_squared(va->co.approx, v2->co.approx) <=
1728  vec2<double>::distance_squared(vb->co.approx, v2->co.approx)) {
1729  fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1730  }
1731  else {
1732  fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1733  }
1734  break;
1735  }
1736  }
1737 } // namespace blender::meshintersect
1738 
1746 template<typename T>
1747 bool get_next_crossing_from_vert(CDT_state<T> *cdt_state,
1748  CrossData<T> *cd,
1749  CrossData<T> *cd_next,
1750  const CDTVert<T> *v2)
1751 {
1752  SymEdge<T> *tstart = cd->vert->symedge;
1753  SymEdge<T> *t = tstart;
1754  CDTVert<T> *vcur = cd->vert;
1755  bool ok = false;
1756  do {
1757  /* The ray from `vcur` to v2 has to go either between two successive
1758  * edges around `vcur` or exactly along them. This time through the
1759  * loop, check to see if the ray goes along `vcur-va`
1760  * or between `vcur-va` and `vcur-vb`, where va is the end of t
1761  * and vb is the next vertex (on the next rot edge around vcur, but
1762  * should also be the next vert of triangle starting with `vcur-va`. */
1763  if (t->face != cdt_state->cdt.outer_face && tri_orient(t) < 0) {
1764  BLI_assert(false); /* Shouldn't happen. */
1765  }
1766  CDTVert<T> *va = t->next->vert;
1767  CDTVert<T> *vb = t->next->next->vert;
1768  int orient1 = filtered_orient2d(t->vert->co, va->co, v2->co);
1769  if (orient1 == 0 && in_line<T>(vcur->co, va->co, v2->co)) {
1770  fill_crossdata_for_through_vert(va, t, cd, cd_next);
1771  ok = true;
1772  break;
1773  }
1774  if (t->face != cdt_state->cdt.outer_face) {
1775  int orient2 = filtered_orient2d(vcur->co, vb->co, v2->co);
1776  /* Don't handle orient2 == 0 case here: next rotation will get it. */
1777  if (orient1 > 0 && orient2 < 0) {
1778  /* Segment intersection. */
1779  t = t->next;
1780  fill_crossdata_for_intersect(vcur->co, v2, t, cd, cd_next, cdt_state->epsilon);
1781  ok = true;
1782  break;
1783  }
1784  }
1785  } while ((t = t->rot) != tstart);
1786  return ok;
1787 }
1788 
1797 template<typename T>
1798 void get_next_crossing_from_edge(CrossData<T> *cd,
1799  CrossData<T> *cd_next,
1800  const CDTVert<T> *v2,
1801  const T epsilon)
1802 {
1803  CDTVert<T> *va = cd->in->vert;
1804  CDTVert<T> *vb = cd->in->next->vert;
1805  vec2<T> curco = vec2<T>::interpolate(va->co.exact, vb->co.exact, cd->lambda);
1806  FatCo<T> fat_curco(curco);
1807  SymEdge<T> *se_ac = sym(cd->in)->next;
1808  CDTVert<T> *vc = se_ac->next->vert;
1809  int orient = filtered_orient2d(fat_curco, v2->co, vc->co);
1810  if (orient < 0) {
1811  fill_crossdata_for_intersect<T>(fat_curco, v2, se_ac->next, cd, cd_next, epsilon);
1812  }
1813  else if (orient > 0.0) {
1814  fill_crossdata_for_intersect(fat_curco, v2, se_ac, cd, cd_next, epsilon);
1815  }
1816  else {
1817  *cd_next = CrossData<T>{0.0, vc, se_ac->next, nullptr};
1818  }
1819 }
1820 
1821 constexpr int inline_crossings_size = 128;
1822 template<typename T>
1823 void dump_crossings(const Vector<CrossData<T>, inline_crossings_size> &crossings)
1824 {
1825  std::cout << "CROSSINGS\n";
1826  for (int i = 0; i < crossings.size(); ++i) {
1827  std::cout << i << ": ";
1828  const CrossData<T> &cd = crossings[i];
1829  if (cd.lambda == 0) {
1830  std::cout << "v" << cd.vert->index;
1831  }
1832  else {
1833  std::cout << "lambda=" << cd.lambda;
1834  }
1835  if (cd.in != nullptr) {
1836  std::cout << " in=" << short_se_dump(cd.in);
1837  std::cout << " out=" << short_se_dump(cd.out);
1838  }
1839  std::cout << "\n";
1840  }
1841 }
1842 
1854 template<typename T>
1855 void add_edge_constraint(
1856  CDT_state<T> *cdt_state, CDTVert<T> *v1, CDTVert<T> *v2, int input_id, LinkNode **r_edges)
1857 {
1858  constexpr int dbg_level = 0;
1859  if (dbg_level > 0) {
1860  std::cout << "\nADD EDGE CONSTRAINT\n" << vertname(v1) << " " << vertname(v2) << "\n";
1861  }
1862  LinkNodePair edge_list = {nullptr, nullptr};
1863 
1864  if (r_edges) {
1865  *r_edges = nullptr;
1866  }
1867 
1868  /*
1869  * Handle two special cases first:
1870  * 1) The two end vertices are the same (can happen because of merging).
1871  * 2) There is already an edge between v1 and v2.
1872  */
1873  if (v1 == v2) {
1874  return;
1875  }
1876  SymEdge<T> *t = find_symedge_between_verts(v1, v2);
1877  if (t != nullptr) {
1878  /* Segment already there. */
1879  add_to_input_ids(&t->edge->input_ids, input_id);
1880  if (r_edges != nullptr) {
1881  BLI_linklist_append(&edge_list, t->edge);
1882  *r_edges = edge_list.list;
1883  }
1884  return;
1885  }
1886 
1887  /*
1888  * Fill crossings array with CrossData points for intersection path from v1 to v2.
1889  *
1890  * At every point, the crossings array has the path so far, except that
1891  * the .out field of the last element of it may not be known yet -- if that
1892  * last element is a vertex, then we won't know the output edge until we
1893  * find the next crossing.
1894  *
1895  * To protect against infinite loops, we keep track of which vertices
1896  * we have visited by setting their visit_index to a new visit epoch.
1897  *
1898  * We check a special case first: where the segment is already there in
1899  * one hop. Saves a bunch of orient2d tests in that common case.
1900  */
1901  int visit = ++cdt_state->visit_count;
1902  Vector<CrossData<T>, inline_crossings_size> crossings;
1903  crossings.append(CrossData<T>(T(0), v1, nullptr, nullptr));
1904  int n;
1905  while (!((n = crossings.size()) > 0 && crossings[n - 1].vert == v2)) {
1906  crossings.append(CrossData<T>());
1907  CrossData<T> *cd = &crossings[n - 1];
1908  CrossData<T> *cd_next = &crossings[n];
1909  bool ok;
1910  if (crossings[n - 1].lambda == 0) {
1911  ok = get_next_crossing_from_vert(cdt_state, cd, cd_next, v2);
1912  }
1913  else {
1914  get_next_crossing_from_edge<T>(cd, cd_next, v2, cdt_state->epsilon);
1915  ok = true;
1916  }
1917  constexpr int unreasonably_large_crossings = 100000;
1918  if (!ok || crossings.size() == unreasonably_large_crossings) {
1919  /* Shouldn't happen but if does, just bail out. */
1920  BLI_assert(false);
1921  return;
1922  }
1923  if (crossings[n].lambda == 0) {
1924  if (crossings[n].vert->visit_index == visit) {
1925  /* Shouldn't happen but if it does, just bail out. */
1926  BLI_assert(false);
1927  return;
1928  }
1929  crossings[n].vert->visit_index = visit;
1930  }
1931  }
1932 
1933  if (dbg_level > 0) {
1934  dump_crossings(crossings);
1935  }
1936 
1937  /*
1938  * Post-process crossings.
1939  * Some crossings may have an intersection crossing followed
1940  * by a vertex crossing that is on the same edge that was just
1941  * intersected. We prefer to go directly from the previous
1942  * crossing directly to the vertex. This may chain backwards.
1943  *
1944  * This loop marks certain crossings as "deleted", by setting
1945  * their lambdas to -1.0.
1946  */
1947  int ncrossings = crossings.size();
1948  for (int i = 2; i < ncrossings; ++i) {
1949  CrossData<T> *cd = &crossings[i];
1950  if (cd->lambda == 0.0) {
1951  CDTVert<T> *v = cd->vert;
1952  int j;
1953  CrossData<T> *cd_prev;
1954  for (j = i - 1; j > 0; --j) {
1955  cd_prev = &crossings[j];
1956  if ((cd_prev->lambda == 0.0 && cd_prev->vert != v) ||
1957  (cd_prev->lambda != 0.0 && cd_prev->in->vert != v && cd_prev->in->next->vert != v)) {
1958  break;
1959  }
1960  cd_prev->lambda = -1.0; /* Mark cd_prev as 'deleted'. */
1961  }
1962  if (j < i - 1) {
1963  /* Some crossings were deleted. Fix the in and out edges across gap. */
1964  cd_prev = &crossings[j];
1965  SymEdge<T> *se;
1966  if (cd_prev->lambda == 0.0) {
1967  se = find_symedge_between_verts(cd_prev->vert, v);
1968  if (se == nullptr) {
1969  return;
1970  }
1971  cd_prev->out = se;
1972  cd->in = nullptr;
1973  }
1974  else {
1975  se = find_symedge_with_face(v, sym(cd_prev->in)->face);
1976  if (se == nullptr) {
1977  return;
1978  }
1979  cd->in = se;
1980  }
1981  }
1982  }
1983  }
1984 
1985  /*
1986  * Insert all intersection points on constrained edges.
1987  */
1988  for (int i = 0; i < ncrossings; ++i) {
1989  CrossData<T> *cd = &crossings[i];
1990  if (cd->lambda != 0.0 && cd->lambda != -1.0 && is_constrained_edge(cd->in->edge)) {
1991  CDTEdge<T> *edge = cdt_state->cdt.split_edge(cd->in, cd->lambda);
1992  cd->vert = edge->symedges[0].vert;
1993  }
1994  }
1995 
1996  /*
1997  * Remove any crossed, non-intersected edges.
1998  */
1999  for (int i = 0; i < ncrossings; ++i) {
2000  CrossData<T> *cd = &crossings[i];
2001  if (cd->lambda != 0.0 && cd->lambda != -1.0 && !is_constrained_edge(cd->in->edge)) {
2002  cdt_state->cdt.delete_edge(cd->in);
2003  }
2004  }
2005 
2006  /*
2007  * Insert segments for v1->v2.
2008  */
2009  SymEdge<T> *tstart = crossings[0].out;
2010  for (int i = 1; i < ncrossings; i++) {
2011  CrossData<T> *cd = &crossings[i];
2012  if (cd->lambda == -1.0) {
2013  continue; /* This crossing was deleted. */
2014  }
2015  t = nullptr;
2016  SymEdge<T> *tnext = t;
2017  CDTEdge<T> *edge;
2018  if (cd->lambda != 0.0) {
2019  if (is_constrained_edge(cd->in->edge)) {
2020  t = cd->vert->symedge;
2021  tnext = sym(t)->next;
2022  }
2023  }
2024  else if (cd->lambda == 0.0) {
2025  t = cd->in;
2026  tnext = cd->out;
2027  if (t == nullptr) {
2028  /* Previous non-deleted crossing must also have been a vert, and segment should exist. */
2029  int j;
2030  CrossData<T> *cd_prev;
2031  for (j = i - 1; j >= 0; j--) {
2032  cd_prev = &crossings[j];
2033  if (cd_prev->lambda != -1.0) {
2034  break;
2035  }
2036  }
2037  BLI_assert(cd_prev->lambda == 0.0);
2038  BLI_assert(cd_prev->out->next->vert == cd->vert);
2039  edge = cd_prev->out->edge;
2040  add_to_input_ids(&edge->input_ids, input_id);
2041  if (r_edges != nullptr) {
2042  BLI_linklist_append(&edge_list, edge);
2043  }
2044  }
2045  }
2046  if (t != nullptr) {
2047  if (tstart->next->vert == t->vert) {
2048  edge = tstart->edge;
2049  }
2050  else {
2051  edge = cdt_state->cdt.add_diagonal(tstart, t);
2052  }
2053  add_to_input_ids(&edge->input_ids, input_id);
2054  if (r_edges != nullptr) {
2055  BLI_linklist_append(&edge_list, edge);
2056  }
2057  /* Now retriangulate upper and lower gaps. */
2058  re_delaunay_triangulate(&cdt_state->cdt, &edge->symedges[0]);
2059  re_delaunay_triangulate(&cdt_state->cdt, &edge->symedges[1]);
2060  }
2061  if (i < ncrossings - 1) {
2062  if (tnext != nullptr) {
2063  tstart = tnext;
2064  }
2065  }
2066  }
2067 
2068  if (r_edges) {
2069  *r_edges = edge_list.list;
2070  }
2071 }
2072 
2079 template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CDT_input<T> &input)
2080 {
2081  int ne = input.edge.size();
2082  int nv = input.vert.size();
2083  for (int i = 0; i < ne; i++) {
2084  int iv1 = input.edge[i].first;
2085  int iv2 = input.edge[i].second;
2086  if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2087  /* Ignore invalid indices in edges. */
2088  continue;
2089  }
2090  CDTVert<T> *v1 = cdt_state->cdt.get_vert_resolve_merge(iv1);
2091  CDTVert<T> *v2 = cdt_state->cdt.get_vert_resolve_merge(iv2);
2092  add_edge_constraint(cdt_state, v1, v2, i, nullptr);
2093  }
2094  cdt_state->face_edge_offset = ne;
2095 }
2096 
2115 template<typename T>
2116 void add_face_ids(
2117  CDT_state<T> *cdt_state, SymEdge<T> *face_symedge, int face_id, int fedge_start, int fedge_end)
2118 {
2119  /* Can't loop forever since eventually would visit every face. */
2120  cdt_state->visit_count++;
2121  int visit = cdt_state->visit_count;
2122  Vector<SymEdge<T> *> stack;
2123  stack.append(face_symedge);
2124  while (!stack.is_empty()) {
2125  SymEdge<T> *se = stack.pop_last();
2126  CDTFace<T> *face = se->face;
2127  if (face->visit_index == visit) {
2128  continue;
2129  }
2130  face->visit_index = visit;
2131  add_to_input_ids(&face->input_ids, face_id);
2132  SymEdge<T> *se_start = se;
2133  for (se = se->next; se != se_start; se = se->next) {
2134  if (!id_range_in_list(se->edge->input_ids, fedge_start, fedge_end)) {
2135  SymEdge<T> *se_sym = sym(se);
2136  CDTFace<T> *face_other = se_sym->face;
2137  if (face_other->visit_index != visit) {
2138  stack.append(se_sym);
2139  }
2140  }
2141  }
2142  }
2143 }
2144 
2145 /* Return a power of 10 that is greater than or equal to x. */
2146 static int power_of_10_greater_equal_to(int x)
2147 {
2148  if (x <= 0) {
2149  return 1;
2150  }
2151  int ans = 1;
2152  BLI_assert(x < INT_MAX / 10);
2153  while (ans < x) {
2154  ans *= 10;
2155  }
2156  return ans;
2157 }
2158 
2167 template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CDT_input<T> &input)
2168 {
2169  int nv = input.vert.size();
2170  int nf = input.face.size();
2171  int fstart = 0;
2172  SymEdge<T> *face_symedge0 = nullptr;
2173  CDTArrangement<T> *cdt = &cdt_state->cdt;
2174  int maxflen = 0;
2175  for (int f = 0; f < nf; f++) {
2176  maxflen = max_ii(maxflen, input.face[f].size());
2177  }
2178  /* For convenience in debugging, make face_edge_offset be a power of 10. */
2179  cdt_state->face_edge_offset = power_of_10_greater_equal_to(
2180  max_ii(maxflen, cdt_state->face_edge_offset));
2181  /* The original_edge encoding scheme doesn't work if the following is false.
2182  * If we really have that many faces and that large a max face length that when multiplied
2183  * together the are >= INT_MAX, then the Delaunay calculation will take unreasonably long anyway.
2184  */
2185  BLI_assert(INT_MAX / cdt_state->face_edge_offset > nf);
2186  for (int f = 0; f < nf; f++) {
2187  int flen = input.face[f].size();
2188  if (flen <= 2) {
2189  /* Ignore faces with fewer than 3 vertices. */
2190  fstart += flen;
2191  continue;
2192  }
2193  int fedge_start = (f + 1) * cdt_state->face_edge_offset;
2194  for (int i = 0; i < flen; i++) {
2195  int face_edge_id = fedge_start + i;
2196  int iv1 = input.face[f][i];
2197  int iv2 = input.face[f][(i + 1) % flen];
2198  if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2199  /* Ignore face edges with invalid vertices. */
2200  continue;
2201  }
2202  CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1);
2203  CDTVert<T> *v2 = cdt->get_vert_resolve_merge(iv2);
2204  LinkNode *edge_list;
2205  add_edge_constraint(cdt_state, v1, v2, face_edge_id, &edge_list);
2206  /* Set a new face_symedge0 each time since earlier ones may not
2207  * survive later symedge splits. Really, just want the one when
2208  * i == flen -1, but this code guards against that one somehow
2209  * being null.
2210  */
2211  if (edge_list != nullptr) {
2212  CDTEdge<T> *face_edge = static_cast<CDTEdge<T> *>(edge_list->link);
2213  face_symedge0 = &face_edge->symedges[0];
2214  if (face_symedge0->vert != v1) {
2215  face_symedge0 = &face_edge->symedges[1];
2216  BLI_assert(face_symedge0->vert == v1);
2217  }
2218  }
2219  BLI_linklist_free(edge_list, nullptr);
2220  }
2221  int fedge_end = fedge_start + flen - 1;
2222  if (face_symedge0 != nullptr) {
2223  add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
2224  }
2225  fstart += flen;
2226  }
2227 }
2228 
2229 /* Delete_edge but try not to mess up outer face.
2230  * Also faces have symedges now, so make sure not
2231  * to mess those up either. */
2232 template<typename T> void dissolve_symedge(CDT_state<T> *cdt_state, SymEdge<T> *se)
2233 {
2234  CDTArrangement<T> *cdt = &cdt_state->cdt;
2235  SymEdge<T> *symse = sym(se);
2236  if (symse->face == cdt->outer_face) {
2237  se = sym(se);
2238  symse = sym(se);
2239  }
2240  if (ELEM(cdt->outer_face->symedge, se, symse)) {
2241  /* Advancing by 2 to get past possible 'sym(se)'. */
2242  if (se->next->next == se) {
2243  cdt->outer_face->symedge = nullptr;
2244  }
2245  else {
2246  cdt->outer_face->symedge = se->next->next;
2247  }
2248  }
2249  else {
2250  if (se->face->symedge == se) {
2251  se->face->symedge = se->next;
2252  }
2253  if (symse->face->symedge == symse) {
2254  symse->face->symedge = symse->next;
2255  }
2256  }
2257  cdt->delete_edge(se);
2258 }
2259 
2263 template<typename T> void remove_non_constraint_edges(CDT_state<T> *cdt_state)
2264 {
2265  for (CDTEdge<T> *e : cdt_state->cdt.edges) {
2266  SymEdge<T> *se = &e->symedges[0];
2267  if (!is_deleted_edge(e) && !is_constrained_edge(e)) {
2268  dissolve_symedge(cdt_state, se);
2269  }
2270  }
2271 }
2272 
2273 /*
2274  * Remove the non-constraint edges, but leave enough of them so that all of the
2275  * faces that would be #BMesh faces (that is, the faces that have some input representative)
2276  * are valid: they can't have holes, they can't have repeated vertices, and they can't have
2277  * repeated edges.
2278  *
2279  * Not essential, but to make the result look more aesthetically nice,
2280  * remove the edges in order of decreasing length, so that it is more likely that the
2281  * final remaining support edges are short, and therefore likely to make a fairly
2282  * direct path from an outer face to an inner hole face.
2283  */
2284 
2288 template<typename T> struct EdgeToSort {
2289  double len_squared = 0.0;
2290  CDTEdge<T> *e{nullptr};
2291 
2292  EdgeToSort() = default;
2293  EdgeToSort(const EdgeToSort &other) : len_squared(other.len_squared), e(other.e)
2294  {
2295  }
2296  EdgeToSort(EdgeToSort &&other) noexcept : len_squared(std::move(other.len_squared)), e(other.e)
2297  {
2298  }
2299  ~EdgeToSort() = default;
2300  EdgeToSort &operator=(const EdgeToSort &other)
2301  {
2302  if (this != &other) {
2303  len_squared = other.len_squared;
2304  e = other.e;
2305  }
2306  return *this;
2307  }
2308  EdgeToSort &operator=(EdgeToSort &&other)
2309  {
2310  len_squared = std::move(other.len_squared);
2311  e = other.e;
2312  return *this;
2313  }
2314 };
2315 
2316 template<typename T> void remove_non_constraint_edges_leave_valid_bmesh(CDT_state<T> *cdt_state)
2317 {
2318  CDTArrangement<T> *cdt = &cdt_state->cdt;
2319  size_t nedges = cdt->edges.size();
2320  if (nedges == 0) {
2321  return;
2322  }
2323  Vector<EdgeToSort<T>> dissolvable_edges;
2324  dissolvable_edges.reserve(cdt->edges.size());
2325  int i = 0;
2326  for (CDTEdge<T> *e : cdt->edges) {
2327  if (!is_deleted_edge(e) && !is_constrained_edge(e)) {
2328  dissolvable_edges.append(EdgeToSort<T>());
2329  dissolvable_edges[i].e = e;
2330  const vec2<double> &co1 = e->symedges[0].vert->co.approx;
2331  const vec2<double> &co2 = e->symedges[1].vert->co.approx;
2332  dissolvable_edges[i].len_squared = vec2<double>::distance_squared(co1, co2);
2333  i++;
2334  }
2335  }
2336  std::sort(dissolvable_edges.begin(),
2337  dissolvable_edges.end(),
2338  [](const EdgeToSort<T> &a, const EdgeToSort<T> &b) -> bool {
2339  return (a.len_squared < b.len_squared);
2340  });
2341  for (EdgeToSort<T> &ets : dissolvable_edges) {
2342  CDTEdge<T> *e = ets.e;
2343  SymEdge<T> *se = &e->symedges[0];
2344  bool dissolve = true;
2345  CDTFace<T> *fleft = se->face;
2346  CDTFace<T> *fright = sym(se)->face;
2347  if (fleft != cdt->outer_face && fright != cdt->outer_face &&
2348  (fleft->input_ids != nullptr || fright->input_ids != nullptr)) {
2349  /* Is there another #SymEdge with same left and right faces?
2350  * Or is there a vertex not part of e touching the same left and right faces? */
2351  for (SymEdge<T> *se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
2352  if (sym(se2)->face == fright ||
2353  (se2->vert != se->next->vert && vert_touches_face(se2->vert, fright))) {
2354  dissolve = false;
2355  }
2356  }
2357  }
2358 
2359  if (dissolve) {
2360  dissolve_symedge(cdt_state, se);
2361  }
2362  }
2363 }
2364 
2365 template<typename T> void remove_outer_edges_until_constraints(CDT_state<T> *cdt_state)
2366 {
2367  // LinkNode *fstack = NULL;
2368  // SymEdge *se, *se_start;
2369  // CDTFace *f, *fsym;
2370  int visit = ++cdt_state->visit_count;
2371 
2372  cdt_state->cdt.outer_face->visit_index = visit;
2373  /* Walk around outer face, adding faces on other side of dissolvable edges to stack. */
2374  Vector<CDTFace<T> *> fstack;
2375  SymEdge<T> *se_start = cdt_state->cdt.outer_face->symedge;
2376  SymEdge<T> *se = se_start;
2377  do {
2378  if (!is_constrained_edge(se->edge)) {
2379  CDTFace<T> *fsym = sym(se)->face;
2380  if (fsym->visit_index != visit) {
2381  fstack.append(fsym);
2382  }
2383  }
2384  } while ((se = se->next) != se_start);
2385 
2386  while (!fstack.is_empty()) {
2387  LinkNode *to_dissolve = nullptr;
2388  bool dissolvable;
2389  CDTFace<T> *f = fstack.pop_last();
2390  if (f->visit_index == visit) {
2391  continue;
2392  }
2393  BLI_assert(f != cdt_state->cdt.outer_face);
2394  f->visit_index = visit;
2395  se_start = se = f->symedge;
2396  do {
2397  dissolvable = !is_constrained_edge(se->edge);
2398  if (dissolvable) {
2399  CDTFace<T> *fsym = sym(se)->face;
2400  if (fsym->visit_index != visit) {
2401  fstack.append(fsym);
2402  }
2403  else {
2404  BLI_linklist_prepend(&to_dissolve, se);
2405  }
2406  }
2407  se = se->next;
2408  } while (se != se_start);
2409  while (to_dissolve != nullptr) {
2410  se = static_cast<SymEdge<T> *>(BLI_linklist_pop(&to_dissolve));
2411  if (se->next != nullptr) {
2412  dissolve_symedge(cdt_state, se);
2413  }
2414  }
2415  }
2416 }
2417 
2422 template<typename T>
2423 void prepare_cdt_for_output(CDT_state<T> *cdt_state, const CDT_output_type output_type)
2424 {
2425  CDTArrangement<T> *cdt = &cdt_state->cdt;
2426  if (cdt->edges.is_empty()) {
2427  return;
2428  }
2429 
2430  /* Make sure all non-deleted faces have a symedge. */
2431  for (CDTEdge<T> *e : cdt->edges) {
2432  if (!is_deleted_edge(e)) {
2433  if (e->symedges[0].face->symedge == nullptr) {
2434  e->symedges[0].face->symedge = &e->symedges[0];
2435  }
2436  if (e->symedges[1].face->symedge == nullptr) {
2437  e->symedges[1].face->symedge = &e->symedges[1];
2438  }
2439  }
2440  }
2441 
2442  if (output_type == CDT_CONSTRAINTS) {
2443  remove_non_constraint_edges(cdt_state);
2444  }
2445  else if (output_type == CDT_CONSTRAINTS_VALID_BMESH) {
2446  remove_non_constraint_edges_leave_valid_bmesh(cdt_state);
2447  }
2448  else if (output_type == CDT_INSIDE) {
2449  remove_outer_edges_until_constraints(cdt_state);
2450  }
2451 }
2452 
2453 template<typename T>
2454 CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
2455  const CDT_input<T> UNUSED(input),
2456  CDT_output_type output_type)
2457 {
2458  prepare_cdt_for_output(cdt_state, output_type);
2460  CDTArrangement<T> *cdt = &cdt_state->cdt;
2461  result.face_edge_offset = cdt_state->face_edge_offset;
2462 
2463  /* All verts without a merge_to_index will be output.
2464  * vert_to_output_map[i] will hold the output vertex index
2465  * corresponding to the vert in position i in cdt->verts.
2466  * This first loop sets vert_to_output_map for un-merged verts. */
2467  int verts_size = cdt->verts.size();
2468  Array<int> vert_to_output_map(verts_size);
2469  int nv = 0;
2470  for (int i = 0; i < verts_size; ++i) {
2471  CDTVert<T> *v = cdt->verts[i];
2472  if (v->merge_to_index == -1) {
2473  vert_to_output_map[i] = nv;
2474  ++nv;
2475  }
2476  }
2477  if (nv <= 0) {
2478  return result;
2479  }
2480  /* Now we can set vert_to_output_map for merged verts,
2481  * and also add the input indices of merged verts to the input_ids
2482  * list of the merge target if they were an original input id. */
2483  if (nv < verts_size) {
2484  for (int i = 0; i < verts_size; ++i) {
2485  CDTVert<T> *v = cdt->verts[i];
2486  if (v->merge_to_index != -1) {
2487  if (i < cdt_state->input_vert_tot) {
2488  add_to_input_ids(&cdt->verts[v->merge_to_index]->input_ids, i);
2489  }
2490  vert_to_output_map[i] = vert_to_output_map[v->merge_to_index];
2491  }
2492  }
2493  }
2494  result.vert = Array<vec2<T>>(nv);
2495  result.vert_orig = Array<Vector<int>>(nv);
2496  int i_out = 0;
2497  for (int i = 0; i < verts_size; ++i) {
2498  CDTVert<T> *v = cdt->verts[i];
2499  if (v->merge_to_index == -1) {
2500  result.vert[i_out] = v->co.exact;
2501  if (i < cdt_state->input_vert_tot) {
2502  result.vert_orig[i_out].append(i);
2503  }
2504  for (LinkNode *ln = v->input_ids; ln; ln = ln->next) {
2505  result.vert_orig[i_out].append(POINTER_AS_INT(ln->link));
2506  }
2507  ++i_out;
2508  }
2509  }
2510 
2511  /* All non-deleted edges will be output. */
2512  int ne = std::count_if(cdt->edges.begin(), cdt->edges.end(), [](const CDTEdge<T> *e) -> bool {
2513  return !is_deleted_edge(e);
2514  });
2515  result.edge = Array<std::pair<int, int>>(ne);
2516  result.edge_orig = Array<Vector<int>>(ne);
2517  int e_out = 0;
2518  for (const CDTEdge<T> *e : cdt->edges) {
2519  if (!is_deleted_edge(e)) {
2520  int vo1 = vert_to_output_map[e->symedges[0].vert->index];
2521  int vo2 = vert_to_output_map[e->symedges[1].vert->index];
2522  result.edge[e_out] = std::pair<int, int>(vo1, vo2);
2523  for (LinkNode *ln = e->input_ids; ln; ln = ln->next) {
2524  result.edge_orig[e_out].append(POINTER_AS_INT(ln->link));
2525  }
2526  ++e_out;
2527  }
2528  }
2529 
2530  /* All non-deleted, non-outer faces will be output. */
2531  int nf = std::count_if(cdt->faces.begin(), cdt->faces.end(), [=](const CDTFace<T> *f) -> bool {
2532  return !f->deleted && f != cdt->outer_face;
2533  });
2534  result.face = Array<Vector<int>>(nf);
2535  result.face_orig = Array<Vector<int>>(nf);
2536  int f_out = 0;
2537  for (const CDTFace<T> *f : cdt->faces) {
2538  if (!f->deleted && f != cdt->outer_face) {
2539  SymEdge<T> *se = f->symedge;
2540  BLI_assert(se != nullptr);
2541  SymEdge<T> *se_start = se;
2542  do {
2543  result.face[f_out].append(vert_to_output_map[se->vert->index]);
2544  se = se->next;
2545  } while (se != se_start);
2546  for (LinkNode *ln = f->input_ids; ln; ln = ln->next) {
2547  result.face_orig[f_out].append(POINTER_AS_INT(ln->link));
2548  }
2549  ++f_out;
2550  }
2551  }
2552  return result;
2553 }
2554 
2559 template<typename T> void add_input_verts(CDT_state<T> *cdt_state, const CDT_input<T> &input)
2560 {
2561  for (int i = 0; i < cdt_state->input_vert_tot; ++i) {
2562  cdt_state->cdt.add_vert(input.vert[i]);
2563  }
2564 }
2565 
2566 template<typename T>
2567 CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_type)
2568 {
2569  int nv = input.vert.size();
2570  int ne = input.edge.size();
2571  int nf = input.face.size();
2572  CDT_state<T> cdt_state(nv, ne, nf, input.epsilon);
2573  add_input_verts(&cdt_state, input);
2574  initial_triangulation(&cdt_state.cdt);
2575  add_edge_constraints(&cdt_state, input);
2576  add_face_constraints(&cdt_state, input);
2577  return get_cdt_output(&cdt_state, input, output_type);
2578 }
2579 
2580 blender::meshintersect::CDT_result<double> delaunay_2d_calc(const CDT_input<double> &input,
2581  CDT_output_type output_type)
2582 {
2583  return delaunay_calc(input, output_type);
2584 }
2585 
2586 #ifdef WITH_GMP
2587 blender::meshintersect::CDT_result<mpq_class> delaunay_2d_calc(const CDT_input<mpq_class> &input,
2588  CDT_output_type output_type)
2589 {
2590  return delaunay_calc(input, output_type);
2591 }
2592 #endif
2593 
2594 } /* namespace blender::meshintersect */
2595 
2596 /* C interface. */
2597 
2606  const CDT_output_type output_type)
2607 {
2608  blender::meshintersect::CDT_input<double> in;
2609  in.vert = blender::Array<blender::meshintersect::vec2<double>>(input->verts_len);
2610  in.edge = blender::Array<std::pair<int, int>>(input->edges_len);
2611  in.face = blender::Array<blender::Vector<int>>(input->faces_len);
2612  for (int v = 0; v < input->verts_len; ++v) {
2613  double x = static_cast<double>(input->vert_coords[v][0]);
2614  double y = static_cast<double>(input->vert_coords[v][1]);
2615  in.vert[v] = blender::meshintersect::vec2<double>(x, y);
2616  }
2617  for (int e = 0; e < input->edges_len; ++e) {
2618  in.edge[e] = std::pair<int, int>(input->edges[e][0], input->edges[e][1]);
2619  }
2620  for (int f = 0; f < input->faces_len; ++f) {
2621  in.face[f] = blender::Vector<int>(input->faces_len_table[f]);
2622  int fstart = input->faces_start_table[f];
2623  for (int j = 0; j < input->faces_len_table[f]; ++j) {
2624  in.face[f][j] = input->faces[fstart + j];
2625  }
2626  }
2627  in.epsilon = static_cast<double>(input->epsilon);
2628 
2629  blender::meshintersect::CDT_result<double> res = blender::meshintersect::delaunay_2d_calc(
2630  in, output_type);
2631 
2632  ::CDT_result *output = static_cast<::CDT_result *>(MEM_mallocN(sizeof(*output), __func__));
2633  int nv = output->verts_len = res.vert.size();
2634  int ne = output->edges_len = res.edge.size();
2635  int nf = output->faces_len = res.face.size();
2636  int tot_v_orig = 0;
2637  int tot_e_orig = 0;
2638  int tot_f_orig = 0;
2639  int tot_f_lens = 0;
2640  for (int v = 0; v < nv; ++v) {
2641  tot_v_orig += res.vert_orig[v].size();
2642  }
2643  for (int e = 0; e < ne; ++e) {
2644  tot_e_orig += res.edge_orig[e].size();
2645  }
2646  for (int f = 0; f < nf; ++f) {
2647  tot_f_orig += res.face_orig[f].size();
2648  tot_f_lens += res.face[f].size();
2649  }
2650 
2651  output->vert_coords = static_cast<decltype(output->vert_coords)>(
2652  MEM_malloc_arrayN(nv, sizeof(output->vert_coords[0]), __func__));
2653  output->verts_orig = static_cast<int *>(MEM_malloc_arrayN(tot_v_orig, sizeof(int), __func__));
2654  output->verts_orig_start_table = static_cast<int *>(
2655  MEM_malloc_arrayN(nv, sizeof(int), __func__));
2656  output->verts_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nv, sizeof(int), __func__));
2657  output->edges = static_cast<decltype(output->edges)>(
2658  MEM_malloc_arrayN(ne, sizeof(output->edges[0]), __func__));
2659  output->edges_orig = static_cast<int *>(MEM_malloc_arrayN(tot_e_orig, sizeof(int), __func__));
2660  output->edges_orig_start_table = static_cast<int *>(
2661  MEM_malloc_arrayN(ne, sizeof(int), __func__));
2662  output->edges_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(ne, sizeof(int), __func__));
2663  output->faces = static_cast<int *>(MEM_malloc_arrayN(tot_f_lens, sizeof(int), __func__));
2664  output->faces_start_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
2665  output->faces_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
2666  output->faces_orig = static_cast<int *>(MEM_malloc_arrayN(tot_f_orig, sizeof(int), __func__));
2667  output->faces_orig_start_table = static_cast<int *>(
2668  MEM_malloc_arrayN(nf, sizeof(int), __func__));
2669  output->faces_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
2670 
2671  int v_orig_index = 0;
2672  for (int v = 0; v < nv; ++v) {
2673  output->vert_coords[v][0] = static_cast<float>(res.vert[v][0]);
2674  output->vert_coords[v][1] = static_cast<float>(res.vert[v][1]);
2675  int this_start = v_orig_index;
2676  output->verts_orig_start_table[v] = this_start;
2677  for (int j : res.vert_orig[v].index_range()) {
2678  output->verts_orig[v_orig_index++] = res.vert_orig[v][j];
2679  }
2680  output->verts_orig_len_table[v] = v_orig_index - this_start;
2681  }
2682  int e_orig_index = 0;
2683  for (int e = 0; e < ne; ++e) {
2684  output->edges[e][0] = res.edge[e].first;
2685  output->edges[e][1] = res.edge[e].second;
2686  int this_start = e_orig_index;
2687  output->edges_orig_start_table[e] = this_start;
2688  for (int j : res.edge_orig[e].index_range()) {
2689  output->edges_orig[e_orig_index++] = res.edge_orig[e][j];
2690  }
2691  output->edges_orig_len_table[e] = e_orig_index - this_start;
2692  }
2693  int f_orig_index = 0;
2694  int f_index = 0;
2695  for (int f = 0; f < nf; ++f) {
2696  output->faces_start_table[f] = f_index;
2697  int flen = res.face[f].size();
2698  output->faces_len_table[f] = flen;
2699  for (int j = 0; j < flen; ++j) {
2700  output->faces[f_index++] = res.face[f][j];
2701  }
2702  int this_start = f_orig_index;
2703  output->faces_orig_start_table[f] = this_start;
2704  for (int k : res.face_orig[f].index_range()) {
2705  output->faces_orig[f_orig_index++] = res.face_orig[f][k];
2706  }
2707  output->faces_orig_len_table[f] = f_orig_index - this_start;
2708  }
2709  return output;
2710 }
2711 
2712 extern "C" void BLI_delaunay_2d_cdt_free(::CDT_result *result)
2713 {
2714  MEM_freeN(result->vert_coords);
2715  MEM_freeN(result->edges);
2716  MEM_freeN(result->faces);
2717  MEM_freeN(result->faces_start_table);
2718  MEM_freeN(result->faces_len_table);
2719  MEM_freeN(result->verts_orig);
2720  MEM_freeN(result->verts_orig_start_table);
2721  MEM_freeN(result->verts_orig_len_table);
2722  MEM_freeN(result->edges_orig);
2723  MEM_freeN(result->edges_orig_start_table);
2724  MEM_freeN(result->edges_orig_len_table);
2725  MEM_freeN(result->faces_orig);
2726  MEM_freeN(result->faces_orig_start_table);
2727  MEM_freeN(result->faces_orig_len_table);
2728  MEM_freeN(result);
2729 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
CDT_result * BLI_delaunay_2d_cdt_calc(const CDT_input *input, const CDT_output_type output_type)
CDT_output_type
@ CDT_CONSTRAINTS_VALID_BMESH
@ CDT_CONSTRAINTS
@ CDT_INSIDE
struct CDT_input CDT_input
void BLI_delaunay_2d_cdt_free(CDT_result *result)
MINLINE int max_ii(int a, int b)
Math vector functions needed specifically for mesh intersect and boolean.
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
btGeneric6DofConstraint & operator=(btGeneric6DofConstraint &other)
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
#define output
const char * label
#define SY(y)
#define SX(x)
#define rot(x, k)
static float verts[][3]
int count
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
#define T
static char faces[256]
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
double math_to_double< double >(const double v)
static double math_to_double(const T UNUSED(v))
std::ostream & operator<<(std::ostream &os, const CDT_result< T > &r)
static T math_abs(const T v)
static double epsilon
int orient2d(const double2 &a, const double2 &b, const double2 &c)
int incircle(const double2 &a, const double2 &b, const double2 &c, const double2 &d)
std::string to_string(const T &n)
float co[3]
Definition: bmesh_class.h:99
struct BMEdge * e
Definition: bmesh_class.h:109
LinkNode * list
Definition: BLI_linklist.h:50
void * link
Definition: BLI_linklist.h:40
struct LinkNode * next
Definition: BLI_linklist.h:39
static const char hex[17]
Definition: thumbs.c:173
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float distance(const float2 &a, const float2 &b)
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 fabs(const float2 &a)
ccl_device_inline float len_squared(const float3 a)