Salome HOME
This is an improvement to use one AND filter in the viewer context. It serves to...
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_SketchBuilder.cpp
index ed3bf8fec901edecef4e221c3a9f8b6c55a4a515..4e894827d7f63d037da9748132f9784a6107f721 100644 (file)
@@ -3,6 +3,7 @@
 // Author:      Artem ZHIDKOV
 
 #include <GeomAlgoAPI_SketchBuilder.h>
+#include <GeomAPI_PlanarEdges.h>
 
 #include <set>
 
@@ -79,11 +80,11 @@ static void removeWasteEdges(std::list<TopoDS_Vertex>::iterator& theStartVertex,
 
 
 void GeomAlgoAPI_SketchBuilder::createFaces(
-    const boost::shared_ptr<GeomAPI_Pnt>& theOrigin, const boost::shared_ptr<GeomAPI_Dir>& theDirX,
-    const boost::shared_ptr<GeomAPI_Dir>& theDirY, const boost::shared_ptr<GeomAPI_Dir>& theNorm,
-    const std::list<boost::shared_ptr<GeomAPI_Shape> >& theFeatures,
-    std::list<boost::shared_ptr<GeomAPI_Shape> >& theResultFaces,
-    std::list<boost::shared_ptr<GeomAPI_Shape> >& theResultWires)
+    const std::shared_ptr<GeomAPI_Pnt>& theOrigin, const std::shared_ptr<GeomAPI_Dir>& theDirX,
+    const std::shared_ptr<GeomAPI_Dir>& theDirY, const std::shared_ptr<GeomAPI_Dir>& theNorm,
+    const std::list<std::shared_ptr<GeomAPI_Shape> >& theFeatures,
+    std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces,
+    std::list<std::shared_ptr<GeomAPI_Shape> >& 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<boost::shared_ptr<GeomAPI_Shape> > anEdges;
-  std::list<boost::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
+  std::list<std::shared_ptr<GeomAPI_Shape> > anEdges;
+  std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
   for (; aFeatIt != theFeatures.end(); aFeatIt++) {
-    boost::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
+    std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
     const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
     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<TopoDS_Shape>();
   } else {
-    std::list<boost::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = anEdges.begin();
+    std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = anEdges.begin();
     for (; anIt != anEdges.end(); anIt++) {
-      boost::shared_ptr<GeomAPI_Shape> aPreview(*anIt);
+      std::shared_ptr<GeomAPI_Shape> aPreview(*anIt);
       aBuilder.AddArgument(aPreview->impl<TopoDS_Edge>());
     }
     aPF.SetArguments(aBuilder.Arguments());
@@ -155,6 +156,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
   while (aMapVE.Extent() > 0) {
     if (aCurVertex.IsNull())
       return;
+    if (!aProcEdges.empty())
+      aBindingEdge = aProcEdges.back();
     findNextVertex(aCurVertex, aMapVE, aCurDir, aCurNorm, aNextVertex, aBindingEdge, aNextDir);
     aCurNorm = aNorm;
 
@@ -216,7 +219,7 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
       TopoDS_Face aPatch;
       createFace(*aVertIter, anEdgeIter, aProcEdges.end(), aPlane, aPatch);
       if (!aPatch.IsNull()) {
-        boost::shared_ptr<GeomAPI_Shape> aFace(new GeomAPI_Shape);
+        std::shared_ptr<GeomAPI_Shape> aFace(new GeomAPI_Shape);
         aFace->setImpl(new TopoDS_Face(aPatch));
         theResultFaces.push_back(aFace);
       }
@@ -237,18 +240,58 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
       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();
       }
     }
 
@@ -280,7 +323,7 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
         std::list<TopoDS_Wire>::const_iterator aTailIter = aTail.begin();
         for (; aTailIter != aTail.end(); aTailIter++)
           if (!aTailIter->IsNull()) {
-            boost::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
+            std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
             aWire->setImpl(new TopoDS_Shape(*aTailIter));
             theResultWires.push_back(aWire);
           }
@@ -328,13 +371,30 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
     fixIntersections(theResultFaces);
 }
 
+void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+                                            const std::shared_ptr<GeomAPI_Dir>& theDirX,
+                                            const std::shared_ptr<GeomAPI_Dir>& theDirY,
+                                            const std::shared_ptr<GeomAPI_Dir>& theNorm,
+                                            const std::shared_ptr<GeomAPI_Shape>& theWire,
+                                            std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
+{
+  std::shared_ptr<GeomAPI_PlanarEdges> aWire = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
+  if(!aWire)
+    return;
+  // Filter wires, return only faces.
+  std::list<std::shared_ptr<GeomAPI_Shape> > aFilteredWires;
+  createFaces(theOrigin, theDirX, theDirY, theNorm,
+              aWire->getEdges(), theResultFaces, aFilteredWires);
+}
+
+
 void GeomAlgoAPI_SketchBuilder::fixIntersections(
-    std::list<boost::shared_ptr<GeomAPI_Shape> >& theFaces)
+    std::list<std::shared_ptr<GeomAPI_Shape> >& theFaces)
 {
   BRepClass_FaceClassifier aClassifier;
 
-  std::list<boost::shared_ptr<GeomAPI_Shape> >::iterator anIter1 = theFaces.begin();
-  std::list<boost::shared_ptr<GeomAPI_Shape> >::iterator anIter2;
+  std::list<std::shared_ptr<GeomAPI_Shape> >::iterator anIter1 = theFaces.begin();
+  std::list<std::shared_ptr<GeomAPI_Shape> >::iterator anIter2;
   for (; anIter1 != theFaces.end(); anIter1++) {
     anIter2 = anIter1;
     for (++anIter2; anIter2 != theFaces.end(); anIter2++) {
@@ -344,7 +404,8 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections(
       for (; aVert2.More(); aVert2.Next()) {
         const TopoDS_Vertex& aV = (const TopoDS_Vertex&)aVert2.Current();
         aClassifier.Perform(aF1, BRep_Tool::Pnt(aV), tolerance);
-        if (aClassifier.State() != TopAbs_IN && aClassifier.State() != TopAbs_ON)
+        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
@@ -354,29 +415,42 @@ void GeomAlgoAPI_SketchBuilder::fixIntersections(
         for (; aVert1.More(); aVert1.Next()) {
           const TopoDS_Vertex& aV = (const TopoDS_Vertex&)aVert2.Current();
           aClassifier.Perform(aF2, BRep_Tool::Pnt(aV), tolerance);
-          if (aClassifier.State() != TopAbs_IN && aClassifier.State() != TopAbs_ON)
+          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<TopoDS_Shape>(), (*anIter1)->impl<TopoDS_Shape>());
           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<GeomAPI_Shape> 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<GeomAPI_Shape> 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<TopoDS_Shape>(), (*anIter2)->impl<TopoDS_Shape>());
         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<GeomAPI_Shape> 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<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+            aShape->setImpl(new TopoDS_Shape(anExp.Current()));
+            theFaces.push_back(aShape);
+          }
         }
       }
     }
@@ -412,7 +486,9 @@ void findNextVertex(const TopoDS_Vertex& theStartVertex,
                     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()) {
@@ -424,7 +500,7 @@ void findNextVertex(const TopoDS_Vertex& theStartVertex,
     // 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;
@@ -450,6 +526,18 @@ void findNextVertex(const TopoDS_Vertex& theStartVertex,
       }
     }
   }
+
+  // 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<const TopoDS_Edge&>(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,