43 return (
v < 0) ? -
v :
v;
47 template<> mpq_class math_abs<mpq_class>(
const mpq_class
v)
53 template<>
double math_abs<double>(
const double v)
65 template<>
double math_to_double<mpq_class>(
const mpq_class
v)
87 template<
typename Arith_t>
struct CDTVert;
88 template<
typename Arith_t>
struct CDTEdge;
89 template<
typename Arith_t>
struct CDTFace;
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};
109 template<
typename T>
inline SymEdge<T> *sym(
const SymEdge<T> *se)
111 return se->next->rot;
115 template<
typename T>
inline SymEdge<T> *prev(
const SymEdge<T> *se)
117 return se->rot->next->rot;
122 template<
typename T>
struct FatCo {
125 vec2<double> abs_approx;
129 FatCo(
const vec2<mpq_class> &
v);
131 FatCo(
const vec2<double> &
v);
135 template<>
struct FatCo<mpq_class> {
136 vec2<mpq_class> exact;
138 vec2<double> abs_approx;
141 : exact(vec2<mpq_class>(0, 0)), approx(vec2<
double>(0, 0)), abs_approx(vec2<
double>(0, 0))
145 FatCo(
const vec2<mpq_class> &
v)
148 approx = vec2<double>(
v.x.get_d(),
v.y.get_d());
149 abs_approx = vec2<double>(
fabs(approx.x),
fabs(approx.y));
152 FatCo(
const vec2<double> &
v)
154 exact = vec2<mpq_class>(
v.x,
v.y);
156 abs_approx = vec2<double>(
fabs(approx.x),
fabs(approx.y));
161 template<>
struct FatCo<
double> {
164 vec2<double> abs_approx;
166 FatCo() : exact(vec2<
double>(0, 0)), approx(vec2<
double>(0, 0)), abs_approx(vec2<
double>(0, 0))
171 FatCo(
const vec2<mpq_class> &
v)
173 exact = vec2<double>(
v.x.get_d(),
v.y.get_d());
175 abs_approx = vec2<double>(
fabs(approx.x),
fabs(approx.y));
179 FatCo(
const vec2<double> &
v)
183 abs_approx = vec2<double>(
fabs(approx.x),
fabs(approx.y));
187 template<
typename T> std::ostream &
operator<<(std::ostream &stream,
const FatCo<T> &co)
189 stream <<
"(" << co.approx.x <<
", " << co.approx.y <<
")";
193 template<
typename T>
struct CDTVert {
197 SymEdge<T> *symedge{
nullptr};
203 int merge_to_index{-1};
208 explicit CDTVert(
const vec2<T> &pt);
211 template<
typename Arith_t>
struct CDTEdge {
215 SymEdge<Arith_t> symedges[2]{SymEdge<Arith_t>(), SymEdge<Arith_t>()};
220 template<
typename Arith_t>
struct CDTFace {
222 SymEdge<Arith_t> *symedge{
nullptr};
233 template<
typename Arith_t>
struct CDTArrangement {
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};
247 CDTArrangement() =
default;
252 void reserve(
int num_verts,
int num_edges,
int num_faces);
258 CDTVert<Arith_t> *add_vert(
const vec2<Arith_t> &pt);
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);
275 CDTFace<Arith_t> *add_face();
278 CDTEdge<Arith_t> *add_vert_to_symedge_edge(CDTVert<Arith_t> *
v, SymEdge<Arith_t> *se);
286 CDTEdge<Arith_t> *add_diagonal(SymEdge<Arith_t> *s1, SymEdge<Arith_t> *s2);
292 CDTEdge<Arith_t> *connect_separate_parts(SymEdge<Arith_t> *se1, SymEdge<Arith_t> *se2);
298 CDTEdge<Arith_t> *split_edge(SymEdge<Arith_t> *se, Arith_t lambda);
305 void delete_edge(SymEdge<Arith_t> *se);
311 CDTVert<Arith_t> *get_vert_resolve_merge(
int i)
313 CDTVert<Arith_t> *
v = this->verts[i];
314 if (
v->merge_to_index != -1) {
315 v = this->verts[
v->merge_to_index];
321 template<
typename T>
class CDT_state {
323 CDTArrangement<T> cdt;
332 int face_edge_offset;
336 explicit CDT_state(
int num_input_verts,
int num_input_edges,
int num_input_faces,
T epsilon);
339 template<
typename T> CDTArrangement<T>::~CDTArrangement()
341 for (
int i : this->verts.index_range()) {
342 CDTVert<T> *
v = this->verts[i];
345 this->verts[i] =
nullptr;
347 for (
int i : this->edges.index_range()) {
348 CDTEdge<T> *
e = this->edges[i];
351 this->edges[i] =
nullptr;
353 for (
int i : this->faces.index_range()) {
354 CDTFace<T> *f = this->faces[i];
357 this->faces[i] =
nullptr;
364 template<
typename T> std::string vertname(
const CDTVert<T> *
v)
366 std::stringstream ss;
367 ss <<
"[" <<
v->index <<
"]";
372 static std::string trunc_ptr(
const void *p)
374 constexpr
int TRUNC_PTR_MASK = 0xFFFF;
375 std::stringstream ss;
380 template<
typename T> std::string sename(
const SymEdge<T> *se)
382 std::stringstream ss;
383 ss <<
"{" << trunc_ptr(se) <<
"}";
387 template<
typename T> std::ostream &
operator<<(std::ostream &os,
const SymEdge<T> &se)
390 os << vertname(se.vert) <<
"(" << se.vert->co <<
"->" << se.next->vert->co <<
")"
391 << vertname(se.next->vert);
394 os << vertname(se.vert) <<
"(" << se.vert->co <<
"->NULL)";
399 template<
typename T> std::ostream &
operator<<(std::ostream &os,
const SymEdge<T> *se)
405 template<
typename T> std::string short_se_dump(
const SymEdge<T> *se)
408 return std::string(
"NULL");
410 return vertname(se->vert) +
411 (se->next ==
nullptr ? std::string(
"[NULL]") : vertname(se->
next->vert));
414 template<
typename T> std::ostream &
operator<<(std::ostream &os,
const CDT_state<T> &cdt_state)
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) {
424 os <<
" merge to " << vertname(cdt_state.cdt.verts[
v->merge_to_index]) <<
"\n";
426 const SymEdge<T> *se =
v->symedge;
428 constexpr
int print_count_limit = 25;
430 os <<
" edges out:\n";
432 if (se->next ==
NULL) {
433 os <<
" [NULL] next/rot symedge, se=" << trunc_ptr(se) <<
"\n";
436 if (se->next->next ==
NULL) {
437 os <<
" [NULL] next-next/rot symedge, se=" << trunc_ptr(se) <<
"\n";
440 const CDTVert<T> *vother = sym(se)->vert;
441 os <<
" " << vertname(vother) <<
"(e=" << trunc_ptr(se->edge)
442 <<
", se=" << trunc_ptr(se) <<
")\n";
445 }
while (se !=
v->symedge && cnt < print_count_limit);
450 for (
const CDTEdge<T> *
e : cdt_state.cdt.edges) {
451 if (
e->symedges[0].next ==
nullptr) {
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";
464 os <<
"outer_face=" << trunc_ptr(cdt_state.cdt.outer_face) <<
"\n";
466 if (cdt_state.cdt.outer_face->symedge !=
nullptr) {
467 for (
const CDTFace<T> *f : cdt_state.cdt.faces) {
469 os << trunc_ptr(f) <<
" symedge=" << trunc_ptr(f->symedge) <<
"\n";
476 template<
typename T>
void cdt_draw(
const std::string &
label,
const CDTArrangement<T> &cdt)
478 static bool append =
false;
484 const char *drawfile =
"./debug_draw.html";
486 const char *drawfile =
"/tmp/debug_draw.html";
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;
497 if (cdt.verts.size() == 0) {
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];
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;
519 double width = maxx - minx;
520 double height = maxy - miny;
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);
528 double scale = view_width /
width;
530 # define SX(x) (((x)-minx) * scale)
531 # define SY(y) ((maxy - (y)) * scale)
535 f.open(drawfile, std::ios_base::app);
541 std::cout <<
"Could not open file " << drawfile <<
"\n";
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";
552 for (
const CDTEdge<T> *
e : cdt.edges) {
553 if (
e->symedges[0].next ==
nullptr) {
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";
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])
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";
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";
598 static int filtered_orient2d(
const FatCo<T> &
a,
const FatCo<T> &b,
const FatCo<T> &
c);
602 int filtered_orient2d<mpq_class>(
const FatCo<mpq_class> &
a,
603 const FatCo<mpq_class> &b,
604 const FatCo<mpq_class> &
c)
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;
620 int filtered_orient2d<double>(
const FatCo<double> &
a,
621 const FatCo<double> &b,
622 const FatCo<double> &
c)
624 return orient2d(
a.approx, b.approx,
c.approx);
631 static int filtered_incircle(
const FatCo<T> &
a,
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)
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);
660 double sup_adx =
a.abs_approx[0] + d.abs_approx[0];
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;
667 double sup_cdxbdy = sup_cdx * sup_bdy;
668 double sup_alift = sup_adx * sup_adx + sup_ady * sup_ady;
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);
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);
682 return incircle(
a.exact, b.exact,
c.exact, d.exact);
687 int filtered_incircle<double>(
const FatCo<double> &
a,
688 const FatCo<double> &b,
689 const FatCo<double> &
c,
690 const FatCo<double> &d)
692 return incircle(
a.approx, b.approx,
c.approx, d.approx);
701 template<
typename T>
static bool in_line(
const FatCo<T> &
a,
const FatCo<T> &b,
const FatCo<T> &
c);
705 bool in_line<mpq_class>(
const FatCo<mpq_class> &
a,
706 const FatCo<mpq_class> &b,
707 const FatCo<mpq_class> &
c)
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) {
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) {
728 vec2<mpq_class> exact_ab = b.exact -
a.exact;
729 vec2<mpq_class> exact_ac =
c.exact -
a.exact;
733 vec2<mpq_class> exact_bc =
c.exact - b.exact;
739 bool in_line<double>(
const FatCo<double> &
a,
const FatCo<double> &b,
const FatCo<double> &
c)
741 vec2<double> ab = b.approx -
a.approx;
742 vec2<double> ac =
c.approx -
a.approx;
746 vec2<double> bc =
c.approx - b.approx;
750 template<> CDTVert<double>::CDTVert(
const vec2<double> &pt)
753 this->co.approx = pt;
754 this->co.abs_approx = pt;
755 this->input_ids =
nullptr;
756 this->symedge =
nullptr;
758 this->merge_to_index = -1;
759 this->visit_index = 0;
763 template<> CDTVert<mpq_class>::CDTVert(
const vec2<mpq_class> &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;
771 this->merge_to_index = -1;
772 this->visit_index = 0;
776 template<
typename T> CDTVert<T> *CDTArrangement<T>::add_vert(
const vec2<T> &pt)
778 CDTVert<T> *
v =
new CDTVert<T>(pt);
779 int index = this->verts.append_and_get_index(
v);
785 CDTEdge<T> *CDTArrangement<T>::add_edge(CDTVert<T> *
v1,
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;
796 sesym->face = fright;
798 if (
v1->symedge ==
nullptr) {
802 if (
v2->symedge ==
nullptr) {
805 se->next = sesym->next = se->rot = sesym->rot =
nullptr;
809 template<
typename T> CDTFace<T> *CDTArrangement<T>::add_face()
811 CDTFace<T> *f =
new CDTFace<T>();
812 this->faces.append(f);
816 template<
typename T>
void CDTArrangement<T>::reserve(
int num_verts,
int num_edges,
int num_faces)
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);
825 CDT_state<T>::CDT_state(
int num_input_verts,
int num_input_edges,
int num_input_faces,
T epsilon)
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();
831 this->visit_count = 0;
834 static bool id_in_list(
const LinkNode *id_list,
int id)
838 for (ln = id_list; ln !=
nullptr; ln = ln->
next) {
847 static bool id_range_in_list(
const LinkNode *id_list,
int range_start,
int range_end)
852 for (ln = id_list; ln !=
nullptr; ln = ln->
next) {
854 if (
id >= range_start &&
id <= range_end) {
861 static void add_to_input_ids(
LinkNode **dst,
int input_id)
863 if (!id_in_list(*dst, input_id)) {
872 for (ln = src; ln !=
nullptr; ln = ln->
next) {
877 template<
typename T>
inline bool is_border_edge(
const CDTEdge<T> *
e,
const CDT_state<T> *cdt)
879 return e->symedges[0].face == cdt->outer_face ||
e->symedges[1].face == cdt->outer_face;
882 template<
typename T>
inline bool is_constrained_edge(
const CDTEdge<T> *
e)
884 return e->input_ids !=
nullptr;
887 template<
typename T>
inline bool is_deleted_edge(
const CDTEdge<T> *
e)
889 return e->symedges[0].next ==
nullptr;
892 template<
typename T>
inline bool is_original_vert(
const CDTVert<T> *
v, CDT_state<T> *cdt)
894 return (
v->index < cdt->input_vert_tot);
899 SymEdge<T> *find_symedge_between_verts(
const CDTVert<T> *
v1,
const CDTVert<T> *
v2)
901 SymEdge<T> *
t =
v1->symedge;
902 SymEdge<T> *tstart =
t;
904 if (
t->next->vert ==
v2) {
907 }
while ((
t =
t->rot) != tstart);
914 template<
typename T> SymEdge<T> *find_symedge_with_face(
const CDTVert<T> *
v,
const CDTFace<T> *f)
916 SymEdge<T> *
t =
v->symedge;
917 SymEdge<T> *tstart =
t;
922 }
while ((
t =
t->rot) != tstart);
929 template<
typename T>
inline bool exists_edge(
const CDTVert<T> *
v1,
const CDTVert<T> *
v2)
931 return find_symedge_between_verts(
v1,
v2) !=
nullptr;
937 template<
typename T>
bool vert_touches_face(
const CDTVert<T> *
v,
const CDTFace<T> *f)
939 SymEdge<T> *se =
v->symedge;
944 }
while ((se = se->rot) !=
v->symedge);
956 template<
typename T> CDTEdge<T> *CDTArrangement<T>::add_diagonal(SymEdge<T> *s1, SymEdge<T> *s2)
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];
969 s2prev->next = sdiagsym;
970 s1prev->next = sdiag;
972 sdiag->rot = s1prevsym;
974 sdiagsym->rot = s2prevsym;
975 for (SymEdge<T> *se = s2; se != sdiag; se = se->next) {
978 add_list_to_input_ids(&fnew->input_ids, fold->input_ids);
983 CDTEdge<T> *CDTArrangement<T>::add_vert_to_symedge_edge(CDTVert<T> *
v, SymEdge<T> *se)
985 SymEdge<T> *se_rot = se->rot;
986 SymEdge<T> *se_rotsym = sym(se_rot);
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];
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;
1005 template<
typename T>
1006 CDTEdge<T> *CDTArrangement<T>::connect_separate_parts(SymEdge<T> *se1, SymEdge<T> *se2)
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];
1017 new_se_sym->next = se1;
1018 new_se->rot = se1_rot;
1019 new_se_sym->rot = se2_rot;
1021 se2->rot = new_se_sym;
1022 se1_rotsym->next = new_se;
1023 se2_rotsym->next = new_se_sym;
1032 template<
typename T> CDTEdge<T> *CDTArrangement<T>::split_edge(SymEdge<T> *se,
T 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);
1044 SymEdge<T> *newse = &
e->symedges[0];
1045 SymEdge<T> *newsesym = &
e->symedges[1];
1047 newsesym->next = sesym;
1048 newse->next = senext;
1051 senext->rot = newsesym;
1052 newsesym->rot = sesymprevsym;
1053 sesymprev->next = newsesym;
1054 if (newsesym->vert->symedge == sesym) {
1055 newsesym->vert->symedge = newsesym;
1057 add_list_to_input_ids(&
e->input_ids, se->edge->input_ids);
1082 template<
typename T>
void CDTArrangement<T>::delete_edge(SymEdge<T> *se)
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);
1106 if (!v1_isolated && !v2_isolated && aface != bface) {
1107 for (SymEdge<T> *k = i; k != f; k = k->next) {
1114 v1->symedge =
nullptr;
1116 else if (
v1->symedge == se) {
1120 v2->symedge =
nullptr;
1122 else if (
v2->symedge == sesym) {
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;
1137 template<
typename T>
class SiteInfo {
1146 template<
typename T>
bool site_lexicographic_sort(
const SiteInfo<T> &
a,
const SiteInfo<T> &b)
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]) {
1153 if (co_a[0] > co_b[0]) {
1156 if (co_a[1] < co_b[1]) {
1159 if (co_a[1] > co_b[1]) {
1162 return a.orig_index < b.orig_index;
1170 template<
typename T>
void find_site_merges(Array<SiteInfo<T>> &sites)
1172 int n = sites.size();
1173 for (
int i = 0; i < n - 1; ++i) {
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;
1185 template<
typename T>
inline bool vert_left_of_symedge(CDTVert<T> *
v, SymEdge<T> *se)
1187 return filtered_orient2d(
v->
co, se->vert->co, se->next->vert->co) > 0;
1190 template<
typename T>
inline bool vert_right_of_symedge(CDTVert<T> *
v, SymEdge<T> *se)
1192 return filtered_orient2d(
v->
co, se->next->vert->co, se->vert->co) > 0;
1196 template<
typename T>
1197 inline bool dc_tri_valid(SymEdge<T> *se, SymEdge<T> *basel, SymEdge<T> *basel_sym)
1199 return filtered_orient2d(se->next->vert->co, basel_sym->vert->co, basel->vert->co) > 0;
1208 template<
typename T>
1209 void dc_tri(CDTArrangement<T> *cdt,
1210 Array<SiteInfo<T>> &sites,
1216 constexpr
int dbg_level = 0;
1217 if (dbg_level > 0) {
1218 std::cout <<
"DC_TRI start=" << start <<
" end=" << end <<
"\n";
1220 int n = end - start;
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];
1237 *r_le = &ea->symedges[0];
1238 *r_re = &ea->symedges[1];
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);
1245 cdt->add_diagonal(&eb->symedges[0], &ea->symedges[0]);
1246 *r_le = &ea->symedges[0];
1247 *r_re = &eb->symedges[0];
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;
1256 *r_le = &ea->symedges[0];
1257 *r_re = &eb->symedges[0];
1263 BLI_assert(n2 >= 2 && end - (start + n2) >= 2);
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) {
1279 cdt_draw(lab, *cdt);
1284 if (vert_left_of_symedge(rdi->vert, ldi)) {
1287 else if (vert_right_of_symedge(ldi->vert, rdi)) {
1288 rdi = sym(rdi)->rot;
1294 if (dbg_level > 0) {
1295 std::cout <<
"common lower tangent in between\n"
1296 <<
"rdi " << rdi <<
"\n"
1297 <<
"ldi" << ldi <<
"\n";
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);
1307 if (ldi->vert == ldo->vert) {
1310 if (rdi->vert == rdo->vert) {
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";
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";
1331 while (filtered_incircle(basel_sym->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";
1339 SymEdge<T> *
t = lcand->rot;
1340 cdt->delete_edge(sym(lcand));
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";
1350 while (filtered_incircle(basel_sym->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";
1358 SymEdge<T> *
t = sym(rcand)->next;
1359 cdt->delete_edge(rcand);
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";
1372 if (!valid_lcand && !valid_rcand) {
1377 if (!valid_lcand || (valid_rcand && filtered_incircle(lcand->next->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";
1386 ebasel = cdt->add_diagonal(rcand->next, basel_sym);
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";
1394 ebasel = cdt->add_diagonal(basel_sym->next, sym(lcand));
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);
1405 BLI_assert(sym(ldo)->face == cdt->outer_face && rdo->face == cdt->outer_face);
1409 template<
typename T>
void dc_triangulate(CDTArrangement<T> *cdt, Array<SiteInfo<T>> &sites)
1414 int nsites = sites.size();
1415 while (j < nsites) {
1417 sites[i] = sites[j++];
1418 if (sites[i].
v->merge_to_index < 0) {
1428 dc_tri(cdt, sites, 0, n, &le, &re);
1449 template<
typename T>
void initial_triangulation(CDTArrangement<T> *cdt)
1451 int n = cdt->verts.size();
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;
1460 std::sort(sites.begin(), sites.end(), site_lexicographic_sort<T>);
1461 find_site_merges(sites);
1462 dc_triangulate(cdt, sites);
1472 template<
typename T>
static void re_delaunay_triangulate(CDTArrangement<T> *cdt, SymEdge<T> *se)
1474 if (se->face == cdt->outer_face || sym(se)->face == cdt->outer_face) {
1479 for (SymEdge<T> *ss = se->next; ss != se; ss = ss->next) {
1487 SymEdge<T> *first = se->next->next;
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) {
1501 CDTEdge<T> *ebc =
nullptr;
1502 CDTEdge<T> *eca =
nullptr;
1503 if (!exists_edge(b,
c)) {
1504 ebc = cdt->add_diagonal(se->next, cse);
1506 if (!exists_edge(
c,
a)) {
1507 eca = cdt->add_diagonal(cse, se);
1511 re_delaunay_triangulate(cdt, &ebc->symedges[1]);
1514 re_delaunay_triangulate(cdt, &eca->symedges[1]);
1518 template<
typename T>
inline int tri_orient(
const SymEdge<T> *
t)
1520 return filtered_orient2d(
t->vert->co,
t->next->vert->co,
t->next->next->vert->co);
1548 template<
typename T>
class CrossData {
1555 CrossData() : lambda(
T(0)), vert(nullptr), in(nullptr), out(nullptr)
1558 CrossData(
T l, CDTVert<T> *
v, SymEdge<T> *i, SymEdge<T> *o) : lambda(
l), vert(
v), in(i), out(o)
1561 CrossData(
const CrossData &other)
1562 : lambda(other.lambda), vert(other.vert), in(other.in), out(other.out)
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))
1572 ~CrossData() =
default;
1573 CrossData &
operator=(
const CrossData &other)
1575 if (
this != &other) {
1576 lambda = other.lambda;
1583 CrossData &
operator=(CrossData &&other) noexcept
1585 lambda = std::move(other.lambda);
1586 vert = std::move(other.vert);
1587 in = std::move(other.in);
1588 out = std::move(other.out);
1593 template<
typename T>
1594 bool get_next_crossing_from_vert(CDT_state<T> *cdt_state,
1596 CrossData<T> *cd_next,
1597 const CDTVert<T> *
v2);
1606 template<
typename T>
1607 void fill_crossdata_for_through_vert(CDTVert<T> *
v,
1610 CrossData<T> *cd_next)
1614 cd_next->lambda =
T(0);
1616 cd_next->in =
nullptr;
1617 cd_next->out =
nullptr;
1618 if (cd->lambda == 0) {
1624 if (se->vert !=
v) {
1626 if (se->vert !=
v) {
1648 template<
typename T>
1649 void fill_crossdata_for_intersect(
const FatCo<T> &curco,
1650 const CDTVert<T> *
v2,
1653 CrossData<T> *cd_next,
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);
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: {
1669 if (!std::is_same<T, mpq_class>::value) {
1674 if (lambda * len_ab <=
epsilon) {
1675 fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1677 else if ((1 - lambda) * len_ab <=
epsilon) {
1678 fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1681 *cd_next = CrossData<T>(lambda,
nullptr,
t,
nullptr);
1682 if (cd->lambda == 0) {
1688 *cd_next = CrossData<T>(lambda,
nullptr,
t,
nullptr);
1689 if (cd->lambda == 0) {
1695 case vec2<T>::isect_result::LINE_LINE_EXACT: {
1697 fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1699 else if (lambda == 1) {
1700 fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1703 *cd_next = CrossData<T>(lambda,
nullptr,
t,
nullptr);
1704 if (cd->lambda == 0) {
1710 case vec2<T>::isect_result::LINE_LINE_NONE: {
1712 if (std::is_same<T, mpq_class>::value) {
1717 const T middle_lambda = 0.5;
1718 if (lambda <= middle_lambda) {
1719 fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
1722 fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
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);
1732 fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
1746 template<
typename T>
1747 bool get_next_crossing_from_vert(CDT_state<T> *cdt_state,
1749 CrossData<T> *cd_next,
1750 const CDTVert<T> *
v2)
1752 SymEdge<T> *tstart = cd->vert->symedge;
1753 SymEdge<T> *
t = tstart;
1754 CDTVert<T> *vcur = cd->vert;
1763 if (
t->face != cdt_state->cdt.outer_face && tri_orient(
t) < 0) {
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);
1774 if (
t->face != cdt_state->cdt.outer_face) {
1775 int orient2 = filtered_orient2d(vcur->co, vb->co,
v2->
co);
1777 if (orient1 > 0 && orient2 < 0) {
1780 fill_crossdata_for_intersect(vcur->co,
v2,
t, cd, cd_next, cdt_state->epsilon);
1785 }
while ((
t =
t->rot) != tstart);
1797 template<
typename T>
1798 void get_next_crossing_from_edge(CrossData<T> *cd,
1799 CrossData<T> *cd_next,
1800 const CDTVert<T> *
v2,
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);
1811 fill_crossdata_for_intersect<T>(fat_curco,
v2, se_ac->next, cd, cd_next,
epsilon);
1813 else if (orient > 0.0) {
1814 fill_crossdata_for_intersect(fat_curco,
v2, se_ac, cd, cd_next,
epsilon);
1817 *cd_next = CrossData<T>{0.0, vc, se_ac->next,
nullptr};
1821 constexpr
int inline_crossings_size = 128;
1822 template<
typename T>
1823 void dump_crossings(
const Vector<CrossData<T>, inline_crossings_size> &crossings)
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;
1833 std::cout <<
"lambda=" << cd.lambda;
1835 if (cd.in !=
nullptr) {
1836 std::cout <<
" in=" << short_se_dump(cd.in);
1837 std::cout <<
" out=" << short_se_dump(cd.out);
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)
1858 constexpr
int dbg_level = 0;
1859 if (dbg_level > 0) {
1860 std::cout <<
"\nADD EDGE CONSTRAINT\n" << vertname(
v1) <<
" " << vertname(
v2) <<
"\n";
1876 SymEdge<T> *
t = find_symedge_between_verts(
v1,
v2);
1879 add_to_input_ids(&
t->edge->input_ids, input_id);
1880 if (r_edges !=
nullptr) {
1882 *r_edges = edge_list.
list;
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));
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];
1910 if (crossings[n - 1].lambda == 0) {
1911 ok = get_next_crossing_from_vert(cdt_state, cd, cd_next,
v2);
1914 get_next_crossing_from_edge<T>(cd, cd_next,
v2, cdt_state->epsilon);
1917 constexpr
int unreasonably_large_crossings = 100000;
1918 if (!ok || crossings.size() == unreasonably_large_crossings) {
1923 if (crossings[n].lambda == 0) {
1924 if (crossings[n].vert->visit_index == visit) {
1929 crossings[n].vert->visit_index = visit;
1933 if (dbg_level > 0) {
1934 dump_crossings(crossings);
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;
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)) {
1960 cd_prev->lambda = -1.0;
1964 cd_prev = &crossings[j];
1966 if (cd_prev->lambda == 0.0) {
1967 se = find_symedge_between_verts(cd_prev->vert,
v);
1968 if (se ==
nullptr) {
1975 se = find_symedge_with_face(
v, sym(cd_prev->in)->face);
1976 if (se ==
nullptr) {
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;
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);
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) {
2016 SymEdge<T> *tnext =
t;
2018 if (cd->lambda != 0.0) {
2019 if (is_constrained_edge(cd->in->edge)) {
2020 t = cd->vert->symedge;
2021 tnext = sym(
t)->next;
2024 else if (cd->lambda == 0.0) {
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) {
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) {
2047 if (tstart->next->vert ==
t->vert) {
2048 edge = tstart->edge;
2051 edge = cdt_state->cdt.add_diagonal(tstart,
t);
2053 add_to_input_ids(&edge->input_ids, input_id);
2054 if (r_edges !=
nullptr) {
2058 re_delaunay_triangulate(&cdt_state->cdt, &edge->symedges[0]);
2059 re_delaunay_triangulate(&cdt_state->cdt, &edge->symedges[1]);
2061 if (i < ncrossings - 1) {
2062 if (tnext !=
nullptr) {
2069 *r_edges = edge_list.
list;
2079 template<
typename T>
void add_edge_constraints(CDT_state<T> *cdt_state,
const CDT_input<T> &input)
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) {
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);
2094 cdt_state->face_edge_offset = ne;
2115 template<
typename T>
2117 CDT_state<T> *cdt_state, SymEdge<T> *face_symedge,
int face_id,
int fedge_start,
int fedge_end)
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) {
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);
2146 static int power_of_10_greater_equal_to(
int x)
2167 template<
typename T>
void add_face_constraints(CDT_state<T> *cdt_state,
const CDT_input<T> &input)
2169 int nv = input.vert.size();
2170 int nf = input.face.size();
2172 SymEdge<T> *face_symedge0 =
nullptr;
2173 CDTArrangement<T> *cdt = &cdt_state->cdt;
2175 for (
int f = 0; f < nf; f++) {
2176 maxflen =
max_ii(maxflen, input.face[f].size());
2179 cdt_state->face_edge_offset = power_of_10_greater_equal_to(
2180 max_ii(maxflen, cdt_state->face_edge_offset));
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();
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) {
2202 CDTVert<T> *
v1 = cdt->get_vert_resolve_merge(iv1);
2203 CDTVert<T> *
v2 = cdt->get_vert_resolve_merge(iv2);
2205 add_edge_constraint(cdt_state,
v1,
v2, face_edge_id, &edge_list);
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];
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);
2232 template<
typename T>
void dissolve_symedge(CDT_state<T> *cdt_state, SymEdge<T> *se)
2234 CDTArrangement<T> *cdt = &cdt_state->cdt;
2235 SymEdge<T> *symse = sym(se);
2236 if (symse->face == cdt->outer_face) {
2240 if (
ELEM(cdt->outer_face->symedge, se, symse)) {
2242 if (se->next->next == se) {
2243 cdt->outer_face->symedge =
nullptr;
2246 cdt->outer_face->symedge = se->next->next;
2250 if (se->face->symedge == se) {
2251 se->face->symedge = se->next;
2253 if (symse->face->symedge == symse) {
2254 symse->face->symedge = symse->next;
2257 cdt->delete_edge(se);
2263 template<
typename T>
void remove_non_constraint_edges(CDT_state<T> *cdt_state)
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);
2288 template<
typename T>
struct EdgeToSort {
2290 CDTEdge<T> *
e{
nullptr};
2292 EdgeToSort() =
default;
2296 EdgeToSort(EdgeToSort &&other) noexcept :
len_squared(std::move(other.len_squared)),
e(other.e)
2299 ~EdgeToSort() =
default;
2300 EdgeToSort &
operator=(
const EdgeToSort &other)
2302 if (
this != &other) {
2308 EdgeToSort &
operator=(EdgeToSort &&other)
2316 template<
typename T>
void remove_non_constraint_edges_leave_valid_bmesh(CDT_state<T> *cdt_state)
2318 CDTArrangement<T> *cdt = &cdt_state->cdt;
2319 size_t nedges = cdt->edges.size();
2323 Vector<EdgeToSort<T>> dissolvable_edges;
2324 dissolvable_edges.reserve(cdt->edges.size());
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);
2337 dissolvable_edges.end(),
2338 [](
const EdgeToSort<T> &
a,
const EdgeToSort<T> &b) ->
bool {
2339 return (a.len_squared < b.len_squared);
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)) {
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))) {
2360 dissolve_symedge(cdt_state, se);
2365 template<
typename T>
void remove_outer_edges_until_constraints(CDT_state<T> *cdt_state)
2370 int visit = ++cdt_state->visit_count;
2372 cdt_state->cdt.outer_face->visit_index = visit;
2374 Vector<CDTFace<T> *> fstack;
2375 SymEdge<T> *se_start = cdt_state->cdt.outer_face->symedge;
2376 SymEdge<T> *se = se_start;
2378 if (!is_constrained_edge(se->edge)) {
2379 CDTFace<T> *fsym = sym(se)->face;
2380 if (fsym->visit_index != visit) {
2381 fstack.append(fsym);
2384 }
while ((se = se->next) != se_start);
2386 while (!fstack.is_empty()) {
2389 CDTFace<T> *f = fstack.pop_last();
2390 if (f->visit_index == visit) {
2394 f->visit_index = visit;
2395 se_start = se = f->symedge;
2397 dissolvable = !is_constrained_edge(se->edge);
2399 CDTFace<T> *fsym = sym(se)->face;
2400 if (fsym->visit_index != visit) {
2401 fstack.append(fsym);
2408 }
while (se != se_start);
2409 while (to_dissolve !=
nullptr) {
2411 if (se->next !=
nullptr) {
2412 dissolve_symedge(cdt_state, se);
2422 template<
typename T>
2423 void prepare_cdt_for_output(CDT_state<T> *cdt_state,
const CDT_output_type output_type)
2425 CDTArrangement<T> *cdt = &cdt_state->cdt;
2426 if (cdt->edges.is_empty()) {
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];
2436 if (
e->symedges[1].face->symedge ==
nullptr) {
2437 e->symedges[1].face->symedge = &
e->symedges[1];
2443 remove_non_constraint_edges(cdt_state);
2446 remove_non_constraint_edges_leave_valid_bmesh(cdt_state);
2449 remove_outer_edges_until_constraints(cdt_state);
2453 template<
typename T>
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;
2467 int verts_size = cdt->verts.size();
2468 Array<int> vert_to_output_map(verts_size);
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;
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);
2490 vert_to_output_map[i] = vert_to_output_map[
v->merge_to_index];
2494 result.vert = Array<vec2<T>>(nv);
2495 result.vert_orig = Array<Vector<int>>(nv);
2497 for (
int i = 0; i < verts_size; ++i) {
2498 CDTVert<T> *
v = cdt->verts[i];
2499 if (
v->merge_to_index == -1) {
2501 if (i < cdt_state->input_vert_tot) {
2502 result.vert_orig[i_out].append(i);
2512 int ne = std::count_if(cdt->edges.begin(), cdt->edges.end(), [](
const CDTEdge<T> *
e) ->
bool {
2513 return !is_deleted_edge(e);
2515 result.edge = Array<std::pair<int, int>>(ne);
2516 result.edge_orig = Array<Vector<int>>(ne);
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);
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;
2534 result.face = Array<Vector<int>>(nf);
2535 result.face_orig = Array<Vector<int>>(nf);
2537 for (
const CDTFace<T> *f : cdt->faces) {
2538 if (!f->deleted && f != cdt->outer_face) {
2539 SymEdge<T> *se = f->symedge;
2541 SymEdge<T> *se_start = se;
2543 result.face[f_out].append(vert_to_output_map[se->vert->index]);
2545 }
while (se != se_start);
2559 template<
typename T>
void add_input_verts(CDT_state<T> *cdt_state,
const CDT_input<T> &input)
2561 for (
int i = 0; i < cdt_state->input_vert_tot; ++i) {
2562 cdt_state->cdt.add_vert(input.vert[i]);
2566 template<
typename T>
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);
2580 blender::meshintersect::CDT_result<double> delaunay_2d_calc(
const CDT_input<double> &input,
2583 return delaunay_calc(input, output_type);
2587 blender::meshintersect::CDT_result<mpq_class> delaunay_2d_calc(
const CDT_input<mpq_class> &input,
2590 return delaunay_calc(input, output_type);
2608 blender::meshintersect::CDT_input<double> in;
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);
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]);
2620 for (
int f = 0; f < input->faces_len; ++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];
2627 in.epsilon =
static_cast<double>(input->epsilon);
2629 blender::meshintersect::CDT_result<double> res = blender::meshintersect::delaunay_2d_calc(
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();
2640 for (
int v = 0;
v < nv; ++
v) {
2641 tot_v_orig += res.vert_orig[
v].size();
2643 for (
int e = 0;
e < ne; ++
e) {
2644 tot_e_orig += res.edge_orig[
e].size();
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();
2651 output->vert_coords =
static_cast<decltype(
output-
>vert_coords)>(
2654 output->verts_orig_start_table =
static_cast<int *
>(
2660 output->edges_orig_start_table =
static_cast<int *
>(
2667 output->faces_orig_start_table =
static_cast<int *
>(
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];
2680 output->verts_orig_len_table[
v] = v_orig_index - this_start;
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];
2691 output->edges_orig_len_table[
e] = e_orig_index - this_start;
2693 int f_orig_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];
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];
2707 output->faces_orig_len_table[f] = f_orig_index - this_start;
CDT_result * BLI_delaunay_2d_cdt_calc(const CDT_input *input, const CDT_output_type output_type)
@ CDT_CONSTRAINTS_VALID_BMESH
struct CDT_input CDT_input
void BLI_delaunay_2d_cdt_free(CDT_result *result)
void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc)
void void void void BLI_linklist_append(LinkNodePair *list_pair, void *ptr) ATTR_NONNULL(1)
void void void * BLI_linklist_pop(LinkNode **listp) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_linklist_prepend(LinkNode **listp, void *ptr) ATTR_NONNULL(1)
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 POINTER_AS_INT(i)
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.
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void(* MEM_freeN)(void *vmemh)
void *(* MEM_mallocN)(size_t len, const char *str)
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)
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)
static const char hex[17]
__forceinline const avxi abs(const avxi &a)
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)