#include <GeomAlgoAPI_ShapeTools.h>
#include <GeomAlgoAPI_SketchBuilder.h>
#include <GeomAlgoAPI_Copy.h>
+#include <GeomAlgoAPI_NonPlanarFace.h>
//=================================================================================================
BuildPlugin_Face::BuildPlugin_Face()
// Collect base shapes.
ListOfShape anEdges;
+ ListOfShape aNonPlanarEdges;
ListOfShape anOriginalFaces;
ListOfShape aContexts;
+
getOriginalShapesAndContexts(BASE_OBJECTS_ID(), anOriginalFaces, aContexts);
anOriginalFaces.clear();
std::list< std::shared_ptr<GeomAPI_Dir> > aListOfNormals;
}
}
- for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
- GeomShapePtr anEdge = anExp.current();
- anEdges.push_back(anEdge);
- }
-
// check whether the context is a sketch, in this case store its normal for further needs
std::shared_ptr<GeomAPI_PlanarEdges> aSketch =
std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContext);
if (aSketch)
aListOfNormals.push_back(aSketch->norm());
+
+ bool isPlanar(aShape->isPlanar() || aSketch);
+
+ for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdge = anExp.current();
+ isPlanar? anEdges.push_back(anEdge) : aNonPlanarEdges.push_back(anEdge);
+ }
+ }
+
+ if (!anEdges.empty())
+ {
+ //check is planar objects belong to nke
+ std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
+ if(!aPln.get())
+ {
+ aNonPlanarEdges.insert(aNonPlanarEdges.end(), anEdges.begin(), anEdges.end());
+ anEdges.clear();
+ }
}
// Build faces by edges.
buildFacesByEdges(anEdges, aListOfNormals, aFaces, aFaceBuilder);
int aNbFacesFromEdges = (int)aFaces.size();
+ // Build non-planar faces by edges.
+ GeomMakeShapePtr aNonPlanarFaceBuilder;
+ int aNbNonPlanarFaces = (int)aFaces.size();
+ if(!aNonPlanarEdges.empty())
+ {
+ ListOfShape aNonPlanarFaces;
+ buildNonPlanarFacesByEdges(aNonPlanarEdges, aNonPlanarFaces, aNonPlanarFaceBuilder);
+ // Add non-planar faces to common faces list.
+ aFaces.insert(aFaces.end(), aNonPlanarFaces.begin(), aNonPlanarFaces.end());
+ aNbNonPlanarFaces += (int)aNonPlanarFaces.size();
+ }
+
// Add faces selected by user.
aFaces.insert(aFaces.end(), anOriginalFaces.begin(), anOriginalFaces.end());
std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
if (anIndex < aNbFacesFromEdges)
aMakeShapeList->appendAlgo(aFaceBuilder);
+ else if(anIndex < aNbNonPlanarFaces)
+ aMakeShapeList->appendAlgo(aNonPlanarFaceBuilder);
GeomShapePtr aShape = *anIt;
GeomMakeShapePtr aCopy(new GeomAlgoAPI_Copy(aShape));
ListOfShape aBaseShapes;
if (anIndex < aNbFacesFromEdges)
aBaseShapes = anEdges;
+ else if(anIndex < aNbNonPlanarFaces)
+ aBaseShapes = aNonPlanarEdges;
else
aBaseShapes.push_back(aShape);
storeResult(aMakeShapeList, aBaseShapes, aContexts, aCopy->shape(), anIndex++);
removeResults(anIndex);
}
+//==================================================================================================
void BuildPlugin_Face::buildFacesByEdges(
const ListOfShape& theEdges,
const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(),
aWires, theFaces);
}
+
+//==================================================================================================
+void BuildPlugin_Face::buildNonPlanarFacesByEdges(
+ const ListOfShape& theShapes,
+ ListOfShape& theFaces,
+ std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const
+{
+
+ // Get faces.
+ std::shared_ptr<GeomAlgoAPI_NonPlanarFace> aNonPlanarFaceBuilder
+ (new GeomAlgoAPI_NonPlanarFace(theShapes));
+ theFaces = aNonPlanarFaceBuilder->faces();
+ theBuilderAlgo = aNonPlanarFaceBuilder;
+
+}
const std::list< std::shared_ptr<GeomAPI_Dir> >& theNormals,
std::list< std::shared_ptr<GeomAPI_Shape> >& theFaces,
std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const;
+
+ void buildNonPlanarFacesByEdges(const ListOfShape& theShapes,
+ ListOfShape& theFaces,
+ std::shared_ptr<GeomAlgoAPI_MakeShape>& theBuilderAlgo) const;
};
#endif
#include <GeomAlgoAPI_WireBuilder.h>
#include <GeomAlgoAPI_MakeVolume.h>
#include <GeomAlgoAPI_Tools.h>
+#include <GeomAlgoAPI_NonPlanarFace.h>
#include <GeomValidators_FeatureKind.h>
#include <GeomValidators_ShapeType.h>
bool hasFaces = false;
// Collect base shapes.
- ListOfShape anEdges;
+ ListOfShape anAllEdges;
+ ListOfShape aPlanarEdges;
+ ListOfShape aNonPlanarEdges;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
GeomShapePtr aShape = aSelection->value();
continue;
}
+ bool isPlanar(aShape->isPlanar());
for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
hasEdgesOrWires = true;
GeomShapePtr anEdge = anExp.current();
- anEdges.push_back(anEdge);
+ anAllEdges.push_back(anEdge);
+ isPlanar? aPlanarEdges.push_back(anEdge): aNonPlanarEdges.push_back(anEdge);
}
}
if (hasFaces && hasEdgesOrWires) {
theError = "Faces and edges/wires should be selected together.";
return false;
- } else if (hasEdgesOrWires && anEdges.empty()) {
+ } else if (hasEdgesOrWires && anAllEdges.empty()) {
theError = "Objects are not selected.";
return false;
}
// Check that edges does not have intersections.
- if(anEdges.size() > 1) {
- GeomAlgoAPI_PaveFiller aPaveFiller(anEdges, false);
+ if(anAllEdges.size() > 1) {
+ GeomAlgoAPI_PaveFiller aPaveFiller(anAllEdges, false);
if(!aPaveFiller.isDone()) {
theError = "Error while checking if edges intersects.";
return false;
anExp(aSectedEdges, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
anEdgesNum++;
}
- if(anEdgesNum != anEdges.size()) {
+ if(anEdgesNum != anAllEdges.size()) {
theError = "Selected objects have intersections.";
return false;
}
}
- if (!anEdges.empty()) {
+ //check only planar onjects
+ bool isPlanarBelongToOnePlane(false);
+ if (!aPlanarEdges.empty()) {
// Check that they are planar.
- std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
- if(!aPln.get()) {
- theError = "Selected object(s) should belong to only one plane.";
- return false;
+ std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(aPlanarEdges);
+ if(aPln.get()) {
+ // Check that selected objects have closed contours.
+ isPlanarBelongToOnePlane = true;
+ GeomAlgoAPI_SketchBuilder aBuilder(aPln, aPlanarEdges);
+ const ListOfShape& aFaces = aBuilder.faces();
+ if(aFaces.empty()) {
+ theError = "Selected planar objects do not generate closed contour.";
+ return false;
+ }
}
+ }
- // Check that selected objects have closed contours.
- GeomAlgoAPI_SketchBuilder aBuilder(aPln, anEdges);
- const ListOfShape& aFaces = aBuilder.faces();
+ //check non planar objects
+ if(!aNonPlanarEdges.empty() || (!aPlanarEdges.empty() && !isPlanarBelongToOnePlane))
+ {
+ GeomAlgoAPI_NonPlanarFace aNonPlanarFaceBuilder(isPlanarBelongToOnePlane? aNonPlanarEdges : anAllEdges);
+ const ListOfShape& aFaces = aNonPlanarFaceBuilder.faces();
if(aFaces.empty()) {
- theError = "Selected objects do not generate closed contour.";
+ theError = "Selected non-planar objects do not generate closed contour.";
return false;
}
}
--- /dev/null
+# Copyright (C) 2017-2023 CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# 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
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""Test de la création de faces gauches"""
+
+import salome
+
+salome.salome_init()
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Point
+l_noms = list()
+l_coo = list()
+l_coo.append((0, 0, 0))
+l_coo.append((1, 8, 0))
+l_coo.append((3, 10, 4))
+l_coo.append((5, 5, 5))
+l_coo.append((2, 3, 1))
+for iaux, (coo_x,coo_y,coo_z) in enumerate(l_coo):
+ point = model.addPoint(Part_1_doc, coo_x,coo_y,coo_z)
+ nom = "P_{}".format(iaux)
+ point.setName(nom)
+ point.result().setName(nom)
+ l_noms.append(nom)
+
+### Create Interpolation
+Interpolation_1_objects = list()
+for nom in l_noms:
+ Interpolation_1_objects.append(model.selection("VERTEX", "all-in-{}".format(nom)))
+Interpolation_1 = model.addInterpolation(Part_1_doc, Interpolation_1_objects, True, False)
+
+### Create Wire
+Wire_1 = model.addWire(Part_1_doc, [model.selection("EDGE", "Interpolation_1_1")], False)
+
+### Create Face
+Face_1 = model.addFace(Part_1_doc, [model.selection("WIRE", "Wire_1_1")])
+
+model.end()
+
+if salome.sg.hasDesktop():
+ salome.sg.updateObjBrowser()
--- /dev/null
+# Copyright (C) 2017-2023 CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# 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
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+import sys
+import salome
+
+salome.salome_init()
+import salome_notebook
+notebook = salome_notebook.NoteBook()
+sys.path.insert(0, r'/home/eksu/S2')
+
+###
+### SHAPER component
+###
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Points
+Point_2 = model.addPoint(Part_1_doc, 0, 0, 0)
+Point_3 = model.addPoint(Part_1_doc, 10, 0, 0)
+Point_4 = model.addPoint(Part_1_doc, 0, 10, 0)
+Point_5 = model.addPoint(Part_1_doc, 10, 10, 3)
+
+### Create Edges
+Edge_1 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Point_2"))
+Edge_2 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Edge_1_1/Modified_Vertex&Point_2/Point_2"), model.selection("VERTEX", "Point_4"))
+Edge_3 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Edge_2_1/Modified_Vertex&Point_4/Point_4"), model.selection("VERTEX", "Point_3"))
+Edge_4 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Point_3"), model.selection("VERTEX", "Point_1"))
+
+### Create Wire
+Wire_1_objects = [model.selection("EDGE", "Edge_1_1"),
+ model.selection("EDGE", "Edge_2_1"),
+ model.selection("EDGE", "Edge_4_1"),
+ model.selection("EDGE", "Edge_3_1")]
+Wire_1 = model.addWire(Part_1_doc, Wire_1_objects, False)
+
+### Create Face
+Face_1_objects = [model.selection("EDGE", "Wire_1_1/Modified_Edge&Edge_1_1/Edge_1_1"),
+ model.selection("EDGE", "Wire_1_1/Modified_Edge&Edge_2_1/Edge_2_1"),
+ model.selection("EDGE", "Wire_1_1/Modified_Edge&Edge_4_1/Edge_4_1"),
+ model.selection("EDGE", "Wire_1_1/Modified_Edge&Edge_3_1/Edge_3_1")]
+Face_1 = model.addFace(Part_1_doc, Face_1_objects)
+
+model.end()
+
+###
+### SHAPERSTUDY component
+###
+
+model.publishToShaperStudy()
+import SHAPERSTUDY
+Face_1_1, = SHAPERSTUDY.shape(model.featureStringId(Face_1))
+
+if salome.sg.hasDesktop():
+ salome.sg.updateObjBrowser()
Select one or several faces in viewer. Additionally, a face can be build by a closed wire or a set of edges composing a closed wire.
+It is possible to build a non-planar face by selecting non-planar wire or set of edges composing a closed wire, which do not belong to only one plane.
+
It is also possible to select a whole sketch result from the object browser. In this case, the smallest closed contour of the sketch will be transformed to the planar face.
**Apply** button creates faces.
Test20469.py
Test20513_1.py
Test20513_2.py
-)
\ No newline at end of file
+ TestNonPlanarFace.py
+ TestNonPlanarFace_Edges.py
+)
BRepBuilderAPI_FindPlane aFindPlane(aShape);
bool isFound = aFindPlane.Found() == Standard_True;
- if(!isFound && aShapeType == TopAbs_EDGE) {
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFirst, aLast);
- Handle(Standard_Type) aType = aCurve->DynamicType();
-
- if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
- Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
- aType = aTrimCurve->BasisCurve()->DynamicType();
- }
+ if(!isFound) {
+
+ auto checkEdge = [](const TopoDS_Shape& theShape){
+ if(theShape.ShapeType()!= TopAbs_EDGE)
+ return false;
+
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aFirst, aLast);
+ Handle(Standard_Type) aType = aCurve->DynamicType();
+ if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
+ Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+ aType = aTrimCurve->BasisCurve()->DynamicType();
+ }
- if(aType == STANDARD_TYPE(Geom_Line)
- || aType == STANDARD_TYPE(Geom_Conic)
- || aType == STANDARD_TYPE(Geom_Circle)
- || aType == STANDARD_TYPE(Geom_Ellipse)
- || aType == STANDARD_TYPE(Geom_Hyperbola)
- || aType == STANDARD_TYPE(Geom_Parabola)) {
- isFound = true;
+ if(aType == STANDARD_TYPE(Geom_Line)
+ || aType == STANDARD_TYPE(Geom_Conic)
+ || aType == STANDARD_TYPE(Geom_Circle)
+ || aType == STANDARD_TYPE(Geom_Ellipse)
+ || aType == STANDARD_TYPE(Geom_Hyperbola)
+ || aType == STANDARD_TYPE(Geom_Parabola)) {
+ return true;
+ }
+ return false;
+ };
+
+ if(aShapeType == TopAbs_WIRE){
+ //check if wire consist of only one edge
+ int aNbEdges = 0;
+ TopExp_Explorer anExp(aShape, TopAbs_EDGE);
+ for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
+ aNbEdges++;
+ if(aNbEdges == 1){
+ const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
+ isFound = checkEdge(anEdge);
+ }
+ else{
+ //if more than one edge, check is not valid
+ isFound = false;
+ break;
+ }
+ }
+ }
+ else if(aShapeType == TopAbs_EDGE){
+ isFound = checkEdge(aShape);
}
}
GeomAlgoAPI_GlueFaces.h
GeomAlgoAPI_LimitTolerance.h
GeomAlgoAPI_Utils.h
+ GeomAlgoAPI_NonPlanarFace.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_CanonicalRecognition.cpp
GeomAlgoAPI_LimitTolerance.cpp
GeomAlgoAPI_Utils.cpp
+ GeomAlgoAPI_NonPlanarFace.cpp
)
SET(PROJECT_LIBRARIES
%shared_ptr(GeomAlgoAPI_Rotation)
%shared_ptr(GeomAlgoAPI_Sewing)
%shared_ptr(GeomAlgoAPI_SketchBuilder)
+%shared_ptr(GeomAlgoAPI_NonPlanarFace)
%shared_ptr(GeomAlgoAPI_ShapeBuilder)
%shared_ptr(GeomAlgoAPI_Translation)
%shared_ptr(GeomAlgoAPI_Transform)
%include "GeomAlgoAPI_WireBuilder.h"
%include "GeomAlgoAPI_Sewing.h"
%include "GeomAlgoAPI_ShapeBuilder.h"
+%include "GeomAlgoAPI_NonPlanarFace.h"
%include "GeomAlgoAPI_Exception.h"
%include "GeomAlgoAPI_ShapeAPI.h"
%include "GeomAlgoAPI_Copy.h"
--- /dev/null
+// Copyright (C) 2014-2023 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <GeomAlgoAPI_NonPlanarFace.h>
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <BRepBuilderAPI_Copy.hxx>
+#include <BRepOffsetAPI_MakeFilling.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BOPTools_AlgoTools.hxx>
+
+#include <GeomAPI_Shape.h>
+#include <Geom_Surface.hxx>
+
+#include <ShapeFix_Face.hxx>
+#include <ShapeAnalysis_FreeBounds.hxx>
+#include <ShapeFix_ShapeTolerance.hxx>
+#include <TopTools_HSequenceOfShape.hxx>
+#include <TColStd_IndexedDataMapOfTransientTransient.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+//==================================================================================================
+GeomAlgoAPI_NonPlanarFace::GeomAlgoAPI_NonPlanarFace(
+ const ListOfShape& theEdges)
+{
+ build(theEdges);
+}
+
+//==================================================================================================
+void GeomAlgoAPI_NonPlanarFace::build
+ (const ListOfShape& theEdges)
+{
+ myResultFaces.clear();
+ setDone(false);
+ if (theEdges.empty())
+ {
+ return;
+ }
+
+ //prepare edges
+ Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
+ TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
+ TopTools_MapOfShape aMapEdges;
+ for (auto anEdge: theEdges)
+ {
+ const TopoDS_Edge& aTEdge = anEdge->impl<TopoDS_Edge>();
+ if (aMapEdges.Add(aTEdge))
+ {
+ BRepBuilderAPI_Copy aCopy(aTEdge, Standard_False, Standard_False);
+ const TopoDS_Shape& aCopyEdge = aCopy.Shape();
+ aSeqEdgesIn->Append(aCopyEdge);
+ }
+ }
+
+ // no edges
+ if (aSeqEdgesIn->IsEmpty())
+ {
+ return;
+ }
+
+ // Connect edges to wires of maximum length
+ Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
+ ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(), Standard_False, aSeqWiresOut);
+
+ // prepare compound result
+ BRep_Builder aBuilder;
+ TopoDS_Compound aResult;
+ aBuilder.MakeCompound(aResult);
+
+ // try to construct face for each non-planar wire
+ for(int ind = 1; ind <= aSeqWiresOut->Length(); ind++)
+ {
+ if(!aSeqWiresOut->Value(ind).Closed())
+ {
+ continue;
+ }
+ TopoDS_Wire aWire = TopoDS::Wire(aSeqWiresOut->Value(ind));
+
+ // try to construct filling surface
+ BRepOffsetAPI_MakeFilling aMF;
+ BRepTools_WireExplorer aWExp(aWire);
+ for (; aWExp.More(); aWExp.Next())
+ {
+ aMF.Add(TopoDS::Edge(aWExp.Current()), GeomAbs_C0);
+ }
+ aMF.Build();
+ if (!aMF.IsDone())
+ {
+ return;
+ }
+ // Result of filling
+ TopoDS_Shape aFillRes = aMF.Shape();
+ Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFillRes));
+ BRepBuilderAPI_MakeFace aMakeFace(aGS, aWire);
+ if (aMakeFace.IsDone())
+ {
+ TopoDS_Face aNewFace = aMakeFace.Face();
+ Handle(ShapeFix_Face) aFix = new ShapeFix_Face(aNewFace);
+ aFix->Perform();
+ aFix->FixOrientation();
+ aNewFace = aFix->Face();
+
+ //check and fix pcurves, if necessary
+ TopExp_Explorer aExpE;
+ Standard_Real aT, aTolE, aDMax;
+ ShapeFix_ShapeTolerance sat;
+ aExpE.Init(aNewFace, TopAbs_EDGE);
+ for (; aExpE.More(); aExpE.Next())
+ {
+ const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
+ if (!BOPTools_AlgoTools::ComputeTolerance(aNewFace, aE, aDMax, aT)) continue;
+ aTolE = BRep_Tool::Tolerance(aE);
+ if (aDMax < aTolE) continue;
+
+ sat.LimitTolerance(aE, aDMax);
+ }
+
+ // store face
+ aBuilder.Add(aResult, aNewFace);
+ std::shared_ptr<GeomAPI_Shape> aResFace(new GeomAPI_Shape);
+ 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);
+}
--- /dev/null
+// Copyright (C) 2014-2023 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef GeomAlgoAPI_NonPlanarFace_H_
+#define GeomAlgoAPI_NonPlanarFace_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+/** \class GeomAlgoAPI_NonPlanarFace
+ * \ingroup DataAlgo
+ * \brief Creates non planar faces
+ */
+class GeomAlgoAPI_NonPlanarFace : public GeomAlgoAPI_MakeShape
+{
+public:
+
+ /// Creates list of faces based on the non-planar wires
+ /// \param theEdges list of input non-planar edges.
+ GEOMALGOAPI_EXPORT
+ GeomAlgoAPI_NonPlanarFace(const ListOfShape& theEdges);
+
+ /// Return list of created faces
+ GEOMALGOAPI_EXPORT const ListOfShape& faces() const
+ { return myResultFaces; }
+
+private:
+ /// \brief Perform operation
+ /// \param theEdges list of selected wires.
+ GEOMALGOAPI_EXPORT void build(const ListOfShape& theEdges);
+
+ std::list<std::shared_ptr<GeomAPI_Shape> > myResultFaces;
+};
+
+#endif
#include "GeomAlgoAPI_Rotation.h"
#include "GeomAlgoAPI_ShapeTools.h"
#include "GeomAlgoAPI_SketchBuilder.h"
+ #include "GeomAlgoAPI_NonPlanarFace.h"
#include "GeomAlgoAPI_BREPExport.h"
#include "GeomAlgoAPI_IGESExport.h"
#include "GeomAlgoAPI_STEPExport.h"