28using namespace blender::math;
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) {
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) {
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\">[";
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;
678 double bdx =
b.approx[0] - d.
approx[0];
681 double bdy =
b.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);
695 double sup_bdx =
b.abs_approx[0] + d.
abs_approx[0];
698 double sup_bdy =
b.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);
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;
764 if (
dot(exact_ab, exact_ac) < 0) {
767 mpq2 exact_bc = c.
exact -
b.exact;
768 return dot(exact_bc, exact_ac) >= 0;
777 if (
dot(ab, ac) < 0) {
781 return dot(bc, ac) >= 0;
787 this->
co.approx = pt;
788 this->
co.abs_approx = pt;
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);
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)
861 this->
cdt.reserve(input_verts_num, input_edges_num, input_faces_num);
862 this->
cdt.outer_face = this->
cdt.add_face();
871 for (
int id : id_list) {
872 if (
id >= range_start &&
id <= range_end) {
886 for (
int value : src) {
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;
920 if (t->
next->vert ==
v2) {
923 }
while ((t = t->
rot) != tstart);
938 }
while ((t = t->
rot) != tstart);
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) {
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]) {
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;
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;
1265 else if (orient < 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) +
")";
1310 if (dbg_level > 0) {
1311 std::cout <<
"common lower tangent in between\n"
1312 <<
"rdi " << rdi <<
"\n"
1313 <<
"ldi" << ldi <<
"\n";
1319 if (dbg_level > 1) {
1320 std::cout <<
"basel " << basel;
1321 cdt_draw(
"after basel made", *cdt);
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";
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";
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";
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";
1418 if (dbg_level > 2) {
1419 cdt_draw(
"after adding new crossedge", *cdt);
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;
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) {
1602 lambda = std::move(other.lambda);
1603 vert = std::move(other.vert);
1604 in = std::move(other.in);
1605 out = std::move(other.out);
1613 CrossData<T> *cd_next,
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) {
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) {
1793 if (t->
face != cdt_state->
cdt.outer_face) {
1796 if (orient1 > 0 && orient2 < 0) {
1804 }
while ((t = t->
rot) != tstart);
1832 else if (orient > 0.0) {
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) {
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;
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) {
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) {
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) {
2017 for (
int i = 0; i < ncrossings; ++i) {
2020 cdt_state->
cdt.delete_edge(cd->
in);
2028 for (
int i = 1; i < ncrossings; i++) {
2030 if (cd->
lambda == -1.0) {
2038 t = cd->
vert->symedge;
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;
2100 int nv = input.
vert.size();
2101 for (
int i = 0; i < ne; i++) {
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);
2110 int id = cdt_state->
need_ids ? i : 0;
2142 stack.
append(face_symedge);
2152 for (se = se->
next; se != se_start; se = se->
next) {
2171 BLI_assert(
x < std::numeric_limits<int>::max() / 10);
2193 int nv = input.
vert.size();
2200 maxflen = std::max<int>(maxflen, input_faces[f].
size());
2210 int faces_added = 0;
2213 if (face.
size() <= 2) {
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) {
2230 int id = cdt_state->
need_ids ? face_edge_id : 0;
2235 if (edge_list !=
nullptr) {
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);
2256 add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
2276 if (se->
next->next == se) {
2284 if (se->
face->symedge == se) {
2287 if (symse->
face->symedge == symse) {
2288 symse->
face->symedge = symse->
next;
2334 if (
this != &other) {
2351 size_t nedges = cdt->
edges.size();
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);
2376 bool dissolve =
true;
2385 if (
sym(se2)->face == fright ||
2403 cdt_state->
cdt.outer_face->visit_index = visit;
2415 }
while ((se = se->
next) != se_start);
2439 }
while (se != se_start);
2440 while (to_dissolve !=
nullptr) {
2442 if (se->
next !=
nullptr) {
2452 for (
int i : cdt->
faces.index_range()) {
2469 }
while (se != se_start);
2492 for (
int i : cdt->
faces.index_range()) {
2493 cdt->
faces[i]->visit_index = -1;
2495 int cur_region = -1;
2497 for (
int i : cdt->
faces.index_range()) {
2502 region_rep_face.
append(f);
2519 }
while (se != se_start);
2535 f->
symedge->next->next->vert->co.exact[0]) /
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;
2591 if (cdt->
edges.is_empty()) {
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];
2649 int verts_size = cdt->
verts.size();
2652 for (
int i = 0; i < verts_size; ++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) {
2668 if (
v->merge_to_index != -1) {
2670 if (i < cdt_state->input_vert_num) {
2674 vert_to_output_map[i] = vert_to_output_map[
v->merge_to_index];
2683 for (
int i = 0; i < verts_size; ++i) {
2685 if (
v->merge_to_index == -1) {
2686 result.vert[i_out] =
v->co.exact;
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);
2701 return !is_deleted_edge(e);
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);
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;
2737 result.face[f_out].append(vert_to_output_map[se->
vert->index]);
2739 }
while (se != se_start);
2742 result.face_orig[f_out].append(face);
2758 cdt_state->
cdt.add_vert(input.
vert[i]);
2765 int nv = input.
vert.size();
2767 int nf = input.
face.size();
2790 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)
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)
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)
local_group_size(16, 16) .push_constant(Type b
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 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)