From 560e73238f263b0305fd01740210f3d187d867ae Mon Sep 17 00:00:00 2001 From: Bruno Levy Date: Mon, 6 Nov 2023 14:37:22 +0100 Subject: [PATCH] Now each constrained edges keeps a linked list of edge constraints, so that one keeps the information of several constraints that land on the same edges. It will be useful for the upcoming 2D CSG operations between polygons. --- src/lib/geogram/delaunay/CDT_2d.cpp | 38 ++++++----- src/lib/geogram/delaunay/CDT_2d.h | 87 +++++++++++++++++++------- src/lib/geogram/numerics/interval_nt.h | 2 +- 3 files changed, 86 insertions(+), 41 deletions(-) diff --git a/src/lib/geogram/delaunay/CDT_2d.cpp b/src/lib/geogram/delaunay/CDT_2d.cpp index a292f4e0d75a..02b11f39a556 100644 --- a/src/lib/geogram/delaunay/CDT_2d.cpp +++ b/src/lib/geogram/delaunay/CDT_2d.cpp @@ -111,7 +111,9 @@ namespace GEO { Tadj_.resize(0); v2T_.resize(0); Tflags_.resize(0); - Tecnstr_.resize(0); + Tecnstr_first_.resize(0); + ecnstr_val_.resize(0); + ecnstr_next_.resize(0); Tnext_.resize(0); Tprev_.resize(0); } @@ -453,7 +455,7 @@ namespace GEO { // Edge is flagged as constraint here, because // it will not be seen by constraint enforcement. index_t le_cnstr_edge = (v1 == W.j) ? (le+2)%3 : (le+1)%3; - Tset_edge_cnstr_with_neighbor( + Tadd_edge_cnstr_with_neighbor( t_around_v, le_cnstr_edge, ncnstr_-1 ); CDT_LOG( @@ -479,13 +481,13 @@ namespace GEO { geo_debug_assert(o1 != ZERO || o2 != ZERO); if(o1 == ZERO && o3*o4 < 0 && v1 != W.v_prev) { v_next = v1; - Tset_edge_cnstr_with_neighbor( + Tadd_edge_cnstr_with_neighbor( t_around_v, (le + 2)%3, ncnstr_-1 ); return true; } else if(o2 == ZERO && o3*o4 < 0 && v2 != W.v_prev) { v_next = v2; - Tset_edge_cnstr_with_neighbor( + Tadd_edge_cnstr_with_neighbor( t_around_v, (le + 1)%3, ncnstr_-1 ); return true; @@ -530,13 +532,13 @@ namespace GEO { CDT_LOG(" Cnstr isect with:" << v1 << "-" << v2); v_next = create_intersection( ncnstr()-1, W.i, W.j, - Tedge_cnstr(W.t,0), v1, v2 + edge_cnstr(Tedge_cnstr_first(W.t,0)), v1, v2 ); insert_vertex_in_edge(v_next,W.t,0); // Mark new edge as constraint if walker was previously // on a vertex. if(W.v_prev != index_t(-1)) { - Tset_edge_cnstr_with_neighbor(W.t,2,ncnstr_-1); + Tadd_edge_cnstr_with_neighbor(W.t,2,ncnstr_-1); } } else { CDT_LOG(" Isect: t=" << W.t <<" E=" << v1 <<"-"<< v2); @@ -579,7 +581,7 @@ namespace GEO { (Tv(t,1) == j && Tv(t,2) == i) ) { // Set constraint flag if the new edge is the constrained edge - Tset_edge_cnstr_with_neighbor(t,0,ncnstr_-1); + Tadd_edge_cnstr_with_neighbor(t,0,ncnstr_-1); } else { // Memorize new edge as "to be Delaunayized" if(N.initialized()) { @@ -885,7 +887,9 @@ namespace GEO { t_new, Tv(t,0), Tv(t,1), Tv(t,2), adj0, adj1, adj2, - Tedge_cnstr(t,0), Tedge_cnstr(t,1), Tedge_cnstr(t,2) + Tedge_cnstr_first(t,0), + Tedge_cnstr_first(t,1), + Tedge_cnstr_first(t,2) ); Tflags_[t_new] = 0; } @@ -894,7 +898,7 @@ namespace GEO { T_.resize(3*nT_new); Tadj_.resize(3*nT_new); Tflags_.resize(nT_new); - Tecnstr_.resize(3*nT_new); + Tecnstr_first_.resize(3*nT_new); Tnext_.resize(nT_new); Tprev_.resize(nT_new); @@ -912,7 +916,7 @@ namespace GEO { void CDTBase2d::insert_vertex_in_edge( index_t v, index_t t, index_t le1, DList& S ) { - index_t cnstr = Tedge_cnstr(t,le1); + index_t cnstr_first = Tedge_cnstr_first(t,le1); index_t t1 = t; index_t t2 = Tadj(t1,le1); index_t v1 = Tv(t1,le1); @@ -942,10 +946,10 @@ namespace GEO { Tadj_back_connect(t2,0,t2); Tadj_back_connect(t3,0,t2); Tadj_back_connect(t4,0,t1); - Tset_edge_cnstr(t1,1,cnstr); - Tset_edge_cnstr(t2,2,cnstr); - Tset_edge_cnstr(t3,1,cnstr); - Tset_edge_cnstr(t4,2,cnstr); + Tset_edge_cnstr_first(t1,1,cnstr_first); + Tset_edge_cnstr_first(t2,2,cnstr_first); + Tset_edge_cnstr_first(t3,1,cnstr_first); + Tset_edge_cnstr_first(t4,2,cnstr_first); if(S.initialized()) { S.push_back(t1); S.push_back(t2); @@ -962,8 +966,8 @@ namespace GEO { Tset(t2,v,v3,v1,t1_adj2,t1,index_t(-1)); Tadj_back_connect(t1,0,t1); Tadj_back_connect(t2,0,t1); - Tset_edge_cnstr(t1,1,cnstr); - Tset_edge_cnstr(t2,2,cnstr); + Tset_edge_cnstr_first(t1,1,cnstr_first); + Tset_edge_cnstr_first(t2,2,cnstr_first); if(S.initialized()) { S.push_back(t1); S.push_back(t2); @@ -1226,7 +1230,7 @@ namespace GEO { (E.first == i && E.second == j) || (E.first == j && E.second == i) ) { - Tset_edge_cnstr_with_neighbor(eT(E),0,ncnstr_-1); + Tadd_edge_cnstr_with_neighbor(eT(E),0,ncnstr_-1); } else { N.push_back(E); } diff --git a/src/lib/geogram/delaunay/CDT_2d.h b/src/lib/geogram/delaunay/CDT_2d.h index dd12771d8f7c..ccfac4bfd73d 100644 --- a/src/lib/geogram/delaunay/CDT_2d.h +++ b/src/lib/geogram/delaunay/CDT_2d.h @@ -671,9 +671,9 @@ namespace GEO { Tadj_[3*t ] = adj1; Tadj_[3*t+1] = adj2; Tadj_[3*t+2] = adj3; - Tecnstr_[3*t] = e1cnstr; - Tecnstr_[3*t+1] = e2cnstr; - Tecnstr_[3*t+2] = e3cnstr; + Tecnstr_first_[3*t] = e1cnstr; + Tecnstr_first_[3*t+1] = e2cnstr; + Tecnstr_first_[3*t+2] = e3cnstr; v2T_[v1] = t; v2T_[v2] = t; v2T_[v3] = t; @@ -697,7 +697,7 @@ namespace GEO { t, T_[i], T_[j], T_[k], Tadj_[i], Tadj_[j], Tadj_[k], - Tecnstr_[i], Tecnstr_[j], Tecnstr_[k] + Tecnstr_first_[i], Tecnstr_first_[j], Tecnstr_first_[k] ); } } @@ -766,7 +766,7 @@ namespace GEO { } index_t le2 = Tadj_find(t2,prev_t2_adj_e2); Tadj_set(t2,le2,t1); - Tset_edge_cnstr(t1,le1,Tedge_cnstr(t2,le2)); + Tset_edge_cnstr_first(t1,le1,Tedge_cnstr_first(t2,le2)); } /** @@ -778,7 +778,7 @@ namespace GEO { index_t nc = (t+1)*3; // new number of corners T_.resize(nc, index_t(-1)); Tadj_.resize(nc, index_t(-1)); - Tecnstr_.resize(nc, index_t(-1)); + Tecnstr_first_.resize(nc, index_t(-1)); Tflags_.resize(t+1,0); Tnext_.resize(t+1,index_t(-1)); Tprev_.resize(t+1,index_t(-1)); @@ -789,45 +789,84 @@ namespace GEO { * \brief Gets the constraint associated with an edge * \param[in] t a triangle * \param[in] le local edge index, in 0,1,2 - * \return the constraint associated with this edge, or - * index_t(-1) if there is no such constraint. + * \return the edge constraints iterator associated with this edge or + * index_t(-1) if the edge is not constrained. */ - index_t Tedge_cnstr(index_t t, index_t le) const { + index_t Tedge_cnstr_first(index_t t, index_t le) const { geo_debug_assert(t < nT()); geo_debug_assert(le < 3); - return Tecnstr_[3*t+le]; + return Tecnstr_first_[3*t+le]; } + + /** + * \brief Sets the constraints list associated with an edge + * \param[in] t a triangle + * \param[in] le local edge index, in 0,1,2 + * \param[in] ecit the edge constraint iterator that points to + * the first constraint associated with the edge + */ + void Tset_edge_cnstr_first( + index_t t, index_t le, index_t ecit + ) { + geo_debug_assert(t < nT()); + geo_debug_assert(le < 3); + Tecnstr_first_[3*t+le] = ecit; + } + /** - * \brief Sets an edge as constrained + * \brief Gets the successor of an edge constraint iterator + * \param[in] ecit the edge constraint iterator + * \return the edge constraint iterator to the successor of \p ecit + * or index_t(-1) if \p ecit is the last of the list. + */ + index_t edge_cnstr_next(index_t ecit) const { + return ecnstr_next_[ecit]; + } + + /** + * \brief Gets an edge constraint fro an edge constraint iterator + * \param[in] ecit the edge constraint iterator. Needs to be a valid + * iterator, different from index_t(-1). + * \return the edge constraint associated with the iterator. + */ + index_t edge_cnstr(index_t ecit) const { + return ecnstr_val_[ecit]; + } + + /** + * \brief Adds a constraint to a triangle edge * \param[in] t a triangle * \param[in] le local edge index, in 0,1,2 - * \param[in] cnstr_id identifier of the constrained edge + * \param[in] cnstr_id the constraint */ - void Tset_edge_cnstr( - index_t t, index_t le, index_t cnstr_id + void Tadd_edge_cnstr( + index_t t, index_t le, index_t cnstr_id ) { geo_debug_assert(t < nT()); geo_debug_assert(le < 3); - Tecnstr_[3*t+le] = cnstr_id; + ecnstr_val_.push_back(cnstr_id); + ecnstr_next_.push_back(Tedge_cnstr_first(t,le)); + Tset_edge_cnstr_first(t,le, ecnstr_val_.size()-1); } /** - * \brief Sets an edge as constrained in triangle and in neighbor + * \brief Adds a constraint to a triangle edge and to the neighboring + * edge if it exists * \param[in] t a triangle * \param[in] le local edge index, in 0,1,2 - * \param[in] cnstr_id identifier of the constrained edge + * \param[in] cnstr_id the constraint */ - void Tset_edge_cnstr_with_neighbor( - index_t t, index_t le, index_t cnstr_id + void Tadd_edge_cnstr_with_neighbor( + index_t t, index_t le, index_t cnstr_id ) { geo_debug_assert(t < nT()); geo_debug_assert(le < 3); - Tset_edge_cnstr(t, le, cnstr_id); + Tadd_edge_cnstr(t, le, cnstr_id); index_t t2 = Tadj(t,le); if(t2 != index_t(-1)) { index_t le2 = Tadj_find(t2,t); - Tset_edge_cnstr(t2,le2,cnstr_id); + Tadd_edge_cnstr(t2,le2,cnstr_id); } } @@ -839,7 +878,7 @@ namespace GEO { * \retval false otherwise */ bool Tedge_is_constrained(index_t t, index_t le) const { - return (Tedge_cnstr(t,le) != index_t(-1)); + return (Tedge_cnstr_first(t,le) != index_t(-1)); } /** @@ -1195,7 +1234,9 @@ namespace GEO { vector Tadj_; /**< triangles adjacency array */ vector v2T_; /**< vertex to triangle back pointer */ vector Tflags_; /**< triangle flags */ - vector Tecnstr_; /**< triangle edge constraint */ + vector Tecnstr_first_; /**< index in edge constraints list */ + vector ecnstr_val_; /**< edge constraints list, indices */ + vector ecnstr_next_; /**< edge constraints list, links */ vector Tnext_; /**< doubly connected triangle list */ vector Tprev_; /**< doubly connected triangle list */ bool delaunay_; /**< if set, compute a CDT, else just a CT */ diff --git a/src/lib/geogram/numerics/interval_nt.h b/src/lib/geogram/numerics/interval_nt.h index 2664b8c0c384..f43d47e1f86c 100644 --- a/src/lib/geogram/numerics/interval_nt.h +++ b/src/lib/geogram/numerics/interval_nt.h @@ -713,7 +713,7 @@ namespace GEO { intervalRN result = a; return result *= b; } - + typedef intervalRN interval_nt; // Seems that valgrind does not support RU //typedef intervalRU interval_nt;