]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Invalid shape after extrusion (issue #1203)
authorazv <azv@opencascade.com>
Fri, 15 Jan 2016 13:43:07 +0000 (16:43 +0300)
committerazv <azv@opencascade.com>
Fri, 15 Jan 2016 13:46:19 +0000 (16:46 +0300)
1. Use General Fuse to build areas of a sketch
2. Update unit tests

src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.h
src/ModelAPI/Test/Test1064.py
src/PythonAPI/examples/Platine.py

index 75b707138859188b41d815e09a41c82cee393385..9713fda503f839eb42b77fa19d9725fcdd31d295 100644 (file)
@@ -7,81 +7,15 @@
 #include <GeomAlgoAPI_SketchBuilder.h>
 #include <GeomAPI_PlanarEdges.h>
 
-#include <set>
-
-#include <gp_Dir.hxx>
-#include <gp_Pln.hxx>
-
 #include <BOPAlgo_Builder.hxx>
-#include <BOPAlgo_Operation.hxx>
-#include <BOPAlgo_PaveFiller.hxx>
-#include <BOPTools.hxx>
 #include <BRep_Builder.hxx>
-#include <BRep_Curve3D.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepAlgoAPI_Cut.hxx>
-#include <BRepBuilderAPI_MakeFace.hxx>
-#include <BRepClass_FaceClassifier.hxx>
-#include <Geom_Curve.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
 #include <Geom_Plane.hxx>
-#include <TopExp.hxx>
+#include <Precision.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Wire.hxx>
-
-#include <Precision.hxx>
-
-#include <assert.h>
-
-#ifndef DBL_MAX
-#define DBL_MAX 1.7976931348623158e+308 
-#endif
-
-const double tolerance = Precision::Confusion();
-// This value helps to find direction on the boundaries of curve.
-// It is not significant for lines, but is used for circles to avoid 
-// wrong directions of movement (when two edges are tangent on the certain vertex)
-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_Vertex& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
-                                            const gp_Dir& theDirX, const gp_Dir& theDirY);
-
-static gp_Dir calculateStartNormal(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
-                                   const TopoDS_Vertex& theStart, const gp_Dir& theNormal);
-
-/// \brief Search the vertex on the sketch candidate to be the next one in the loop
-static void findNextVertex(const TopoDS_Vertex& theStartVertex,
-                           const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
-                           const gp_Dir& theStartDir, const gp_Dir& theNormal,
-                           TopoDS_Vertex& theNextVertex, TopoDS_Edge& theNextEdge,
-                           gp_Dir& theNextDir);
-
-/// \brief Create planar face using the edges surrounding it
-static void createFace(const TopoDS_Vertex& theStartVertex,
-                       const std::list<TopoDS_Edge>::iterator& theStartEdge,
-                       const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                       const gp_Pln& thePlane, TopoDS_Face& theResFace);
-
-/// \bief Create planar wire
-static void createWireList(const TopoDS_Vertex& theStartVertex,
-                           const std::list<TopoDS_Edge>::iterator& theStartEdge,
-                           const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                           const std::set<TopoDS_Edge*>& theEdgesInLoops,
-                           std::list<TopoDS_Wire>& theResWires);
-
-/// \brief Calculate outer tengency on the edge in specified vertex
-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<TopoDS_Vertex>::iterator& theStartVertex,
-                             std::list<TopoDS_Edge>::iterator& theStartEdge,
-                             const std::list<TopoDS_Vertex>::iterator& theEndOfVertexes,
-                             const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                             BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE);
+#include <TopTools_ListIteratorOfListOfShape.hxx>
 
 
 void GeomAlgoAPI_SketchBuilder::createFaces(
@@ -89,315 +23,66 @@ void GeomAlgoAPI_SketchBuilder::createFaces(
     const std::shared_ptr<GeomAPI_Dir>& theDirX,
     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)
+    std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
 {
   if (theFeatures.empty())
     return;
 
-  // Create the list of edges with shared vertexes
-  BOPAlgo_Builder aBuilder;
-  BOPAlgo_PaveFiller aPF;
-  TopoDS_Shape aFeaturesCompound;
+  BRep_Builder aBuilder;
+  // Planar face, where the sketch was built
+  Handle(Geom_Surface) aPlane(new Geom_Plane(theOrigin->impl<gp_Pnt>(), theNorm->impl<gp_Dir>()));
+  TopoDS_Face aPlnFace;
+  aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
 
-  // Obtain only edges from the features list
-  std::list<std::shared_ptr<GeomAPI_Shape> > anEdges;
+  // Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
+  BOPAlgo_Builder aBB;
+  aBB.AddArgument(aPlnFace);
+
+  BOPCol_ListOfShape anEdges;
+  BOPCol_ListIteratorOfListOfShape aShapeIt;
   std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theFeatures.begin();
   for (; aFeatIt != theFeatures.end(); 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);
-  }
-
-  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<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = anEdges.begin();
-    for (; anIt != anEdges.end(); anIt++) {
-      std::shared_ptr<GeomAPI_Shape> aPreview(*anIt);
-      aBuilder.AddArgument(aPreview->impl<TopoDS_Edge>());
-    }
-    aPF.SetArguments(aBuilder.Arguments());
-    aPF.Perform();
-    int aErr = aPF.ErrorStatus();
-    if (aErr)
-      return;
-    aBuilder.PerformWithFiller(aPF);
-    aErr = aBuilder.ErrorStatus();
-    if (aErr)
-      return;
-    aFeaturesCompound = aBuilder.Shape();
+      aBB.AddArgument(anEdge);
   }
-
-  BOPCol_IndexedDataMapOfShapeListOfShape aMapVE;  // map between vertexes and edges
-  BOPTools::MapShapesAndAncestors(aFeaturesCompound, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
-  if (aMapVE.IsEmpty())  // in case of not-initialized circle
+  aBB.Perform();
+  if (aBB.ErrorStatus())
     return;
 
-  gp_Dir aDirX = theDirX->impl<gp_Dir>();
-  gp_Dir aNorm = theNorm->impl<gp_Dir>();
-  gp_Dir aDirY = aNorm.Crossed(aDirX);
-
-  gp_Pln aPlane(theOrigin->impl<gp_Pnt>(), aNorm);
-
-  // Set of edges used in loops
-  std::set<TopoDS_Edge*> anEdgesInLoops;
-  // Lists for processed vertexes and edges
-  std::list<TopoDS_Vertex> aProcVertexes;
-  std::list<TopoDS_Edge> aProcEdges;
-
-  // Search the start vertex
-  TopoDS_Vertex aCurVertex = findStartVertex(aMapVE, aDirX, aDirY);
-  aProcVertexes.push_back(aCurVertex);
-  gp_Dir aCurDir = aDirY.Reversed();
-  gp_Dir aCurNorm = calculateStartNormal(aMapVE, aCurVertex, aNorm);
-
-  // Go through the edges and find loops
-  TopoDS_Vertex aNextVertex;
-  TopoDS_Edge aBindingEdge;
-  gp_Dir aNextDir;
-  bool hasBranches = false;
-  while (aMapVE.Extent() > 0) {
-    if (aCurVertex.IsNull())
-      return;
-    if (!aProcEdges.empty())
-      aBindingEdge = aProcEdges.back();
-    findNextVertex(aCurVertex, aMapVE, aCurDir, aCurNorm, aNextVertex, aBindingEdge, aNextDir);
-    if (aMapVE.FindFromKey(aCurVertex).Size() > 2)
-      hasBranches = true;
-    aCurNorm = aNorm;
+  // Collect faces
+  const TopTools_ListOfShape& anAreas = aBB.Modified(aPlnFace);
+  TopTools_ListIteratorOfListOfShape anIt(anAreas);
+  for (; anIt.More(); anIt.Next()) {
+    TopoDS_Face aFace = TopoDS::Face(anIt.Value());
+    // avoid infinite faces
+    BRepTopAdaptor_FClass2d aFClass(aFace, Precision::Confusion());
+    if (aFClass.PerformInfinitePoint() == TopAbs_IN)
+      continue;
 
-    // Try to find next vertex in the list of already processed
-    bool isLoopFound = false;
-    std::list<TopoDS_Vertex>::iterator aVertIter = aProcVertexes.begin();
-    std::list<TopoDS_Edge>::iterator anEdgeIter = aProcEdges.begin();
-    for (; aVertIter != aProcVertexes.end(); aVertIter++) {
-      if (aVertIter->IsSame(aNextVertex)) {
-        isLoopFound = true;
+    // remove internal edges from faces
+    TopExp_Explorer anExp(aFace, TopAbs_EDGE);
+    for (; anExp.More(); anExp.Next())
+      if (anExp.Current().Orientation() == TopAbs_INTERNAL)
         break;
-      }
-      if (anEdgeIter != aProcEdges.end())
-        anEdgeIter++;
-    }
-
-    bool isCircleFound = (isLoopFound && anEdgeIter == aProcEdges.end());
-    aProcVertexes.push_back(aNextVertex);
-    aProcEdges.push_back(aBindingEdge);
-
-    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 (hasBranches) {
-        // Check the orientation of the loop
-        gp_Dir aCN = getOuterEdgeDirection(*anEdgeIter, *aVertIter);
-        gp_Dir aCP = getOuterEdgeDirection(aProcEdges.back(), *aVertIter);
-        aCN.Reverse();
-        aCP.Reverse();
-        bool isWrongOrient = false;
-        double aDotCross = aCN.DotCross(aCP, aNorm);
-        if (aDotCross < -tolerance)
-          isWrongOrient = true;
-        else if (aDotCross < 0.1) {
-          std::list<TopoDS_Edge>::iterator aEIt = anEdgeIter, aEIt1 = aProcEdges.end();
-          ++aEIt; --aEIt1;
-          if (aEIt != aEIt1) {
-            gp_XYZ aStartV = BRep_Tool::Pnt(*aVertIter).XYZ();
-            // verify all vertices in the loop to be inside the angle between aCN and aCP
-            std::list<TopoDS_Vertex>::iterator aVIt = aVertIter;
-            std::list<TopoDS_Vertex>::iterator aEndIt = aProcVertexes.end();
-            ++aVIt; ++aVIt; --aEndIt; --aEndIt;
-            for (; aVIt != aEndIt && !isWrongOrient; ++aVIt) {
-              gp_XYZ aDir(BRep_Tool::Pnt(*aVIt).XYZ() - aStartV);
-              isWrongOrient = aCN.XYZ().DotCross(aDir, aNorm.XYZ()) < -tolerance;
-            }
-          }
-        }
-
-        if (isWrongOrient) {
-          // The found loop has wrong orientation and may contain sub-loops.
-          // Need to check it once again with another initial direction.
-          aCurVertex = *aVertIter;
-          do {
-            aProcVertexes.pop_back();
-            aProcEdges.pop_back();
-          } while (aCurVertex != aProcVertexes.back());
-          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;
-      }
-
-      hasBranches = false;
-
-      // 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()) {
-        std::shared_ptr<GeomAPI_Shape> 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<TopoDS_Edge>::iterator anIter;
-      for (anIter = anEdgeIter; anIter != aProcEdges.end(); anIter++)
-        anEdgesInLoops.insert(&(*anIter));
-      // remove unnecessary edges
-      std::list<TopoDS_Vertex>::iterator aCopyVLoop = aVertIter;
-      std::list<TopoDS_Edge>::iterator aCopyELoop = anEdgeIter;
-      removeWasteEdges(aVertIter, anEdgeIter, aProcVertexes.end(), aProcEdges.end(), aMapVE);
-
-      // revert the list of remaining edges
-      std::list<TopoDS_Vertex> aRemainVertexes;
-      for (; aVertIter != aProcVertexes.end(); aVertIter++)
-        aRemainVertexes.push_front(*aVertIter);
-      std::list<TopoDS_Edge> 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());
-
-      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();
-      }
-    }
-
-    // if next vertex connected only to alone edge, this is a part of wire (not a closed loop),
-    // 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<TopoDS_Vertex>::reverse_iterator aVRIter = aProcVertexes.rbegin();
-      std::list<TopoDS_Edge>::reverse_iterator aERIter = aProcEdges.rbegin();
-      if (aVRIter != aProcVertexes.rend())
-        aVRIter++;
-      if (aERIter != aProcEdges.rend())
-        aERIter++;
-
-      for (; aERIter != aProcEdges.rend(); aERIter++, aVRIter++)
-        if (aMapVE.FindFromKey(*aVRIter).Size() > 2)
-          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<TopoDS_Edge>::iterator aEIter;
-        TopoDS_Edge aCurEdge;
-        if (aERIter != aProcEdges.rend()) {
-          aEIter = aERIter.base();
-          aCurEdge = *aERIter;
-        } else
-          aEIter = aProcEdges.begin();
-        std::list<TopoDS_Wire> aTail;
-        createWireList(*aVRIter, aEIter, aProcEdges.end(), anEdgesInLoops, aTail);
-        std::list<TopoDS_Wire>::const_iterator aTailIter = aTail.begin();
-        for (; aTailIter != aTail.end(); aTailIter++)
-          if (!aTailIter->IsNull()) {
-            std::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
-            aWire->setImpl(new TopoDS_Shape(*aTailIter));
-            theResultWires.push_back(aWire);
-          }
-        std::list<TopoDS_Vertex>::iterator aVIter = aVRIter.base();
-        std::list<TopoDS_Edge>::iterator aEItCopy = aEIter;
-        removeWasteEdges(--aVIter, aEItCopy, aProcVertexes.end(), aProcEdges.end(), aMapVE);
-
-        aProcEdges.erase(aEIter, aProcEdges.end());
-        aVIter = aVRIter.base();
-        aProcVertexes.erase(aVIter, aProcVertexes.end());
-
-        if (!aProcVertexes.empty()) {
-          aNextVertex = aProcVertexes.back();
-          aProcVertexes.clear();
-          aProcEdges.clear();
-          aProcVertexes.push_back(aNextVertex);
-        }
-      } else {  // there is no branching vertex in the list of proceeded,
-                // so we should revert the list and go the opposite way
-        aProcVertexes.reverse();
-        aProcEdges.reverse();
-        aNextVertex = aProcVertexes.back();
-        aNextDir =
-            aProcEdges.empty() ? aDirY : getOuterEdgeDirection(aProcEdges.back(), aNextVertex);
-      }
-    }
-
-    // When all edges of current component of connectivity are processed,
-    // we should repeat procedure for finding initial vertex in the remaining
-    if (!aMapVE.IsEmpty() && !aMapVE.Contains(aNextVertex)) {
-      aProcVertexes.clear();
-      aProcEdges.clear();
-
-      aNextVertex = findStartVertex(aMapVE, aDirX, aDirY);
-      aProcVertexes.push_back(aNextVertex);
-      aNextDir = aDirY.Reversed();
-      aCurNorm = calculateStartNormal(aMapVE, aNextVertex, aNorm);
+    if (anExp.More()) {
+      TopoDS_Face aNewFace;
+      aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
+      TopoDS_Wire aWire;
+      aBuilder.MakeWire(aWire);
+      for (anExp.ReInit(); anExp.More(); anExp.Next())
+        if (anExp.Current().Orientation() != TopAbs_INTERNAL)
+          aBuilder.Add(aWire, anExp.Current());
+      aBuilder.Add(aNewFace, aWire);
+      aFace = aNewFace;
     }
 
-    aCurVertex = aNextVertex;
-    aCurDir = aNextDir;
+    // Store face
+    std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
+    aResFace->setImpl(new TopoDS_Face(aFace));
+    theResultFaces.push_back(aResFace);
   }
-
-  if (theResultFaces.size() > 1)
-    fixIntersections(theResultFaces);
 }
 
 void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
@@ -406,341 +91,17 @@ void GeomAlgoAPI_SketchBuilder::createFaces(const std::shared_ptr<GeomAPI_Pnt>&
                                             const std::shared_ptr<GeomAPI_Shape>& theWire,
                                             std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
 {
-  std::list<std::shared_ptr<GeomAPI_Shape> > aFilteredWires;
   std::shared_ptr<GeomAPI_PlanarEdges> aWire = 
     std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
   if(aWire) {
     // Filter wires, return only faces.
-    createFaces(theOrigin, theDirX, theNorm,
-                aWire->getEdges(), theResultFaces, aFilteredWires);
-
-    return;
+    createFaces(theOrigin, theDirX, theNorm, aWire->getEdges(), theResultFaces);
   } else { // it may be only one circle
     std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
     if (anEdge) {
       std::list<std::shared_ptr<GeomAPI_Shape> > aList;
       aList.push_back(anEdge);
-      createFaces(theOrigin, theDirX, theNorm,
-                  aList, theResultFaces, aFilteredWires);
+      createFaces(theOrigin, theDirX, theNorm, aList, theResultFaces);
     }
   }
 }
-
-
-void GeomAlgoAPI_SketchBuilder::fixIntersections(
-    std::list<std::shared_ptr<GeomAPI_Shape> >& theFaces)
-{
-  BRepClass_FaceClassifier aClassifier;
-
-  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++) {
-      const TopoDS_Face& aF1 = (*anIter1)->impl<TopoDS_Face>();
-      assert(aF1.ShapeType() == TopAbs_FACE);  // all items in result list should be faces
-      TopExp_Explorer aVert2((*anIter2)->impl<TopoDS_Shape>(), TopAbs_VERTEX);
-      for (; aVert2.More(); aVert2.Next()) {
-        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
-        const TopoDS_Face& aF2 = (*anIter2)->impl<TopoDS_Face>();
-        assert(aF2.ShapeType() == TopAbs_FACE);  // all items in result list should be faces
-        TopExp_Explorer aVert1((*anIter1)->impl<TopoDS_Shape>(), TopAbs_VERTEX);
-        for (; aVert1.More(); aVert1.Next()) {
-          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<TopoDS_Shape>(), (*anIter1)->impl<TopoDS_Shape>());
-          aCut.Build();
-          TopExp_Explorer anExp(aCut.Shape(), TopAbs_FACE);
-          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);
-        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);
-          }
-        }
-      }
-    }
-  }
-}
-
-// =================== Auxiliary functions ====================================
-const TopoDS_Vertex& findStartVertex(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
-                                    const gp_Dir& theDirX, const gp_Dir& theDirY)
-{
-  int aStartVertexInd = 1;
-  double aMaxX = -DBL_MAX;
-  double aMaxY = -DBL_MAX;
-  int aNbVert = theMapVE.Extent();
-  for (int i = 1; i <= aNbVert; i++) {
-    const TopoDS_Vertex& aV = (const TopoDS_Vertex&) theMapVE.FindKey(i);
-    const gp_Pnt& aVertPnt = BRep_Tool::Pnt(aV);
-
-    double aX = aVertPnt.XYZ().Dot(theDirX.XYZ());
-    double aY = aVertPnt.XYZ().Dot(theDirY.XYZ());
-    if ((aX > aMaxX || (fabs(aX - aMaxX) < tolerance && aY > aMaxY))
-        && theMapVE.FindFromIndex(i).Extent() > 1) {
-      aMaxX = aX;
-      aMaxY = aY;
-      aStartVertexInd = i;
-    }
-  }
-  return static_cast<const TopoDS_Vertex&>(theMapVE.FindKey(aStartVertexInd));
-}
-
-gp_Dir calculateStartNormal(const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
-                            const TopoDS_Vertex& theStart, const gp_Dir& theNormal)
-{
-  gp_Dir aNorm = theNormal.Reversed();
-
-  const BOPCol_ListOfShape& anEdgesList = theMapVE.FindFromKey(theStart);
-  BOPCol_ListOfShape::Iterator aEdIter(anEdgesList);
-  for (; aEdIter.More(); aEdIter.Next()) {
-    const TopoDS_Edge& anEdge = static_cast<const TopoDS_Edge&>(aEdIter.Value());
-    gp_Dir aTang = getOuterEdgeDirection(anEdge, theStart);
-    if (aTang.X() < 0.0) {
-      aNorm = theNormal;
-      break;
-    }
-  }
-  return aNorm;
-}
-
-void findNextVertex(const TopoDS_Vertex& theStartVertex,
-                    const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
-                    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()) {
-    const TopoDS_Edge& anEdge = static_cast<const TopoDS_Edge&>(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 (anEdgesNum > 1 && fabs(fabs(aProj) - 1) < tolerance)
-      continue;
-    if (theStartDir.DotCross(aTang, theNormal) < tolerance)
-      aProj *= -1.0;
-
-    if (aProj < aBestEdgeProj) {
-      aBestEdgeProj = aProj;
-      theNextEdge = anEdge;
-      TopExp_Explorer aVertExp(theNextEdge, TopAbs_VERTEX);
-      for (; aVertExp.More(); aVertExp.Next())
-        if (!aVertExp.Current().IsSame(theStartVertex)) {
-          theNextVertex = static_cast<const TopoDS_Vertex&>(aVertExp.Current());
-          theNextDir = getOuterEdgeDirection(anEdge, theNextVertex);
-          break;
-        }
-      if (!aVertExp.More()) {  // This edge is a full circle
-        TopoDS_Vertex aV1, aV2;
-        TopExp::Vertices(theNextEdge, aV1, aV2);
-        if (aV1.Orientation() == theStartVertex.Orientation())
-          theNextVertex = aV2;
-        else
-          theNextVertex = aV1;
-        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<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,
-                          TopoDS_Shape& theSpliceVertex, TopoDS_Wire& theWire)
-{
-  TopoDS_Edge anEdge = theEdge;
-  bool isCurVertChanged = false;
-  TopoDS_Shape aCurVertChanged;
-
-  TopExp_Explorer aVertExp(theEdge, TopAbs_VERTEX);
-  for (; aVertExp.More(); aVertExp.Next()) {
-    const TopoDS_Shape& aVertex = aVertExp.Current();
-    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.IsSame(theSpliceVertex)) {
-      aCurVertChanged = aVertex;
-      isCurVertChanged = true;
-    }
-  }
-  theSpliceVertex = isCurVertChanged ? aCurVertChanged : aVertExp.Current();
-
-  theBuilder.Add(theWire, anEdge);
-}
-
-void createFace(const TopoDS_Vertex& theStartVertex,
-                const std::list<TopoDS_Edge>::iterator& theStartEdge,
-                const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                const gp_Pln& thePlane,
-                TopoDS_Face& theResFace)
-{
-  TopoDS_Wire aResWire;
-  BRep_Builder aBuilder;
-  aBuilder.MakeWire(aResWire);
-
-  TopoDS_Vertex aCurVertex = theStartVertex;
-  std::list<TopoDS_Edge>::const_iterator anEdgeIter = theStartEdge;
-  for (; anEdgeIter != theEndOfEdges; anEdgeIter++) {
-    if (!anEdgeIter->IsNull())
-      addEdgeToWire(*anEdgeIter, aBuilder, aCurVertex, aResWire);
-  }
-
-  BRepBuilderAPI_MakeFace aFaceBuilder(thePlane, aResWire);
-  if (aFaceBuilder.Error() == BRepBuilderAPI_FaceDone)
-    theResFace = aFaceBuilder.Face();
-}
-
-void createWireList(const TopoDS_Vertex& theStartVertex,
-                    const std::list<TopoDS_Edge>::iterator& theStartEdge,
-                    const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                    const std::set<TopoDS_Edge*>& theEdgesInLoops,
-                    std::list<TopoDS_Wire>& theResWires)
-{
-  BRep_Builder aBuilder;
-  bool needNewWire = true;
-  TopoDS_Vertex aCurVertex = theStartVertex;
-
-  std::list<TopoDS_Edge>::iterator anIter = theStartEdge;
-  while (anIter != theEndOfEdges) {
-    while (anIter != theEndOfEdges && needNewWire && theEdgesInLoops.count(&(*anIter)) != 0) {
-      TopExp_Explorer aVertExp(*anIter, TopAbs_VERTEX);
-      for (; aVertExp.More(); aVertExp.Next())
-        if (!aVertExp.Current().IsSame(aCurVertex)) {
-          aCurVertex = static_cast<const TopoDS_Vertex&>(aVertExp.Current());
-          break;
-        }
-      anIter++;
-    }
-    if (anIter == theEndOfEdges)
-      break;
-
-    if (needNewWire) {  // The new wire should be created
-      TopoDS_Wire aWire;
-      aBuilder.MakeWire(aWire);
-      theResWires.push_back(aWire);
-      needNewWire = false;
-    } 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;
-    }
-
-    addEdgeToWire(*anIter, aBuilder, aCurVertex, theResWires.back());
-    anIter++;
-  }
-}
-
-gp_Dir getOuterEdgeDirection(const TopoDS_Edge& theEdge, const TopoDS_Vertex& theVertex)
-{
-  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.
-  double aFirst, aLast;
-  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast);
-
-  gp_Pnt aPnt;
-  gp_Vec aTang;
-  // A direction is determined not in the boundary points but in the points with small shift.
-  // It was done to avoid tangency between circle and other edge in the shared vertex.
-  aCurve->D1(aFirst + shift > aLast ? aFirst : aFirst + shift, aPnt, aTang);
-  aCurve->D0(aFirst, aPnt);
-  if (aVertexPnt.IsEqual(aPnt, tolerance))
-    return gp_Dir(aTang.Reversed());
-
-  aCurve->D1(aLast - shift < aFirst ? aLast : aLast - shift, aPnt, aTang);
-  return gp_Dir(aTang);
-}
-
-void removeWasteEdges(std::list<TopoDS_Vertex>::iterator& theStartVertex,
-                      std::list<TopoDS_Edge>::iterator& theStartEdge,
-                      const std::list<TopoDS_Vertex>::iterator& theEndOfVertexes,
-                      const std::list<TopoDS_Edge>::iterator& theEndOfEdges,
-                      BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE)
-{
-  bool isVertStep = true;
-  while (theStartVertex != theEndOfVertexes && theStartEdge != theEndOfEdges) {
-    BOPCol_ListOfShape& aBunch = theMapVE.ChangeFromKey(*theStartVertex);
-    BOPCol_ListOfShape::Iterator anApprEdge(aBunch);
-    for (; anApprEdge.More(); anApprEdge.Next())
-      if (anApprEdge.Value().IsSame(*theStartEdge))
-        break;
-    if (anApprEdge.More())
-      aBunch.Remove(anApprEdge);
-
-    if (isVertStep)
-      theStartVertex++;
-    else {
-      theStartEdge++;
-      // check current vertex to be a branching point
-      // if so, it will be a new starting point to find a loop
-      if (aBunch.Size() > 1)
-        break;
-    }
-    isVertStep = !isVertStep;
-  }
-
-  // The map of vertex-edges may be changed
-  BOPCol_IndexedDataMapOfShapeListOfShape aMapVECopy;
-  BOPCol_IndexedDataMapOfShapeListOfShape::Iterator aMapIter(theMapVE);
-  for (int ind = 1; aMapIter.More(); aMapIter.Next(), ind++)
-    if (!aMapIter.Value().IsEmpty())
-      aMapVECopy.Add(theMapVE.FindKey(ind), aMapIter.Value());
-  theMapVE.Clear();
-  theMapVE.Exchange(aMapVECopy);
-}
-
index f442df89d27bece92f75b516b1e61d5b2a62cc34..4ebeb902963fb0b195ad643300835980eb9f1436 100644 (file)
 class GEOMALGOAPI_EXPORT GeomAlgoAPI_SketchBuilder
 {
  public:
-  /** \brief Creates list of faces and unclosed wires on basis of the features of the sketch
+  /** \brief Creates list of faces based on the features of the sketch
    *  \param[in]  theOrigin      origin point of the sketch
    *  \param[in]  theDirX        x-direction of the sketch
    *  \param[in]  theNorm        normal of the sketch
    *  \param[in]  theFeatures    initial features of the sketch
    *  \param[out] theResultFaces faces based on closed wires
-   *  \param[out] theResultWires unclosed wires of the sketch
    *
-   *  The algorithm searches all loops of edges surrounding lesser squares.
-   *  It finds the vertex with minimal coordinates along X axis (theDirX) and then 
-   *  goes through the edges passing the surrounding area on the left.
+   *  The algorithm searches all loops of edges surrounding lesser areas.
    */
   static void createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
                           const std::shared_ptr<GeomAPI_Dir>& theDirX,
                           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);
+                          std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces);
 
   /** \brief Creates list of faces and unclosed wires on basis of the features of the sketch
    *  \param[in]  theOrigin      origin point of the sketch
@@ -49,21 +45,13 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_SketchBuilder
    *  \param[in]  theWire        a wire which contains all edges
    *  \param[out] theResultFaces faces based on closed wires
    *
-   *  The algorithm searches all loops of edges surrounding lesser squares.
-   *  It finds the vertex with minimal coordinates along X axis (theDirX) and then
-   *  goes through the edges passing the surrounding area on the left.
+   *  The algorithm searches all loops of edges surrounding lesser areas.
    */
   static void createFaces(const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
                           const std::shared_ptr<GeomAPI_Dir>& theDirX,
                           const std::shared_ptr<GeomAPI_Dir>& theNorm,
                           const std::shared_ptr<GeomAPI_Shape>& theWire,
                           std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces);
-
-  /** \brief Searches intersections between the faces in the list 
-   *         and make holes in the faces to avoid intersections
-   *  \param[in,out] theFaces list of faces to proccess
-   */
-  static void fixIntersections(std::list<std::shared_ptr<GeomAPI_Shape> >& theFaces);
 };
 
 #endif
index c73dfd17d9633503c56894647420408ff1975c1f..e5c24f218c3c6b0e5289105d42e3c2d7a37127a2 100644 (file)
@@ -73,7 +73,7 @@ aSession.setActiveDocument(aPartSet)
 aPlane = aPartSet.addFeature("Plane")
 aPlane.string("CreationMethod").setValue("PlaneByFaceAndDistance")
 aPlane.real("distance").setValue(0)
-aPlane.selection("planeFace").selectSubShape("face", "Part_1/Extrusion_1_1/LateralFace_3")
+aPlane.selection("planeFace").selectSubShape("face", "Part_1/Extrusion_1_1/LateralFace_2")
 aSession.finishOperation()
 
 #=========================================================================
index 8a1a3dfcab04d416a7cab033f0d614d2ef90c3d6..6cdfa3c28771d0a70c755143ab24513d1d83555e 100644 (file)
@@ -54,7 +54,7 @@ def vertical_body():
 
 def bottom_body():
     # Create XOY sketch
-    sketch = model.addSketch(part, "Extrusion_1_1/LateralFace_2")
+    sketch = model.addSketch(part, "Extrusion_1_1/LateralFace_5")
 
     # Create base polygon
     points = [(0, 0), (0, L), (P, L), (P, 16 + 16), (P - 20, 16 + 16), (P - 20, 16), (P, 16), (P, 0)]
@@ -92,7 +92,7 @@ def bottom_body():
     sketch.setCoincident(arc.endPoint(), h1.startPoint())
 
     # Binding
-    left_e = sketch.addLine("Extrusion_1_1/LateralFace_2&Extrusion_1_1/ToFace_1")
+    left_e = sketch.addLine("Extrusion_1_1/LateralFace_5&Extrusion_1_1/ToFace_1")
     sketch.setCoincident(left_e.startPoint(), left.endPoint())
     sketch.setCoincident(left_e.endPoint(), left.startPoint())
 
@@ -107,7 +107,7 @@ def bottom_body():
 
 def body_3():
     # Create XOZ sketch
-    sketch = model.addSketch(part, "Boolean_1_1/Modified_3")
+    sketch = model.addSketch(part, "Boolean_1_1/Modified_4")
 
     # Create base polygon
     H, L, l, r = 28, 40, 8, 12
@@ -145,7 +145,7 @@ def body_3():
     sketch.setRadius(arc.result(), r)
 
     # Binding
-    bottom_e = sketch.addLine("Boolean_1_1/Modified_1&Boolean_1_1/Modified_3")
+    bottom_e = sketch.addLine("Boolean_1_1/Modified_1&Boolean_1_1/Modified_4")
     sketch.setCoincident(bottom_e.result(), bottom.startPoint())
     sketch.setCoincident(bottom_e.startPoint(), bottom.endPoint())
 
@@ -173,7 +173,7 @@ def body_4():
     sketch.setCoincident(bottom_e.endPoint(), bottom.startPoint())
     sketch.setCoincident(bottom_e.startPoint(), left.startPoint())
 
-    left_e = sketch.addLine("Boolean_2_1/Modified_3&Boolean_2_1/Modified_2")
+    left_e = sketch.addLine("Boolean_2_1/Modified_4&Boolean_2_1/Modified_2")
     sketch.setCoincident(left_e.startPoint(), left.endPoint())
 
     model.do()  #!!!