X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_SketchBuilder.cpp;h=4e894827d7f63d037da9748132f9784a6107f721;hb=32e205a228d74cdc2627143cb32360e9a557d7dc;hp=528227b61091094f5085a8ac436b569741cf3696;hpb=8dc74f82810d5f597b78633b457efb0ef4f89f9f;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp index 528227b61..4e894827d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp @@ -3,6 +3,7 @@ // Author: Artem ZHIDKOV #include +#include #include @@ -15,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -44,46 +44,47 @@ const double tolerance = Precision::Confusion(); const double shift = acos(1.0 - 3.0 * tolerance); /// \brief Search first vertex - the vertex with lowest x coordinate, which is used in 2 edges at least -static const TopoDS_Shape& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE, +static const TopoDS_Vertex& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE, const gp_Dir& theDirX, const gp_Dir& theDirY); /// \brief Search the vertex on the sketch candidate to be the next one in the loop -static void findNextVertex(const TopoDS_Shape& theStartVertex, +static void findNextVertex(const TopoDS_Vertex& theStartVertex, const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap, const gp_Dir& theStartDir, const gp_Dir& theNormal, - TopoDS_Shape& theNextVertex, TopoDS_Shape& theNextEdge, + TopoDS_Vertex& theNextVertex, TopoDS_Edge& theNextEdge, gp_Dir& theNextDir); /// \brief Create planar face using the edges surrounding it -static void createFace(const TopoDS_Shape& theStartVertex, - const std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfEdges, +static void createFace(const TopoDS_Vertex& theStartVertex, + const std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfEdges, const gp_Pln& thePlane, TopoDS_Face& theResFace); /// \bief Create planar wire -static void createWireList(const TopoDS_Shape& theStartVertex, - const std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfEdges, - const std::set& theEdgesInLoops, +static void createWireList(const TopoDS_Vertex& theStartVertex, + const std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfEdges, + const std::set& theEdgesInLoops, std::list& theResWires); /// \brief Calculate outer tengency on the edge in specified vertex -static gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge, const TopoDS_Shape& theVertex); +static gp_Dir getOuterEdgeDirection(const TopoDS_Edge& theEdge, const TopoDS_Vertex& theVertex); /// \brief Unnecessary edges will be removed from the map. /// Positions of iterator will be updated -static void removeWasteEdges(std::list::iterator& theStartVertex, - std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfVertexes, - const std::list::iterator& theEndOfEdges, +static void removeWasteEdges(std::list::iterator& theStartVertex, + std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfVertexes, + const std::list::iterator& theEndOfEdges, BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE); + void GeomAlgoAPI_SketchBuilder::createFaces( - const boost::shared_ptr& theOrigin, const boost::shared_ptr& theDirX, - const boost::shared_ptr& theDirY, const boost::shared_ptr& theNorm, - const std::list >& theFeatures, - std::list >& theResultFaces, - std::list >& theResultWires) + const std::shared_ptr& theOrigin, const std::shared_ptr& theDirX, + const std::shared_ptr& theDirY, const std::shared_ptr& theNorm, + const std::list >& theFeatures, + std::list >& theResultFaces, + std::list >& theResultWires) { if (theFeatures.empty()) return; @@ -94,10 +95,10 @@ void GeomAlgoAPI_SketchBuilder::createFaces( TopoDS_Shape aFeaturesCompound; // Obtain only edges from the features list - std::list > anEdges; - std::list >::const_iterator aFeatIt = theFeatures.begin(); + std::list > anEdges; + std::list >::const_iterator aFeatIt = theFeatures.begin(); for (; aFeatIt != theFeatures.end(); aFeatIt++) { - boost::shared_ptr aShape(*aFeatIt); + std::shared_ptr aShape(*aFeatIt); const TopoDS_Edge& anEdge = aShape->impl(); if (anEdge.ShapeType() == TopAbs_EDGE) anEdges.push_back(aShape); @@ -106,9 +107,9 @@ void GeomAlgoAPI_SketchBuilder::createFaces( if (anEdges.size() == 1) { // If there is only one feature, BOPAlgo_Builder will decline to work. Need to process it anyway aFeaturesCompound = anEdges.front()->impl(); } else { - std::list >::const_iterator anIt = anEdges.begin(); + std::list >::const_iterator anIt = anEdges.begin(); for (; anIt != anEdges.end(); anIt++) { - boost::shared_ptr aPreview(*anIt); + std::shared_ptr aPreview(*anIt); aBuilder.AddArgument(aPreview->impl()); } aPF.SetArguments(aBuilder.Arguments()); @@ -135,49 +136,55 @@ void GeomAlgoAPI_SketchBuilder::createFaces( gp_Pln aPlane(theOrigin->impl(), aNorm); // Set of edges used in loops - std::set anEdgesInLoops; + std::set anEdgesInLoops; // Lists for processed vertexes and edges - std::list aProcVertexes; - std::list aProcEdges; + std::list aProcVertexes; + std::list aProcEdges; // Search the start vertex - TopoDS_Shape aStartVertex = findStartVertex(aMapVE, aDirX, aDirY); + TopoDS_Vertex aStartVertex = findStartVertex(aMapVE, aDirX, aDirY); aProcVertexes.push_back(aStartVertex); - TopoDS_Shape aCurVertex = aStartVertex; + TopoDS_Vertex aCurVertex = aStartVertex; gp_Dir aCurDir = aDirY.Reversed(); gp_Dir aCurNorm = aNorm.Reversed(); // Go through the edges and find loops - TopoDS_Shape aNextVertex; - TopoDS_Shape aBindingEdge; + TopoDS_Vertex aNextVertex; + TopoDS_Edge aBindingEdge; gp_Dir aNextDir; while (aMapVE.Extent() > 0) { if (aCurVertex.IsNull()) return; + if (!aProcEdges.empty()) + aBindingEdge = aProcEdges.back(); findNextVertex(aCurVertex, aMapVE, aCurDir, aCurNorm, aNextVertex, aBindingEdge, aNextDir); aCurNorm = aNorm; // Try to find next vertex in the list of already processed - std::list::iterator aVertIter = aProcVertexes.begin(); - std::list::iterator anEdgeIter = aProcEdges.begin(); + bool isLoopFound = false; + std::list::iterator aVertIter = aProcVertexes.begin(); + std::list::iterator anEdgeIter = aProcEdges.begin(); for (; aVertIter != aProcVertexes.end(); aVertIter++) { - if (aVertIter->TShape() == aNextVertex.TShape()) + if (aVertIter->IsSame(aNextVertex)) { + isLoopFound = true; break; + } if (anEdgeIter != aProcEdges.end()) anEdgeIter++; } + bool isCircleFound = (isLoopFound && anEdgeIter == aProcEdges.end()); aProcVertexes.push_back(aNextVertex); aProcEdges.push_back(aBindingEdge); - // The loop was found - if (aVertIter != aProcVertexes.end()) { - // If the binding edge is a full circle, then the list may be empty before addition. Need to update edge iterator - if (aProcEdges.size() == 1) - anEdgeIter = aProcEdges.begin(); - - if (aVertIter != aProcVertexes.begin()) { + if (isLoopFound) { + // If the binding edge is a full circle, then it may be added recently. Need to update edge iterator + if (isCircleFound) { + anEdgeIter = aProcEdges.end(); + anEdgeIter--; + } + else if (aVertIter != aProcVertexes.begin()) { // Check the orientation of the loop gp_Dir aCN = getOuterEdgeDirection(*anEdgeIter, *aVertIter); gp_Dir aCP = getOuterEdgeDirection(aProcEdges.back(), *aVertIter); @@ -185,56 +192,106 @@ void GeomAlgoAPI_SketchBuilder::createFaces( aCP.Reverse(); if (aCN.DotCross(aCP, aNorm) < -tolerance) { // The found loop has wrong orientation and may contain sub-loops. - // Need to check it onle again with another initial direction. + // Need to check it once again with another initial direction. aCurVertex = *aVertIter; do { aProcVertexes.pop_back(); aProcEdges.pop_back(); } while (aCurVertex != aProcVertexes.back()); - aCurDir = getOuterEdgeDirection(aProcEdges.back(), aCurVertex); + aCurDir = aCN.Reversed(); aCurNorm = aNorm.Reversed(); continue; } } + if (!isCircleFound && anEdgeIter != aProcEdges.end() && + anEdgeIter->IsSame(aProcEdges.back())) { // The loop on the same edge taken twice + aProcVertexes.pop_back(); + aProcEdges.pop_back(); + aCurVertex = aProcVertexes.back(); + aCurDir = getOuterEdgeDirection(aProcEdges.back(), aCurVertex); + aCurNorm = aNorm.Reversed(); + continue; + } + // When the orientation is correct or the edges looped through // the first element, create new face and remove unnecessary edges. TopoDS_Face aPatch; createFace(*aVertIter, anEdgeIter, aProcEdges.end(), aPlane, aPatch); if (!aPatch.IsNull()) { - boost::shared_ptr aFace(new GeomAPI_Shape); + std::shared_ptr aFace(new GeomAPI_Shape); aFace->setImpl(new TopoDS_Face(aPatch)); theResultFaces.push_back(aFace); } // push the edges used in the loop to the map - std::list::iterator anIter; + std::list::iterator anIter; for (anIter = anEdgeIter; anIter != aProcEdges.end(); anIter++) - anEdgesInLoops.insert(anIter->TShape()); + anEdgesInLoops.insert(&(*anIter)); // remove unnecessary edges - std::list::iterator aCopyVLoop = aVertIter; - std::list::iterator aCopyELoop = anEdgeIter; + std::list::iterator aCopyVLoop = aVertIter; + std::list::iterator aCopyELoop = anEdgeIter; removeWasteEdges(aVertIter, anEdgeIter, aProcVertexes.end(), aProcEdges.end(), aMapVE); // revert the list of remaining edges - std::list aRemainVertexes; + std::list aRemainVertexes; for (; aVertIter != aProcVertexes.end(); aVertIter++) aRemainVertexes.push_front(*aVertIter); - std::list aRemainEdges; + std::list aRemainEdges; for (; anEdgeIter != aProcEdges.end(); anEdgeIter++) aRemainEdges.push_front(*anEdgeIter); // remove edges and vertexes used in the loop and add remaining ones + if (aCopyVLoop != aProcVertexes.begin()) { + aVertIter = aCopyVLoop; + aVertIter--; + } else + aVertIter = aProcVertexes.end(); aProcVertexes.erase(aCopyVLoop, aProcVertexes.end()); aProcVertexes.insert(aProcVertexes.end(), aRemainVertexes.begin(), aRemainVertexes.end()); + if (aCopyELoop != aProcEdges.begin()) { + anEdgeIter = aCopyELoop; + anEdgeIter--; + } else + anEdgeIter = aProcEdges.end(); aProcEdges.erase(aCopyELoop, aProcEdges.end()); aProcEdges.insert(aProcEdges.end(), aRemainEdges.begin(), aRemainEdges.end()); - // Recalculate current vertex and current direction - if (!aProcVertexes.empty()) { - aNextVertex = aProcVertexes.back(); - if (!aProcEdges.empty()) - aNextDir = getOuterEdgeDirection(aProcEdges.back(), aNextVertex); - else - aNextDir = aDirY; + if (aVertIter == aProcVertexes.end()) + aVertIter = aProcVertexes.begin(); + else + aVertIter++; + if (anEdgeIter == aProcEdges.end()) + anEdgeIter = aProcEdges.begin(); + else + anEdgeIter++; + aCopyVLoop = aVertIter; + aCopyELoop = anEdgeIter; + + if (aVertIter != aProcVertexes.end() && + aMapVE.Contains(*aVertIter) && aMapVE.FindFromKey(*aVertIter).Extent() <= 1) + removeWasteEdges(aVertIter, anEdgeIter, aProcVertexes.end(), aProcEdges.end(), aMapVE); + if (aCopyVLoop != aVertIter) + aProcVertexes.erase(aCopyVLoop, aVertIter); + if (aCopyELoop != anEdgeIter) + aProcEdges.erase(aCopyELoop, anEdgeIter); + + // Check whether the next vertex already exists + if (aVertIter != aProcVertexes.end()) + aVertIter++; + if (aVertIter != aProcVertexes.end() && anEdgeIter != aProcEdges.end()) { + aNextVertex = *aVertIter; + aNextDir = getOuterEdgeDirection(*anEdgeIter, aNextVertex); + aProcVertexes.erase(++aVertIter, aProcVertexes.end()); + aProcEdges.erase(++anEdgeIter, aProcEdges.end()); + } else { + // Recalculate current vertex and current direction + aProcEdges.clear(); + aProcVertexes.clear(); + if (aMapVE.Extent() > 0) { + aNextVertex = findStartVertex(aMapVE, aDirX, aDirY); + aProcVertexes.push_back(aNextVertex); + } + aNextDir = aDirY.Reversed(); + aCurNorm = aNorm.Reversed(); } } @@ -242,8 +299,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces( // we need to go back through the list of already checked edges to find a branching vertex if (!aMapVE.IsEmpty() && aMapVE.Contains(aNextVertex) && aMapVE.FindFromKey(aNextVertex).Size() == 1) { - std::list::reverse_iterator aVRIter = aProcVertexes.rbegin(); - std::list::reverse_iterator aERIter = aProcEdges.rbegin(); + std::list::reverse_iterator aVRIter = aProcVertexes.rbegin(); + std::list::reverse_iterator aERIter = aProcEdges.rbegin(); if (aVRIter != aProcVertexes.rend()) aVRIter++; if (aERIter != aProcEdges.rend()) @@ -254,8 +311,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces( break; if (aERIter != aProcEdges.rend() || (aVRIter != aProcVertexes.rend() && aMapVE.FindFromKey(*aVRIter).Size() == 1)) { // the branching vertex was found or current list of edges is a wire without branches - std::list::iterator aEIter; - TopoDS_Shape aCurEdge; + std::list::iterator aEIter; + TopoDS_Edge aCurEdge; if (aERIter != aProcEdges.rend()) { aEIter = aERIter.base(); aCurEdge = *aERIter; @@ -266,12 +323,12 @@ void GeomAlgoAPI_SketchBuilder::createFaces( std::list::const_iterator aTailIter = aTail.begin(); for (; aTailIter != aTail.end(); aTailIter++) if (!aTailIter->IsNull()) { - boost::shared_ptr aWire(new GeomAPI_Shape); + std::shared_ptr aWire(new GeomAPI_Shape); aWire->setImpl(new TopoDS_Shape(*aTailIter)); theResultWires.push_back(aWire); } - std::list::iterator aVIter = aVRIter.base(); - std::list::iterator aEItCopy = aEIter; + std::list::iterator aVIter = aVRIter.base(); + std::list::iterator aEItCopy = aEIter; removeWasteEdges(--aVIter, aEItCopy, aProcVertexes.end(), aProcEdges.end(), aMapVE); aProcEdges.erase(aEIter, aProcEdges.end()); @@ -299,7 +356,6 @@ void GeomAlgoAPI_SketchBuilder::createFaces( aProcVertexes.clear(); aProcEdges.clear(); - TopoDS_Shape aStartEdge; aStartVertex = findStartVertex(aMapVE, aDirX, aDirY); aProcVertexes.push_back(aStartVertex); aNextVertex = aStartVertex; @@ -315,13 +371,30 @@ void GeomAlgoAPI_SketchBuilder::createFaces( fixIntersections(theResultFaces); } +void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr& theOrigin, + const std::shared_ptr& theDirX, + const std::shared_ptr& theDirY, + const std::shared_ptr& theNorm, + const std::shared_ptr& theWire, + std::list >& theResultFaces) +{ + std::shared_ptr aWire = std::dynamic_pointer_cast(theWire); + if(!aWire) + return; + // Filter wires, return only faces. + std::list > aFilteredWires; + createFaces(theOrigin, theDirX, theDirY, theNorm, + aWire->getEdges(), theResultFaces, aFilteredWires); +} + + void GeomAlgoAPI_SketchBuilder::fixIntersections( - std::list >& theFaces) + std::list >& theFaces) { BRepClass_FaceClassifier aClassifier; - std::list >::iterator anIter1 = theFaces.begin(); - std::list >::iterator anIter2; + std::list >::iterator anIter1 = theFaces.begin(); + std::list >::iterator anIter2; for (; anIter1 != theFaces.end(); anIter1++) { anIter2 = anIter1; for (++anIter2; anIter2 != theFaces.end(); anIter2++) { @@ -329,9 +402,10 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( assert(aF1.ShapeType() == TopAbs_FACE); // all items in result list should be faces TopExp_Explorer aVert2((*anIter2)->impl(), TopAbs_VERTEX); for (; aVert2.More(); aVert2.Next()) { - Handle(BRep_TVertex) aV = Handle(BRep_TVertex)::DownCast(aVert2.Current().TShape()); - aClassifier.Perform(aF1, aV->Pnt(), tolerance); - if (aClassifier.State() != TopAbs_IN) + const TopoDS_Vertex& aV = (const TopoDS_Vertex&)aVert2.Current(); + aClassifier.Perform(aF1, BRep_Tool::Pnt(aV), tolerance); + TopAbs_State aState = aClassifier.State(); + if (aState != TopAbs_IN && aState != TopAbs_ON) break; } if (aVert2.More()) { // second shape is not inside first, change the shapes order and repeat comparision @@ -339,31 +413,44 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( assert(aF2.ShapeType() == TopAbs_FACE); // all items in result list should be faces TopExp_Explorer aVert1((*anIter1)->impl(), TopAbs_VERTEX); for (; aVert1.More(); aVert1.Next()) { - Handle(BRep_TVertex) aV = Handle(BRep_TVertex)::DownCast(aVert1.Current().TShape()); - aClassifier.Perform(aF2, aV->Pnt(), tolerance); - if (aClassifier.State() != TopAbs_IN) + const TopoDS_Vertex& aV = (const TopoDS_Vertex&)aVert2.Current(); + aClassifier.Perform(aF2, BRep_Tool::Pnt(aV), tolerance); + TopAbs_State aState = aClassifier.State(); + if (aState != TopAbs_IN && aState != TopAbs_ON) break; } if (!aVert1.More()) { // first shape should be cut from the second BRepAlgoAPI_Cut aCut((*anIter2)->impl(), (*anIter1)->impl()); aCut.Build(); TopExp_Explorer anExp(aCut.Shape(), TopAbs_FACE); - (*anIter2)->setImpl(new TopoDS_Shape(anExp.Current())); - for (anExp.Next(); anExp.More(); anExp.Next()) { - boost::shared_ptr aShape(new GeomAPI_Shape); - aShape->setImpl(new TopoDS_Shape(anExp.Current())); - theFaces.push_back(aShape); + bool isFirstFace = true; + for (; anExp.More(); anExp.Next()) { + if (anExp.Current().ShapeType() != TopAbs_FACE) continue; + if (isFirstFace) { + (*anIter2)->setImpl(new TopoDS_Shape(anExp.Current())); + isFirstFace = false; + } else { + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(anExp.Current())); + theFaces.push_back(aShape); + } } } } else { // second shape should be cut from the first BRepAlgoAPI_Cut aCut((*anIter1)->impl(), (*anIter2)->impl()); aCut.Build(); TopExp_Explorer anExp(aCut.Shape(), TopAbs_FACE); - (*anIter1)->setImpl(new TopoDS_Shape(anExp.Current())); - for (anExp.Next(); anExp.More(); anExp.Next()) { - boost::shared_ptr aShape(new GeomAPI_Shape); - aShape->setImpl(new TopoDS_Shape(anExp.Current())); - theFaces.push_back(aShape); + bool isFirstFace = true; + for (; anExp.More(); anExp.Next()) { + if (anExp.Current().ShapeType() != TopAbs_FACE) continue; + if (isFirstFace) { + (*anIter1)->setImpl(new TopoDS_Shape(anExp.Current())); + isFirstFace = false; + } else { + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(anExp.Current())); + theFaces.push_back(aShape); + } } } } @@ -371,7 +458,7 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections( } // =================== Auxiliary functions ==================================== -const TopoDS_Shape& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE, +const TopoDS_Vertex& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE, const gp_Dir& theDirX, const gp_Dir& theDirY) { int aStartVertexInd = 1; @@ -380,8 +467,7 @@ const TopoDS_Shape& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShap int aNbVert = theMapVE.Extent(); for (int i = 1; i <= aNbVert; i++) { const TopoDS_Vertex& aV = (const TopoDS_Vertex&) theMapVE.FindKey(i); - const Handle(BRep_TVertex)& aVert = (const Handle(BRep_TVertex)&) aV.TShape(); - const gp_Pnt& aVertPnt = aVert->Pnt(); + const gp_Pnt& aVertPnt = BRep_Tool::Pnt(aV); double aX = aVertPnt.XYZ().Dot(theDirX.XYZ()); double aY = aVertPnt.XYZ().Dot(theDirY.XYZ()); @@ -392,51 +478,66 @@ const TopoDS_Shape& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShap aStartVertexInd = i; } } - return theMapVE.FindKey(aStartVertexInd); + return static_cast(theMapVE.FindKey(aStartVertexInd)); } -void findNextVertex(const TopoDS_Shape& theStartVertex, +void findNextVertex(const TopoDS_Vertex& theStartVertex, const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap, - const gp_Dir& theStartDir, const gp_Dir& theNormal, TopoDS_Shape& theNextVertex, - TopoDS_Shape& theNextEdge, gp_Dir& theNextDir) + const gp_Dir& theStartDir, const gp_Dir& theNormal, TopoDS_Vertex& theNextVertex, + TopoDS_Edge& theNextEdge, gp_Dir& theNextDir) { + theNextVertex = TopoDS_Vertex(); const BOPCol_ListOfShape& anEdgesList = theVertexEdgeMap.FindFromKey(theStartVertex); + int anEdgesNum = anEdgesList.Extent(); BOPCol_ListOfShape::Iterator aEdIter(anEdgesList); double aBestEdgeProj = DBL_MAX; for (; aEdIter.More(); aEdIter.Next()) { - gp_Dir aTang = getOuterEdgeDirection(aEdIter.Value(), theStartVertex); + const TopoDS_Edge& anEdge = static_cast(aEdIter.Value()); + gp_Dir aTang = getOuterEdgeDirection(anEdge, theStartVertex); aTang.Reverse(); // The projection is normalized in segment (-1, 1), // where (-1, 0] corresponds to the angles (pi/2, 0] between theStartDir and aTang // and [0, 1) corresponds to the angles [0, -pi/2) double aProj = (aTang.Dot(theStartDir) - 1.0) * 0.5; - if (fabs(fabs(aProj) - 1) < tolerance) + if (anEdgesNum > 1 && fabs(fabs(aProj) - 1) < tolerance) continue; if (theStartDir.DotCross(aTang, theNormal) < tolerance) aProj *= -1.0; if (aProj < aBestEdgeProj) { aBestEdgeProj = aProj; - theNextEdge = aEdIter.Value(); + theNextEdge = anEdge; TopExp_Explorer aVertExp(theNextEdge, TopAbs_VERTEX); for (; aVertExp.More(); aVertExp.Next()) - if (aVertExp.Current().TShape() != theStartVertex.TShape()) { - theNextVertex = aVertExp.Current(); - theNextDir = getOuterEdgeDirection(aEdIter.Value(), theNextVertex); + if (!aVertExp.Current().IsSame(theStartVertex)) { + theNextVertex = static_cast(aVertExp.Current()); + theNextDir = getOuterEdgeDirection(anEdge, theNextVertex); break; } if (!aVertExp.More()) { // This edge is a full circle TopoDS_Vertex aV1, aV2; - TopExp::Vertices(*(const TopoDS_Edge*) (&theNextEdge), aV1, aV2); + TopExp::Vertices(theNextEdge, aV1, aV2); if (aV1.Orientation() == theStartVertex.Orientation()) theNextVertex = aV2; else theNextVertex = aV1; - theNextDir = getOuterEdgeDirection(aEdIter.Value(), theNextVertex); + theNextDir = getOuterEdgeDirection(anEdge, theNextVertex); } } } + + // Probably there are two tangent edges. We will take the edge differs from current one + if (theNextVertex.IsNull() && anEdgesNum == 2) { + BOPCol_ListOfShape::Iterator aEdIter(anEdgesList); + if (aEdIter.Value() == theNextEdge) + aEdIter.Next(); + theNextEdge = static_cast(aEdIter.Value()); + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(theNextEdge, aV1, aV2); + theNextVertex = theStartVertex.IsSame(aV1) ? aV2 : aV1; + theNextDir = getOuterEdgeDirection(theNextEdge, theNextVertex); + } } static void addEdgeToWire(const TopoDS_Edge& theEdge, const BRep_Builder& theBuilder, @@ -449,12 +550,12 @@ static void addEdgeToWire(const TopoDS_Edge& theEdge, const BRep_Builder& theBui TopExp_Explorer aVertExp(theEdge, TopAbs_VERTEX); for (; aVertExp.More(); aVertExp.Next()) { const TopoDS_Shape& aVertex = aVertExp.Current(); - if (aVertex.TShape() == theSpliceVertex.TShape() + if (aVertex.IsSame(theSpliceVertex) && aVertex.Orientation() != theEdge.Orientation()) { // Current vertex is the last for the edge, so its orientation is wrong, need to revert the edge anEdge.Reverse(); break; } - if (aVertex.TShape() != theSpliceVertex.TShape()) { + if (!aVertex.IsSame(theSpliceVertex)) { aCurVertChanged = aVertex; isCurVertChanged = true; } @@ -464,21 +565,21 @@ static void addEdgeToWire(const TopoDS_Edge& theEdge, const BRep_Builder& theBui theBuilder.Add(theWire, anEdge); } -void createFace(const TopoDS_Shape& theStartVertex, - const std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfEdges, const gp_Pln& thePlane, +void createFace(const TopoDS_Vertex& theStartVertex, + const std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfEdges, + const gp_Pln& thePlane, TopoDS_Face& theResFace) { TopoDS_Wire aResWire; BRep_Builder aBuilder; aBuilder.MakeWire(aResWire); - TopoDS_Shape aCurVertex = theStartVertex; - std::list::const_iterator anEdgeIter = theStartEdge; + TopoDS_Vertex aCurVertex = theStartVertex; + std::list::const_iterator anEdgeIter = theStartEdge; for (; anEdgeIter != theEndOfEdges; anEdgeIter++) { - TopoDS_Edge anEdge = *((TopoDS_Edge*) (&(*anEdgeIter))); - if (!anEdge.IsNull()) - addEdgeToWire(anEdge, aBuilder, aCurVertex, aResWire); + if (!anEdgeIter->IsNull()) + addEdgeToWire(*anEdgeIter, aBuilder, aCurVertex, aResWire); } BRepBuilderAPI_MakeFace aFaceBuilder(thePlane, aResWire); @@ -486,23 +587,23 @@ void createFace(const TopoDS_Shape& theStartVertex, theResFace = aFaceBuilder.Face(); } -void createWireList(const TopoDS_Shape& theStartVertex, - const std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfEdges, - const std::set& theEdgesInLoops, +void createWireList(const TopoDS_Vertex& theStartVertex, + const std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfEdges, + const std::set& theEdgesInLoops, std::list& theResWires) { BRep_Builder aBuilder; bool needNewWire = true; - TopoDS_Shape aCurVertex = theStartVertex; + TopoDS_Vertex aCurVertex = theStartVertex; - std::list::iterator anIter = theStartEdge; + std::list::iterator anIter = theStartEdge; while (anIter != theEndOfEdges) { - while (anIter != theEndOfEdges && needNewWire && theEdgesInLoops.count(anIter->TShape()) != 0) { + while (anIter != theEndOfEdges && needNewWire && theEdgesInLoops.count(&(*anIter)) != 0) { TopExp_Explorer aVertExp(*anIter, TopAbs_VERTEX); for (; aVertExp.More(); aVertExp.Next()) - if (aVertExp.Current().TShape() != aCurVertex.TShape()) { - aCurVertex = aVertExp.Current(); + if (!aVertExp.Current().IsSame(aCurVertex)) { + aCurVertex = static_cast(aVertExp.Current()); break; } anIter++; @@ -515,32 +616,25 @@ void createWireList(const TopoDS_Shape& theStartVertex, aBuilder.MakeWire(aWire); theResWires.push_back(aWire); needNewWire = false; - } else if (theEdgesInLoops.count(anIter->TShape()) != 0) { // There was found the edge already used in loop. - // Current wire should be released and new one should started + } else if (theEdgesInLoops.count(&(*anIter)) != 0) { // There was found the edge already used in loop. + // Current wire should be released and new one should started needNewWire = true; continue; } - TopoDS_Edge anEdge = *((TopoDS_Edge*) (&(*anIter))); - addEdgeToWire(anEdge, aBuilder, aCurVertex, theResWires.back()); + addEdgeToWire(*anIter, aBuilder, aCurVertex, theResWires.back()); anIter++; } } -gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge, const TopoDS_Shape& theVertex) +gp_Dir getOuterEdgeDirection(const TopoDS_Edge& theEdge, const TopoDS_Vertex& theVertex) { - const Handle(BRep_TVertex)& aVertex = (const Handle(BRep_TVertex)&) theVertex.TShape(); - gp_Pnt aVertexPnt = aVertex->Pnt(); - - const Handle(BRep_TEdge)& anEdge = (const Handle(BRep_TEdge)&) theEdge.TShape(); + gp_Pnt aVertexPnt = BRep_Tool::Pnt(theVertex); // Convert the edge to the curve to calculate the tangency. // There should be only one curve in the edge. - Handle(BRep_Curve3D) aEdCurve = - Handle(BRep_Curve3D)::DownCast(anEdge->Curves().First()); double aFirst, aLast; - aEdCurve->Range(aFirst, aLast); - Handle(Geom_Curve) aCurve = aEdCurve->Curve3D(); + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast); gp_Pnt aPnt; gp_Vec aTang; @@ -555,10 +649,10 @@ gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge, const TopoDS_Shape& th return gp_Dir(aTang); } -void removeWasteEdges(std::list::iterator& theStartVertex, - std::list::iterator& theStartEdge, - const std::list::iterator& theEndOfVertexes, - const std::list::iterator& theEndOfEdges, +void removeWasteEdges(std::list::iterator& theStartVertex, + std::list::iterator& theStartEdge, + const std::list::iterator& theEndOfVertexes, + const std::list::iterator& theEndOfEdges, BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE) { bool isVertStep = true; @@ -566,7 +660,7 @@ void removeWasteEdges(std::list::iterator& theStartVertex, BOPCol_ListOfShape& aBunch = theMapVE.ChangeFromKey(*theStartVertex); BOPCol_ListOfShape::Iterator anApprEdge(aBunch); for (; anApprEdge.More(); anApprEdge.Next()) - if (anApprEdge.Value() == *theStartEdge) + if (anApprEdge.Value().IsSame(*theStartEdge)) break; if (anApprEdge.More()) aBunch.Remove(anApprEdge);