Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/delaunay_2d.cc')
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc370
1 files changed, 235 insertions, 135 deletions
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index 24a58103a10..4582ea69d9b 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -19,6 +19,7 @@
*/
#include <algorithm>
+#include <atomic>
#include <fstream>
#include <iostream>
#include <sstream>
@@ -29,6 +30,8 @@
#include "BLI_math_boolean.hh"
#include "BLI_math_mpq.hh"
#include "BLI_mpq2.hh"
+#include "BLI_set.hh"
+#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "BLI_delaunay_2d.h"
@@ -77,8 +80,8 @@ template<> double math_to_double<double>(const double v)
* Define a templated 2D arrangement of vertices, edges, and faces.
* The #SymEdge data structure is the basis for a structure that allows
* easy traversal to neighboring (by topology) geometric elements.
- * Each of #CDTVert, #CDTEdge, and #CDTFace have an input_id linked list,
- * whose nodes contain integers that keep track of which input verts, edges,
+ * Each of #CDTVert, #CDTEdge, and #CDTFace have an input_id set,
+ * which contain integers that keep track of which input verts, edges,
* and faces, respectively, that the element was derived from.
*
* While this could be cleaned up some, it is usable by other routines in Blender
@@ -195,8 +198,8 @@ template<typename T> struct CDTVert {
FatCo<T> co;
/** Some edge attached to it. */
SymEdge<T> *symedge{nullptr};
- /** List of corresponding vertex input ids. */
- LinkNode *input_ids{nullptr};
+ /** Set of corresponding vertex input ids. Not used if don't need_ids. */
+ blender::Set<int> input_ids;
/** Index into array that #CDTArrangement keeps. */
int index{-1};
/** Index of a CDTVert that this has merged to. -1 if no merge. */
@@ -209,8 +212,10 @@ template<typename T> struct CDTVert {
};
template<typename Arith_t> struct CDTEdge {
- /** List of input edge ids that this is part of. */
- LinkNode *input_ids{nullptr};
+ /** Set of input edge ids that this is part of.
+ * If don't need_ids, then should contain 0 if it is a constrained edge,
+ * else empty. */
+ blender::Set<int> input_ids;
/** The directed edges for this edge. */
SymEdge<Arith_t> symedges[2]{SymEdge<Arith_t>(), SymEdge<Arith_t>()};
@@ -220,8 +225,10 @@ template<typename Arith_t> struct CDTEdge {
template<typename Arith_t> struct CDTFace {
/** A symedge in face; only used during output, so only valid then. */
SymEdge<Arith_t> *symedge{nullptr};
- /** List of input face ids that this is part of. */
- LinkNode *input_ids{nullptr};
+ /** Set of input face ids that this is part of.
+ * If don't need_ids, then should contain 0 if it is part of a constrained face,
+ * else empty. */
+ blender::Set<int> input_ids;
/** Used by algorithms operating on CDT structures. */
int visit_index{0};
/** Marks this face no longer used. */
@@ -334,27 +341,30 @@ template<typename T> class CDT_state {
int face_edge_offset;
/** How close before coords considered equal. */
T epsilon;
+ /** Do we need to track ids? */
+ bool need_ids;
- explicit CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon);
+ explicit CDT_state(
+ int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids);
};
template<typename T> CDTArrangement<T>::~CDTArrangement()
{
for (int i : this->verts.index_range()) {
CDTVert<T> *v = this->verts[i];
- BLI_linklist_free(v->input_ids, nullptr);
+ v->input_ids.clear();
delete v;
this->verts[i] = nullptr;
}
for (int i : this->edges.index_range()) {
CDTEdge<T> *e = this->edges[i];
- BLI_linklist_free(e->input_ids, nullptr);
+ e->input_ids.clear();
delete e;
this->edges[i] = nullptr;
}
for (int i : this->faces.index_range()) {
CDTFace<T> *f = this->faces[i];
- BLI_linklist_free(f->input_ids, nullptr);
+ f->input_ids.clear();
delete f;
this->faces[i] = nullptr;
}
@@ -431,11 +441,11 @@ template<typename T> std::ostream &operator<<(std::ostream &os, const CDT_state<
if (se) {
os << " edges out:\n";
do {
- if (se->next == NULL) {
+ if (se->next == nullptr) {
os << " [NULL] next/rot symedge, se=" << trunc_ptr(se) << "\n";
break;
}
- if (se->next->next == NULL) {
+ if (se->next->next == nullptr) {
os << " [NULL] next-next/rot symedge, se=" << trunc_ptr(se) << "\n";
break;
}
@@ -495,6 +505,7 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
constexpr int vert_radius = 3;
constexpr bool draw_vert_labels = true;
constexpr bool draw_edge_labels = false;
+ constexpr bool draw_face_labels = false;
if (cdt.verts.size() == 0) {
return;
@@ -559,7 +570,7 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
const CDTVert<T> *v = e->symedges[1].vert;
const vec2<double> &uco = u->co.approx;
const vec2<double> &vco = v->co.approx;
- int strokew = e->input_ids == nullptr ? thin_line : thick_line;
+ int strokew = e->input_ids.size() == 0 ? thin_line : thick_line;
f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
<< SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\""
<< SY(vco[1]) << "\">\n";
@@ -586,6 +597,54 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
++i;
}
+ if (draw_face_labels) {
+ for (const CDTFace<T> *face : cdt.faces) {
+ if (!face->deleted) {
+ /* Since may not have prepared output yet, need a slow find of a SymEdge for this face. */
+ const SymEdge<T> *se_face_start = nullptr;
+ for (const CDTEdge<T> *e : cdt.edges) {
+ if (e->symedges[0].face == face) {
+ se_face_start = &e->symedges[0];
+ break;
+ }
+ if (e->symedges[1].face == face) {
+ se_face_start = &e->symedges[1];
+ }
+ }
+ if (se_face_start != nullptr) {
+ /* Find center of face. */
+ int face_nverts = 0;
+ vec2<double> cen(0.0, 0.0);
+ if (face == cdt.outer_face) {
+ cen.x = minx;
+ cen.y = miny;
+ }
+ else {
+ const SymEdge<T> *se = se_face_start;
+ do {
+ if (se->face == face) {
+ cen = cen + se->vert->co.approx;
+ face_nverts++;
+ }
+ } while ((se = se->next) != se_face_start);
+ if (face_nverts > 0) {
+ cen = cen / double(face_nverts);
+ }
+ }
+ f << "<text x=\"" << SX(cen[0]) << "\" y=\"" << SY(cen[1]) << "\""
+ << " font-size=\"small\">[";
+ f << trunc_ptr(face);
+ if (face->input_ids.size() > 0) {
+ for (int id : face->input_ids) {
+ f << " " << id;
+ }
+ }
+ f << "]</text>\n";
+ }
+ }
+ }
+ }
+
append = true;
# undef SX
# undef SY
@@ -754,7 +813,6 @@ template<> CDTVert<double>::CDTVert(const vec2<double> &pt)
this->co.exact = pt;
this->co.approx = pt;
this->co.abs_approx = pt; /* Not used, so doesn't matter. */
- this->input_ids = nullptr;
this->symedge = nullptr;
this->index = -1;
this->merge_to_index = -1;
@@ -767,7 +825,6 @@ template<> CDTVert<mpq_class>::CDTVert(const vec2<mpq_class> &pt)
this->co.exact = pt;
this->co.approx = double2(pt.x.get_d(), pt.y.get_d());
this->co.abs_approx = double2(fabs(this->co.approx.x), fabs(this->co.approx.y));
- this->input_ids = nullptr;
this->symedge = nullptr;
this->index = -1;
this->merge_to_index = -1;
@@ -824,35 +881,21 @@ template<typename T> void CDTArrangement<T>::reserve(int num_verts, int num_edge
}
template<typename T>
-CDT_state<T>::CDT_state(int num_input_verts, int num_input_edges, int num_input_faces, T epsilon)
+CDT_state<T>::CDT_state(
+ int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids)
{
this->input_vert_tot = num_input_verts;
this->cdt.reserve(num_input_verts, num_input_edges, num_input_faces);
this->cdt.outer_face = this->cdt.add_face();
this->epsilon = epsilon;
+ this->need_ids = need_ids;
this->visit_count = 0;
}
-static bool id_in_list(const LinkNode *id_list, int id)
-{
- const LinkNode *ln;
-
- for (ln = id_list; ln != nullptr; ln = ln->next) {
- if (POINTER_AS_INT(ln->link) == id) {
- return true;
- }
- }
- return false;
-}
-
/* Is any id in (range_start, range_start+1, ... , range_end) in id_list? */
-static bool id_range_in_list(const LinkNode *id_list, int range_start, int range_end)
+static bool id_range_in_list(const blender::Set<int> &id_list, int range_start, int range_end)
{
- const LinkNode *ln;
- int id;
-
- for (ln = id_list; ln != nullptr; ln = ln->next) {
- id = POINTER_AS_INT(ln->link);
+ for (int id : id_list) {
if (id >= range_start && id <= range_end) {
return true;
}
@@ -860,19 +903,15 @@ static bool id_range_in_list(const LinkNode *id_list, int range_start, int range
return false;
}
-static void add_to_input_ids(LinkNode **dst, int input_id)
+static void add_to_input_ids(blender::Set<int> &dst, int input_id)
{
- if (!id_in_list(*dst, input_id)) {
- BLI_linklist_prepend(dst, POINTER_FROM_INT(input_id));
- }
+ dst.add(input_id);
}
-static void add_list_to_input_ids(LinkNode **dst, const LinkNode *src)
+static void add_list_to_input_ids(blender::Set<int> &dst, const blender::Set<int> &src)
{
- const LinkNode *ln;
-
- for (ln = src; ln != nullptr; ln = ln->next) {
- add_to_input_ids(dst, POINTER_AS_INT(ln->link));
+ for (int value : src) {
+ dst.add(value);
}
}
@@ -883,7 +922,7 @@ template<typename T> inline bool is_border_edge(const CDTEdge<T> *e, const CDT_s
template<typename T> inline bool is_constrained_edge(const CDTEdge<T> *e)
{
- return e->input_ids != nullptr;
+ return e->input_ids.size() > 0;
}
template<typename T> inline bool is_deleted_edge(const CDTEdge<T> *e)
@@ -979,7 +1018,7 @@ template<typename T> CDTEdge<T> *CDTArrangement<T>::add_diagonal(SymEdge<T> *s1,
for (SymEdge<T> *se = s2; se != sdiag; se = se->next) {
se->face = fnew;
}
- add_list_to_input_ids(&fnew->input_ids, fold->input_ids);
+ add_list_to_input_ids(fnew->input_ids, fold->input_ids);
return ediag;
}
@@ -1058,7 +1097,7 @@ template<typename T> CDTEdge<T> *CDTArrangement<T>::split_edge(SymEdge<T> *se, T
if (newsesym->vert->symedge == sesym) {
newsesym->vert->symedge = newsesym;
}
- add_list_to_input_ids(&e->input_ids, se->edge->input_ids);
+ add_list_to_input_ids(e->input_ids, se->edge->input_ids);
return e;
}
@@ -1880,7 +1919,7 @@ void add_edge_constraint(
SymEdge<T> *t = find_symedge_between_verts(v1, v2);
if (t != nullptr) {
/* Segment already there. */
- add_to_input_ids(&t->edge->input_ids, input_id);
+ add_to_input_ids(t->edge->input_ids, input_id);
if (r_edges != nullptr) {
BLI_linklist_append(&edge_list, t->edge);
*r_edges = edge_list.list;
@@ -2041,7 +2080,7 @@ void add_edge_constraint(
BLI_assert(cd_prev->lambda == 0.0);
BLI_assert(cd_prev->out->next->vert == cd->vert);
edge = cd_prev->out->edge;
- add_to_input_ids(&edge->input_ids, input_id);
+ add_to_input_ids(edge->input_ids, input_id);
if (r_edges != nullptr) {
BLI_linklist_append(&edge_list, edge);
}
@@ -2054,7 +2093,7 @@ void add_edge_constraint(
else {
edge = cdt_state->cdt.add_diagonal(tstart, t);
}
- add_to_input_ids(&edge->input_ids, input_id);
+ add_to_input_ids(edge->input_ids, input_id);
if (r_edges != nullptr) {
BLI_linklist_append(&edge_list, edge);
}
@@ -2093,7 +2132,8 @@ template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CD
}
CDTVert<T> *v1 = cdt_state->cdt.get_vert_resolve_merge(iv1);
CDTVert<T> *v2 = cdt_state->cdt.get_vert_resolve_merge(iv2);
- add_edge_constraint(cdt_state, v1, v2, i, nullptr);
+ int id = cdt_state->need_ids ? i : 0;
+ add_edge_constraint(cdt_state, v1, v2, id, nullptr);
}
cdt_state->face_edge_offset = ne;
}
@@ -2132,7 +2172,7 @@ void add_face_ids(
continue;
}
face->visit_index = visit;
- add_to_input_ids(&face->input_ids, face_id);
+ add_to_input_ids(face->input_ids, face_id);
SymEdge<T> *se_start = se;
for (se = se->next; se != se_start; se = se->next) {
if (!id_range_in_list(se->edge->input_ids, fedge_start, fedge_end)) {
@@ -2168,7 +2208,10 @@ static int power_of_10_greater_equal_to(int x)
* order around each face in turn. And then the next face starts at
* cdt->face_edge_offset beyond the start for the previous face.
*/
-template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CDT_input<T> &input)
+template<typename T>
+void add_face_constraints(CDT_state<T> *cdt_state,
+ const CDT_input<T> &input,
+ CDT_output_type output_type)
{
int nv = input.vert.size();
int nf = input.face.size();
@@ -2206,7 +2249,8 @@ template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CD
CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1);
CDTVert<T> *v2 = cdt->get_vert_resolve_merge(iv2);
LinkNode *edge_list;
- add_edge_constraint(cdt_state, v1, v2, face_edge_id, &edge_list);
+ int id = cdt_state->need_ids ? face_edge_id : 0;
+ add_edge_constraint(cdt_state, v1, v2, id, &edge_list);
/* Set a new face_symedge0 each time since earlier ones may not
* survive later symedge splits. Really, just want the one when
* i == flen -1, but this code guards against that one somehow
@@ -2224,7 +2268,16 @@ template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CD
}
int fedge_end = fedge_start + flen - 1;
if (face_symedge0 != nullptr) {
- add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
+ /* We need to propagate face ids to all faces that represent #f, if #need_ids.
+ * Even if `need_ids == false`, we need to propagate at least the fact that
+ * the face ids set would be non-empty if the output type is one of the ones
+ * making valid BMesh faces. */
+ int id = cdt_state->need_ids ? f : 0;
+ add_face_ids(cdt_state, face_symedge0, id, fedge_start, fedge_end);
+ if (cdt_state->need_ids || (output_type == CDT_CONSTRAINTS_VALID_BMESH ||
+ output_type == CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES)) {
+ add_face_ids(cdt_state, face_symedge0, f, fedge_start, fedge_end);
+ }
}
fstart += flen;
}
@@ -2349,7 +2402,7 @@ template<typename T> void remove_non_constraint_edges_leave_valid_bmesh(CDT_stat
CDTFace<T> *fleft = se->face;
CDTFace<T> *fright = sym(se)->face;
if (fleft != cdt->outer_face && fright != cdt->outer_face &&
- (fleft->input_ids != nullptr || fright->input_ids != nullptr)) {
+ (fleft->input_ids.size() > 0 || fright->input_ids.size() > 0)) {
/* Is there another #SymEdge with same left and right faces?
* Or is there a vertex not part of e touching the same left and right faces? */
for (SymEdge<T> *se2 = se->next; dissolve && se2 != se; se2 = se2->next) {
@@ -2507,30 +2560,33 @@ template<typename T> void detect_holes(CDT_state<T> *cdt_state)
mid.exact[1] = (f->symedge->vert->co.exact[1] + f->symedge->next->vert->co.exact[1] +
f->symedge->next->next->vert->co.exact[1]) /
3;
- int hits = 0;
+ std::atomic<int> hits = 0;
/* TODO: Use CDT data structure here to greatly reduce search for intersections! */
- for (const CDTEdge<T> *e : cdt->edges) {
- if (!is_deleted_edge(e) && is_constrained_edge(e)) {
- if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) {
- continue; /* Don't count hits on edges between faces in same region. */
- }
- auto isect = vec2<T>::isect_seg_seg(ray_end.exact,
- mid.exact,
- e->symedges[0].vert->co.exact,
- e->symedges[1].vert->co.exact);
- switch (isect.kind) {
- case vec2<T>::isect_result::LINE_LINE_CROSS: {
- hits++;
- break;
+ threading::parallel_for(cdt->edges.index_range(), 256, [&](IndexRange range) {
+ for (const int i : range) {
+ const CDTEdge<T> *e = cdt->edges[i];
+ if (!is_deleted_edge(e) && is_constrained_edge(e)) {
+ if (e->symedges[0].face->visit_index == e->symedges[1].face->visit_index) {
+ continue; /* Don't count hits on edges between faces in same region. */
+ }
+ auto isect = vec2<T>::isect_seg_seg(ray_end.exact,
+ mid.exact,
+ e->symedges[0].vert->co.exact,
+ e->symedges[1].vert->co.exact);
+ switch (isect.kind) {
+ case vec2<T>::isect_result::LINE_LINE_CROSS: {
+ hits++;
+ break;
+ }
+ case vec2<T>::isect_result::LINE_LINE_EXACT:
+ case vec2<T>::isect_result::LINE_LINE_NONE:
+ case vec2<T>::isect_result::LINE_LINE_COLINEAR:
+ break;
}
- case vec2<T>::isect_result::LINE_LINE_EXACT:
- case vec2<T>::isect_result::LINE_LINE_NONE:
- case vec2<T>::isect_result::LINE_LINE_COLINEAR:
- break;
}
}
- }
- f->hole = (hits % 2) == 0;
+ });
+ f->hole = (hits.load() % 2) == 0;
}
/* Finally, propagate hole status to all holes of a region. */
@@ -2631,25 +2687,31 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
for (int i = 0; i < verts_size; ++i) {
CDTVert<T> *v = cdt->verts[i];
if (v->merge_to_index != -1) {
- if (i < cdt_state->input_vert_tot) {
- add_to_input_ids(&cdt->verts[v->merge_to_index]->input_ids, i);
+ if (cdt_state->need_ids) {
+ if (i < cdt_state->input_vert_tot) {
+ add_to_input_ids(cdt->verts[v->merge_to_index]->input_ids, i);
+ }
}
vert_to_output_map[i] = vert_to_output_map[v->merge_to_index];
}
}
}
result.vert = Array<vec2<T>>(nv);
- result.vert_orig = Array<Vector<int>>(nv);
+ if (cdt_state->need_ids) {
+ result.vert_orig = Array<Vector<int>>(nv);
+ }
int i_out = 0;
for (int i = 0; i < verts_size; ++i) {
CDTVert<T> *v = cdt->verts[i];
if (v->merge_to_index == -1) {
result.vert[i_out] = v->co.exact;
- if (i < cdt_state->input_vert_tot) {
- result.vert_orig[i_out].append(i);
- }
- for (LinkNode *ln = v->input_ids; ln; ln = ln->next) {
- result.vert_orig[i_out].append(POINTER_AS_INT(ln->link));
+ if (cdt_state->need_ids) {
+ if (i < cdt_state->input_vert_tot) {
+ result.vert_orig[i_out].append(i);
+ }
+ for (int vert : v->input_ids) {
+ result.vert_orig[i_out].append(vert);
+ }
}
++i_out;
}
@@ -2660,15 +2722,19 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
return !is_deleted_edge(e);
});
result.edge = Array<std::pair<int, int>>(ne);
- result.edge_orig = Array<Vector<int>>(ne);
+ if (cdt_state->need_ids) {
+ result.edge_orig = Array<Vector<int>>(ne);
+ }
int e_out = 0;
for (const CDTEdge<T> *e : cdt->edges) {
if (!is_deleted_edge(e)) {
int vo1 = vert_to_output_map[e->symedges[0].vert->index];
int vo2 = vert_to_output_map[e->symedges[1].vert->index];
result.edge[e_out] = std::pair<int, int>(vo1, vo2);
- for (LinkNode *ln = e->input_ids; ln; ln = ln->next) {
- result.edge_orig[e_out].append(POINTER_AS_INT(ln->link));
+ if (cdt_state->need_ids) {
+ for (int edge : e->input_ids) {
+ result.edge_orig[e_out].append(edge);
+ }
}
++e_out;
}
@@ -2679,7 +2745,9 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
return !f->deleted && f != cdt->outer_face;
});
result.face = Array<Vector<int>>(nf);
- result.face_orig = Array<Vector<int>>(nf);
+ if (cdt_state->need_ids) {
+ result.face_orig = Array<Vector<int>>(nf);
+ }
int f_out = 0;
for (const CDTFace<T> *f : cdt->faces) {
if (!f->deleted && f != cdt->outer_face) {
@@ -2690,8 +2758,10 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
result.face[f_out].append(vert_to_output_map[se->vert->index]);
se = se->next;
} while (se != se_start);
- for (LinkNode *ln = f->input_ids; ln; ln = ln->next) {
- result.face_orig[f_out].append(POINTER_AS_INT(ln->link));
+ if (cdt_state->need_ids) {
+ for (int face : f->input_ids) {
+ result.face_orig[f_out].append(face);
+ }
}
++f_out;
}
@@ -2716,11 +2786,11 @@ CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_ty
int nv = input.vert.size();
int ne = input.edge.size();
int nf = input.face.size();
- CDT_state<T> cdt_state(nv, ne, nf, input.epsilon);
+ CDT_state<T> cdt_state(nv, ne, nf, input.epsilon, input.need_ids);
add_input_verts(&cdt_state, input);
initial_triangulation(&cdt_state.cdt);
add_edge_constraints(&cdt_state, input);
- add_face_constraints(&cdt_state, input);
+ add_face_constraints(&cdt_state, input, output_type);
return get_cdt_output(&cdt_state, input, output_type);
}
@@ -2772,6 +2842,7 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input,
}
}
in.epsilon = static_cast<double>(input->epsilon);
+ in.need_ids = input->need_ids;
blender::meshintersect::CDT_result<double> res = blender::meshintersect::delaunay_2d_calc(
in, output_type);
@@ -2784,74 +2855,101 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input,
int tot_e_orig = 0;
int tot_f_orig = 0;
int tot_f_lens = 0;
- for (int v = 0; v < nv; ++v) {
- tot_v_orig += res.vert_orig[v].size();
- }
- for (int e = 0; e < ne; ++e) {
- tot_e_orig += res.edge_orig[e].size();
+ if (input->need_ids) {
+ for (int v = 0; v < nv; ++v) {
+ tot_v_orig += res.vert_orig[v].size();
+ }
+ for (int e = 0; e < ne; ++e) {
+ tot_e_orig += res.edge_orig[e].size();
+ }
}
for (int f = 0; f < nf; ++f) {
- tot_f_orig += res.face_orig[f].size();
+ if (input->need_ids) {
+ tot_f_orig += res.face_orig[f].size();
+ }
tot_f_lens += res.face[f].size();
}
output->vert_coords = static_cast<decltype(output->vert_coords)>(
MEM_malloc_arrayN(nv, sizeof(output->vert_coords[0]), __func__));
- output->verts_orig = static_cast<int *>(MEM_malloc_arrayN(tot_v_orig, sizeof(int), __func__));
- output->verts_orig_start_table = static_cast<int *>(
- MEM_malloc_arrayN(nv, sizeof(int), __func__));
- output->verts_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nv, sizeof(int), __func__));
output->edges = static_cast<decltype(output->edges)>(
MEM_malloc_arrayN(ne, sizeof(output->edges[0]), __func__));
- output->edges_orig = static_cast<int *>(MEM_malloc_arrayN(tot_e_orig, sizeof(int), __func__));
- output->edges_orig_start_table = static_cast<int *>(
- MEM_malloc_arrayN(ne, sizeof(int), __func__));
- output->edges_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(ne, sizeof(int), __func__));
output->faces = static_cast<int *>(MEM_malloc_arrayN(tot_f_lens, sizeof(int), __func__));
output->faces_start_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
output->faces_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
- output->faces_orig = static_cast<int *>(MEM_malloc_arrayN(tot_f_orig, sizeof(int), __func__));
- output->faces_orig_start_table = static_cast<int *>(
- MEM_malloc_arrayN(nf, sizeof(int), __func__));
- output->faces_orig_len_table = static_cast<int *>(MEM_malloc_arrayN(nf, sizeof(int), __func__));
+ if (input->need_ids) {
+ output->verts_orig = static_cast<int *>(MEM_malloc_arrayN(tot_v_orig, sizeof(int), __func__));
+ output->verts_orig_start_table = static_cast<int *>(
+ MEM_malloc_arrayN(nv, sizeof(int), __func__));
+ output->verts_orig_len_table = static_cast<int *>(
+ MEM_malloc_arrayN(nv, sizeof(int), __func__));
+ output->edges_orig = static_cast<int *>(MEM_malloc_arrayN(tot_e_orig, sizeof(int), __func__));
+ output->edges_orig_start_table = static_cast<int *>(
+ MEM_malloc_arrayN(ne, sizeof(int), __func__));
+ output->edges_orig_len_table = static_cast<int *>(
+ MEM_malloc_arrayN(ne, sizeof(int), __func__));
+ output->faces_orig = static_cast<int *>(MEM_malloc_arrayN(tot_f_orig, sizeof(int), __func__));
+ output->faces_orig_start_table = static_cast<int *>(
+ MEM_malloc_arrayN(nf, sizeof(int), __func__));
+ output->faces_orig_len_table = static_cast<int *>(
+ MEM_malloc_arrayN(nf, sizeof(int), __func__));
+ }
+ else {
+ output->verts_orig = nullptr;
+ output->verts_orig_start_table = nullptr;
+ output->verts_orig_len_table = nullptr;
+ output->edges_orig = nullptr;
+ output->edges_orig_start_table = nullptr;
+ output->edges_orig_len_table = nullptr;
+ output->faces_orig = nullptr;
+ output->faces_orig_start_table = nullptr;
+ output->faces_orig_len_table = nullptr;
+ }
int v_orig_index = 0;
for (int v = 0; v < nv; ++v) {
output->vert_coords[v][0] = static_cast<float>(res.vert[v][0]);
output->vert_coords[v][1] = static_cast<float>(res.vert[v][1]);
- int this_start = v_orig_index;
- output->verts_orig_start_table[v] = this_start;
- for (int j : res.vert_orig[v].index_range()) {
- output->verts_orig[v_orig_index++] = res.vert_orig[v][j];
+ if (input->need_ids) {
+ int this_start = v_orig_index;
+ output->verts_orig_start_table[v] = this_start;
+ for (int j : res.vert_orig[v].index_range()) {
+ output->verts_orig[v_orig_index++] = res.vert_orig[v][j];
+ }
+ output->verts_orig_len_table[v] = v_orig_index - this_start;
}
- output->verts_orig_len_table[v] = v_orig_index - this_start;
}
int e_orig_index = 0;
for (int e = 0; e < ne; ++e) {
output->edges[e][0] = res.edge[e].first;
output->edges[e][1] = res.edge[e].second;
- int this_start = e_orig_index;
- output->edges_orig_start_table[e] = this_start;
- for (int j : res.edge_orig[e].index_range()) {
- output->edges_orig[e_orig_index++] = res.edge_orig[e][j];
+ if (input->need_ids) {
+ int this_start = e_orig_index;
+ output->edges_orig_start_table[e] = this_start;
+ for (int j : res.edge_orig[e].index_range()) {
+ output->edges_orig[e_orig_index++] = res.edge_orig[e][j];
+ }
+ output->edges_orig_len_table[e] = e_orig_index - this_start;
}
- output->edges_orig_len_table[e] = e_orig_index - this_start;
}
int f_orig_index = 0;
int f_index = 0;
for (int f = 0; f < nf; ++f) {
+
output->faces_start_table[f] = f_index;
int flen = res.face[f].size();
output->faces_len_table[f] = flen;
for (int j = 0; j < flen; ++j) {
output->faces[f_index++] = res.face[f][j];
}
- int this_start = f_orig_index;
- output->faces_orig_start_table[f] = this_start;
- for (int k : res.face_orig[f].index_range()) {
- output->faces_orig[f_orig_index++] = res.face_orig[f][k];
+ if (input->need_ids) {
+ int this_start = f_orig_index;
+ output->faces_orig_start_table[f] = this_start;
+ for (int k : res.face_orig[f].index_range()) {
+ output->faces_orig[f_orig_index++] = res.face_orig[f][k];
+ }
+ output->faces_orig_len_table[f] = f_orig_index - this_start;
}
- output->faces_orig_len_table[f] = f_orig_index - this_start;
}
return output;
}
@@ -2863,14 +2961,16 @@ extern "C" void BLI_delaunay_2d_cdt_free(::CDT_result *result)
MEM_freeN(result->faces);
MEM_freeN(result->faces_start_table);
MEM_freeN(result->faces_len_table);
- MEM_freeN(result->verts_orig);
- MEM_freeN(result->verts_orig_start_table);
- MEM_freeN(result->verts_orig_len_table);
- MEM_freeN(result->edges_orig);
- MEM_freeN(result->edges_orig_start_table);
- MEM_freeN(result->edges_orig_len_table);
- MEM_freeN(result->faces_orig);
- MEM_freeN(result->faces_orig_start_table);
- MEM_freeN(result->faces_orig_len_table);
+ if (result->verts_orig) {
+ MEM_freeN(result->verts_orig);
+ MEM_freeN(result->verts_orig_start_table);
+ MEM_freeN(result->verts_orig_len_table);
+ MEM_freeN(result->edges_orig);
+ MEM_freeN(result->edges_orig_start_table);
+ MEM_freeN(result->edges_orig_len_table);
+ MEM_freeN(result->faces_orig);
+ MEM_freeN(result->faces_orig_start_table);
+ MEM_freeN(result->faces_orig_len_table);
+ }
MEM_freeN(result);
}