34 return (
v < 0) ? -
v :
v;
78template<
typename T>
struct CDTVert;
79template<
typename T>
struct CDTEdge;
80template<
typename T>
struct CDTFace;
102 return se->
next->rot;
108 return se->
rot->next->rot;
126template<>
struct FatCo<mpq_class> {
175 stream <<
"(" << co.
approx.x <<
", " << co.
approx.y <<
")";
244 void reserve(
int verts_num,
int edges_num,
int faces_num);
303 if (
v->merge_to_index != -1) {
304 v = this->verts[
v->merge_to_index];
328 int input_verts_num,
int input_edges_num,
int input_faces_num, T
epsilon,
bool need_ids);
333 for (
int i : this->
verts.index_range()) {
335 v->input_ids.clear();
337 this->
verts[i] =
nullptr;
339 for (
int i : this->edges.index_range()) {
341 e->input_ids.clear();
343 this->edges[i] =
nullptr;
345 for (
int i : this->
faces.index_range()) {
349 this->
faces[i] =
nullptr;
358 std::stringstream ss;
359 ss <<
"[" <<
v->index <<
"]";
366 constexpr int TRUNC_PTR_MASK = 0xFFFF;
367 std::stringstream ss;
374 std::stringstream ss;
400 return std::string(
"null");
408 os <<
"\nCDT\n\nVERTS\n";
412 if (
v->merge_to_index == -1) {
416 os <<
" merge to " <<
vertname(cdt_state.
cdt.verts[
v->merge_to_index]) <<
"\n";
420 constexpr int print_count_limit = 25;
422 os <<
" edges out:\n";
424 if (se->
next ==
nullptr) {
425 os <<
" [null] next/rot symedge, se=" <<
trunc_ptr(se) <<
"\n";
428 if (se->
next->next ==
nullptr) {
429 os <<
" [null] next-next/rot symedge, se=" <<
trunc_ptr(se) <<
"\n";
437 }
while (se !=
v->symedge &&
count < print_count_limit);
443 if (
e->symedges[0].next ==
nullptr) {
447 for (
int i = 0; i < 2; ++i) {
456 os <<
"outer_face=" <<
trunc_ptr(cdt_state.
cdt.outer_face) <<
"\n";
458 if (cdt_state.
cdt.outer_face->symedge !=
nullptr) {
470 static bool append =
false;
476 const char *drawfile =
"./cdt_debug_draw.html";
478 const char *drawfile =
"/tmp/cdt_debug_draw.html";
480 constexpr int max_draw_width = 1800;
481 constexpr int max_draw_height = 1600;
482 constexpr double margin_expand = 0.05;
483 constexpr int thin_line = 1;
484 constexpr int thick_line = 4;
485 constexpr int vert_radius = 3;
486 constexpr bool draw_vert_labels =
true;
487 constexpr bool draw_edge_labels =
false;
488 constexpr bool draw_face_labels =
false;
490 if (cdt.
verts.is_empty()) {
493 double2 vmin(std::numeric_limits<double>::max());
494 double2 vmax(std::numeric_limits<double>::lowest());
498 double draw_margin = ((vmax.x - vmin.x) + (vmax.y - vmin.y)) * margin_expand;
499 double minx = vmin.x - draw_margin;
500 double maxx = vmax.x + draw_margin;
501 double miny = vmin.y - draw_margin;
502 double maxy = vmax.y + draw_margin;
504 double width = maxx - minx;
505 double height = maxy - miny;
506 double aspect = height / width;
507 int view_width = max_draw_width;
508 int view_height = int(view_width * aspect);
509 if (view_height > max_draw_height) {
510 view_height = max_draw_height;
511 view_width = int(view_height / aspect);
513 double scale = view_width / width;
515# define SX(x) (((x)-minx) * scale)
516# define SY(y) ((maxy - (y)) * scale)
520 f.open(drawfile, std::ios_base::app);
526 std::cout <<
"Could not open file " << drawfile <<
"\n";
530 f <<
"<div>" <<
label <<
"</div>\n<div>\n"
531 <<
"<svg version=\"1.1\" "
532 "xmlns=\"http://www.w3.org/2000/svg\" "
533 "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
534 "xml:space=\"preserve\"\n"
535 <<
"width=\"" << view_width <<
"\" height=\"" << view_height <<
"\">n";
538 if (
e->symedges[0].next ==
nullptr) {
545 int strokew =
e->input_ids.size() == 0 ? thin_line : thick_line;
546 f << R
"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
547 <<
SX(uco[0]) <<
"\" y1=\"" <<
SY(uco[1]) <<
"\" x2=\"" <<
SX(vco[0]) <<
"\" y2=\""
548 <<
SY(vco[1]) <<
"\">\n";
551 if (draw_edge_labels) {
552 f <<
"<text x=\"" <<
SX((uco[0] + vco[0]) / 2) <<
"\" y=\"" <<
SY((uco[1] + vco[1]) / 2)
553 << R
"(" font-size="small">)";
561 f << R
"(<circle fill="black" cx=")" << SX(v->co.approx[0]) << "\" cy=\"" <<
SY(
v->
co.approx[1])
562 <<
"\" r=\"" << vert_radius <<
"\">\n";
563 f <<
" <title>[" << i <<
"]" <<
v->
co.approx <<
"</title>\n";
565 if (draw_vert_labels) {
566 f <<
"<text x=\"" <<
SX(
v->
co.approx[0]) + vert_radius <<
"\" y=\""
567 <<
SY(
v->
co.approx[1]) - vert_radius << R
"(" font-size="small">[)" << i << "]</text>\n";
572 if (draw_face_labels) {
573 for (
const CDTFace<T> *face : cdt.
faces) {
574 if (!face->deleted) {
576 const SymEdge<T> *se_face_start =
nullptr;
577 for (
const CDTEdge<T> *
e : cdt.
edges) {
578 if (
e->symedges[0].face == face) {
579 se_face_start = &
e->symedges[0];
582 if (
e->symedges[1].face == face) {
583 se_face_start = &
e->symedges[1];
586 if (se_face_start !=
nullptr) {
595 const SymEdge<T> *se = se_face_start;
597 if (se->face == face) {
598 cen = cen + se->vert->co.approx;
601 }
while ((se = se->next) != se_face_start);
602 if (face_nverts > 0) {
603 cen = cen / double(face_nverts);
606 f <<
"<text x=\"" <<
SX(cen[0]) <<
"\" y=\"" <<
SY(cen[1]) <<
"\""
607 <<
" font-size=\"small\">[";
609 if (face->input_ids.size() > 0) {
610 for (
int id : face->input_ids) {
636 const FatCo<mpq_class> &
b,
637 const FatCo<mpq_class> &c)
639 double det = (a.approx[0] - c.approx[0]) * (
b.approx[1] - c.approx[1]) -
640 (a.approx[1] - c.approx[1]) * (
b.approx[0] - c.approx[0]);
641 double supremum = (a.abs_approx[0] + c.abs_approx[0]) * (
b.abs_approx[1] + c.abs_approx[1]) +
642 (a.abs_approx[1] + c.abs_approx[1]) * (
b.abs_approx[0] + c.abs_approx[0]);
643 constexpr double index_orient2d = 6;
644 double err_bound = supremum * index_orient2d * DBL_EPSILON;
645 if (
fabs(det) > err_bound) {
646 return det > 0 ? 1 : -1;
648 return orient2d(a.exact,
b.exact, c.exact);
654 const FatCo<double> &
b,
655 const FatCo<double> &c)
657 return orient2d(a.approx,
b.approx, c.approx);
672 const FatCo<mpq_class> &
b,
673 const FatCo<mpq_class> &c,
674 const FatCo<mpq_class> &d)
676 double adx = a.approx[0] - d.approx[0];
677 double bdx =
b.approx[0] - d.approx[0];
678 double cdx = c.approx[0] - d.approx[0];
679 double ady = a.approx[1] - d.approx[1];
680 double bdy =
b.approx[1] - d.approx[1];
681 double cdy = c.approx[1] - d.approx[1];
682 double bdxcdy = bdx * cdy;
683 double cdxbdy = cdx * bdy;
684 double alift = adx * adx + ady * ady;
685 double cdxady = cdx * ady;
686 double adxcdy = adx * cdy;
687 double blift = bdx * bdx + bdy * bdy;
688 double adxbdy = adx * bdy;
689 double bdxady = bdx * ady;
690 double clift = cdx * cdx + cdy * cdy;
691 double det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
693 double sup_adx = a.abs_approx[0] + d.abs_approx[0];
694 double sup_bdx =
b.abs_approx[0] + d.abs_approx[0];
695 double sup_cdx = c.abs_approx[0] + d.abs_approx[0];
696 double sup_ady = a.abs_approx[1] + d.abs_approx[1];
697 double sup_bdy =
b.abs_approx[1] + d.abs_approx[1];
698 double sup_cdy = c.abs_approx[1] + d.abs_approx[1];
699 double sup_bdxcdy = sup_bdx * sup_cdy;
700 double sup_cdxbdy = sup_cdx * sup_bdy;
701 double sup_alift = sup_adx * sup_adx + sup_ady * sup_ady;
702 double sup_cdxady = sup_cdx * sup_ady;
703 double sup_adxcdy = sup_adx * sup_cdy;
704 double sup_blift = sup_bdx * sup_bdx + sup_bdy * sup_bdy;
705 double sup_adxbdy = sup_adx * sup_bdy;
706 double sup_bdxady = sup_bdx * sup_ady;
707 double sup_clift = sup_cdx * sup_cdx + sup_cdy * sup_cdy;
708 double sup_det = sup_alift * (sup_bdxcdy + sup_cdxbdy) + sup_blift * (sup_cdxady + sup_adxcdy) +
709 sup_clift * (sup_adxbdy + sup_bdxady);
711 double err_bound = sup_det * index * DBL_EPSILON;
712 if (
fabs(det) > err_bound) {
713 return det < 0.0 ? -1 : (det > 0.0 ? 1 : 0);
715 return incircle(a.exact,
b.exact, c.exact, d.exact);
721 const FatCo<double> &
b,
722 const FatCo<double> &c,
723 const FatCo<double> &d)
725 return incircle(a.approx,
b.approx, c.approx, d.approx);
734template<
typename T>
static bool in_line(
const FatCo<T> &a,
const FatCo<T> &
b,
const FatCo<T> &c);
739 const FatCo<mpq_class> &
b,
740 const FatCo<mpq_class> &c)
744 double2 ac = c.approx - a.approx;
745 double2 supremum_ab =
b.abs_approx + a.abs_approx;
746 double2 supremum_bc = c.abs_approx +
b.abs_approx;
747 double2 supremum_ac = c.abs_approx + a.abs_approx;
748 double dot_ab_ac = ab.x * ac.x + ab.y * ac.y;
749 double supremum_dot_ab_ac = supremum_ab.x * supremum_ac.x + supremum_ab.y * supremum_ac.y;
750 constexpr double index = 6;
751 double err_bound = supremum_dot_ab_ac * index * DBL_EPSILON;
752 if (dot_ab_ac < -err_bound) {
755 double dot_bc_ac = bc.x * ac.x + bc.y * ac.y;
756 double supremum_dot_bc_ac = supremum_bc.x * supremum_ac.x + supremum_bc.y * supremum_ac.y;
757 err_bound = supremum_dot_bc_ac * index * DBL_EPSILON;
758 if (dot_bc_ac < -err_bound) {
761 mpq2 exact_ab =
b.exact - a.exact;
762 mpq2 exact_ac = c.exact - a.exact;
763 if (
dot(exact_ab, exact_ac) < 0) {
766 mpq2 exact_bc = c.exact -
b.exact;
767 return dot(exact_bc, exact_ac) >= 0;
772bool in_line<double>(
const FatCo<double> &a,
const FatCo<double> &
b,
const FatCo<double> &c)
775 double2 ac = c.approx - a.approx;
776 if (
dot(ab, ac) < 0) {
780 return dot(bc, ac) >= 0;
786 this->co.approx = pt;
787 this->co.abs_approx = pt;
788 this->symedge =
nullptr;
790 this->merge_to_index = -1;
791 this->visit_index = 0;
798 this->co.approx =
double2(pt.x.get_d(), pt.y.get_d());
799 this->co.abs_approx =
double2(
fabs(this->co.approx.x),
fabs(this->co.approx.y));
800 this->symedge =
nullptr;
802 this->merge_to_index = -1;
803 this->visit_index = 0;
810 int index = this->
verts.append_and_get_index(v);
822 this->edges.append(
e);
827 sesym->
face = fright;
833 if (
v2->symedge ==
nullptr) {
843 this->
faces.append(f);
850 this->
verts.reserve(2 * verts_num);
851 this->edges.reserve(3 * verts_num + 2 * edges_num + 3 * 2 * faces_num);
852 this->
faces.reserve(2 * verts_num + 2 * edges_num + 2 * faces_num);
857 int input_verts_num,
int input_edges_num,
int input_faces_num, T epsilon,
bool need_ids)
859 this->input_vert_num = input_verts_num;
860 this->cdt.
reserve(input_verts_num, input_edges_num, input_faces_num);
862 this->epsilon = epsilon;
863 this->need_ids = need_ids;
864 this->visit_count = 0;
870 for (
int id : id_list) {
871 if (
id >= range_start &&
id <= range_end) {
885 for (
int value : src) {
890template<
typename T>
inline bool is_border_edge(
const CDTEdge<T> *
e,
const CDT_state<T> *cdt)
892 return e->symedges[0].face == cdt->outer_face ||
e->symedges[1].face == cdt->outer_face;
897 return e->input_ids.size() > 0;
902 return e->symedges[0].next ==
nullptr;
907 return (
v->index < cdt->input_vert_num);
916 SymEdge<T> *t = v1->symedge;
917 SymEdge<T> *tstart = t;
919 if (t->next->vert ==
v2) {
922 }
while ((t = t->rot) != tstart);
931 SymEdge<T> *t =
v->symedge;
932 SymEdge<T> *tstart = t;
937 }
while ((t = t->rot) != tstart);
944template<
typename T>
inline bool exists_edge(
const CDTVert<T> *v1,
const CDTVert<T> *
v2)
954 SymEdge<T> *se =
v->symedge;
959 }
while ((se = se->rot) !=
v->symedge);
984 s2prev->
next = sdiagsym;
985 s1prev->
next = sdiag;
987 sdiag->
rot = s1prevsym;
989 sdiagsym->
rot = s2prevsym;
1007 new_se_sym->
next = new_se;
1008 new_se->
rot = new_se;
1009 new_se_sym->
rot = se_rot;
1010 se->
rot = new_se_sym;
1011 se_rotsym->
next = new_se_sym;
1032 new_se_sym->
next = se1;
1033 new_se->
rot = se1_rot;
1034 new_se_sym->
rot = se2_rot;
1036 se2->
rot = new_se_sym;
1037 se1_rotsym->
next = new_se;
1038 se2_rotsym->
next = new_se_sym;
1062 newsesym->
next = sesym;
1063 newse->
next = senext;
1066 senext->
rot = newsesym;
1067 newsesym->
rot = sesymprevsym;
1068 sesymprev->
next = newsesym;
1069 if (newsesym->
vert->symedge == sesym) {
1070 newsesym->
vert->symedge = newsesym;
1110 bool v1_isolated = (i == se);
1111 bool v2_isolated = (f == sesym);
1121 if (!v1_isolated && !v2_isolated && aface != bface) {
1135 v2->symedge =
nullptr;
1137 else if (
v2->symedge == sesym) {
1143 sesym->
next = sesym->
rot =
nullptr;
1144 if (!v1_isolated && !v2_isolated && aface != bface) {
1146 if (this->outer_face == bface) {
1147 this->outer_face = aface;
1165 if (co_a[0] < co_b[0]) {
1168 if (co_a[0] > co_b[0]) {
1171 if (co_a[1] < co_b[1]) {
1174 if (co_a[1] > co_b[1]) {
1187 int n = sites.size();
1188 for (
int i = 0; i < n - 1; ++i) {
1190 while (j < n && sites[j].
v->
co.exact == sites[i].v->co.exact) {
1191 sites[j].v->merge_to_index = sites[i].orig_index;
1212inline bool dc_tri_valid(SymEdge<T> *se, SymEdge<T> *basel, SymEdge<T> *basel_sym)
1214 return filtered_orient2d(se->next->vert->co, basel_sym->vert->co, basel->vert->co) > 0;
1231 constexpr int dbg_level = 0;
1232 if (dbg_level > 0) {
1233 std::cout <<
"DC_TRI start=" << start <<
" end=" << end <<
"\n";
1235 int n = end - start;
1244 CDTVert<T> *v1 = sites[start].v;
1245 CDTVert<T> *
v2 = sites[start + 1].v;
1246 CDTEdge<T> *ea = cdt->add_edge(v1,
v2, cdt->outer_face, cdt->outer_face);
1247 ea->symedges[0].next = &ea->symedges[1];
1248 ea->symedges[1].next = &ea->symedges[0];
1249 ea->symedges[0].rot = &ea->symedges[0];
1250 ea->symedges[1].rot = &ea->symedges[1];
1252 *r_le = &ea->symedges[0];
1253 *r_re = &ea->symedges[1];
1256 CDTVert<T> *v3 = sites[start + 2].v;
1257 CDTEdge<T> *eb = cdt->add_vert_to_symedge_edge(v3, &ea->symedges[1]);
1260 cdt->add_diagonal(&eb->symedges[0], &ea->symedges[0]);
1261 *r_le = &ea->symedges[0];
1262 *r_re = &eb->symedges[0];
1264 else if (orient < 0) {
1265 cdt->add_diagonal(&ea->symedges[0], &eb->symedges[0]);
1266 *r_le = ea->symedges[0].rot;
1267 *r_re = eb->symedges[0].rot;
1271 *r_le = &ea->symedges[0];
1272 *r_re = &eb->symedges[0];
1278 BLI_assert(n2 >= 2 && end - (start + n2) >= 2);
1283 dc_tri(cdt, sites, start, start + n2, &ldo, &ldi);
1284 dc_tri(cdt, sites, start + n2, end, &rdi, &rdo);
1285 if (dbg_level > 0) {
1286 std::cout <<
"\nDC_TRI merge step for start=" << start <<
", end=" << end <<
"\n";
1287 std::cout <<
"ldo " << ldo <<
"\n"
1288 <<
"ldi " << ldi <<
"\n"
1289 <<
"rdi " << rdi <<
"\n"
1290 <<
"rdo " << rdo <<
"\n";
1291 if (dbg_level > 1) {
1292 std::string lab =
"dc_tri (" + std::to_string(start) +
"," + std::to_string(start + n2) +
1293 ")(" + std::to_string(start + n2) +
"," + std::to_string(end) +
")";
1303 rdi =
sym(rdi)->rot;
1309 if (dbg_level > 0) {
1310 std::cout <<
"common lower tangent in between\n"
1311 <<
"rdi " << rdi <<
"\n"
1312 <<
"ldi" << ldi <<
"\n";
1315 CDTEdge<T> *ebasel = cdt->connect_separate_parts(
sym(rdi)->
next, ldi);
1316 SymEdge<T> *basel = &ebasel->symedges[0];
1317 SymEdge<T> *basel_sym = &ebasel->symedges[1];
1318 if (dbg_level > 1) {
1319 std::cout <<
"basel " << basel;
1320 cdt_draw(
"after basel made", *cdt);
1322 if (ldi->vert == ldo->vert) {
1325 if (rdi->vert == rdo->vert) {
1333 SymEdge<T> *lcand = basel_sym->rot;
1334 SymEdge<T> *rcand = basel_sym->next;
1335 if (dbg_level > 1) {
1336 std::cout <<
"\ntop of merge loop\n";
1337 std::cout <<
"lcand " << lcand <<
"\n"
1338 <<
"rcand " << rcand <<
"\n"
1339 <<
"basel " << basel <<
"\n";
1342 if (dbg_level > 1) {
1343 std::cout <<
"found valid lcand\n";
1344 std::cout <<
" lcand" << lcand <<
"\n";
1348 lcand->next->vert->co,
1349 lcand->rot->next->vert->co) > 0.0)
1351 if (dbg_level > 1) {
1352 std::cout <<
"incircle says to remove lcand\n";
1353 std::cout <<
" lcand" << lcand <<
"\n";
1355 SymEdge<T> *t = lcand->rot;
1356 cdt->delete_edge(
sym(lcand));
1362 if (dbg_level > 1) {
1363 std::cout <<
"found valid rcand\n";
1364 std::cout <<
" rcand" << rcand <<
"\n";
1368 rcand->next->vert->co,
1369 sym(rcand)->
next->next->vert->co) > 0.0)
1371 if (dbg_level > 0) {
1372 std::cout <<
"incircle says to remove rcand\n";
1373 std::cout <<
" rcand" << rcand <<
"\n";
1375 SymEdge<T> *t =
sym(rcand)->next;
1376 cdt->delete_edge(rcand);
1381 bool valid_lcand =
dc_tri_valid(lcand, basel, basel_sym);
1382 bool valid_rcand =
dc_tri_valid(rcand, basel, basel_sym);
1383 if (dbg_level > 0) {
1384 std::cout <<
"after bubbling up, valid_lcand=" << valid_lcand
1385 <<
", valid_rand=" << valid_rcand <<
"\n";
1386 std::cout <<
"lcand" << lcand <<
"\n"
1387 <<
"rcand" << rcand <<
"\n";
1389 if (!valid_lcand && !valid_rcand) {
1397 lcand->next->vert->co, lcand->vert->co, rcand->vert->co, rcand->next->vert->co) > 0))
1399 if (dbg_level > 0) {
1400 std::cout <<
"connecting rcand\n";
1401 std::cout <<
" se1=basel_sym" << basel_sym <<
"\n";
1402 std::cout <<
" se2=rcand->next" << rcand->next <<
"\n";
1404 ebasel = cdt->add_diagonal(rcand->next, basel_sym);
1407 if (dbg_level > 0) {
1408 std::cout <<
"connecting lcand\n";
1409 std::cout <<
" se1=sym(lcand)" <<
sym(lcand) <<
"\n";
1410 std::cout <<
" se2=basel_sym->next" << basel_sym->next <<
"\n";
1412 ebasel = cdt->add_diagonal(basel_sym->next,
sym(lcand));
1414 basel = &ebasel->symedges[0];
1415 basel_sym = &ebasel->symedges[1];
1416 BLI_assert(basel_sym->face == cdt->outer_face);
1417 if (dbg_level > 2) {
1418 cdt_draw(
"after adding new crossedge", *cdt);
1423 BLI_assert(
sym(ldo)->face == cdt->outer_face && rdo->face == cdt->outer_face);
1432 int nsites = sites.size();
1433 while (j < nsites) {
1435 sites[i] = sites[j++];
1436 if (sites[i].
v->merge_to_index < 0) {
1446 dc_tri(cdt, sites, 0, n, &le, &re);
1469 int n = cdt->verts.size();
1474 for (
int i = 0; i < n; ++i) {
1475 sites[i].v = cdt->verts[i];
1476 sites[i].orig_index = i;
1492 if (se->face == cdt->outer_face ||
sym(se)->face == cdt->outer_face) {
1497 for (
const SymEdge<T> *ss = se->next; ss != se; ss = ss->next) {
1505 SymEdge<T> *first = se->next->next;
1507 CDTVert<T> *a = se->vert;
1508 CDTVert<T> *
b = se->next->vert;
1509 CDTVert<T> *c = first->vert;
1510 SymEdge<T> *cse = first;
1511 for (SymEdge<T> *ss = first->next; ss != se; ss = ss->next) {
1512 CDTVert<T> *
v = ss->vert;
1519 CDTEdge<T> *ebc =
nullptr;
1520 CDTEdge<T> *eca =
nullptr;
1522 ebc = cdt->add_diagonal(se->next, cse);
1525 eca = cdt->add_diagonal(cse, se);
1538 return filtered_orient2d(t->vert->co, t->next->vert->co, t->next->next->vert->co);
1578 : lambda(other.lambda), vert(other.vert),
in(other.
in),
out(other.
out)
1582 : lambda(std::move(other.lambda)),
1583 vert(std::move(other.vert)),
1584 in(std::move(other.in)),
1585 out(std::move(other.out))
1591 if (
this != &other) {
1601 lambda = std::move(other.lambda);
1602 vert = std::move(other.vert);
1603 in = std::move(other.in);
1604 out = std::move(other.out);
1613 const CDTVert<T> *
v2);
1632 cd_next->
in =
nullptr;
1633 cd_next->
out =
nullptr;
1640 if (se->vert !=
v) {
1642 if (se->vert !=
v) {
1666 const CDTVert<T> *
v2,
1672 CDTVert<T> *va = t->vert;
1673 CDTVert<T> *vb = t->next->vert;
1674 CDTVert<T> *vc = t->next->next->vert;
1675 SymEdge<T> *se_vcvb =
sym(t->next);
1676 SymEdge<T> *se_vcva = t->next->next;
1677 BLI_assert(se_vcva->vert == vc && se_vcva->next->vert == va);
1678 BLI_assert(se_vcvb->vert == vc && se_vcvb->next->vert == vb);
1680 auto isect =
isect_seg_seg(va->co.exact, vb->co.exact, curco.exact,
v2->
co.exact);
1681 T &lambda = isect.lambda;
1682 switch (isect.kind) {
1685 if (!std::is_same_v<T, mpq_class>)
1690 double len_ab =
distance(va->co.approx, vb->co.approx);
1691 if (lambda * len_ab <= epsilon) {
1694 else if ((1 - lambda) * len_ab <= epsilon) {
1716 else if (lambda == 1) {
1729 if (std::is_same_v<T, mpq_class>) {
1734 const T middle_lambda = 0.5;
1735 if (lambda <= middle_lambda) {
1768 const CDTVert<T> *
v2)
1770 SymEdge<T> *tstart = cd->
vert->symedge;
1771 SymEdge<T> *t = tstart;
1772 CDTVert<T> *vcur = cd->
vert;
1781 if (t->face != cdt_state->cdt.outer_face &&
tri_orient(t) < 0) {
1784 CDTVert<T> *va = t->next->vert;
1785 CDTVert<T> *vb = t->next->next->vert;
1792 if (t->face != cdt_state->cdt.outer_face) {
1795 if (orient1 > 0 && orient2 < 0) {
1803 }
while ((t = t->rot) != tstart);
1818 const CDTVert<T> *
v2,
1821 CDTVert<T> *va = cd->
in->vert;
1822 CDTVert<T> *vb = cd->
in->next->vert;
1824 FatCo<T> fat_curco(curco);
1825 SymEdge<T> *se_ac =
sym(cd->
in)->next;
1826 CDTVert<T> *vc = se_ac->next->vert;
1831 else if (orient > 0.0) {
1835 *cd_next =
CrossData<T>{0.0, vc, se_ac->next,
nullptr};
1841 std::cout <<
"CROSSINGS\n";
1842 for (
int i = 0; i < crossings.size(); ++i) {
1843 std::cout << i <<
": ";
1846 std::cout <<
"v" << cd.
vert->index;
1849 std::cout <<
"lambda=" << cd.
lambda;
1851 if (cd.
in !=
nullptr) {
1872 CDT_state<T> *cdt_state, CDTVert<T> *v1, CDTVert<T> *
v2,
int input_id,
LinkNode **r_edges)
1874 constexpr int dbg_level = 0;
1875 if (dbg_level > 0) {
1876 std::cout <<
"\nADD EDGE CONSTRAINT\n" <<
vertname(v1) <<
" " <<
vertname(
v2) <<
"\n";
1896 if (r_edges !=
nullptr) {
1898 *r_edges = edge_list.
list;
1917 int visit = ++cdt_state->visit_count;
1921 while (!((n = crossings.
size()) > 0 && crossings[n - 1].vert ==
v2)) {
1926 if (crossings[n - 1].lambda == 0) {
1933 constexpr int unreasonably_large_crossings = 100000;
1934 if (!ok || crossings.
size() == unreasonably_large_crossings) {
1939 if (crossings[n].lambda == 0) {
1940 if (crossings[n].vert->visit_index == visit) {
1945 crossings[n].vert->visit_index = visit;
1949 if (dbg_level > 0) {
1963 int ncrossings = crossings.
size();
1964 for (
int i = 2; i < ncrossings; ++i) {
1967 CDTVert<T> *
v = cd->
vert;
1970 for (j = i - 1; j > 0; --j) {
1971 cd_prev = &crossings[j];
1972 if ((cd_prev->
lambda == 0.0 && cd_prev->
vert !=
v) ||
1973 (cd_prev->
lambda != 0.0 && cd_prev->
in->vert !=
v && cd_prev->
in->next->vert !=
v))
1981 cd_prev = &crossings[j];
1983 if (cd_prev->
lambda == 0.0) {
1985 if (se ==
nullptr) {
1993 if (se ==
nullptr) {
2005 for (
int i = 0; i < ncrossings; ++i) {
2008 CDTEdge<T> *edge = cdt_state->cdt.split_edge(cd->
in, cd->
lambda);
2009 cd->
vert = edge->symedges[0].vert;
2016 for (
int i = 0; i < ncrossings; ++i) {
2019 cdt_state->cdt.delete_edge(cd->
in);
2026 SymEdge<T> *tstart = crossings[0].out;
2027 for (
int i = 1; i < ncrossings; i++) {
2029 if (cd->
lambda == -1.0) {
2033 SymEdge<T> *tnext = t;
2037 t = cd->
vert->symedge;
2038 tnext =
sym(t)->next;
2041 else if (cd->
lambda == 0.0) {
2048 for (j = i - 1; j >= 0; j--) {
2049 cd_prev = &crossings[j];
2050 if (cd_prev->
lambda != -1.0) {
2056 edge = cd_prev->
out->edge;
2058 if (r_edges !=
nullptr) {
2064 if (tstart->next->vert == t->vert) {
2065 edge = tstart->edge;
2068 edge = cdt_state->cdt.add_diagonal(tstart, t);
2071 if (r_edges !=
nullptr) {
2078 if (i < ncrossings - 1) {
2079 if (tnext !=
nullptr) {
2086 *r_edges = edge_list.
list;
2098 int ne =
input.edge.size();
2099 int nv =
input.vert.size();
2100 for (
int i = 0; i < ne; i++) {
2101 int iv1 =
input.edge[i].first;
2102 int iv2 =
input.edge[i].second;
2103 if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2107 CDTVert<T> *v1 = cdt_state->cdt.get_vert_resolve_merge(iv1);
2108 CDTVert<T> *
v2 = cdt_state->cdt.get_vert_resolve_merge(iv2);
2109 int id = cdt_state->need_ids ? i : 0;
2112 cdt_state->face_edge_offset = ne;
2135 CDT_state<T> *cdt_state, SymEdge<T> *face_symedge,
int face_id,
int fedge_start,
int fedge_end)
2138 cdt_state->visit_count++;
2139 int visit = cdt_state->visit_count;
2141 stack.
append(face_symedge);
2144 CDTFace<T> *face = se->face;
2145 if (face->visit_index == visit) {
2148 face->visit_index = visit;
2150 SymEdge<T> *se_start = se;
2151 for (se = se->next; se != se_start; se = se->next) {
2153 SymEdge<T> *se_sym =
sym(se);
2154 CDTFace<T> *face_other = se_sym->face;
2155 if (face_other->visit_index != visit) {
2170 BLI_assert(
x < std::numeric_limits<int>::max() / 10);
2189 const CDT_input<T> &
input,
2192 int nv =
input.vert.size();
2194 SymEdge<T> *face_symedge0 =
nullptr;
2195 CDTArrangement<T> *cdt = &cdt_state->cdt;
2199 maxflen = std::max<int>(maxflen, input_faces[f].
size());
2203 std::max(maxflen, cdt_state->face_edge_offset));
2208 BLI_assert(std::numeric_limits<int>::max() / cdt_state->face_edge_offset > input_faces.
size());
2209 int faces_added = 0;
2212 if (face.
size() <= 2) {
2216 int fedge_start = (f + 1) * cdt_state->face_edge_offset;
2218 int face_edge_id = fedge_start + i;
2220 int iv2 = face[(i + 1) % face.
size()];
2221 if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2226 CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1);
2227 CDTVert<T> *
v2 = cdt->get_vert_resolve_merge(iv2);
2229 int id = cdt_state->need_ids ? face_edge_id : 0;
2234 if (edge_list !=
nullptr) {
2235 CDTEdge<T> *face_edge =
static_cast<CDTEdge<T> *
>(edge_list->
link);
2236 face_symedge0 = &face_edge->symedges[0];
2237 if (face_symedge0->vert != v1) {
2238 face_symedge0 = &face_edge->symedges[1];
2244 int fedge_end = fedge_start + face.
size() - 1;
2245 if (face_symedge0 !=
nullptr) {
2250 int id = cdt_state->need_ids ? f : 0;
2251 add_face_ids(cdt_state, face_symedge0,
id, fedge_start, fedge_end);
2252 if (cdt_state->need_ids ||
2255 add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
2267 CDTArrangement<T> *cdt = &cdt_state->cdt;
2268 SymEdge<T> *symse =
sym(se);
2269 if (symse->face == cdt->outer_face) {
2273 if (
ELEM(cdt->outer_face->symedge, se, symse)) {
2275 if (se->next->next == se) {
2276 cdt->outer_face->symedge =
nullptr;
2279 cdt->outer_face->symedge = se->next->next;
2283 if (se->face->symedge == se) {
2284 se->face->symedge = se->next;
2286 if (symse->face->symedge == symse) {
2287 symse->face->symedge = symse->next;
2290 cdt->delete_edge(se);
2298 for (CDTEdge<T> *
e : cdt_state->cdt.edges) {
2299 SymEdge<T> *se = &
e->symedges[0];
2323 CDTEdge<T> *
e{
nullptr};
2333 if (
this != &other) {
2349 CDTArrangement<T> *cdt = &cdt_state->cdt;
2350 size_t nedges = cdt->
edges.size();
2355 dissolvable_edges.
reserve(cdt->edges.size());
2357 for (CDTEdge<T> *
e : cdt->edges) {
2360 dissolvable_edges[i].e =
e;
2361 const double2 &co1 =
e->symedges[0].vert->
co.approx;
2362 const double2 &co2 =
e->symedges[1].vert->
co.approx;
2367 std::sort(dissolvable_edges.
begin(),
2368 dissolvable_edges.
end(),
2370 return (a.len_squared < b.len_squared);
2373 CDTEdge<T> *
e = ets.
e;
2374 SymEdge<T> *se = &
e->symedges[0];
2375 bool dissolve =
true;
2376 CDTFace<T> *fleft = se->face;
2377 CDTFace<T> *fright =
sym(se)->face;
2378 if (fleft != cdt->outer_face && fright != cdt->outer_face &&
2379 (fleft->input_ids.size() > 0 || fright->input_ids.size() > 0))
2383 for (SymEdge<T> *se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
2384 if (
sym(se2)->face == fright ||
2400 int visit = ++cdt_state->visit_count;
2402 cdt_state->cdt.outer_face->visit_index = visit;
2405 SymEdge<T> *se_start = cdt_state->cdt.outer_face->symedge;
2406 SymEdge<T> *se = se_start;
2409 CDTFace<T> *fsym =
sym(se)->face;
2410 if (fsym->visit_index != visit) {
2414 }
while ((se = se->next) != se_start);
2420 if (f->visit_index == visit) {
2424 f->visit_index = visit;
2425 se_start = se = f->symedge;
2429 CDTFace<T> *fsym =
sym(se)->face;
2430 if (fsym->visit_index != visit) {
2438 }
while (se != se_start);
2439 while (to_dissolve !=
nullptr) {
2441 if (se->next !=
nullptr) {
2450 CDTArrangement<T> *cdt = &cdt_state->cdt;
2451 for (
int i : cdt->faces.index_range()) {
2452 CDTFace<T> *f = cdt->
faces[i];
2453 if (!f->deleted && f->hole) {
2455 SymEdge<T> *se = f->symedge;
2456 SymEdge<T> *se_start = se;
2457 SymEdge<T> *se_next =
nullptr;
2468 }
while (se != se_start);
2485 CDTArrangement<T> *cdt = &cdt_state->cdt;
2491 for (
int i : cdt->faces.index_range()) {
2492 cdt->
faces[i]->visit_index = -1;
2494 int cur_region = -1;
2495 cdt->outer_face->visit_index = -2;
2496 for (
int i : cdt->faces.index_range()) {
2497 CDTFace<T> *f = cdt->faces[i];
2498 if (!f->deleted && f->symedge && f->visit_index == -1) {
2501 region_rep_face.
append(f);
2504 if (f->visit_index != -1) {
2507 f->visit_index = cur_region;
2508 SymEdge<T> *se_start = f->symedge;
2509 SymEdge<T> *se = se_start;
2512 CDTFace<T> *fsym =
sym(se)->face;
2513 if (fsym && !fsym->deleted && fsym->visit_index == -1) {
2518 }
while (se != se_start);
2522 cdt_state->visit_count = ++cur_region;
2531 CDTFace<T> *f = region_rep_face[i];
2533 mid.exact[0] = (f->symedge->vert->co.exact[0] + f->symedge->next->vert->co.exact[0] +
2534 f->symedge->next->next->vert->co.exact[0]) /
2536 mid.exact[1] = (f->symedge->vert->co.exact[1] + f->symedge->next->vert->co.exact[1] +
2537 f->symedge->next->next->vert->co.exact[1]) /
2539 std::atomic<int> hits = 0;
2542 for (const int i : range) {
2543 const CDTEdge<T> *e = cdt->edges[i];
2544 if (!is_deleted_edge(e) && is_constrained_edge(e)) {
2545 if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) {
2548 auto isect = isect_seg_seg(ray_end.exact,
2550 e->symedges[0].vert->co.exact,
2551 e->symedges[1].vert->co.exact);
2552 switch (isect.kind) {
2553 case isect_result<VecBase<T, 2>>::LINE_LINE_CROSS: {
2557 case isect_result<VecBase<T, 2>>::LINE_LINE_EXACT:
2558 case isect_result<VecBase<T, 2>>::LINE_LINE_NONE:
2559 case isect_result<VecBase<T, 2>>::LINE_LINE_COLINEAR:
2565 f->hole = (hits.load() % 2) == 0;
2569 for (
int i : cdt->
faces.index_range()) {
2570 CDTFace<T> *f = cdt->
faces[i];
2571 int region = f->visit_index;
2575 CDTFace<T> *f_region_rep = region_rep_face[region];
2577 f->hole = f_region_rep->hole;
2589 CDTArrangement<T> *cdt = &cdt_state->cdt;
2590 if (cdt->edges.is_empty()) {
2595 for (CDTEdge<T> *
e : cdt->edges) {
2597 if (
e->symedges[0].face->symedge ==
nullptr) {
2598 e->symedges[0].face->symedge = &
e->symedges[0];
2600 if (
e->symedges[1].face->symedge ==
nullptr) {
2601 e->symedges[1].face->symedge = &
e->symedges[1];
2635 const CDT_input<T> ,
2641 CDTArrangement<T> *cdt = &cdt_state->cdt;
2642 result.face_edge_offset = cdt_state->face_edge_offset;
2648 int verts_size = cdt->
verts.size();
2651 for (
int i = 0; i < verts_size; ++i) {
2652 CDTVert<T> *
v = cdt->verts[i];
2653 if (
v->merge_to_index == -1) {
2654 vert_to_output_map[i] = nv;
2664 if (nv < verts_size) {
2665 for (
int i = 0; i < verts_size; ++i) {
2666 CDTVert<T> *
v = cdt->verts[i];
2667 if (
v->merge_to_index != -1) {
2668 if (cdt_state->need_ids) {
2669 if (i < cdt_state->input_vert_num) {
2673 vert_to_output_map[i] = vert_to_output_map[
v->merge_to_index];
2678 if (cdt_state->need_ids) {
2682 for (
int i = 0; i < verts_size; ++i) {
2683 CDTVert<T> *
v = cdt->verts[i];
2684 if (
v->merge_to_index == -1) {
2686 if (cdt_state->need_ids) {
2687 if (i < cdt_state->input_vert_num) {
2688 result.vert_orig[i_out].append(i);
2690 for (
int vert :
v->input_ids) {
2691 result.vert_orig[i_out].append(vert);
2699 int ne = std::count_if(cdt->edges.begin(), cdt->edges.end(), [](
const CDTEdge<T> *
e) ->
bool {
2700 return !is_deleted_edge(e);
2703 if (cdt_state->need_ids) {
2707 for (
const CDTEdge<T> *
e : cdt->edges) {
2709 int vo1 = vert_to_output_map[
e->symedges[0].vert->index];
2710 int vo2 = vert_to_output_map[
e->symedges[1].vert->index];
2711 result.edge[e_out] = std::pair<int, int>(vo1, vo2);
2712 if (cdt_state->need_ids) {
2713 for (
int edge :
e->input_ids) {
2714 result.edge_orig[e_out].append(edge);
2722 int nf = std::count_if(cdt->faces.begin(), cdt->faces.end(), [=](
const CDTFace<T> *f) ->
bool {
2723 return !f->deleted && f != cdt->outer_face;
2726 if (cdt_state->need_ids) {
2730 for (
const CDTFace<T> *f : cdt->faces) {
2731 if (!f->deleted && f != cdt->outer_face) {
2732 SymEdge<T> *se = f->symedge;
2734 SymEdge<T> *se_start = se;
2736 result.face[f_out].append(vert_to_output_map[se->vert->index]);
2738 }
while (se != se_start);
2739 if (cdt_state->need_ids) {
2740 for (
int face : f->input_ids) {
2741 result.face_orig[f_out].append(face);
2756 for (
int i = 0; i < cdt_state->input_vert_num; ++i) {
2757 cdt_state->cdt.add_vert(
input.vert[i]);
2764 int nv =
input.vert.size();
2765 int ne =
input.edge.size();
2766 int nf =
input.face.size();
2767 CDT_state<T> cdt_state(nv, ne, nf,
input.epsilon,
input.need_ids);
@ CDT_CONSTRAINTS_VALID_BMESH
@ CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES
void void void * BLI_linklist_pop(LinkNode **listp) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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 BLI_linklist_prepend(LinkNode **listp, void *ptr) ATTR_NONNULL(1)
Math vector functions needed specifically for mesh intersect and boolean.
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_AS_INT(i)
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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
CrossData(const CrossData &other)
CrossData(CrossData &&other) noexcept
CrossData & operator=(CrossData &&other) noexcept
CrossData & operator=(const CrossData &other)
CrossData(T l, CDTVert< T > *v, SymEdge< T > *i, SymEdge< T > *o)
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
CDT_state(int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids)
bool vert_touches_face(const CDTVert< T > *v, const CDTFace< T > *f)
bool is_deleted_edge(const CDTEdge< T > *e)
bool vert_left_of_symedge(CDTVert< T > *v, SymEdge< T > *se)
static void add_to_input_ids(blender::Set< int > &dst, int input_id)
void dump_crossings(const Span< CrossData< T > > crossings)
void add_face_ids(CDT_state< T > *cdt_state, SymEdge< T > *face_symedge, int face_id, int fedge_start, int fedge_end)
void fill_crossdata_for_intersect(const FatCo< T > &curco, const CDTVert< T > *v2, SymEdge< T > *t, CrossData< T > *cd, CrossData< T > *cd_next, const T epsilon)
void prepare_cdt_for_output(CDT_state< T > *cdt_state, const CDT_output_type output_type)
static int power_of_10_greater_equal_to(int x)
blender::meshintersect::CDT_result< double > delaunay_2d_calc(const CDT_input< double > &input, CDT_output_type output_type)
bool is_constrained_edge(const CDTEdge< T > *e)
static int filtered_orient2d(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c)
bool get_next_crossing_from_vert(CDT_state< T > *cdt_state, CrossData< T > *cd, CrossData< T > *cd_next, const CDTVert< T > *v2)
SymEdge< T > * find_symedge_between_verts(const CDTVert< T > *v1, const CDTVert< T > *v2)
SymEdge< T > * find_symedge_with_face(const CDTVert< T > *v, const CDTFace< T > *f)
void detect_holes(CDT_state< T > *cdt_state)
bool is_original_vert(const CDTVert< T > *v, CDT_state< T > *cdt)
void remove_non_constraint_edges(CDT_state< T > *cdt_state)
int filtered_orient2d< double >(const FatCo< double > &a, const FatCo< double > &b, const FatCo< double > &c)
bool exists_edge(const CDTVert< T > *v1, const CDTVert< T > *v2)
static void re_delaunay_triangulate(CDTArrangement< T > *cdt, SymEdge< T > *se)
void get_next_crossing_from_edge(CrossData< T > *cd, CrossData< T > *cd_next, const CDTVert< T > *v2, const T epsilon)
CDT_result< T > get_cdt_output(CDT_state< T > *cdt_state, const CDT_input< T >, CDT_output_type output_type)
static bool in_line(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c)
void remove_non_constraint_edges_leave_valid_bmesh(CDT_state< T > *cdt_state)
int tri_orient(const SymEdge< T > *t)
void add_edge_constraint(CDT_state< T > *cdt_state, CDTVert< T > *v1, CDTVert< T > *v2, int input_id, LinkNode **r_edges)
bool vert_right_of_symedge(CDTVert< T > *v, SymEdge< T > *se)
int filtered_incircle< double >(const FatCo< double > &a, const FatCo< double > &b, const FatCo< double > &c, const FatCo< double > &d)
void add_edge_constraints(CDT_state< T > *cdt_state, const CDT_input< T > &input)
bool dc_tri_valid(SymEdge< T > *se, SymEdge< T > *basel, SymEdge< T > *basel_sym)
CDT_result< T > delaunay_calc(const CDT_input< T > &input, CDT_output_type output_type)
bool in_line< double >(const FatCo< double > &a, const FatCo< double > &b, const FatCo< double > &c)
void fill_crossdata_for_through_vert(CDTVert< T > *v, SymEdge< T > *cd_out, CrossData< T > *cd, CrossData< T > *cd_next)
void dc_tri(CDTArrangement< T > *cdt, Array< SiteInfo< T > > &sites, int start, int end, SymEdge< T > **r_le, SymEdge< T > **r_re)
void remove_outer_edges_until_constraints(CDT_state< T > *cdt_state)
static bool id_range_in_list(const blender::Set< int > &id_list, int range_start, int range_end)
void find_site_merges(Array< SiteInfo< T > > &sites)
void remove_faces_in_holes(CDT_state< T > *cdt_state)
void dc_triangulate(CDTArrangement< T > *cdt, Array< SiteInfo< T > > &sites)
void dissolve_symedge(CDT_state< T > *cdt_state, SymEdge< T > *se)
bool site_lexicographic_sort(const SiteInfo< T > &a, const SiteInfo< T > &b)
int add_face_constraints(CDT_state< T > *cdt_state, const CDT_input< T > &input, CDT_output_type output_type)
void initial_triangulation(CDTArrangement< T > *cdt)
void add_input_verts(CDT_state< T > *cdt_state, const CDT_input< T > &input)
static int filtered_incircle(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c, const FatCo< T > &d)
static void add_list_to_input_ids(blender::Set< int > &dst, const blender::Set< int > &src)
bool is_border_edge(const CDTEdge< T > *e, const CDT_state< T > *cdt)
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
isect_result< VecBase< T, Size > > isect_seg_seg(const VecBase< T, Size > &v1, const VecBase< T, Size > &v2, const VecBase< T, Size > &v3, const VecBase< T, Size > &v4)
std::ostream & operator<<(std::ostream &stream, EulerOrder order)
T distance(const T &a, const T &b)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
void min_max(const T &value, T &min, T &max)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
double math_to_double< double >(const double v)
std::string sename(const SymEdge< T > *se)
std::string vertname(const CDTVert< T > *v)
void cdt_draw(const std::string &label, const CDTArrangement< T > &cdt)
std::string short_se_dump(const SymEdge< T > *se)
SymEdge< T > * sym(const SymEdge< T > *se)
static std::string trunc_ptr(const void *p)
double math_abs< double >(const double v)
double math_to_double(const T)
SymEdge< T > * prev(const SymEdge< T > *se)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
int orient2d(const double2 &a, const double2 &b, const double2 &c)
VecBase< double, 2 > double2
int incircle(const double2 &a, const double2 &b, const double2 &c, const double2 &d)
EdgeToSort(EdgeToSort &&other) noexcept
EdgeToSort & operator=(EdgeToSort &&other)
EdgeToSort & operator=(const EdgeToSort &other)
EdgeToSort(const EdgeToSort &other)
CDTEdge< T > * split_edge(SymEdge< T > *se, T lambda)
void reserve(int verts_num, int edges_num, int faces_num)
CDTVert< T > * get_vert_resolve_merge(int i)
CDTEdge< T > * add_edge(CDTVert< T > *v1, CDTVert< T > *v2, CDTFace< T > *fleft, CDTFace< T > *fright)
void delete_edge(SymEdge< T > *se)
CDTVert< T > * add_vert(const VecBase< T, 2 > &pt)
CDTEdge< T > * connect_separate_parts(SymEdge< T > *se1, SymEdge< T > *se2)
CDTFace< T > * outer_face
CDTEdge< T > * add_vert_to_symedge_edge(CDTVert< T > *v, SymEdge< T > *se)
Vector< CDTVert< T > * > verts
CDTEdge< T > * add_diagonal(SymEdge< T > *s1, SymEdge< T > *s2)
Vector< CDTFace< T > * > faces
Vector< CDTEdge< T > * > edges
CDTFace< T > * add_face()
blender::Set< int > input_ids
blender::Set< int > input_ids
CDTVert(const VecBase< T, 2 > &pt)
blender::Set< int > input_ids