diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index 36abdee5b4..2986c7fd00 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,10 @@ #include #include #include +#include +#include + +#include #include "modelRefine.h" using namespace ModelRefine; @@ -51,7 +56,6 @@ struct EdgePoints { gp_Pnt v1, v2; TopoDS_Edge edge; }; - static std::list sort_Edges(double tol3d, const std::vector& edges) { tol3d = tol3d * tol3d; @@ -119,14 +123,14 @@ static std::list sort_Edges(double tol3d, const std::vector &edges) +void ModelRefine::getFaceEdges(const TopoDS_Face &face, EdgeVectorType &edges) { TopExp_Explorer it; for (it.Init(face, TopAbs_EDGE); it.More(); it.Next()) edges.push_back(TopoDS::Edge(it.Current())); } -bool ModelRefine::hasSharedEdges(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo) +bool ModelRefine::hasSharedEdges(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) { std::vector faceOneEdges, faceTwoEdges; getFaceEdges(faceOne, faceOneEdges); @@ -144,15 +148,15 @@ bool ModelRefine::hasSharedEdges(const TopoDS_Shape &faceOne, const TopoDS_Shape return false; } -TopoDS_Wire ModelRefine::facesBoundary(const FaceVectorType &faces) +void ModelRefine::boundaryEdges(const FaceVectorType &faces, EdgeVectorType &edgesOut) { - //this finds the perimeter of equal, adjacent faces. + //this finds all the boundary edges. Maybe more than one boundary. std::list edges; FaceVectorType::const_iterator faceIt; for (faceIt = faces.begin(); faceIt != faces.end(); ++faceIt) { - std::vector faceEdges; - std::vector::iterator faceEdgesIt; + EdgeVectorType faceEdges; + EdgeVectorType::iterator faceEdgesIt; getFaceEdges(*faceIt, faceEdges); for (faceEdgesIt = faceEdges.begin(); faceEdgesIt != faceEdges.end(); ++faceEdgesIt) { @@ -172,20 +176,8 @@ TopoDS_Wire ModelRefine::facesBoundary(const FaceVectorType &faces) } } - //put into vector for stolen function. - std::vector edgeVector; - edgeVector.reserve(edges.size()); - std::copy(edges.begin(), edges.end(), back_inserter(edgeVector)); - - std::list edgeSorted; - edgeSorted = sort_Edges(Precision::Confusion(), edgeVector); - - BRepLib_MakeWire wireMaker; - std::list::iterator sortedIt; - for (sortedIt = edgeSorted.begin(); sortedIt != edgeSorted.end(); ++sortedIt) - wireMaker.Add(*sortedIt); - - return wireMaker.Wire(); + edgesOut.reserve(edges.size()); + std::copy(edges.begin(), edges.end(), back_inserter(edgesOut)); } TopoDS_Shell ModelRefine::removeFaces(const TopoDS_Shell &shell, const FaceVectorType &faces) @@ -197,6 +189,66 @@ TopoDS_Shell ModelRefine::removeFaces(const TopoDS_Shell &shell, const FaceVecto return TopoDS::Shell(rebuilder.Apply(shell)); } +bool ModelRefine::areEdgesConnected(const TopoDS_Edge &edgeOne, const TopoDS_Edge &edgeTwo) +{ + TopoDS_Vertex e1v1, e1v2, e2v1, e2v2; + ShapeAnalysis_Edge analysis; + e1v1 = analysis.FirstVertex(edgeOne); + e1v2 = analysis.LastVertex(edgeOne); + e2v1 = analysis.FirstVertex(edgeTwo); + e2v2 = analysis.LastVertex(edgeTwo); + + return e1v1.IsSame(e2v1) || e1v1.IsSame(e2v2) || e1v2.IsSame(e2v1) || e1v2.IsSame(e2v2); +} + +void BoundaryEdgeSplitter::split(const EdgeVectorType &edgesIn) +{ + EdgeVectorType::const_iterator workIt; + for (workIt = edgesIn.begin(); workIt != edgesIn.end(); ++workIt) + { + TopoDS_Edge current = *workIt; + + if (isProcessed(current)) + continue; + + EdgeVectorType temp; + temp.reserve(edgesIn.size() + 1); + temp.push_back(current); + //recursive call + splitRecursive(temp, edgesIn); + groupedEdges.push_back(temp); + } +} + +void BoundaryEdgeSplitter::splitRecursive(EdgeVectorType &tempEdges, const EdgeVectorType &workEdges) +{ + EdgeVectorType::iterator tempIt; + EdgeVectorType::const_iterator workIt; + for (tempIt = tempEdges.begin(); tempIt != tempEdges.end(); ++tempIt) + { + for (workIt = workEdges.begin(); workIt != workEdges.end(); ++workIt) + { + if ((*tempIt).IsSame(*workIt)) + continue; + if (isProcessed(*workIt)) + continue; + if (areEdgesConnected(*tempIt, *workIt)) + { + tempEdges.push_back(*workIt); + processed.push_back(*workIt); + splitRecursive(tempEdges, workEdges); + } + } + } +} + +bool BoundaryEdgeSplitter::isProcessed(const TopoDS_Edge &edge) +{ + if (std::find(processed.begin(), processed.end(), edge) == processed.end()) + return false; + return true; +} + //////////////////////////////////////////////////////////////////////////////////////////// void FaceTypeSplitter::addShell(const TopoDS_Shell &shellIn) @@ -219,20 +271,22 @@ void FaceTypeSplitter::split() TopExp_Explorer shellIt; for (shellIt.Init(shell, TopAbs_FACE); shellIt.More(); shellIt.Next()) { - GeomAbs_SurfaceType currentType = FaceTypedBase::getFaceType(shellIt.Current()); + TopoDS_Face tempFace(TopoDS::Face(shellIt.Current())); + GeomAbs_SurfaceType currentType = FaceTypedBase::getFaceType(tempFace); SplitMapType::iterator mapIt = typeMap.find(currentType); if (mapIt == typeMap.end()) continue; - (*mapIt).second.push_back(TopoDS::Face(shellIt.Current())); + (*mapIt).second.push_back(tempFace); } } -FaceVectorType FaceTypeSplitter::getTypedFaceVector(const GeomAbs_SurfaceType &type) const +const FaceVectorType& FaceTypeSplitter::getTypedFaceVector(const GeomAbs_SurfaceType &type) const { if (this->hasType(type)) return (*(typeMap.find(type))).second; //error here. - return FaceVectorType(); + static FaceVectorType error; + return error; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -338,9 +392,9 @@ void FaceEqualitySplitter::split(const FaceVectorType &faces, FaceTypedBase *obj ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -GeomAbs_SurfaceType FaceTypedBase::getFaceType(TopoDS_Shape faceIn) +GeomAbs_SurfaceType FaceTypedBase::getFaceType(const TopoDS_Face &faceIn) { - Handle(Geom_Surface) surface = BRep_Tool::Surface(TopoDS::Face(faceIn)); + Handle(Geom_Surface) surface = BRep_Tool::Surface(faceIn); GeomAdaptor_Surface surfaceTest(surface); return surfaceTest.GetType(); } @@ -351,10 +405,10 @@ FaceTypedPlane::FaceTypedPlane() : FaceTypedBase(GeomAbs_Plane) { } -bool FaceTypedPlane::isEqual(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo) const +bool FaceTypedPlane::isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const { - Handle(Geom_Plane) planeSurfaceOne = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(TopoDS::Face(faceOne))); - Handle(Geom_Plane) planeSurfaceTwo = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(TopoDS::Face(faceTwo))); + Handle(Geom_Plane) planeSurfaceOne = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(faceOne)); + Handle(Geom_Plane) planeSurfaceTwo = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(faceTwo)); if (planeSurfaceOne.IsNull() || planeSurfaceTwo.IsNull()) return false;//error? gp_Pln planeOne(planeSurfaceOne->Pln()); @@ -370,8 +424,67 @@ GeomAbs_SurfaceType FaceTypedPlane::getType() const TopoDS_Face FaceTypedPlane::buildFace(const FaceVectorType &faces) const { - TopoDS_Wire newWire = ModelRefine::facesBoundary(faces); - return BRepBuilderAPI_MakeFace(newWire); + EdgeVectorType bEdges; + boundaryEdges(faces, bEdges); + + BoundaryEdgeSplitter bSplitter; + bSplitter.split(bEdges); + + + //parallel vectors. Topo* doesn't have less than. map wouldn't work. + FaceVectorType facesParallel; + std::vector wiresParallel; + + std::vector splitEdges = bSplitter.getGroupedEdges(); + std::vector::iterator splitIt; + for (splitIt = splitEdges.begin(); splitIt != splitEdges.end(); ++splitIt) + { + std::list sortedEdges; + sortedEdges = sort_Edges(Precision::Confusion(), *splitIt); + + BRepLib_MakeWire wireMaker; + std::list::iterator sortedIt; + for (sortedIt = sortedEdges.begin(); sortedIt != sortedEdges.end(); ++sortedIt) + wireMaker.Add(*sortedIt); + TopoDS_Wire currentWire = wireMaker.Wire(); + + TopoDS_Face currentFace = BRepBuilderAPI_MakeFace(currentWire, Standard_True); + + facesParallel.push_back(currentFace); + wiresParallel.push_back(currentWire); + } + if (facesParallel.size() < 1)//shouldn't be here. + return BRepBuilderAPI_MakeFace();//will cause exception. + if (facesParallel.size() == 1) + return (facesParallel.front()); + + TopoDS_Face current; + current = facesParallel.at(0); + //now we have more than one wire. + //there has to be a better way to determin which face is inside other + //without have to build all the faces. + for(size_t index(1); indexD0(0.5, 0.5, point); + BRepClass_FaceClassifier faceTest(current, point, Precision::Confusion()); + if (faceTest.State() == TopAbs_EXTERNAL) + current = facesParallel.at(index); + } + + ShapeFix_Face faceFix(current); + for (size_t index(0); indexCylinder(); diff --git a/src/Mod/Part/App/modelRefine.h b/src/Mod/Part/App/modelRefine.h index f93ca27674..56da2493a4 100644 --- a/src/Mod/Part/App/modelRefine.h +++ b/src/Mod/Part/App/modelRefine.h @@ -27,37 +27,36 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include namespace ModelRefine { typedef std::vector FaceVectorType; + typedef std::vector EdgeVectorType; - void getFaceEdges(TopoDS_Shape face, std::vector &edges); - bool hasSharedEdges(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo); - TopoDS_Wire facesBoundary(const FaceVectorType &faces); + void getFaceEdges(const TopoDS_Face &face, EdgeVectorType &edges); + bool hasSharedEdges(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo); + void boundaryEdges(const FaceVectorType &faces, EdgeVectorType &edgesOut); TopoDS_Shell removeFaces(const TopoDS_Shell &shell, const FaceVectorType &faces); + bool areEdgesConnected(const TopoDS_Edge &edgeOne, const TopoDS_Edge &edgeTwo); class FaceTypedBase { private: FaceTypedBase(){} protected: - FaceTypedBase(GeomAbs_SurfaceType typeIn){surfaceType = typeIn;} + FaceTypedBase(const GeomAbs_SurfaceType &typeIn){surfaceType = typeIn;} public: - virtual bool isEqual(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo) const = 0; + virtual bool isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const = 0; virtual GeomAbs_SurfaceType getType() const = 0; virtual TopoDS_Face buildFace(const FaceVectorType &faces) const = 0; - static GeomAbs_SurfaceType getFaceType(TopoDS_Shape faceIn); + static GeomAbs_SurfaceType getFaceType(const TopoDS_Face &faceIn); protected: GeomAbs_SurfaceType surfaceType; @@ -68,7 +67,7 @@ namespace ModelRefine private: FaceTypedPlane(); public: - virtual bool isEqual(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo) const; + virtual bool isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const; virtual GeomAbs_SurfaceType getType() const; virtual TopoDS_Face buildFace(const FaceVectorType &faces) const; friend FaceTypedPlane& getPlaneObject(); @@ -80,7 +79,7 @@ namespace ModelRefine private: FaceTypedCylinder(); public: - virtual bool isEqual(const TopoDS_Shape &faceOne, const TopoDS_Shape &faceTwo) const; + virtual bool isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const; virtual GeomAbs_SurfaceType getType() const; virtual TopoDS_Face buildFace(const FaceVectorType &faces) const; friend FaceTypedCylinder& getCylinderObject(); @@ -96,7 +95,7 @@ namespace ModelRefine void registerType(const GeomAbs_SurfaceType &type); bool hasType(const GeomAbs_SurfaceType &type) const; void split(); - FaceVectorType getTypedFaceVector(const GeomAbs_SurfaceType &type) const; + const FaceVectorType& getTypedFaceVector(const GeomAbs_SurfaceType &type) const; private: SplitMapType typeMap; TopoDS_Shell shell; @@ -108,7 +107,7 @@ namespace ModelRefine FaceAdjacencySplitter(){} void split(const FaceVectorType &facesIn); int getGroupCount() const {return adjacencyArray.size();} - FaceVectorType getGroup(const std::size_t &index) const {return adjacencyArray[index];} + const FaceVectorType& getGroup(const std::size_t &index) const {return adjacencyArray[index];} private: bool hasBeenMapped(const TopoDS_Face &shape); @@ -122,11 +121,25 @@ namespace ModelRefine FaceEqualitySplitter(){} void split(const FaceVectorType &faces, FaceTypedBase *object); int getGroupCount() const {return equalityVector.size();} - FaceVectorType getGroup(const std::size_t &index) const {return equalityVector[index];} + const FaceVectorType& getGroup(const std::size_t &index) const {return equalityVector[index];} private: std::vector equalityVector; - }; + }; + + class BoundaryEdgeSplitter + { + public: + BoundaryEdgeSplitter(){} + void split(const EdgeVectorType &edgesIn); + const std::vector& getGroupedEdges(){return groupedEdges;} + + private: + void splitRecursive(EdgeVectorType &tempEdges, const EdgeVectorType &workEdges); + bool isProcessed(const TopoDS_Edge &edge); + EdgeVectorType processed; + std::vector groupedEdges; + }; class FaceUniter {