-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2020 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include <GeomAlgoAPI_SketchBuilder.h>
#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_Pln.h>
+
#include <BOPAlgo_Builder.hxx>
#include <BRep_Builder.hxx>
+#include <BRepTools_WireExplorer.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>
return aStart;
}
-static TopoDS_Vertex findStartVertex(const TopoDS_Shape& theShape,
+static TopoDS_Vertex findStartVertex(const TopoDS_Wire& theWire, const TopoDS_Face& theFace,
const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
{
// Try to find edge lying on the one of original edges.
if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
- TopExp_Explorer anExp(theShape, TopAbs_EDGE);
+ BRepTools_WireExplorer anExp(theWire, theFace);
for (; anExp.More(); anExp.Next()) {
- const TopoDS_Edge& aShapeEdge = TopoDS::Edge(anExp.Current());
+ const TopoDS_Edge& aShapeEdge = anExp.Current();
double aF, aL;
Handle(Geom_Curve) aShapeCurve = BRep_Tool::Curve(aShapeEdge, aF, aL);
if (aShapeCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
}
// start vertex is not found, use algorithm to search vertex with the greatest coordinates
- return findStartVertex(theShape);
+ return findStartVertex(theWire);
}
// returns true if the first shape must be located earlier than the second
if (!theAreaToIndex.IsBound(aShape)) { // fill the list of curve indices
NCollection_List<int> aNewList;
TopExp_Explorer anEdgesExp(aShape, TopAbs_EDGE);
- for(; anEdgesExp.More(); anEdgesExp.Next()) {
+ for (; anEdgesExp.More(); anEdgesExp.Next()) {
double aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(
TopoDS::Edge(anEdgesExp.Current()), aFirst, aLast);
aNewList.Append(theCurveToIndex.Find(aCurve));
}
}
- NCollection_Array1<int> aNewArray(1, aNewList.Extent());
- NCollection_List<int>::Iterator aListIter(aNewList);
- for(int anIndex = 1; aListIter.More(); aListIter.Next(), anIndex++) {
- aNewArray.SetValue(anIndex, aListIter.Value());
+ if (aNewList.Extent()) {
+ NCollection_Array1<int> aNewArray(1, aNewList.Extent());
+ NCollection_List<int>::Iterator aListIter(aNewList);
+ for (int anIndex = 1; aListIter.More(); aListIter.Next(), anIndex++) {
+ aNewArray.SetValue(anIndex, aListIter.Value());
+ }
+ std::sort(aNewArray.begin(), aNewArray.end());
+ theAreaToIndex.Bind(aShape, aNewArray);
}
- std::sort(aNewArray.begin(), aNewArray.end());
- theAreaToIndex.Bind(aShape, aNewArray);
}
}
- // compare lists of indices one by one to find chich list indices are lower
- NCollection_Array1<int>::Iterator aFirstList(theAreaToIndex.ChangeFind(theFirst));
- NCollection_Array1<int>::Iterator aSecondList(theAreaToIndex.ChangeFind(theSecond));
- for(; aFirstList.More() && aSecondList.More(); aFirstList.Next(), aSecondList.Next()) {
- if (aFirstList.Value() < aSecondList.Value()) return true;
- if (aFirstList.Value() > aSecondList.Value()) return false;
+ bool isFirst;
+ bool aGeomCompare = !theAreaToIndex.IsBound(theFirst) || !theAreaToIndex.IsBound(theSecond);
+ if (!aGeomCompare) {
+ // compare lists of indices one by one to find chich list indices are lower
+ NCollection_Array1<int>::Iterator aFirstList(theAreaToIndex.ChangeFind(theFirst));
+ NCollection_Array1<int>::Iterator aSecondList(theAreaToIndex.ChangeFind(theSecond));
+ for (; aFirstList.More() && aSecondList.More(); aFirstList.Next(), aSecondList.Next()) {
+ if (aFirstList.Value() < aSecondList.Value()) return true;
+ if (aFirstList.Value() > aSecondList.Value()) return false;
+ }
+ aGeomCompare = !aFirstList.More() && !aSecondList.More();
+ isFirst = !aFirstList.More();
+ } else {
+ isFirst = !theAreaToIndex.IsBound(theFirst);
}
// if faces are identical by curves names (circle splitted by line in seam-point), use parameters
- if (!aFirstList.More() && !aSecondList.More()) {
+ if (aGeomCompare) {
GProp_GProps aGProps;
BRepGProp::SurfaceProperties(theFirst, aGProps);
gp_Pnt aCentre1 = aGProps.CentreOfMass();
return aCentre1.X() + aCentre1.Y() + aCentre1.Z() < aCentre2.X() + aCentre2.Y() + aCentre2.Z();
}
// if in first list there is no elements left, it is the first
- return !aFirstList.More();
+ return isFirst;
}
// sorts faces (in theAreas list) to make persistent order: by initial shapes edges
-static void sortFaces(TopTools_ListOfShape& theAreas,
+static void sortAreas(TopTools_ListOfShape& theAreas,
const std::list<std::shared_ptr<GeomAPI_Shape> >& theInitialShapes)
{
// collect indices of all edges to operate them quickly
}
}
-void GeomAlgoAPI_SketchBuilder::createFaces(
+void GeomAlgoAPI_SketchBuilder::build(
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)
+ const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges)
{
- if (theFeatures.empty())
+ myResultFaces.clear();
+ setDone(false);
+ if (theEdges.empty())
return;
BRep_Builder aBuilder;
aBuilder.MakeFace(aPlnFace, aPlane, Precision::Confusion());
// Use General Fuse algorithm to prepare all subfaces, bounded by given list of edges
- BOPAlgo_Builder aBB;
- aBB.AddArgument(aPlnFace);
+ BOPAlgo_Builder* aBB = new BOPAlgo_Builder;
+ 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++) {
+ setImpl(aBB);
+ setBuilderType(OCCT_BOPAlgo_Builder);
+
+ NCollection_List<TopoDS_Shape> anEdges;
+ NCollection_List<TopoDS_Shape>::Iterator aShapeIt;
+ std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFeatIt = theEdges.begin();
+ for (; aFeatIt != theEdges.end(); aFeatIt++) {
std::shared_ptr<GeomAPI_Shape> aShape(*aFeatIt);
const TopoDS_Edge& anEdge = aShape->impl<TopoDS_Edge>();
if (anEdge.ShapeType() == TopAbs_EDGE)
- aBB.AddArgument(anEdge);
+ aBB->AddArgument(anEdge);
}
- aBB.Perform();
-#ifdef USE_OCCT_720
- if (aBB.HasErrors())
- return;
-#else
- if (aBB.ErrorStatus())
+ aBB->Perform();
+ if (aBB->HasErrors())
return;
-#endif
+
+ TopoDS_Compound aResult;
+ aBuilder.MakeCompound(aResult);
+
// Collect faces
- TopTools_ListOfShape anAreas = aBB.Modified(aPlnFace);
- sortFaces(anAreas, theFeatures); // sort faces by the edges in them
+ TopTools_ListOfShape anAreas = aBB->Modified(aPlnFace);
+ sortAreas(anAreas, theEdges); // sort faces by the edges in them
TopTools_ListIteratorOfListOfShape anIt(anAreas);
for (; anIt.More(); anIt.Next()) {
TopoDS_Face aFace = TopoDS::Face(anIt.Value());
TopoDS_Face aNewFace;
aBuilder.MakeFace(aNewFace, aPlane, Precision::Confusion());
- // iterate on wires
+ // sort inner wires according to the original edges as well as faces
+ TopTools_ListOfShape aWires;
TopExp_Explorer aWireExp(aFace, TopAbs_WIRE);
- for (; aWireExp.More(); aWireExp.Next()) {
- TopoDS_Wire aWire = TopoDS::Wire(aWireExp.Current());
+ for (; aWireExp.More(); aWireExp.Next())
+ aWires.Append(aWireExp.Current());
+ if (aWires.Size() > 2) {
+ TopoDS_Shape anOuterWire = aWires.First();
+ aWires.RemoveFirst();
+ sortAreas(aWires, theEdges);
+ aWires.Prepend(anOuterWire);
+ }
+
+ // iterate on wires
+ for (TopTools_ListIteratorOfListOfShape aWIt(aWires); aWIt.More(); aWIt.Next()) {
+ TopoDS_Wire aWire = TopoDS::Wire(aWIt.Value());
// to make faces equal on different platforms, we will find
// a vertex lying on an edge with the lowest index in the list of initial edges
- TopoDS_Vertex aStartVertex = findStartVertex(aWire, theFeatures);
+ TopoDS_Vertex aStartVertex = findStartVertex(aWire, aFace, theEdges);
TopoDS_Wire aNewWire;
aBuilder.MakeWire(aNewWire);
bool aStartFound = false;
// remove internal edges from faces and make wire start from found vertex
- TopExp_Explorer anExp(aWire, TopAbs_EDGE);
+ BRepTools_WireExplorer anExp(aWire, aFace);
for (; anExp.More(); anExp.Next()) {
if (anExp.Current().Orientation() == TopAbs_INTERNAL)
continue;
if (!aStartFound) {
- const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
+ const TopoDS_Edge& anEdge = anExp.Current();
TopoDS_Vertex aV1, aV2;
TopExp::Vertices(anEdge, aV1, aV2, Standard_True);
if (aV1.IsSame(aStartVertex) == Standard_True)
aBuilder.Add(aNewWire, *aSkIt);
// check the wire is empty
- anExp.Init(aNewWire, TopAbs_EDGE);
+ anExp.Init(aNewWire);
if (anExp.More())
aBuilder.Add(aNewFace, aNewWire);
}
// store face
- aFace = aNewFace;
+ aBuilder.Add(aResult, aNewFace);
std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
- aResFace->setImpl(new TopoDS_Face(aFace));
- theResultFaces.push_back(aResFace);
+ aResFace->setImpl(new TopoDS_Face(aNewFace));
+ myResultFaces.push_back(aResFace);
}
+
+ // update results
+ GeomShapePtr aResShape(new GeomAPI_Shape);
+ aResShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aResShape);
+ setDone(true);
}
-void GeomAlgoAPI_SketchBuilder::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)
+GeomAlgoAPI_SketchBuilder::GeomAlgoAPI_SketchBuilder(
+ const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const std::list<std::shared_ptr<GeomAPI_Shape> >& theEdges)
+{
+ build(thePlane->location(), thePlane->xDirection(), thePlane->direction(), theEdges);
+}
+
+GeomAlgoAPI_SketchBuilder::GeomAlgoAPI_SketchBuilder(
+ 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::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);
+ build(theOrigin, theDirX, theNorm, aWire->getEdges());
} 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);
+ build(theOrigin, theDirX, theNorm, aList);
}
}
}