From cc0465315cf6a161dfcd8193e5f4074cee19d445 Mon Sep 17 00:00:00 2001 From: artem-ogre Date: Wed, 29 Jan 2025 22:59:21 +0100 Subject: [PATCH] Refactor code for simplicity --- CDT/extras/InitializeWithGrid.h | 2 +- CDT/include/CDT.h | 2 +- CDT/include/CDTUtils.h | 151 ++++++++++++++++++-------------- CDT/include/CDTUtils.hpp | 56 ------------ CDT/include/KDTree.h | 10 +-- CDT/include/LocatorKDTree.h | 4 +- CDT/include/Triangulation.h | 14 ++- CDT/include/Triangulation.hpp | 60 ++++++------- CDT/src/CDT.cpp | 5 -- CDT/tests/cdt.test.cpp | 2 +- 10 files changed, 127 insertions(+), 179 deletions(-) diff --git a/CDT/extras/InitializeWithGrid.h b/CDT/extras/InitializeWithGrid.h index 0bf3b04e..9b873153 100644 --- a/CDT/extras/InitializeWithGrid.h +++ b/CDT/extras/InitializeWithGrid.h @@ -62,7 +62,7 @@ void generateGridVertices( TXCoordIter xiter = xfirst; for(std::size_t ix = 0; xiter != xlast; ++xiter, ++ix) { - *outVertsFirst++ = V2d::make(*xiter, *yiter); + *outVertsFirst++ = V2d(*xiter, *yiter); const std::size_t i = iy * xres + ix; TriIndVec vTris; vTris.reserve(6); diff --git a/CDT/include/CDT.h b/CDT/include/CDT.h index a8055a38..809f544e 100644 --- a/CDT/include/CDT.h +++ b/CDT/include/CDT.h @@ -306,7 +306,7 @@ DuplicatesInfo FindDuplicates( typename PosToIndex::const_iterator it; bool isUnique; tie(it, isUnique) = uniqueVerts.insert( - std::make_pair(V2d::make(getX(*first), getY(*first)), iOut)); + std::make_pair(V2d(getX(*first), getY(*first)), iOut)); if(isUnique) { di.mapping[iIn] = iOut++; diff --git a/CDT/include/CDTUtils.h b/CDT/include/CDTUtils.h index f9394e80..d3e04a46 100644 --- a/CDT/include/CDTUtils.h +++ b/CDT/include/CDTUtils.h @@ -100,8 +100,6 @@ std::string to_string(const T& value) namespace CDT { -namespace detail -{ /// Needed for c++03 compatibility (no uniform initialization available) template array arr3(const T& v0, const T& v1, const T& v2) @@ -109,7 +107,14 @@ array arr3(const T& v0, const T& v1, const T& v2) const array out = {v0, v1, v2}; return out; } -} // namespace detail + +/// Needed for c++03 compatibility (no uniform initialization available) +template +array arr3(const T& v) +{ + const array out = {v, v, v}; + return out; +} /// 2D vector template @@ -118,8 +123,17 @@ struct CDT_EXPORT V2d T x; ///< X-coordinate T y; ///< Y-coordinate - /// Create vector from X and Y coordinates - static V2d make(T x, T y); + /// Vertex with zero coordinates + V2d() + : x(T(0)) + , y(T(0)) + {} + + /// Vertex with given coordinates + V2d(const T x, const T y) + : x(x) + , y(y) + {} }; /// X- coordinate getter for V2d @@ -187,6 +201,12 @@ struct CDT_EXPORT Box2d V2d min; ///< min box corner V2d max; ///< max box corner + /// Box that doesn't contain any point + Box2d() + : min(std::numeric_limits::max(), std::numeric_limits::max()) + , max(-std::numeric_limits::max(), -std::numeric_limits::max()) + {} + /// Envelop box around a point void envelopPoint(const V2d& p) { @@ -201,54 +221,71 @@ struct CDT_EXPORT Box2d min.y = std::min(y, min.y); max.y = std::max(y, max.y); } -}; -/// Bounding box of a collection of custom 2D points given coordinate getters -template < - typename T, - typename TVertexIter, - typename TGetVertexCoordX, - typename TGetVertexCoordY> -Box2d envelopBox( - TVertexIter first, - TVertexIter last, - TGetVertexCoordX getX, - TGetVertexCoordY getY) -{ - const T max = std::numeric_limits::max(); - Box2d box = {{max, max}, {-max, -max}}; - for(; first != last; ++first) + /// Envelop box around a collection of custom points + template < + typename TVertexIter, + typename TGetVertexCoordX, + typename TGetVertexCoordY> + void envelopPoints( + TVertexIter first, + TVertexIter last, + TGetVertexCoordX getX, + TGetVertexCoordY getY) { - box.envelopPoint(getX(*first), getY(*first)); + for(; first != last; ++first) + { + envelopPoint(getX(*first), getY(*first)); + } } - return box; -} -/// Bounding box of a collection of 2D points -template -CDT_EXPORT Box2d envelopBox(const std::vector >& vertices); + /// Envelop box around a collection of points + void envelopPoints(const std::vector >& vertices) + { + envelopPoints( + vertices.begin(), vertices.end(), getX_V2d, getY_V2d); + } +}; /// Edge connecting two vertices: vertex with smaller index is always first /// @note: hash Edge is specialized at the bottom struct CDT_EXPORT Edge { /// Constructor - Edge(VertInd iV1, VertInd iV2); + Edge(const VertInd iV1, const VertInd iV2) + : m_vertices( + iV1 < iV2 ? std::make_pair(iV1, iV2) : std::make_pair(iV2, iV1)) + {} /// Equals operator - bool operator==(const Edge& other) const; + bool operator==(const Edge& other) const + { + return m_vertices == other.m_vertices; + } /// Not-equals operator - bool operator!=(const Edge& other) const; + bool operator!=(const Edge& other) const + { + return !(this->operator==(other)); + } /// V1 getter - VertInd v1() const; + VertInd v1() const + { + return m_vertices.first; + } /// V2 getter - VertInd v2() const; + VertInd v2() const + { + return m_vertices.second; + } /// Edges' vertices - const std::pair& verts() const; + const std::pair& verts() const + { + return m_vertices; + } private: std::pair m_vertices; @@ -290,30 +327,17 @@ struct CDT_EXPORT Triangle VerticesArr3 vertices; ///< triangle's three vertices NeighborsArr3 neighbors; ///< triangle's three neighbors - /** - * Factory method - * @note needed for c++03 compatibility (no uniform initialization - * available) - */ - static Triangle - make(const array& vertices, const array& neighbors) - { - const Triangle t = {vertices, neighbors}; - return t; - } + /// Triangle with no vertices and no neighbors + Triangle() + : vertices(arr3(noVertex)) + , neighbors(arr3(noNeighbor)) + {} - /** - * Factory method for creating uninitialized triangle - * @note needed for c++03 compatibility (no uniform initialization - * available) - */ - static Triangle uninitialized() - { - const Triangle t = { - detail::arr3(noVertex, noVertex, noVertex), - detail::arr3(noNeighbor, noNeighbor, noNeighbor)}; - return t; - } + /// Triangle with given vertices and neighbors + Triangle(const VerticesArr3& vertices, const NeighborsArr3& neighbors) + : vertices(vertices) + , neighbors(neighbors) + {} /// Next triangle adjacent to a vertex (clockwise) /// @returns pair of next triangle and the other vertex of a common edge @@ -343,6 +367,7 @@ struct CDT_EXPORT Triangle return std::make_pair(neighbors[1], vertices[1]); } + /// Check if triangle contains a vertex bool containsVertex(const VertInd i) const { return std::find(vertices.begin(), vertices.end(), i) != vertices.end(); @@ -487,6 +512,7 @@ namespace std namespace boost #endif { + #ifdef CDT_USE_STRONG_TYPING /// Vertex index hasher @@ -536,16 +562,13 @@ struct hash static std::size_t hashEdge(const CDT::Edge& e) { - const std::pair& vv = e.verts(); - std::size_t seed1(0); - hashCombine(seed1, vv.first); - hashCombine(seed1, vv.second); - std::size_t seed2(0); - hashCombine(seed2, vv.second); - hashCombine(seed2, vv.first); - return std::min(seed1, seed2); + std::size_t seed(0); + hashCombine(seed, e.v1()); + hashCombine(seed, e.v2()); + return seed; } }; + } // namespace std/boost #endif // header guard diff --git a/CDT/include/CDTUtils.hpp b/CDT/include/CDTUtils.hpp index 001098ae..e2757cb3 100644 --- a/CDT/include/CDTUtils.hpp +++ b/CDT/include/CDTUtils.hpp @@ -16,62 +16,6 @@ namespace CDT { -//***************************************************************************** -// V2d -//***************************************************************************** -template -V2d V2d::make(const T x, const T y) -{ - V2d out = {x, y}; - return out; -} - -//***************************************************************************** -// Box2d -//***************************************************************************** -template -Box2d envelopBox(const std::vector >& vertices) -{ - return envelopBox( - vertices.begin(), vertices.end(), getX_V2d, getY_V2d); -} - -//***************************************************************************** -// Edge -//***************************************************************************** -CDT_INLINE_IF_HEADER_ONLY Edge::Edge(VertInd iV1, VertInd iV2) - : m_vertices( - iV1 < iV2 ? std::make_pair(iV1, iV2) : std::make_pair(iV2, iV1)) -{} - -CDT_INLINE_IF_HEADER_ONLY bool Edge::operator==(const Edge& other) const -{ - return m_vertices == other.m_vertices; -} - -CDT_INLINE_IF_HEADER_ONLY bool Edge::operator!=(const Edge& other) const -{ - return !(this->operator==(other)); -} - -CDT_INLINE_IF_HEADER_ONLY VertInd Edge::v1() const -{ - return m_vertices.first; -} - -CDT_INLINE_IF_HEADER_ONLY VertInd Edge::v2() const -{ - return m_vertices.second; -} - -CDT_INLINE_IF_HEADER_ONLY const std::pair& Edge::verts() const -{ - return m_vertices; -} - -//***************************************************************************** -// Utility functions -//***************************************************************************** CDT_INLINE_IF_HEADER_ONLY Index ccw(Index i) { return Index((i + 1) % 3); diff --git a/CDT/include/KDTree.h b/CDT/include/KDTree.h index 2aa4eb24..f4bbad9d 100644 --- a/CDT/include/KDTree.h +++ b/CDT/include/KDTree.h @@ -81,10 +81,10 @@ class KDTree /// Default constructor KDTree() : m_rootDir(NodeSplitDirection::X) - , m_min(point_type::make( + , m_min(point_type( -std::numeric_limits::max(), -std::numeric_limits::max())) - , m_max(point_type::make( + , m_max(point_type( std::numeric_limits::max(), std::numeric_limits::max())) , m_size(0) @@ -349,10 +349,8 @@ class KDTree for(pd_cit it = data.begin(); it != data.end(); ++it) { const point_type& p = points[*it]; - m_min = point_type::make( - std::min(m_min.x, p.x), std::min(m_min.y, p.y)); - m_max = point_type::make( - std::max(m_max.x, p.x), std::max(m_max.y, p.y)); + m_min = point_type(std::min(m_min.x, p.x), std::min(m_min.y, p.y)); + m_max = point_type(std::max(m_max.x, p.x), std::max(m_max.y, p.y)); } // Make sure bounding box does not have a zero size by adding padding: // zero-size bounding box cannot be extended properly diff --git a/CDT/include/LocatorKDTree.h b/CDT/include/LocatorKDTree.h index bb3684e2..06aa8062 100644 --- a/CDT/include/LocatorKDTree.h +++ b/CDT/include/LocatorKDTree.h @@ -34,8 +34,8 @@ class LocatorKDTree typedef typename std::vector::const_iterator Cit; for(Cit it = points.begin(); it != points.end(); ++it) { - min = V2d_t::make(std::min(min.x, it->x), std::min(min.y, it->y)); - max = V2d_t::make(std::max(max.x, it->x), std::max(max.y, it->y)); + min = V2d_t(std::min(min.x, it->x), std::min(min.y, it->y)); + max = V2d_t(std::max(max.x, it->x), std::max(max.y, it->y)); } m_kdTree = KDTree_t(min, max); for(VertInd i(0); i < points.size(); ++i) diff --git a/CDT/include/Triangulation.h b/CDT/include/Triangulation.h index 25eb0165..f0a77451 100644 --- a/CDT/include/Triangulation.h +++ b/CDT/include/Triangulation.h @@ -746,10 +746,7 @@ class CDT_EXPORT Triangulation void insertVertices_AsProvided(VertInd superGeomVertCount); void insertVertices_Randomized(VertInd superGeomVertCount); - void insertVertices_KDTreeBFS( - VertInd superGeomVertCount, - V2d boxMin, - V2d boxMax); + void insertVertices_KDTreeBFS(VertInd superGeomVertCount, Box2d box); std::pair edgeTriangles(VertInd a, VertInd b) const; bool hasEdge(VertInd a, VertInd b) const; void setAdjacentTriangle(const VertInd v, const TriInd t); @@ -872,18 +869,17 @@ void Triangulation::insertVertices( vertices.reserve(capacityVertices); m_vertTris.reserve(capacityVertices); - const T max = std::numeric_limits::max(); - Box2d box = {{max, max}, {-max, -max}}; + Box2d box; if(isFirstTime) { - box = envelopBox(first, last, getX, getY); + box.envelopPoints(first, last, getX, getY); addSuperTriangle(box); } tryInitNearestPointLocator(); const VertInd nExistingVerts = static_cast(vertices.size()); for(TVertexIter it = first; it != last; ++it) - addNewVertex(V2d::make(getX(*it), getY(*it)), noNeighbor); + addNewVertex(V2d(getX(*it), getY(*it)), noNeighbor); switch(m_vertexInsertionOrder) { @@ -891,7 +887,7 @@ void Triangulation::insertVertices( insertVertices_AsProvided(nExistingVerts); break; case VertexInsertionOrder::Auto: - isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box.min, box.max) + isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box) : insertVertices_Randomized(nExistingVerts); break; } diff --git a/CDT/include/Triangulation.hpp b/CDT/include/Triangulation.hpp index 3f27a535..dc152b49 100644 --- a/CDT/include/Triangulation.hpp +++ b/CDT/include/Triangulation.hpp @@ -286,7 +286,7 @@ TriInd Triangulation::addTriangle(const Triangle& t) template TriInd Triangulation::addTriangle() { - return addTriangle(Triangle::uninitialized()); + return addTriangle(Triangle()); } template @@ -441,7 +441,7 @@ V2d intersectionPosition( const T d_ab = orient2d(a.x, a.y, b.x, b.y, d.x, d.y); const T t_cd = c_ab / (c_ab - d_ab); - return V2d::make( + return V2d( std::fabs(a.x - b.x) < std::fabs(c.x - d.x) ? lerp(a.x, b.x, t_ab) : lerp(c.x, d.x, t_cd), std::fabs(a.y - b.y) < std::fabs(c.y - d.y) ? lerp(a.y, b.y, t_ab) @@ -781,8 +781,7 @@ void Triangulation::conformToEdgeIteration( const V2d& start = vertices[iA]; const V2d& end = vertices[iB]; addNewVertex( - V2d::make((start.x + end.x) / T(2), (start.y + end.y) / T(2)), - noNeighbor); + V2d((start.x + end.x) / T(2), (start.y + end.y) / T(2)), noNeighbor); const std::vector flippedFixedEdges = insertVertex_FlipFixedEdges(iMid); @@ -955,9 +954,7 @@ void Triangulation::addSuperTriangle(const Box2d& box) addNewVertex(posV2, TriInd(0)); addNewVertex(posV3, TriInd(0)); addTriangle( - Triangle::make( - {VertInd(0), VertInd(1), VertInd(2)}, - {noNeighbor, noNeighbor, noNeighbor})); + Triangle(arr3(VertInd(0), VertInd(1), VertInd(2)), arr3(noNeighbor))); if(m_vertexInsertionOrder != VertexInsertionOrder::Auto) { m_nearPtLocator.initialize(vertices); @@ -1245,9 +1242,8 @@ void Triangulation::flipEdge( const TriInd n4) { // change vertices and neighbors - using detail::arr3; - triangles[iT] = Triangle::make(arr3(v4, v1, v3), arr3(n3, iTopo, n4)); - triangles[iTopo] = Triangle::make(arr3(v2, v3, v1), arr3(n2, iT, n1)); + triangles[iT] = Triangle(arr3(v4, v1, v3), arr3(n3, iTopo, n4)); + triangles[iTopo] = Triangle(arr3(v2, v3, v1), arr3(n2, iT, n1)); // adjust neighboring triangles and vertices changeNeighbor(n1, iT, iTopo); changeNeighbor(n4, iTopo, iT); @@ -1293,10 +1289,9 @@ Triangulation::insertVertexInsideTriangle( const TriInd n1 = nn[0], n2 = nn[1], n3 = nn[2]; // make two new triangles and convert current triangle to 3rd new // triangle - using detail::arr3; - triangles[iNewT1] = Triangle::make(arr3(v2, v3, v), arr3(n2, iNewT2, iT)); - triangles[iNewT2] = Triangle::make(arr3(v3, v1, v), arr3(n3, iT, iNewT1)); - t = Triangle::make(arr3(v1, v2, v), arr3(n1, iNewT1, iNewT2)); + triangles[iNewT1] = Triangle(arr3(v2, v3, v), arr3(n2, iNewT2, iT)); + triangles[iNewT2] = Triangle(arr3(v3, v1, v), arr3(n3, iT, iNewT1)); + t = Triangle(arr3(v1, v2, v), arr3(n1, iNewT1, iNewT2)); // adjust adjacent triangles setAdjacentTriangle(v, iT); setAdjacentTriangle(v3, iNewT1); @@ -1346,11 +1341,10 @@ std::stack Triangulation::insertVertexOnEdge( const TriInd n3 = t2.neighbors[i]; const TriInd n2 = t2.neighbors[cw(i)]; // add new triangles and change existing ones - using detail::arr3; - t1 = Triangle::make(arr3(v, v1, v2), arr3(iTnew1, n1, iT2)); - t2 = Triangle::make(arr3(v, v2, v3), arr3(iT1, n2, iTnew2)); - triangles[iTnew1] = Triangle::make(arr3(v, v4, v1), arr3(iTnew2, n4, iT1)); - triangles[iTnew2] = Triangle::make(arr3(v, v3, v4), arr3(iT2, n3, iTnew1)); + t1 = Triangle(arr3(v, v1, v2), arr3(iTnew1, n1, iT2)); + t2 = Triangle(arr3(v, v2, v3), arr3(iT1, n2, iTnew2)); + triangles[iTnew1] = Triangle(arr3(v, v4, v1), arr3(iTnew2, n4, iT1)); + triangles[iTnew2] = Triangle(arr3(v, v3, v4), arr3(iT2, n3, iTnew1)); // adjust adjacent triangles setAdjacentTriangle(v, iT1); setAdjacentTriangle(v4, iTnew1); @@ -1493,9 +1487,8 @@ void Triangulation::flipEdge( const TriInd n4 = triOpoNs[i]; const TriInd n2 = triOpoNs[cw(i)]; // change vertices and neighbors - using detail::arr3; - t = Triangle::make(arr3(v4, v1, v3), arr3(n3, iTopo, n4)); - tOpo = Triangle::make(arr3(v2, v3, v1), arr3(n2, iT, n1)); + t = Triangle(arr3(v4, v1, v3), arr3(n3, iTopo, n4)); + tOpo = Triangle(arr3(v2, v3, v1), arr3(n2, iT, n1)); // adjust neighboring triangles and vertices changeNeighbor(n1, iT, iTopo); changeNeighbor(n4, iTopo, iT); @@ -1637,7 +1630,7 @@ void Triangulation::triangulatePseudoPolygonIteration( // parent to maintain triangulation topology consistency triangles[iParent].neighbors[iInParent] = iT; t.neighbors[0] = iParent; - t.vertices = detail::arr3(a, b, c); + t.vertices = arr3(a, b, c); setAdjacentTriangle(c, iT); } @@ -1894,8 +1887,7 @@ class less_than_y template void Triangulation::insertVertices_KDTreeBFS( VertInd superGeomVertCount, - V2d boxMin, - V2d boxMax) + Box2d box) { // calculate original indices const VertInd vertexCount = @@ -1908,7 +1900,7 @@ void Triangulation::insertVertices_KDTreeBFS( typedef std::vector::iterator It; detail::FixedCapacityQueue, V2d, VertInd> > queue( detail::maxQueueLengthBFSKDTree(vertexCount)); - queue.push(make_tuple(ii.begin(), ii.end(), boxMin, boxMax, VertInd(0))); + queue.push(make_tuple(ii.begin(), ii.end(), box.min, box.max, VertInd(0))); It first, last; V2d newBoxMin, newBoxMax; @@ -1919,7 +1911,7 @@ void Triangulation::insertVertices_KDTreeBFS( while(!queue.empty()) { - tie(first, last, boxMin, boxMax, parent) = queue.front(); + tie(first, last, box.min, box.max, parent) = queue.front(); queue.pop(); assert(first != last); @@ -1930,34 +1922,34 @@ void Triangulation::insertVertices_KDTreeBFS( continue; } const It midIt = first + len / 2; - if(boxMax.x - boxMin.x >= boxMax.y - boxMin.y) + if(box.max.x - box.min.x >= box.max.y - box.min.y) { detail::portable_nth_element(first, midIt, last, cmpX); mid = *midIt; const T split = vertices[mid].x; newBoxMin.x = split; - newBoxMin.y = boxMin.y; + newBoxMin.y = box.min.y; newBoxMax.x = split; - newBoxMax.y = boxMax.y; + newBoxMax.y = box.max.y; } else { detail::portable_nth_element(first, midIt, last, cmpY); mid = *midIt; const T split = vertices[mid].y; - newBoxMin.x = boxMin.x; + newBoxMin.x = box.min.x; newBoxMin.y = split; - newBoxMax.x = boxMax.x; + newBoxMax.x = box.max.x; newBoxMax.y = split; } insertVertex(mid, parent); if(first != midIt) { - queue.push(make_tuple(first, midIt, boxMin, newBoxMax, mid)); + queue.push(make_tuple(first, midIt, box.min, newBoxMax, mid)); } if(midIt + 1 != last) { - queue.push(make_tuple(midIt + 1, last, newBoxMin, boxMax, mid)); + queue.push(make_tuple(midIt + 1, last, newBoxMin, box.max, mid)); } } } diff --git a/CDT/src/CDT.cpp b/CDT/src/CDT.cpp index 68f18fe5..5bbec70c 100644 --- a/CDT/src/CDT.cpp +++ b/CDT/src/CDT.cpp @@ -31,11 +31,6 @@ template struct CDT_EXPORT Box2d; template class CDT_EXPORT Triangulation; template class CDT_EXPORT Triangulation; -template CDT_EXPORT Box2d -envelopBox(const std::vector >&); -template CDT_EXPORT Box2d -envelopBox(const std::vector >&); - template CDT_EXPORT DuplicatesInfo RemoveDuplicates(std::vector >&); template CDT_EXPORT DuplicatesInfo diff --git a/CDT/tests/cdt.test.cpp b/CDT/tests/cdt.test.cpp index d073124c..bd996c7a 100644 --- a/CDT/tests/cdt.test.cpp +++ b/CDT/tests/cdt.test.cpp @@ -109,7 +109,7 @@ readInputFromFile(const std::string& fileName) { T x, y; f >> x >> y; - vv.push_back(V2d::make(x, y)); + vv.emplace_back(x, y); } // Read edges std::vector ee;