From f659df97e98b472213ae61a164f4e7b773a3185c Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 13 Jan 2024 13:07:19 -0600 Subject: [PATCH] Part/Toponaming: makeElementWires linter cleanup --- src/Mod/Part/App/TopoShape.h | 45 ++++- src/Mod/Part/App/TopoShapeExpansion.cpp | 244 ++++++++++++++---------- 2 files changed, 185 insertions(+), 104 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 9ff898c726..9c67e97c23 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -48,7 +48,7 @@ class Color; namespace Part { -class ShapeHasher; +struct ShapeHasher; class TopoShape; class TopoShapeCache; typedef std::unordered_map TopoShapeMap; @@ -890,6 +890,49 @@ private: sortEdges(std::list& edges, bool keepOrder = false, double tol = 0.0); }; +/// Shape hasher that ignore orientation +struct ShapeHasher { + inline size_t operator()(const TopoShape &s) const { + return s.getShape().HashCode(INT_MAX); + } + inline size_t operator()(const TopoDS_Shape &s) const { + return s.HashCode(INT_MAX); + } + inline bool operator()(const TopoShape &a, const TopoShape &b) const { + return a.getShape().IsSame(b.getShape()); + } + inline bool operator()(const TopoDS_Shape &a, const TopoDS_Shape &b) const { + return a.IsSame(b); + } + template + static inline void hash_combine(std::size_t& seed, const T& v) + { + // copied from boost::hash_combine + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + inline size_t operator()(const std::pair &s) const { + size_t res = s.first.getShape().HashCode(INT_MAX); + hash_combine(res, s.second.getShape().HashCode(INT_MAX)); + return res; + } + inline size_t operator()(const std::pair &s) const { + size_t res = s.first.HashCode(INT_MAX); + hash_combine(res, s.second.HashCode(INT_MAX)); + return res; + } + inline bool operator()(const std::pair &a, + const std::pair &b) const { + return a.first.getShape().IsSame(b.first.getShape()) + && a.second.getShape().IsSame(b.second.getShape()); + } + inline bool operator()(const std::pair &a, + const std::pair &b) const { + return a.first.IsSame(b.first) + && a.second.IsSame(b.second); + } +}; + } // namespace Part diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index d30ce54c00..cc0c3a3ffb 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -25,6 +25,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include + #include #include #include @@ -38,6 +40,7 @@ #include "TopoShapeCache.h" #include "TopoShapeOpCode.h" + FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT namespace Part @@ -435,9 +438,11 @@ void TopoShape::mapSubElement(const TopoShape& other, const char* op, bool force mapSubElementForShape(other, op); } -void TopoShape::mapSubElementsTo(std::vector &shapes, const char *op) const { - for(auto &shape : shapes) - shape.mapSubElement(*this,op); +void TopoShape::mapSubElementsTo(std::vector& shapes, const char* op) const +{ + for (auto& shape : shapes) { + shape.mapSubElement(*this, op); + } } std::vector @@ -483,7 +488,7 @@ void TopoShape::mapCompoundSubElements(const std::vector& shapes, con ++count; auto subshape = getSubShape(TopAbs_SHAPE, count, /*silent = */ true); if (!subshape.IsPartner(topoShape._Shape)) { - return; // Not a partner shape, don't do any mapping at all + return; // Not a partner shape, don't do any mapping at all } } auto children {createChildMap(count, shapes, op)}; @@ -551,81 +556,93 @@ TopoShape::makeElementCompound(const std::vector& shapes, const char* return *this; } -TopoShape &TopoShape::makeElementWires(const std::vector &shapes, - const char *op, - double tol, - bool shared, - TopoShapeMap *output) +TopoShape& TopoShape::makeElementWires(const std::vector& shapes, + const char* op, + double tol, + bool shared, + TopoShapeMap* output) { - if(shapes.empty()) - FC_THROWM(NullShapeException, "Null shape");; - if(shapes.size() == 1) - return makeElementWires(shapes[0],op,tol,shared,output); - return makeElementWires(TopoShape(Tag).makeElementCompound(shapes),op,tol,shared,output); + if (shapes.empty()) { + FC_THROWM(NullShapeException, "Null shape"); + } + if (shapes.size() == 1) { + return makeElementWires(shapes[0], op, tol, shared, output); + } + return makeElementWires(TopoShape(Tag).makeElementCompound(shapes), op, tol, shared, output); } -TopoShape &TopoShape::makeElementWires(const TopoShape &shape, - const char *op, - double tol, - bool shared, - TopoShapeMap *output) +TopoShape& TopoShape::makeElementWires(const TopoShape& shape, + const char* op, + double tol, + bool shared, + TopoShapeMap* output) { - if(!op) op = Part::OpCodes::Wire; - if(tolAppend(xp.Current()); - if(!hEdges->Length()) - FC_THROWM(NullShapeException, "Null shape");; + } + if (hEdges->Length() == 0) { + FC_THROWM(NullShapeException, "Null shape"); + } ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges, tol, Standard_True, hWires); - if(!hWires->Length()) - FC_THROWM(NullShapeException, "Null shape");; + if (hWires->Length() == 0) { + FC_THROWM(NullShapeException, "Null shape"); + } std::vector wires; - for (int i=1; i<=hWires->Length(); i++) { + for (int i = 1; i <= hWires->Length(); i++) { auto wire = hWires->Value(i); - wires.push_back(TopoShape(Tag,Hasher,wire)); + wires.push_back(TopoShape(Tag, Hasher, wire)); } - shape.mapSubElementsTo(wires,op); - return makeElementCompound(wires,"",false); + shape.mapSubElementsTo(wires, op); + return makeElementCompound(wires, "", false); } std::vector wires; - std::list edge_list; + std::list edgeList; - for(auto &e : shape.getSubTopoShapes(TopAbs_EDGE)) - edge_list.emplace_back(e); + for (auto& edge : shape.getSubTopoShapes(TopAbs_EDGE)) { + edgeList.emplace_back(edge); + } std::vector edges; - edges.reserve(edge_list.size()); - wires.reserve(edge_list.size()); + edges.reserve(edgeList.size()); + wires.reserve(edgeList.size()); // sort them together to wires - while (edge_list.size() > 0) { + while (!edgeList.empty()) { BRepBuilderAPI_MakeWire mkWire; // add and erase first edge edges.clear(); - edges.push_back(edge_list.front()); + edges.push_back(edgeList.front()); mkWire.Add(TopoDS::Edge(edges.back().getShape())); - edges.back().setShape(mkWire.Edge(),false); - if (output) - (*output)[edges.back()] = edge_list.front(); - edge_list.pop_front(); + edges.back().setShape(mkWire.Edge(), false); + if (output) { + (*output)[edges.back()] = edgeList.front(); + } + edgeList.pop_front(); - TopoDS_Wire new_wire = mkWire.Wire(); // current new wire + TopoDS_Wire new_wire = mkWire.Wire(); // current new wire - // try to connect each edge to the wire, the wire is complete if no more edges are connectible - bool found = false; - do { + // try to connect each edge to the wire, the wire is complete if no more edges are + // connectible + bool found = true; + while (found) { found = false; - for (auto it=edge_list.begin();it!=edge_list.end();++it) { + for (auto it = edgeList.begin(); it != edgeList.end(); ++it) { mkWire.Add(TopoDS::Edge(it->getShape())); if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) { // edge added ==> remove it from list @@ -634,97 +651,111 @@ TopoShape &TopoShape::makeElementWires(const TopoShape &shape, // MakeWire will replace vertex of connected edge, which // effectively creat a new edge. So we need to update the // shape in order to preserve element mapping. - edges.back().setShape(mkWire.Edge(),false); - if (output) + edges.back().setShape(mkWire.Edge(), false); + if (output) { (*output)[edges.back()] = *it; - edge_list.erase(it); + } + edgeList.erase(it); new_wire = mkWire.Wire(); break; } } - } while (found); + } wires.emplace_back(new_wire); wires.back().mapSubElement(edges, op); wires.back().fix(); } - return makeElementCompound(wires,0,false); + return makeElementCompound(wires, nullptr, false); } -struct EdgePoints { +struct EdgePoints +{ gp_Pnt v1, v2; std::list::iterator it; - const TopoShape &edge; - bool closed; + const TopoShape* edge; + bool closed{false}; EdgePoints(std::list::iterator it, double tol) - :it(it), edge(*it), closed(false) + : it(it) + , edge(&*it) { - TopExp_Explorer xp(it->getShape(),TopAbs_VERTEX); + TopExp_Explorer xp(it->getShape(), TopAbs_VERTEX); v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current())); xp.Next(); if (xp.More()) { v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current())); closed = (v2.SquareDistance(v1) <= tol); - } else { + } + else { v2 = v1; closed = true; } } }; -std::deque -TopoShape::sortEdges(std::list& edges, bool keepOrder, double tol) +std::deque TopoShape::sortEdges(std::list& edges, bool keepOrder, double tol) { - if (tol edge_points; - for (auto it = edges.begin(); it != edges.end(); ++it) + std::list edge_points; + for (auto it = edges.begin(); it != edges.end(); ++it) { edge_points.emplace_back(it, tol3d); + } std::deque sorted; - if (edge_points.empty()) + if (edge_points.empty()) { return sorted; + } - gp_Pnt first, last; + gp_Pnt first; + gp_Pnt last; first = edge_points.front().v1; - last = edge_points.front().v2; + last = edge_points.front().v2; - sorted.push_back(edge_points.front().edge); + sorted.push_back(*edge_points.front().edge); edges.erase(edge_points.front().it); - if (edge_points.front().closed) + if (edge_points.front().closed) { return sorted; + } edge_points.erase(edge_points.begin()); - auto reverseEdge = [](const TopoShape &edge) { - Standard_Real first, last; - const Handle(Geom_Curve) & curve = BRep_Tool::Curve(TopoDS::Edge(edge.getShape()), first, last); + auto reverseEdge = [](const TopoShape& edge) { + Standard_Real first = NAN; + Standard_Real last = NAN; + const Handle(Geom_Curve)& curve = + BRep_Tool::Curve(TopoDS::Edge(edge.getShape()), first, last); first = curve->ReversedParameter(first); last = curve->ReversedParameter(last); TopoShape res(BRepBuilderAPI_MakeEdge(curve->Reversed(), last, first)); auto edgeName = Data::IndexedName::fromConst("Edge", 1); - if (auto mapped = edge.getMappedName(edgeName)) - res.elementMap()->setElementName(edgeName, mapped, Tag); + if (auto mapped = edge.getMappedName(edgeName)) { + res.elementMap()->setElementName(edgeName, mapped, res.Tag); + } auto v1Name = Data::IndexedName::fromConst("Vertex", 1); auto v2Name = Data::IndexedName::fromConst("Vertex", 2); auto v1 = edge.getMappedName(v1Name); auto v2 = edge.getMappedName(v2Name); if (v1 && v2) { - res.elementMap()->setElementName(v1Name, v2, Tag); - res.elementMap()->setElementName(v2Name, v1, Tag); + res.elementMap()->setElementName(v1Name, v2, res.Tag); + res.elementMap()->setElementName(v2Name, v1, res.Tag); } else if (v1 && edge.countSubShapes(TopAbs_EDGE) == 1) { // It's possible an edge has only one vertex, so no need to reverse // the name - res.elementMap()->setElementName(v1Name, v1, Tag); + res.elementMap()->setElementName(v1Name, v1, res.Tag); + } + else if (v1) { + res.elementMap()->setElementName(v2Name, v1, res.Tag); + } + else if (v2) { + res.elementMap()->setElementName(v1Name, v2, res.Tag); } - else if (v1) - res.elementMap()->setElementName(v2Name, v1, Tag); - else if (v2) - res.elementMap()->setElementName(v1Name, v2, Tag); return res; }; @@ -732,8 +763,9 @@ TopoShape::sortEdges(std::list& edges, bool keepOrder, double tol) // search for adjacent edge std::list::iterator pEI; for (pEI = edge_points.begin(); pEI != edge_points.end(); ++pEI) { - if (pEI->closed) + if (pEI->closed) { continue; + } if (keepOrder && sorted.size() == 1) { if (pEI->v2.SquareDistance(first) <= tol3d @@ -745,31 +777,31 @@ TopoShape::sortEdges(std::list& edges, bool keepOrder, double tol) if (pEI->v1.SquareDistance(last) <= tol3d) { last = pEI->v2; - sorted.push_back(pEI->edge); + sorted.push_back(*pEI->edge); edges.erase(pEI->it); edge_points.erase(pEI); pEI = edge_points.begin(); break; } - else if (pEI->v2.SquareDistance(first) <= tol3d) { - sorted.push_front(pEI->edge); + if (pEI->v2.SquareDistance(first) <= tol3d) { + sorted.push_front(*pEI->edge); first = pEI->v1; edges.erase(pEI->it); edge_points.erase(pEI); pEI = edge_points.begin(); break; } - else if (pEI->v2.SquareDistance(last) <= tol3d) { + if (pEI->v2.SquareDistance(last) <= tol3d) { last = pEI->v1; - sorted.push_back(reverseEdge(pEI->edge)); + sorted.push_back(reverseEdge(*pEI->edge)); edges.erase(pEI->it); edge_points.erase(pEI); pEI = edge_points.begin(); break; } - else if (pEI->v1.SquareDistance(first) <= tol3d) { + if (pEI->v1.SquareDistance(first) <= tol3d) { first = pEI->v2; - sorted.push_front(reverseEdge(pEI->edge)); + sorted.push_front(reverseEdge(*pEI->edge)); edges.erase(pEI->it); edge_points.erase(pEI); pEI = edge_points.begin(); @@ -786,38 +818,44 @@ TopoShape::sortEdges(std::list& edges, bool keepOrder, double tol) return sorted; } -TopoShape &TopoShape::makeElementOrderedWires(const std::vector &shapes, - const char *op, - double tol, - TopoShapeMap *output) +TopoShape& TopoShape::makeElementOrderedWires(const std::vector& shapes, + const char* op, + double tol, + TopoShapeMap* output) { - if(!op) op = Part::OpCodes::Wire; - if(tol wires; - std::list edge_list; + std::list edgeList; auto shape = TopoShape().makeElementCompound(shapes, "", false); - for(auto &e : shape.getSubTopoShapes(TopAbs_EDGE)) - edge_list.push_back(e); + for (auto& edge : shape.getSubTopoShapes(TopAbs_EDGE)) { + edgeList.push_back(edge); + } - while(edge_list.size()) { + while (!edgeList.empty()) { BRepBuilderAPI_MakeWire mkWire; std::vector edges; - for (auto &edge : sortEdges(edge_list, true, tol)) { + for (auto& edge : sortEdges(edgeList, true, tol)) { edges.push_back(edge); mkWire.Add(TopoDS::Edge(edge.getShape())); // MakeWire will replace vertex of connected edge, which // effectively creat a new edge. So we need to update the shape // in order to preserve element mapping. edges.back().setShape(mkWire.Edge(), false); - if (output) + if (output) { (*output)[edges.back()] = edge; + } } - wires.push_back(mkWire.Wire()); - wires.back().mapSubElement(edges,op); + wires.emplace_back(mkWire.Wire()); + wires.back().mapSubElement(edges, op); } - return makeElementCompound(wires,0,false); + return makeElementCompound(wires, nullptr, false); } } // namespace Part