35 return (
v < 0) ? -
v :
v;
79template<
typename T>
struct CDTVert;
80template<
typename T>
struct CDTEdge;
81template<
typename T>
struct CDTFace;
103 return se->
next->rot;
109 return se->
rot->next->rot;
127template<>
struct FatCo<mpq_class> {
176 stream <<
"(" << co.
approx.x <<
", " << co.
approx.y <<
")";
245 void reserve(
int verts_num,
int edges_num,
int faces_num);
304 if (
v->merge_to_index != -1) {
305 v = this->verts[
v->merge_to_index];
329 int input_verts_num,
int input_edges_num,
int input_faces_num, T
epsilon,
bool need_ids);
334 for (
int i : this->
verts.index_range()) {
336 v->input_ids.clear();
338 this->
verts[i] =
nullptr;
340 for (
int i : this->edges.index_range()) {
342 e->input_ids.clear();
344 this->edges[i] =
nullptr;
346 for (
int i : this->faces.index_range()) {
350 this->faces[i] =
nullptr;
359 std::stringstream ss;
360 ss <<
"[" <<
v->index <<
"]";
367 constexpr int TRUNC_PTR_MASK = 0xFFFF;
368 std::stringstream ss;
375 std::stringstream ss;
401 return std::string(
"null");
409 os <<
"\nCDT\n\nVERTS\n";
413 if (
v->merge_to_index == -1) {
417 os <<
" merge to " <<
vertname(cdt_state.
cdt.verts[
v->merge_to_index]) <<
"\n";
421 constexpr int print_count_limit = 25;
423 os <<
" edges out:\n";
425 if (se->
next ==
nullptr) {
426 os <<
" [null] next/rot symedge, se=" <<
trunc_ptr(se) <<
"\n";
429 if (se->
next->next ==
nullptr) {
430 os <<
" [null] next-next/rot symedge, se=" <<
trunc_ptr(se) <<
"\n";
438 }
while (se !=
v->symedge &&
count < print_count_limit);
444 if (
e->symedges[0].next ==
nullptr) {
448 for (
int i = 0; i < 2; ++i) {
457 os <<
"outer_face=" <<
trunc_ptr(cdt_state.
cdt.outer_face) <<
"\n";
459 if (cdt_state.
cdt.outer_face->symedge !=
nullptr) {
471 static bool append =
false;
477 const char *drawfile =
"./cdt_debug_draw.html";
479 const char *drawfile =
"/tmp/cdt_debug_draw.html";
481 constexpr int max_draw_width = 1800;
482 constexpr int max_draw_height = 1600;
483 constexpr double margin_expand = 0.05;
484 constexpr int thin_line = 1;
485 constexpr int thick_line = 4;
486 constexpr int vert_radius = 3;
487 constexpr bool draw_vert_labels =
true;
488 constexpr bool draw_edge_labels =
false;
489 constexpr bool draw_face_labels =
false;
491 if (cdt.
verts.is_empty()) {
494 double2 vmin(std::numeric_limits<double>::max());
495 double2 vmax(std::numeric_limits<double>::lowest());
499 double draw_margin = ((vmax.x - vmin.x) + (vmax.y - vmin.y)) * margin_expand;
500 double minx = vmin.x - draw_margin;
501 double maxx = vmax.x + draw_margin;
502 double miny = vmin.y - draw_margin;
503 double maxy = vmax.y + draw_margin;
505 double width = maxx - minx;
506 double height = maxy - miny;
507 double aspect = height / width;
508 int view_width = max_draw_width;
509 int view_height =
int(view_width * aspect);
510 if (view_height > max_draw_height) {
511 view_height = max_draw_height;
512 view_width =
int(view_height / aspect);
514 double scale = view_width / width;
516# define SX(x) (((x)-minx) * scale)
517# define SY(y) ((maxy - (y)) * scale)
521 f.open(drawfile, std::ios_base::app);
527 std::cout <<
"Could not open file " << drawfile <<
"\n";
531 f <<
"<div>" <<
label <<
"</div>\n<div>\n"
532 <<
"<svg version=\"1.1\" "
533 "xmlns=\"http://www.w3.org/2000/svg\" "
534 "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
535 "xml:space=\"preserve\"\n"
536 <<
"width=\"" << view_width <<
"\" height=\"" << view_height <<
"\">n";
539 if (
e->symedges[0].next ==
nullptr) {
546 int strokew =
e->input_ids.size() == 0 ? thin_line : thick_line;
547 f << R
"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
548 <<
SX(uco[0]) <<
"\" y1=\"" <<
SY(uco[1]) <<
"\" x2=\"" <<
SX(vco[0]) <<
"\" y2=\""
549 <<
SY(vco[1]) <<
"\">\n";
552 if (draw_edge_labels) {
553 f <<
"<text x=\"" <<
SX((uco[0] + vco[0]) / 2) <<
"\" y=\"" <<
SY((uco[1] + vco[1]) / 2)
554 << R
"(" font-size="small">)";
562 f << R
"(<circle fill="black" cx=")" << SX(v->co.approx[0]) << "\" cy=\"" <<
SY(
v->
co.approx[1])
563 <<
"\" r=\"" << vert_radius <<
"\">\n";
564 f <<
" <title>[" << i <<
"]" <<
v->
co.approx <<
"</title>\n";
566 if (draw_vert_labels) {
567 f <<
"<text x=\"" <<
SX(
v->
co.approx[0]) + vert_radius <<
"\" y=\""
568 <<
SY(
v->
co.approx[1]) - vert_radius << R
"(" font-size="small">[)" << i << "]</text>\n";
573 if (draw_face_labels) {
574 for (
const CDTFace<T> *face : cdt.
faces) {
575 if (!face->deleted) {
577 const SymEdge<T> *se_face_start =
nullptr;
578 for (
const CDTEdge<T> *
e : cdt.
edges) {
579 if (
e->symedges[0].face == face) {
580 se_face_start = &
e->symedges[0];
583 if (
e->symedges[1].face == face) {
584 se_face_start = &
e->symedges[1];
587 if (se_face_start !=
nullptr) {
596 const SymEdge<T> *se = se_face_start;
598 if (se->face == face) {
599 cen = cen + se->vert->co.approx;
602 }
while ((se = se->next) != se_face_start);
603 if (face_nverts > 0) {
604 cen = cen /
double(face_nverts);
607 f <<
"<text x=\"" <<
SX(cen[0]) <<
"\" y=\"" <<
SY(cen[1]) <<
"\""
608 <<
" font-size=\"small\">[";
610 if (face->input_ids.size() > 0) {
611 for (
int id : face->input_ids) {
637 const FatCo<mpq_class> &
b,
638 const FatCo<mpq_class> &c)
640 double det = (a.approx[0] - c.approx[0]) * (
b.approx[1] - c.approx[1]) -
641 (a.approx[1] - c.approx[1]) * (
b.approx[0] - c.approx[0]);
642 double supremum = (a.abs_approx[0] + c.abs_approx[0]) * (
b.abs_approx[1] + c.abs_approx[1]) +
643 (a.abs_approx[1] + c.abs_approx[1]) * (
b.abs_approx[0] + c.abs_approx[0]);
644 constexpr double index_orient2d = 6;
645 double err_bound = supremum * index_orient2d * DBL_EPSILON;
646 if (
fabs(det) > err_bound) {
647 return det > 0 ? 1 : -1;
649 return orient2d(a.exact,
b.exact, c.exact);
655 const FatCo<double> &
b,
656 const FatCo<double> &c)
658 return orient2d(a.approx,
b.approx, c.approx);
673 const FatCo<mpq_class> &
b,
674 const FatCo<mpq_class> &c,
675 const FatCo<mpq_class> &d)
677 double adx = a.approx[0] - d.approx[0];
678 double bdx =
b.approx[0] - d.approx[0];
679 double cdx = c.approx[0] - d.approx[0];
680 double ady = a.approx[1] - d.approx[1];
681 double bdy =
b.approx[1] - d.approx[1];
682 double cdy = c.approx[1] - d.approx[1];
683 double bdxcdy = bdx * cdy;
684 double cdxbdy = cdx * bdy;
685 double alift = adx * adx + ady * ady;
686 double cdxady = cdx * ady;
687 double adxcdy = adx * cdy;
688 double blift = bdx * bdx + bdy * bdy;
689 double adxbdy = adx * bdy;
690 double bdxady = bdx * ady;
691 double clift = cdx * cdx + cdy * cdy;
692 double det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
694 double sup_adx = a.abs_approx[0] + d.abs_approx[0];
695 double sup_bdx =
b.abs_approx[0] + d.abs_approx[0];
696 double sup_cdx = c.abs_approx[0] + d.abs_approx[0];
697 double sup_ady = a.abs_approx[1] + d.abs_approx[1];
698 double sup_bdy =
b.abs_approx[1] + d.abs_approx[1];
699 double sup_cdy = c.abs_approx[1] + d.abs_approx[1];
700 double sup_bdxcdy = sup_bdx * sup_cdy;
701 double sup_cdxbdy = sup_cdx * sup_bdy;
702 double sup_alift = sup_adx * sup_adx + sup_ady * sup_ady;
703 double sup_cdxady = sup_cdx * sup_ady;
704 double sup_adxcdy = sup_adx * sup_cdy;
705 double sup_blift = sup_bdx * sup_bdx + sup_bdy * sup_bdy;
706 double sup_adxbdy = sup_adx * sup_bdy;
707 double sup_bdxady = sup_bdx * sup_ady;
708 double sup_clift = sup_cdx * sup_cdx + sup_cdy * sup_cdy;
709 double sup_det = sup_alift * (sup_bdxcdy + sup_cdxbdy) + sup_blift * (sup_cdxady + sup_adxcdy) +
710 sup_clift * (sup_adxbdy + sup_bdxady);
712 double err_bound = sup_det * index * DBL_EPSILON;
713 if (
fabs(det) > err_bound) {
714 return det < 0.0 ? -1 : (det > 0.0 ? 1 : 0);
716 return incircle(a.exact,
b.exact, c.exact, d.exact);
722 const FatCo<double> &
b,
723 const FatCo<double> &c,
724 const FatCo<double> &d)
726 return incircle(a.approx,
b.approx, c.approx, d.approx);
735template<
typename T>
static bool in_line(
const FatCo<T> &a,
const FatCo<T> &
b,
const FatCo<T> &c);
740 const FatCo<mpq_class> &
b,
741 const FatCo<mpq_class> &c)
745 double2 ac = c.approx - a.approx;
746 double2 supremum_ab =
b.abs_approx + a.abs_approx;
747 double2 supremum_bc = c.abs_approx +
b.abs_approx;
748 double2 supremum_ac = c.abs_approx + a.abs_approx;
749 double dot_ab_ac = ab.x * ac.x + ab.y * ac.y;
750 double supremum_dot_ab_ac = supremum_ab.x * supremum_ac.x + supremum_ab.y * supremum_ac.y;
751 constexpr double index = 6;
752 double err_bound = supremum_dot_ab_ac * index * DBL_EPSILON;
753 if (dot_ab_ac < -err_bound) {
756 double dot_bc_ac = bc.x * ac.x + bc.y * ac.y;
757 double supremum_dot_bc_ac = supremum_bc.x * supremum_ac.x + supremum_bc.y * supremum_ac.y;
758 err_bound = supremum_dot_bc_ac * index * DBL_EPSILON;
759 if (dot_bc_ac < -err_bound) {
762 mpq2 exact_ab =
b.exact - a.exact;
763 mpq2 exact_ac = c.exact - a.exact;
764 if (
dot(exact_ab, exact_ac) < 0) {
767 mpq2 exact_bc = c.exact -
b.exact;
768 return dot(exact_bc, exact_ac) >= 0;
773bool in_line<double>(
const FatCo<double> &a,
const FatCo<double> &
b,
const FatCo<double> &c)
776 double2 ac = c.approx - a.approx;
777 if (
dot(ab, ac) < 0) {
781 return dot(bc, ac) >= 0;
787 this->co.approx = pt;
788 this->co.abs_approx = pt;
789 this->symedge =
nullptr;
791 this->merge_to_index = -1;
792 this->visit_index = 0;
799 this->co.approx =
double2(pt.x.get_d(), pt.y.get_d());
800 this->co.abs_approx =
double2(
fabs(this->co.approx.x),
fabs(this->co.approx.y));
801 this->symedge =
nullptr;
803 this->merge_to_index = -1;
804 this->visit_index = 0;
811 int index = this->
verts.append_and_get_index(v);
823 this->edges.append(
e);
828 sesym->
face = fright;
834 if (
v2->symedge ==
nullptr) {
844 this->faces.append(f);
851 this->
verts.reserve(2 * verts_num);
852 this->edges.reserve(3 * verts_num + 2 * edges_num + 3 * 2 * faces_num);
853 this->faces.reserve(2 * verts_num + 2 * edges_num + 2 * faces_num);
858 int input_verts_num,
int input_edges_num,
int input_faces_num, T epsilon,
bool need_ids)
860 this->input_vert_num = input_verts_num;
861 this->cdt.
reserve(input_verts_num, input_edges_num, input_faces_num);
863 this->epsilon = epsilon;
864 this->need_ids = need_ids;
865 this->visit_count = 0;
871 for (
int id : id_list) {
872 if (
id >= range_start &&
id <= range_end) {
886 for (
int value : src) {
891template<
typename T>
inline bool is_border_edge(
const CDTEdge<T> *
e,
const CDT_state<T> *cdt)
893 return e->symedges[0].face == cdt->outer_face ||
e->symedges[1].face == cdt->outer_face;
898 return e->input_ids.size() > 0;
903 return e->symedges[0].next ==
nullptr;
908 return (
v->index < cdt->input_vert_num);
917 SymEdge<T> *t = v1->symedge;
918 SymEdge<T> *tstart = t;
920 if (t->next->vert ==
v2) {
923 }
while ((t = t->rot) != tstart);
932 SymEdge<T> *t =
v->symedge;
933 SymEdge<T> *tstart = t;
938 }
while ((t = t->rot) != tstart);
945template<
typename T>
inline bool exists_edge(
const CDTVert<T> *v1,
const CDTVert<T> *
v2)
955 SymEdge<T> *se =
v->symedge;
960 }
while ((se = se->rot) !=
v->symedge);
985 s2prev->
next = sdiagsym;
986 s1prev->
next = sdiag;
988 sdiag->
rot = s1prevsym;
990 sdiagsym->
rot = s2prevsym;
1008 new_se_sym->
next = new_se;
1009 new_se->
rot = new_se;
1010 new_se_sym->
rot = se_rot;
1011 se->
rot = new_se_sym;
1012 se_rotsym->
next = new_se_sym;
1033 new_se_sym->
next = se1;
1034 new_se->
rot = se1_rot;
1035 new_se_sym->
rot = se2_rot;
1037 se2->
rot = new_se_sym;
1038 se1_rotsym->
next = new_se;
1039 se2_rotsym->
next = new_se_sym;
1063 newsesym->
next = sesym;
1064 newse->
next = senext;
1067 senext->
rot = newsesym;
1068 newsesym->
rot = sesymprevsym;
1069 sesymprev->
next = newsesym;
1070 if (newsesym->
vert->symedge == sesym) {
1071 newsesym->
vert->symedge = newsesym;
1111 bool v1_isolated = (i == se);
1112 bool v2_isolated = (f == sesym);
1122 if (!v1_isolated && !v2_isolated && aface != bface) {
1136 v2->symedge =
nullptr;
1138 else if (
v2->symedge == sesym) {
1144 sesym->
next = sesym->
rot =
nullptr;
1145 if (!v1_isolated && !v2_isolated && aface != bface) {
1147 if (this->outer_face == bface) {
1148 this->outer_face = aface;
1166 if (co_a[0] < co_b[0]) {
1169 if (co_a[0] > co_b[0]) {
1172 if (co_a[1] < co_b[1]) {
1175 if (co_a[1] > co_b[1]) {
1178 return a.orig_index <
b.orig_index;
1188 int n = sites.size();
1189 for (
int i = 0; i < n - 1; ++i) {
1191 while (j < n && sites[j].
v->
co.exact == sites[i].v->co.exact) {
1192 sites[j].v->merge_to_index = sites[i].orig_index;
1213inline bool dc_tri_valid(SymEdge<T> *se, SymEdge<T> *basel, SymEdge<T> *basel_sym)
1215 return filtered_orient2d(se->next->vert->co, basel_sym->vert->co, basel->vert->co) > 0;
1232 constexpr int dbg_level = 0;
1233 if (dbg_level > 0) {
1234 std::cout <<
"DC_TRI start=" << start <<
" end=" << end <<
"\n";
1236 int n = end - start;
1245 CDTVert<T> *v1 = sites[start].v;
1246 CDTVert<T> *
v2 = sites[start + 1].v;
1247 CDTEdge<T> *ea = cdt->add_edge(v1,
v2, cdt->outer_face, cdt->outer_face);
1248 ea->symedges[0].next = &ea->symedges[1];
1249 ea->symedges[1].next = &ea->symedges[0];
1250 ea->symedges[0].rot = &ea->symedges[0];
1251 ea->symedges[1].rot = &ea->symedges[1];
1253 *r_le = &ea->symedges[0];
1254 *r_re = &ea->symedges[1];
1257 CDTVert<T> *v3 = sites[start + 2].v;
1258 CDTEdge<T> *eb = cdt->add_vert_to_symedge_edge(v3, &ea->symedges[1]);
1261 cdt->add_diagonal(&eb->symedges[0], &ea->symedges[0]);
1262 *r_le = &ea->symedges[0];
1263 *r_re = &eb->symedges[0];
1265 else if (orient < 0) {
1266 cdt->add_diagonal(&ea->symedges[0], &eb->symedges[0]);
1267 *r_le = ea->symedges[0].rot;
1268 *r_re = eb->symedges[0].rot;
1272 *r_le = &ea->symedges[0];
1273 *r_re = &eb->symedges[0];
1279 BLI_assert(n2 >= 2 && end - (start + n2) >= 2);
1284 dc_tri(cdt, sites, start, start + n2, &ldo, &ldi);
1285 dc_tri(cdt, sites, start + n2, end, &rdi, &rdo);
1286 if (dbg_level > 0) {
1287 std::cout <<
"\nDC_TRI merge step for start=" << start <<
", end=" << end <<
"\n";
1288 std::cout <<
"ldo " << ldo <<
"\n"
1289 <<
"ldi " << ldi <<
"\n"
1290 <<
"rdi " << rdi <<
"\n"
1291 <<
"rdo " << rdo <<
"\n";
1292 if (dbg_level > 1) {
1293 std::string lab =
"dc_tri (" + std::to_string(start) +
"," + std::to_string(start + n2) +
1294 ")(" + std::to_string(start + n2) +
"," + std::to_string(end) +
")";
1304 rdi =
sym(rdi)->rot;
1310 if (dbg_level > 0) {
1311 std::cout <<
"common lower tangent in between\n"
1312 <<
"rdi " << rdi <<
"\n"
1313 <<
"ldi" << ldi <<
"\n";
1316 CDTEdge<T> *ebasel = cdt->connect_separate_parts(
sym(rdi)->
next, ldi);
1317 SymEdge<T> *basel = &ebasel->symedges[0];
1318 SymEdge<T> *basel_sym = &ebasel->symedges[1];
1319 if (dbg_level > 1) {
1320 std::cout <<
"basel " << basel;
1321 cdt_draw(
"after basel made", *cdt);
1323 if (ldi->vert == ldo->vert) {
1326 if (rdi->vert == rdo->vert) {
1334 SymEdge<T> *lcand = basel_sym->rot;
1335 SymEdge<T> *rcand = basel_sym->next;
1336 if (dbg_level > 1) {
1337 std::cout <<
"\ntop of merge loop\n";
1338 std::cout <<
"lcand " << lcand <<
"\n"
1339 <<
"rcand " << rcand <<
"\n"
1340 <<
"basel " << basel <<
"\n";
1343 if (dbg_level > 1) {
1344 std::cout <<
"found valid lcand\n";
1345 std::cout <<
" lcand" << lcand <<
"\n";
1349 lcand->next->vert->co,
1350 lcand->rot->next->vert->co) > 0.0)
1352 if (dbg_level > 1) {
1353 std::cout <<
"incircle says to remove lcand\n";
1354 std::cout <<
" lcand" << lcand <<
"\n";
1356 SymEdge<T> *t = lcand->rot;
1357 cdt->delete_edge(
sym(lcand));
1363 if (dbg_level > 1) {
1364 std::cout <<
"found valid rcand\n";
1365 std::cout <<
" rcand" << rcand <<
"\n";
1369 rcand->next->vert->co,
1370 sym(rcand)->
next->next->vert->co) > 0.0)
1372 if (dbg_level > 0) {
1373 std::cout <<
"incircle says to remove rcand\n";
1374 std::cout <<
" rcand" << rcand <<
"\n";
1376 SymEdge<T> *t =
sym(rcand)->next;
1377 cdt->delete_edge(rcand);
1382 bool valid_lcand =
dc_tri_valid(lcand, basel, basel_sym);
1383 bool valid_rcand =
dc_tri_valid(rcand, basel, basel_sym);
1384 if (dbg_level > 0) {
1385 std::cout <<
"after bubbling up, valid_lcand=" << valid_lcand
1386 <<
", valid_rand=" << valid_rcand <<
"\n";
1387 std::cout <<
"lcand" << lcand <<
"\n"
1388 <<
"rcand" << rcand <<
"\n";
1390 if (!valid_lcand && !valid_rcand) {
1398 lcand->next->vert->co, lcand->vert->co, rcand->vert->co, rcand->next->vert->co) > 0))
1400 if (dbg_level > 0) {
1401 std::cout <<
"connecting rcand\n";
1402 std::cout <<
" se1=basel_sym" << basel_sym <<
"\n";
1403 std::cout <<
" se2=rcand->next" << rcand->next <<
"\n";
1405 ebasel = cdt->add_diagonal(rcand->next, basel_sym);
1408 if (dbg_level > 0) {
1409 std::cout <<
"connecting lcand\n";
1410 std::cout <<
" se1=sym(lcand)" <<
sym(lcand) <<
"\n";
1411 std::cout <<
" se2=basel_sym->next" << basel_sym->next <<
"\n";
1413 ebasel = cdt->add_diagonal(basel_sym->next,
sym(lcand));
1415 basel = &ebasel->symedges[0];
1416 basel_sym = &ebasel->symedges[1];
1417 BLI_assert(basel_sym->face == cdt->outer_face);
1418 if (dbg_level > 2) {
1419 cdt_draw(
"after adding new crossedge", *cdt);
1424 BLI_assert(
sym(ldo)->face == cdt->outer_face && rdo->face == cdt->outer_face);
1433 int nsites = sites.size();
1434 while (j < nsites) {
1436 sites[i] = sites[j++];
1437 if (sites[i].
v->merge_to_index < 0) {
1447 dc_tri(cdt, sites, 0, n, &le, &re);
1470 int n = cdt->verts.size();
1475 for (
int i = 0; i < n; ++i) {
1476 sites[i].v = cdt->verts[i];
1477 sites[i].orig_index = i;
1493 if (se->face == cdt->outer_face ||
sym(se)->face == cdt->outer_face) {
1498 for (
const SymEdge<T> *ss = se->next; ss != se; ss = ss->next) {
1506 SymEdge<T> *first = se->next->next;
1508 CDTVert<T> *a = se->vert;
1509 CDTVert<T> *
b = se->next->vert;
1510 CDTVert<T> *c = first->vert;
1511 SymEdge<T> *cse = first;
1512 for (SymEdge<T> *ss = first->next; ss != se; ss = ss->next) {
1513 CDTVert<T> *
v = ss->vert;
1520 CDTEdge<T> *ebc =
nullptr;
1521 CDTEdge<T> *eca =
nullptr;
1523 ebc = cdt->add_diagonal(se->next, cse);
1526 eca = cdt->add_diagonal(cse, se);
1539 return filtered_orient2d(t->vert->co, t->next->vert->co, t->next->next->vert->co);
1574 CrossData() : lambda(T(0)), vert(nullptr), in(nullptr), out(nullptr) {}
1575 CrossData(T
l, CDTVert<T> *
v, SymEdge<T> *i, SymEdge<T> *o) : lambda(
l), vert(
v), in(i), out(o)
1579 : lambda(other.lambda), vert(other.vert), in(other.in), out(other.out)
1583 : lambda(std::move(other.lambda)),
1584 vert(std::move(other.vert)),
1585 in(std::move(other.in)),
1586 out(std::move(other.out))
1592 if (
this != &other) {
1593 lambda = other.lambda;
1602 lambda = std::move(other.lambda);
1603 vert = std::move(other.vert);
1604 in = std::move(other.in);
1605 out = std::move(other.out);
1614 const CDTVert<T> *
v2);
1633 cd_next->
in =
nullptr;
1634 cd_next->
out =
nullptr;
1641 if (se->vert !=
v) {
1643 if (se->vert !=
v) {
1667 const CDTVert<T> *
v2,
1673 CDTVert<T> *va = t->vert;
1674 CDTVert<T> *vb = t->next->vert;
1675 CDTVert<T> *vc = t->next->next->vert;
1676 SymEdge<T> *se_vcvb =
sym(t->next);
1677 SymEdge<T> *se_vcva = t->next->next;
1678 BLI_assert(se_vcva->vert == vc && se_vcva->next->vert == va);
1679 BLI_assert(se_vcvb->vert == vc && se_vcvb->next->vert == vb);
1681 auto isect =
isect_seg_seg(va->co.exact, vb->co.exact, curco.exact,
v2->
co.exact);
1682 T &lambda = isect.lambda;
1683 switch (isect.kind) {
1686 if (!std::is_same<T, mpq_class>::value)
1691 double len_ab =
distance(va->co.approx, vb->co.approx);
1692 if (lambda * len_ab <= epsilon) {
1695 else if ((1 - lambda) * len_ab <= epsilon) {
1717 else if (lambda == 1) {
1730 if (std::is_same<T, mpq_class>::value) {
1735 const T middle_lambda = 0.5;
1736 if (lambda <= middle_lambda) {
1769 const CDTVert<T> *
v2)
1771 SymEdge<T> *tstart = cd->
vert->symedge;
1772 SymEdge<T> *t = tstart;
1773 CDTVert<T> *vcur = cd->
vert;
1782 if (t->face != cdt_state->cdt.outer_face &&
tri_orient(t) < 0) {
1785 CDTVert<T> *va = t->next->vert;
1786 CDTVert<T> *vb = t->next->next->vert;
1793 if (t->face != cdt_state->cdt.outer_face) {
1796 if (orient1 > 0 && orient2 < 0) {
1804 }
while ((t = t->rot) != tstart);
1819 const CDTVert<T> *
v2,
1822 CDTVert<T> *va = cd->
in->vert;
1823 CDTVert<T> *vb = cd->
in->next->vert;
1825 FatCo<T> fat_curco(curco);
1826 SymEdge<T> *se_ac =
sym(cd->
in)->next;
1827 CDTVert<T> *vc = se_ac->next->vert;
1832 else if (orient > 0.0) {
1836 *cd_next =
CrossData<T>{0.0, vc, se_ac->next,
nullptr};
1842 std::cout <<
"CROSSINGS\n";
1843 for (
int i = 0; i < crossings.size(); ++i) {
1844 std::cout << i <<
": ";
1847 std::cout <<
"v" << cd.
vert->index;
1850 std::cout <<
"lambda=" << cd.
lambda;
1852 if (cd.
in !=
nullptr) {
1873 CDT_state<T> *cdt_state, CDTVert<T> *v1, CDTVert<T> *
v2,
int input_id,
LinkNode **r_edges)
1875 constexpr int dbg_level = 0;
1876 if (dbg_level > 0) {
1877 std::cout <<
"\nADD EDGE CONSTRAINT\n" <<
vertname(v1) <<
" " <<
vertname(
v2) <<
"\n";
1897 if (r_edges !=
nullptr) {
1899 *r_edges = edge_list.
list;
1918 int visit = ++cdt_state->visit_count;
1919 Vector<CrossData<T>, 128> crossings;
1922 while (!((n = crossings.size()) > 0 && crossings[n - 1].vert ==
v2)) {
1927 if (crossings[n - 1].lambda == 0) {
1934 constexpr int unreasonably_large_crossings = 100000;
1935 if (!ok || crossings.size() == unreasonably_large_crossings) {
1940 if (crossings[n].lambda == 0) {
1941 if (crossings[n].vert->visit_index == visit) {
1946 crossings[n].vert->visit_index = visit;
1950 if (dbg_level > 0) {
1964 int ncrossings = crossings.size();
1965 for (
int i = 2; i < ncrossings; ++i) {
1968 CDTVert<T> *
v = cd->
vert;
1971 for (j = i - 1; j > 0; --j) {
1972 cd_prev = &crossings[j];
1973 if ((cd_prev->
lambda == 0.0 && cd_prev->
vert !=
v) ||
1974 (cd_prev->
lambda != 0.0 && cd_prev->
in->vert !=
v && cd_prev->
in->next->vert !=
v))
1982 cd_prev = &crossings[j];
1984 if (cd_prev->
lambda == 0.0) {
1986 if (se ==
nullptr) {
1994 if (se ==
nullptr) {
2006 for (
int i = 0; i < ncrossings; ++i) {
2009 CDTEdge<T> *edge = cdt_state->cdt.split_edge(cd->
in, cd->
lambda);
2010 cd->
vert = edge->symedges[0].vert;
2017 for (
int i = 0; i < ncrossings; ++i) {
2020 cdt_state->cdt.delete_edge(cd->
in);
2027 SymEdge<T> *tstart = crossings[0].out;
2028 for (
int i = 1; i < ncrossings; i++) {
2030 if (cd->
lambda == -1.0) {
2034 SymEdge<T> *tnext = t;
2038 t = cd->
vert->symedge;
2039 tnext =
sym(t)->next;
2042 else if (cd->
lambda == 0.0) {
2049 for (j = i - 1; j >= 0; j--) {
2050 cd_prev = &crossings[j];
2051 if (cd_prev->
lambda != -1.0) {
2057 edge = cd_prev->
out->edge;
2059 if (r_edges !=
nullptr) {
2065 if (tstart->next->vert == t->vert) {
2066 edge = tstart->edge;
2069 edge = cdt_state->cdt.add_diagonal(tstart, t);
2072 if (r_edges !=
nullptr) {
2079 if (i < ncrossings - 1) {
2080 if (tnext !=
nullptr) {
2087 *r_edges = edge_list.
list;
2099 int ne = input.edge.size();
2100 int nv = input.vert.size();
2101 for (
int i = 0; i < ne; i++) {
2102 int iv1 = input.edge[i].first;
2103 int iv2 = input.edge[i].second;
2104 if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2108 CDTVert<T> *v1 = cdt_state->cdt.get_vert_resolve_merge(iv1);
2109 CDTVert<T> *
v2 = cdt_state->cdt.get_vert_resolve_merge(iv2);
2110 int id = cdt_state->need_ids ? i : 0;
2113 cdt_state->face_edge_offset = ne;
2136 CDT_state<T> *cdt_state, SymEdge<T> *face_symedge,
int face_id,
int fedge_start,
int fedge_end)
2139 cdt_state->visit_count++;
2140 int visit = cdt_state->visit_count;
2141 Vector<SymEdge<T> *> stack;
2142 stack.append(face_symedge);
2143 while (!stack.is_empty()) {
2144 SymEdge<T> *se = stack.pop_last();
2145 CDTFace<T> *face = se->face;
2146 if (face->visit_index == visit) {
2149 face->visit_index = visit;
2151 SymEdge<T> *se_start = se;
2152 for (se = se->next; se != se_start; se = se->next) {
2154 SymEdge<T> *se_sym =
sym(se);
2155 CDTFace<T> *face_other = se_sym->face;
2156 if (face_other->visit_index != visit) {
2157 stack.append(se_sym);
2171 BLI_assert(x < std::numeric_limits<int>::max() / 10);
2190 const CDT_input<T> &input,
2193 int nv = input.vert.size();
2195 SymEdge<T> *face_symedge0 =
nullptr;
2196 CDTArrangement<T> *cdt = &cdt_state->cdt;
2200 maxflen = std::max<int>(maxflen, input_faces[f].
size());
2204 std::max(maxflen, cdt_state->face_edge_offset));
2209 BLI_assert(std::numeric_limits<int>::max() / cdt_state->face_edge_offset > input_faces.
size());
2210 int faces_added = 0;
2213 if (face.size() <= 2) {
2217 int fedge_start = (f + 1) * cdt_state->face_edge_offset;
2218 for (
const int i : face.index_range()) {
2219 int face_edge_id = fedge_start + i;
2221 int iv2 = face[(i + 1) % face.size()];
2222 if (iv1 < 0 || iv1 >= nv || iv2 < 0 || iv2 >= nv) {
2227 CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1);
2228 CDTVert<T> *
v2 = cdt->get_vert_resolve_merge(iv2);
2230 int id = cdt_state->need_ids ? face_edge_id : 0;
2235 if (edge_list !=
nullptr) {
2236 CDTEdge<T> *face_edge =
static_cast<CDTEdge<T> *
>(edge_list->
link);
2237 face_symedge0 = &face_edge->symedges[0];
2238 if (face_symedge0->vert != v1) {
2239 face_symedge0 = &face_edge->symedges[1];
2245 int fedge_end = fedge_start + face.size() - 1;
2246 if (face_symedge0 !=
nullptr) {
2251 int id = cdt_state->need_ids ? f : 0;
2252 add_face_ids(cdt_state, face_symedge0,
id, fedge_start, fedge_end);
2253 if (cdt_state->need_ids ||
2256 add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
2268 CDTArrangement<T> *cdt = &cdt_state->cdt;
2269 SymEdge<T> *symse =
sym(se);
2270 if (symse->face == cdt->outer_face) {
2274 if (
ELEM(cdt->outer_face->symedge, se, symse)) {
2276 if (se->next->next == se) {
2277 cdt->outer_face->symedge =
nullptr;
2280 cdt->outer_face->symedge = se->next->next;
2284 if (se->face->symedge == se) {
2285 se->face->symedge = se->next;
2287 if (symse->face->symedge == symse) {
2288 symse->face->symedge = symse->next;
2291 cdt->delete_edge(se);
2299 for (CDTEdge<T> *
e : cdt_state->cdt.edges) {
2300 SymEdge<T> *se = &
e->symedges[0];
2324 CDTEdge<T> *
e{
nullptr};
2334 if (
this != &other) {
2350 CDTArrangement<T> *cdt = &cdt_state->cdt;
2351 size_t nedges = cdt->
edges.size();
2355 Vector<EdgeToSort<T>> dissolvable_edges;
2356 dissolvable_edges.reserve(cdt->edges.size());
2358 for (CDTEdge<T> *
e : cdt->edges) {
2361 dissolvable_edges[i].e =
e;
2362 const double2 &co1 =
e->symedges[0].vert->
co.approx;
2363 const double2 &co2 =
e->symedges[1].vert->
co.approx;
2368 std::sort(dissolvable_edges.begin(),
2369 dissolvable_edges.end(),
2371 return (a.len_squared < b.len_squared);
2374 CDTEdge<T> *
e = ets.
e;
2375 SymEdge<T> *se = &
e->symedges[0];
2376 bool dissolve =
true;
2377 CDTFace<T> *fleft = se->face;
2378 CDTFace<T> *fright =
sym(se)->face;
2379 if (fleft != cdt->outer_face && fright != cdt->outer_face &&
2380 (fleft->input_ids.size() > 0 || fright->input_ids.size() > 0))
2384 for (SymEdge<T> *se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
2385 if (
sym(se2)->face == fright ||
2401 int visit = ++cdt_state->visit_count;
2403 cdt_state->cdt.outer_face->visit_index = visit;
2405 Vector<CDTFace<T> *> fstack;
2406 SymEdge<T> *se_start = cdt_state->cdt.outer_face->symedge;
2407 SymEdge<T> *se = se_start;
2410 CDTFace<T> *fsym =
sym(se)->face;
2411 if (fsym->visit_index != visit) {
2412 fstack.append(fsym);
2415 }
while ((se = se->next) != se_start);
2417 while (!fstack.is_empty()) {
2420 CDTFace<T> *f = fstack.pop_last();
2421 if (f->visit_index == visit) {
2425 f->visit_index = visit;
2426 se_start = se = f->symedge;
2430 CDTFace<T> *fsym =
sym(se)->face;
2431 if (fsym->visit_index != visit) {
2432 fstack.append(fsym);
2439 }
while (se != se_start);
2440 while (to_dissolve !=
nullptr) {
2442 if (se->next !=
nullptr) {
2451 CDTArrangement<T> *cdt = &cdt_state->cdt;
2452 for (
int i : cdt->faces.index_range()) {
2453 CDTFace<T> *f = cdt->
faces[i];
2454 if (!f->deleted && f->hole) {
2456 SymEdge<T> *se = f->symedge;
2457 SymEdge<T> *se_start = se;
2458 SymEdge<T> *se_next =
nullptr;
2469 }
while (se != se_start);
2486 CDTArrangement<T> *cdt = &cdt_state->cdt;
2490 Vector<CDTFace<T> *> fstack;
2491 Vector<CDTFace<T> *> region_rep_face;
2492 for (
int i : cdt->faces.index_range()) {
2493 cdt->
faces[i]->visit_index = -1;
2495 int cur_region = -1;
2496 cdt->outer_face->visit_index = -2;
2497 for (
int i : cdt->faces.index_range()) {
2498 CDTFace<T> *f = cdt->faces[i];
2499 if (!f->deleted && f->symedge && f->visit_index == -1) {
2502 region_rep_face.append(f);
2503 while (!fstack.is_empty()) {
2504 CDTFace<T> *f = fstack.pop_last();
2505 if (f->visit_index != -1) {
2508 f->visit_index = cur_region;
2509 SymEdge<T> *se_start = f->symedge;
2510 SymEdge<T> *se = se_start;
2513 CDTFace<T> *fsym =
sym(se)->face;
2514 if (fsym && !fsym->deleted && fsym->visit_index == -1) {
2515 fstack.append(fsym);
2519 }
while (se != se_start);
2523 cdt_state->visit_count = ++cur_region;
2531 for (
int i : region_rep_face.index_range()) {
2532 CDTFace<T> *f = region_rep_face[i];
2534 mid.exact[0] = (f->symedge->vert->co.exact[0] + f->symedge->next->vert->co.exact[0] +
2535 f->symedge->next->next->vert->co.exact[0]) /
2537 mid.exact[1] = (f->symedge->vert->co.exact[1] + f->symedge->next->vert->co.exact[1] +
2538 f->symedge->next->next->vert->co.exact[1]) /
2540 std::atomic<int> hits = 0;
2543 for (const int i : range) {
2544 const CDTEdge<T> *e = cdt->edges[i];
2545 if (!is_deleted_edge(e) && is_constrained_edge(e)) {
2546 if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) {
2549 auto isect = isect_seg_seg(ray_end.exact,
2551 e->symedges[0].vert->co.exact,
2552 e->symedges[1].vert->co.exact);
2553 switch (isect.kind) {
2554 case isect_result<VecBase<T, 2>>::LINE_LINE_CROSS: {
2558 case isect_result<VecBase<T, 2>>::LINE_LINE_EXACT:
2559 case isect_result<VecBase<T, 2>>::LINE_LINE_NONE:
2560 case isect_result<VecBase<T, 2>>::LINE_LINE_COLINEAR:
2566 f->hole = (hits.load() % 2) == 0;
2570 for (
int i : cdt->faces.index_range()) {
2571 CDTFace<T> *f = cdt->
faces[i];
2572 int region = f->visit_index;
2576 CDTFace<T> *f_region_rep = region_rep_face[region];
2578 f->hole = f_region_rep->hole;
2590 CDTArrangement<T> *cdt = &cdt_state->cdt;
2591 if (cdt->edges.is_empty()) {
2596 for (CDTEdge<T> *
e : cdt->edges) {
2598 if (
e->symedges[0].face->symedge ==
nullptr) {
2599 e->symedges[0].face->symedge = &
e->symedges[0];
2601 if (
e->symedges[1].face->symedge ==
nullptr) {
2602 e->symedges[1].face->symedge = &
e->symedges[1];
2636 const CDT_input<T> ,
2642 CDTArrangement<T> *cdt = &cdt_state->cdt;
2643 result.face_edge_offset = cdt_state->face_edge_offset;
2649 int verts_size = cdt->
verts.size();
2652 for (
int i = 0; i < verts_size; ++i) {
2653 CDTVert<T> *
v = cdt->verts[i];
2654 if (
v->merge_to_index == -1) {
2655 vert_to_output_map[i] = nv;
2665 if (nv < verts_size) {
2666 for (
int i = 0; i < verts_size; ++i) {
2667 CDTVert<T> *
v = cdt->verts[i];
2668 if (
v->merge_to_index != -1) {
2669 if (cdt_state->need_ids) {
2670 if (i < cdt_state->input_vert_num) {
2674 vert_to_output_map[i] = vert_to_output_map[
v->merge_to_index];
2679 if (cdt_state->need_ids) {
2683 for (
int i = 0; i < verts_size; ++i) {
2684 CDTVert<T> *
v = cdt->verts[i];
2685 if (
v->merge_to_index == -1) {
2686 result.vert[i_out] =
v->
co.exact;
2687 if (cdt_state->need_ids) {
2688 if (i < cdt_state->input_vert_num) {
2689 result.vert_orig[i_out].append(i);
2691 for (
int vert :
v->input_ids) {
2692 result.vert_orig[i_out].append(vert);
2700 int ne = std::count_if(cdt->edges.begin(), cdt->edges.end(), [](
const CDTEdge<T> *
e) ->
bool {
2701 return !is_deleted_edge(e);
2704 if (cdt_state->need_ids) {
2708 for (
const CDTEdge<T> *
e : cdt->edges) {
2710 int vo1 = vert_to_output_map[
e->symedges[0].vert->index];
2711 int vo2 = vert_to_output_map[
e->symedges[1].vert->index];
2712 result.edge[e_out] = std::pair<int, int>(vo1, vo2);
2713 if (cdt_state->need_ids) {
2714 for (
int edge :
e->input_ids) {
2715 result.edge_orig[e_out].append(edge);
2723 int nf = std::count_if(cdt->faces.begin(), cdt->faces.end(), [=](
const CDTFace<T> *f) ->
bool {
2724 return !f->deleted && f != cdt->outer_face;
2727 if (cdt_state->need_ids) {
2731 for (
const CDTFace<T> *f : cdt->faces) {
2732 if (!f->deleted && f != cdt->outer_face) {
2733 SymEdge<T> *se = f->symedge;
2735 SymEdge<T> *se_start = se;
2737 result.face[f_out].append(vert_to_output_map[se->vert->index]);
2739 }
while (se != se_start);
2740 if (cdt_state->need_ids) {
2741 for (
int face : f->input_ids) {
2742 result.face_orig[f_out].append(face);
2755template<
typename T>
void add_input_verts(CDT_state<T> *cdt_state,
const CDT_input<T> &input)
2757 for (
int i = 0; i < cdt_state->input_vert_num; ++i) {
2758 cdt_state->cdt.add_vert(input.vert[i]);
2765 int nv = input.vert.size();
2766 int ne = input.edge.size();
2767 int nf = input.face.size();
2768 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)
typedef double(DMatrix)[4][4]
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
CDT_state(int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids)
local_group_size(16, 16) .push_constant(Type b
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)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
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 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