27using namespace blender::math;
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();
339 for (
int i : this->
edges.index_range()) {
341 e->input_ids.clear();
345 for (
int i : this->
faces.index_range()) {
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) {
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) {
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\">[";
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;
677 double bdx =
b.approx[0] - d.
approx[0];
680 double bdy =
b.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);
694 double sup_bdx =
b.abs_approx[0] + d.
abs_approx[0];
697 double sup_bdy =
b.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);
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;
763 if (
dot(exact_ab, exact_ac) < 0) {
766 mpq2 exact_bc = c.
exact -
b.exact;
767 return dot(exact_bc, exact_ac) >= 0;
776 if (
dot(ab, ac) < 0) {
780 return dot(bc, ac) >= 0;
786 this->
co.approx = pt;
787 this->
co.abs_approx = pt;
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);
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)
860 this->
cdt.reserve(input_verts_num, input_edges_num, input_faces_num);
861 this->
cdt.outer_face = this->
cdt.add_face();
870 for (
int id : id_list) {
871 if (
id >= range_start &&
id <= range_end) {
885 for (
int value : src) {
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;
919 if (t->
next->vert ==
v2) {
922 }
while ((t = t->
rot) != tstart);
937 }
while ((t = t->
rot) != tstart);
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) {
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;
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;
1264 else if (orient < 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) +
")";
1309 if (dbg_level > 0) {
1310 std::cout <<
"common lower tangent in between\n"
1311 <<
"rdi " << rdi <<
"\n"
1312 <<
"ldi" << ldi <<
"\n";
1318 if (dbg_level > 1) {
1319 std::cout <<
"basel " << basel;
1320 cdt_draw(
"after basel made", *cdt);
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";
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";
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";
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";
1417 if (dbg_level > 2) {
1418 cdt_draw(
"after adding new crossedge", *cdt);
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) {
1476 sites[
i].orig_index =
i;
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);
1612 CrossData<T> *cd_next,
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) {
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) {
1792 if (t->
face != cdt_state->
cdt.outer_face) {
1795 if (orient1 > 0 && orient2 < 0) {
1803 }
while ((t = t->
rot) != tstart);
1831 else if (orient > 0.0) {
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) {
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;
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) {
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) {
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) {
2016 for (
int i = 0;
i < ncrossings; ++
i) {
2019 cdt_state->
cdt.delete_edge(cd->
in);
2027 for (
int i = 1;
i < ncrossings;
i++) {
2029 if (cd->
lambda == -1.0) {
2037 t = cd->
vert->symedge;
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);
2141 stack.
append(face_symedge);
2151 for (se = se->
next; se != se_start; se = se->
next) {
2170 BLI_assert(
x < std::numeric_limits<int>::max() / 10);
2192 int nv =
input.vert.size();
2199 maxflen = std::max<int>(maxflen, input_faces[f].
size());
2209 int faces_added = 0;
2212 if (face.
size() <= 2) {
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) {
2229 int id = cdt_state->
need_ids ? face_edge_id : 0;
2234 if (edge_list !=
nullptr) {
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);
2255 add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
2275 if (se->
next->next == se) {
2283 if (se->
face->symedge == se) {
2286 if (symse->
face->symedge == symse) {
2287 symse->
face->symedge = symse->
next;
2333 if (
this != &other) {
2350 size_t nedges = cdt->
edges.size();
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);
2375 bool dissolve =
true;
2384 if (
sym(se2)->face == fright ||
2402 cdt_state->
cdt.outer_face->visit_index = visit;
2414 }
while ((se = se->
next) != se_start);
2438 }
while (se != se_start);
2439 while (to_dissolve !=
nullptr) {
2441 if (se->
next !=
nullptr) {
2451 for (
int i : cdt->
faces.index_range()) {
2467 }
while (se != se_start);
2490 for (
int i : cdt->
faces.index_range()) {
2491 cdt->
faces[
i]->visit_index = -1;
2493 int cur_region = -1;
2495 for (
int i : cdt->
faces.index_range()) {
2500 region_rep_face.
append(f);
2517 }
while (se != se_start);
2533 f->
symedge->next->next->vert->co.exact[0]) /
2536 f->
symedge->next->next->vert->co.exact[1]) /
2538 std::atomic<int> hits = 0;
2541 for (const int i : range) {
2542 const CDTEdge<T> *e = cdt->edges[i];
2543 if (!is_deleted_edge(e) && is_constrained_edge(e)) {
2544 if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) {
2547 auto isect = isect_seg_seg(ray_end.exact,
2549 e->symedges[0].vert->co.exact,
2550 e->symedges[1].vert->co.exact);
2551 switch (isect.kind) {
2552 case isect_result<VecBase<T, 2>>::LINE_LINE_CROSS: {
2556 case isect_result<VecBase<T, 2>>::LINE_LINE_EXACT:
2557 case isect_result<VecBase<T, 2>>::LINE_LINE_NONE:
2558 case isect_result<VecBase<T, 2>>::LINE_LINE_COLINEAR:
2564 f->hole = (hits.load() % 2) == 0;
2568 for (
int i : cdt->
faces.index_range()) {
2569 CDTFace<T> *f = cdt->faces[
i];
2570 int region = f->visit_index;
2574 CDTFace<T> *f_region_rep = region_rep_face[region];
2576 f->hole = f_region_rep->hole;
2589 if (cdt->
edges.is_empty()) {
2596 if (
e->symedges[0].face->symedge ==
nullptr) {
2597 e->symedges[0].face->symedge = &
e->symedges[0];
2599 if (
e->symedges[1].face->symedge ==
nullptr) {
2600 e->symedges[1].face->symedge = &
e->symedges[1];
2647 int verts_size = cdt->
verts.size();
2650 for (
int i = 0;
i < verts_size; ++
i) {
2652 if (
v->merge_to_index == -1) {
2653 vert_to_output_map[
i] = nv;
2663 if (nv < verts_size) {
2664 for (
int i = 0;
i < verts_size; ++
i) {
2666 if (
v->merge_to_index != -1) {
2672 vert_to_output_map[
i] = vert_to_output_map[
v->merge_to_index];
2681 for (
int i = 0;
i < verts_size; ++
i) {
2683 if (
v->merge_to_index == -1) {
2684 result.vert[i_out] =
v->co.exact;
2687 result.vert_orig[i_out].append(
i);
2689 for (
int vert :
v->input_ids) {
2690 result.vert_orig[i_out].append(vert);
2699 return !is_deleted_edge(e);
2708 int vo1 = vert_to_output_map[
e->symedges[0].vert->index];
2709 int vo2 = vert_to_output_map[
e->symedges[1].vert->index];
2710 result.edge[e_out] = std::pair<int, int>(vo1, vo2);
2712 for (
int edge :
e->input_ids) {
2713 result.edge_orig[e_out].append(edge);
2721 int nf = std::count_if(cdt->
faces.begin(), cdt->
faces.end(), [=](
const CDTFace<T> *f) ->
bool {
2722 return !f->deleted && f != cdt->outer_face;
2735 result.face[f_out].append(vert_to_output_map[se->
vert->index]);
2737 }
while (se != se_start);
2740 result.face_orig[f_out].append(face);
2763 int nv =
input.vert.size();
2764 int ne =
input.edge.size();
2765 int nf =
input.face.size();
2788 return delaunay_calc(
input, output_type);
@ 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)
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)
CrossData(T l, CDTVert< T > *v, SymEdge< T > *i, SymEdge< T > *o)
CrossData(const CrossData &other)
CrossData(CrossData &&other) noexcept
CrossData & operator=(CrossData &&other) noexcept
CrossData & operator=(const CrossData &other)
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)
void detect_holes(CDT_state< T > *cdt_state)
CDT_result< T > delaunay_calc(const CDT_input< T > &input, CDT_output_type output_type)
static void add_list_to_input_ids(blender::Set< int > &dst, const blender::Set< int > &src)
void dissolve_symedge(CDT_state< T > *cdt_state, SymEdge< T > *se)
double math_to_double< double >(const double v)
bool is_original_vert(const CDTVert< T > *v, CDT_state< T > *cdt)
int tri_orient(const SymEdge< T > *t)
SymEdge< T > * find_symedge_with_face(const CDTVert< T > *v, const CDTFace< T > *f)
void add_edge_constraints(CDT_state< T > *cdt_state, const CDT_input< T > &input)
bool is_border_edge(const CDTEdge< T > *e, const CDT_state< T > *cdt)
int add_face_constraints(CDT_state< T > *cdt_state, 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)
bool vert_touches_face(const CDTVert< T > *v, const CDTFace< T > *f)
std::string sename(const SymEdge< T > *se)
void dump_crossings(const Span< CrossData< T > > crossings)
bool vert_left_of_symedge(CDTVert< T > *v, SymEdge< T > *se)
CDT_result< double > delaunay_2d_calc(const CDT_input< double > &input, CDT_output_type output_type)
std::string vertname(const CDTVert< T > *v)
static void add_to_input_ids(blender::Set< int > &dst, int input_id)
void cdt_draw(const std::string &label, const CDTArrangement< T > &cdt)
bool site_lexicographic_sort(const SiteInfo< T > &a, const SiteInfo< T > &b)
bool vert_right_of_symedge(CDTVert< T > *v, SymEdge< T > *se)
std::string short_se_dump(const SymEdge< T > *se)
void find_site_merges(Array< SiteInfo< T > > &sites)
CDT_result< T > get_cdt_output(CDT_state< T > *cdt_state, const CDT_input< T >, CDT_output_type output_type)
void add_edge_constraint(CDT_state< T > *cdt_state, CDTVert< T > *v1, CDTVert< T > *v2, int input_id, LinkNode **r_edges)
bool is_deleted_edge(const CDTEdge< T > *e)
SymEdge< T > * sym(const SymEdge< T > *se)
void dc_triangulate(CDTArrangement< T > *cdt, Array< SiteInfo< T > > &sites)
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 add_face_ids(CDT_state< T > *cdt_state, SymEdge< T > *face_symedge, int face_id, int fedge_start, int fedge_end)
static bool in_line(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c)
static bool id_range_in_list(const blender::Set< int > &id_list, int range_start, int range_end)
void remove_non_constraint_edges(CDT_state< T > *cdt_state)
bool dc_tri_valid(SymEdge< T > *se, SymEdge< T > *basel, SymEdge< T > *basel_sym)
void prepare_cdt_for_output(CDT_state< T > *cdt_state, const CDT_output_type output_type)
static int filtered_orient2d(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c)
bool is_constrained_edge(const CDTEdge< T > *e)
static std::string trunc_ptr(const void *p)
static void re_delaunay_triangulate(CDTArrangement< T > *cdt, SymEdge< T > *se)
void initial_triangulation(CDTArrangement< T > *cdt)
void remove_outer_edges_until_constraints(CDT_state< T > *cdt_state)
double math_abs< double >(const double v)
double math_to_double(const T)
static int power_of_10_greater_equal_to(int x)
void remove_faces_in_holes(CDT_state< T > *cdt_state)
void get_next_crossing_from_edge(CrossData< T > *cd, CrossData< T > *cd_next, const CDTVert< T > *v2, const T epsilon)
void remove_non_constraint_edges_leave_valid_bmesh(CDT_state< T > *cdt_state)
void dc_tri(CDTArrangement< T > *cdt, Array< SiteInfo< T > > &sites, int start, int end, SymEdge< T > **r_le, SymEdge< T > **r_re)
void fill_crossdata_for_through_vert(CDTVert< T > *v, SymEdge< T > *cd_out, CrossData< T > *cd, CrossData< T > *cd_next)
SymEdge< T > * prev(const SymEdge< T > *se)
int filtered_incircle< double >(const FatCo< double > &a, const FatCo< double > &b, const FatCo< double > &c, const FatCo< double > &d)
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 int filtered_incircle(const FatCo< T > &a, const FatCo< T > &b, const FatCo< T > &c, const FatCo< T > &d)
bool get_next_crossing_from_vert(CDT_state< T > *cdt_state, CrossData< T > *cd, CrossData< T > *cd_next, const CDTVert< T > *v2)
void add_input_verts(CDT_state< T > *cdt_state, const CDT_input< T > &input)
SymEdge< T > * find_symedge_between_verts(const CDTVert< T > *v1, const CDTVert< T > *v2)
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)
CDTEdge< T > * add_edge(CDTVert< T > *v1, CDTVert< T > *v2, CDTFace< T > *fleft, CDTFace< T > *fright)
CDTVert< T > * get_vert_resolve_merge(int i)
CDTVert< T > * add_vert(const VecBase< T, 2 > &pt)
CDTFace< T > * outer_face
void delete_edge(SymEdge< T > *se)
CDTEdge< T > * add_vert_to_symedge_edge(CDTVert< T > *v, SymEdge< T > *se)
Vector< CDTVert< T > * > verts
void reserve(int verts_num, int edges_num, int faces_num)
CDTEdge< T > * add_diagonal(SymEdge< T > *s1, SymEdge< T > *s2)
CDTEdge< T > * connect_separate_parts(SymEdge< T > *se1, SymEdge< T > *se2)
CDTEdge< T > * split_edge(SymEdge< T > *se, T lambda)
CDTFace< T > * add_face()
Vector< CDTFace< T > * > faces
Vector< CDTEdge< T > * > edges
blender::Set< int > input_ids
blender::Set< int > input_ids
CDTVert(const VecBase< T, 2 > &pt)
blender::Set< int > input_ids
EdgeToSort(EdgeToSort &&other) noexcept
EdgeToSort(const EdgeToSort &other)
EdgeToSort & operator=(const EdgeToSort &other)
EdgeToSort & operator=(EdgeToSort &&other)