From 1f0899ef3df5e0bcced58a0a44e9bd06fc36b43c Mon Sep 17 00:00:00 2001 From: WandererFan Date: Mon, 14 Nov 2016 17:03:32 -0500 Subject: [PATCH] Improve handling of duplicate edges in projection --- src/Mod/TechDraw/App/DrawProjectSplit.cpp | 108 +++++++++++++++++++++- src/Mod/TechDraw/App/DrawProjectSplit.h | 27 +++++- src/Mod/TechDraw/App/DrawUtil.cpp | 61 ++++++++++++ src/Mod/TechDraw/App/DrawUtil.h | 7 ++ src/Mod/TechDraw/App/DrawViewPart.cpp | 6 +- src/Mod/TechDraw/App/EdgeWalker.cpp | 35 +++++-- src/Mod/TechDraw/App/EdgeWalker.h | 5 +- 7 files changed, 233 insertions(+), 16 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawProjectSplit.cpp b/src/Mod/TechDraw/App/DrawProjectSplit.cpp index 1a3954ca5..addb679d5 100644 --- a/src/Mod/TechDraw/App/DrawProjectSplit.cpp +++ b/src/Mod/TechDraw/App/DrawProjectSplit.cpp @@ -124,8 +124,8 @@ std::vector DrawProjectSplit::getEdgesForWalker(TopoDS_Shape shape, TechDrawGeometry::GeometryObject* DrawProjectSplit::buildGeometryObject( - TopoDS_Shape shape, - gp_Pnt& inputCenter, + TopoDS_Shape shape, + gp_Pnt& inputCenter, Base::Vector3d direction) { TechDrawGeometry::GeometryObject* geometryObject = new TechDrawGeometry::GeometryObject("DrawProjectSplit"); @@ -156,7 +156,7 @@ std::vector DrawProjectSplit::getEdges(TechDrawGeometry::GeometryOb if (!DrawUtil::isZeroEdge(e)) { nonZero.push_back(e); } else { - Base::Console().Message("INFO - DPS::extractFaces found ZeroEdge!\n"); + Base::Console().Message("INFO - DPS::getEdges found ZeroEdge!\n"); } } faceEdges = nonZero; @@ -230,6 +230,8 @@ std::vector DrawProjectSplit::getEdges(TechDrawGeometry::GeometryOb if (newEdges.empty()) { Base::Console().Log("LOG - DPS::extractFaces - no newEdges\n"); } + newEdges = removeDuplicateEdges(newEdges); + return newEdges; } @@ -426,3 +428,103 @@ std::vector DrawProjectSplit::sortSplits(std::vector& s, } +std::vector DrawProjectSplit::removeDuplicateEdges(std::vector& inEdges) +{ + std::vector result; + std::vector temp; + + unsigned int idx = 0; + for (auto& e: inEdges) { + edgeSortItem item; + TopoDS_Vertex v1 = TopExp::FirstVertex(e); + TopoDS_Vertex v2 = TopExp::LastVertex(e); + item.start = DrawUtil::vertex2Vector(v1); + item.end = DrawUtil::vertex2Vector(v2); + item.startAngle = DrawUtil::angleWithX(e,v1); + item.endAngle = DrawUtil::angleWithX(e,v2); + //catch reverse-duplicates + if (DrawUtil::vectorCompare(item.start,item.end) > 0) { + Base::Vector3d vTemp = item.start; + item.start = item.end; + item.end = vTemp; + double aTemp = item.startAngle; + item.startAngle = item.endAngle; + item.endAngle = aTemp; + } + item.idx = idx; + temp.push_back(item); + idx++; + } + + std::vector sorted = sortEdges(temp,true); + auto last = std::unique(sorted.begin(), sorted.end(), edgeSortItem::edgeEqual); //duplicates to back + sorted.erase(last, sorted.end()); //remove dupls + + for (auto& e: sorted) { + result.push_back(inEdges.at(e.idx)); + } + + return result; +} + +std::vector DrawProjectSplit::sortEdges(std::vector& e, bool ascend) +{ + std::vector sorted = e; + std::sort(sorted.begin(), sorted.end(), edgeSortItem::edgeCompare); + if (ascend) { + std::reverse(sorted.begin(),sorted.end()); + } + return sorted; +} + + +//************************* +//* edgeSortItem Methods +//************************* +std::string edgeSortItem::dump(void) +{ + std::string result; + std::stringstream builder; + builder << "edgeSortItem - s: " << DrawUtil::formatVector(start) << " e: " << DrawUtil::formatVector(end) << + " sa: " << startAngle * 180.0/M_PI << " ea: " << endAngle* 180.0/M_PI << " idx: " << idx; + result = builder.str(); + return result; +} + + +//true if "e1 < e2" - for sorting +/*static*/bool edgeSortItem::edgeCompare(const edgeSortItem& e1, const edgeSortItem& e2) +{ + bool result = false; + int vCompare = DrawUtil::vectorCompare(e1.start, e2.start); + if ( vCompare == -1) { + result = true; + } else if (vCompare == 0) { + if (e1.startAngle < e2.startAngle) { + result = true; + } else if (DrawUtil::fpCompare(e1.startAngle, e2.startAngle)) { + if (e1.endAngle < e2.startAngle) { + result = true; + } else if (DrawUtil::fpCompare(e1.endAngle, e2.endAngle)) { + if (e1.idx < e2.idx) { + result = true; + } + } + } + } + return result; +} + +//true if "e1 = e2" - for sorting/unique test +/*static*/bool edgeSortItem::edgeEqual(const edgeSortItem& e1, const edgeSortItem& e2) +{ + bool result = false; + if ( (e1.start == e2.start) && + (e1.end == e2.end) && + (DrawUtil::fpCompare(e1.startAngle,e2.startAngle)) && + (DrawUtil::fpCompare(e1.endAngle,e2.endAngle)) ) { + result = true; + } + return result; +} +// diff --git a/src/Mod/TechDraw/App/DrawProjectSplit.h b/src/Mod/TechDraw/App/DrawProjectSplit.h index d9e708e8d..07165129d 100644 --- a/src/Mod/TechDraw/App/DrawProjectSplit.h +++ b/src/Mod/TechDraw/App/DrawProjectSplit.h @@ -46,12 +46,31 @@ class BaseGeom; namespace TechDraw { -struct splitPoint { +struct splitPoint +{ int i; Base::Vector3d v; double param; }; +class edgeSortItem +{ +public: + edgeSortItem() {} + ~edgeSortItem() {} + + Base::Vector3d start; + Base::Vector3d end; + double startAngle; + double endAngle; + unsigned int idx; + + static bool edgeCompare(const edgeSortItem& e1, const edgeSortItem& e2); + static bool edgeEqual(const edgeSortItem& e1, const edgeSortItem& e2); + std::string dump(void); +}; + + class TechDrawExport DrawProjectSplit { public: @@ -65,12 +84,16 @@ public: static bool isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds = false); static std::vector splitEdges(std::vector orig, std::vector splits); static std::vector split1Edge(TopoDS_Edge e, std::vector splitPoints); - static double simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2); //const; //probably sb static or DrawUtil + static double simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2); static std::vector sortSplits(std::vector& s, bool ascend); static bool splitCompare(const splitPoint& p1, const splitPoint& p2); static bool splitEqual(const splitPoint& p1, const splitPoint& p2); + static std::vector removeDuplicateEdges(std::vector& inEdges); + static std::vector sortEdges(std::vector& e, bool ascend); + + protected: static std::vector getEdges(TechDrawGeometry::GeometryObject* geometryObject); diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index ddaf4c311..d10f518bd 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -27,6 +27,7 @@ # include # include # include +#include # include # include # include @@ -155,6 +156,10 @@ double DrawUtil::angleWithX(TopoDS_Edge e, bool reverse) u = end - start; } result = atan2(u.y,u.x); + if (result < 0) { + result += 2.0 * M_PI; + } + return result; } @@ -200,6 +205,9 @@ double DrawUtil::angleWithX(TopoDS_Edge e, TopoDS_Vertex v) } } result = atan2(uVec.y,uVec.x); + if (result < 0) { //map from [-PI:PI] to [0:2PI] + result += 2.0 * M_PI; + } return result; } @@ -224,6 +232,59 @@ bool DrawUtil::isLastVert(TopoDS_Edge e, TopoDS_Vertex v) return result; } +bool DrawUtil::fpCompare(const double& d1, const double& d2) +{ + bool result = false; + if (std::fabs(d1 - d2) < FLT_EPSILON) { + result = true; + } + return result; +} + +Base::Vector3d DrawUtil::vertex2Vector(const TopoDS_Vertex& v) +{ + gp_Pnt gp = BRep_Tool::Pnt(v); + Base::Vector3d result(gp.X(),gp.Y(),gp.Z()); + return result; +} + +std::string DrawUtil::formatVector(const Base::Vector3d& v) +{ + std::string result; + std::stringstream builder; + builder << " (" << v.x << "," << v.y << "," << v.z << ") "; + result = builder.str(); + return result; +} + +//! compare 2 vectors for sorting purposes ( -1 -> v1 v1 == v2, 1 -> v1 > v2) +int DrawUtil::vectorCompare(const Base::Vector3d& v1, const Base::Vector3d& v2) +{ + int result = 0; + if (v1 == v2) { + return result; + } + + if (v1.x < v2.x) { + result = -1; + } else if (DrawUtil::fpCompare(v1.x, v2.x)) { + if (v1.y < v2.y) { + result = -1; + } else if (DrawUtil::fpCompare(v1.y, v2.y)) { + if (v1.z < v2.z) { + result = -1; + } else { + result = 1; + } + } else { + result = 1; //v2y > v1y + } + } else { + result = 1; //v1x > v2x + } + return result; +} + //based on Function provided by Joe Dowsett, 2014 double DrawUtil::sensibleScale(double working_scale) diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 328b3244f..4500ecdd9 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -34,6 +34,8 @@ #include #include +#include + namespace TechDraw { @@ -50,6 +52,11 @@ class TechDrawExport DrawUtil { static double angleWithX(TopoDS_Edge e, TopoDS_Vertex v); static bool isFirstVert(TopoDS_Edge e, TopoDS_Vertex v); static bool isLastVert(TopoDS_Edge e, TopoDS_Vertex v); + static bool fpCompare(const double& d1, const double& d2); + static Base::Vector3d vertex2Vector(const TopoDS_Vertex& v); + static std::string formatVector(const Base::Vector3d& v); + static int vectorCompare(const Base::Vector3d& v1, const Base::Vector3d& v2); + //debugging routines static void dumpVertexes(const char* text, const TopoDS_Shape& s); diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index a0c40796d..08b099fa6 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -266,7 +266,7 @@ TechDrawGeometry::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape void DrawViewPart::extractFaces() { geometryObject->clearFaceGeom(); - const std::vector& goEdges = + const std::vector& goEdges = geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue()); std::vector::const_iterator itEdge = goEdges.begin(); std::vector origEdges; @@ -349,7 +349,7 @@ void DrawViewPart::extractFaces() std::vector sorted = DrawProjectSplit::sortSplits(splits,true); auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back - sorted.erase(last, sorted.end()); //remove dupls + sorted.erase(last, sorted.end()); //remove dupl splits std::vector newEdges = DrawProjectSplit::splitEdges(faceEdges,sorted); if (newEdges.empty()) { @@ -357,6 +357,8 @@ void DrawViewPart::extractFaces() return; } + newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges); + //find all the wires in the pile of faceEdges EdgeWalker ew; ew.loadEdges(newEdges); diff --git a/src/Mod/TechDraw/App/EdgeWalker.cpp b/src/Mod/TechDraw/App/EdgeWalker.cpp index 7a4a65acc..d6336fbb7 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.cpp +++ b/src/Mod/TechDraw/App/EdgeWalker.cpp @@ -536,6 +536,14 @@ bool WalkerEdge::isEqual(WalkerEdge w) return (i.idx < j.idx); } +std::string WalkerEdge::dump(void) +{ + std::string result; + std::stringstream builder; + builder << "WalkerEdge - v1: " << v1 << " v2: " << v2 << " idx: " << idx << " ed: " << ed; + result = builder.str(); + return result; +} //***************************************** // ewWire Methods @@ -615,24 +623,37 @@ std::string embedItem::dump(void) std::stringstream builder; builder << "embedItem - vertex: " << iVertex << " incidenceList: "; for (auto& ii : incidenceList) { - builder << "e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/M_PI)) << "/ed: " << ii.eDesc; + builder << " e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/M_PI)) << "/ed:" << ii.eDesc; } result = builder.str(); return result; } -/*static*/ bool embedItem::iiCompare(incidenceItem i1, incidenceItem i2) -{ - return (i1.angle > i2.angle); -} - std::vector embedItem::sortIncidenceList (std::vector &list, bool ascend) { //Base::Console().Message("TRACE - eI::sortIncidenceList()\n"); std::vector< incidenceItem > tempList = list; - std::sort(tempList.begin(), tempList.end(), embedItem::iiCompare); + std::sort(tempList.begin(), tempList.end(), incidenceItem::iiCompare); if (ascend) { std::reverse(tempList.begin(),tempList.end()); } return tempList; } + +//************************************* +//* incidenceItem Methods +//************************************* + +/*static*/ bool incidenceItem::iiCompare(const incidenceItem& i1, const incidenceItem& i2) +{ + return (i1.angle > i2.angle); +} + +/*static*/bool incidenceItem::iiEqual(const incidenceItem& i1, const incidenceItem& i2) +{ + //TODO: this should compare edges also but eDesc comparision is by address + bool result = false; + if (i1.angle == i2.angle) { + } + return result; +} diff --git a/src/Mod/TechDraw/App/EdgeWalker.h b/src/Mod/TechDraw/App/EdgeWalker.h index 4fae0a2b0..2eeb49333 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.h +++ b/src/Mod/TechDraw/App/EdgeWalker.h @@ -79,6 +79,7 @@ class WalkerEdge public: static bool weCompare(WalkerEdge i, WalkerEdge j); bool isEqual(WalkerEdge w); + std::string dump(void); std::size_t v1; std::size_t v2; @@ -131,7 +132,8 @@ public: incidenceItem() {} incidenceItem(int idx, double a, edge_t ed) {iEdge = idx; angle = a; eDesc = ed;} ~incidenceItem() {} - + static bool iiCompare(const incidenceItem& i1, const incidenceItem& i2); + static bool iiEqual(const incidenceItem& i1, const incidenceItem& i2); int iEdge; double angle; edge_t eDesc; @@ -149,7 +151,6 @@ public: std::vector incidenceList; std::string dump(void); static std::vector sortIncidenceList (std::vector &list, bool ascend); - static bool iiCompare(incidenceItem i1, incidenceItem i2); };