[EDF] (2023-T3) Creation of a non planar face from a list of edges and points

This commit is contained in:
Ekaterina Sukhareva 2024-03-26 18:22:07 +00:00
parent 0f3f338dc8
commit 5f12362860
20 changed files with 1231 additions and 0 deletions

View File

@ -92,6 +92,7 @@ FIND_PACKAGE(SalomeOmniORB REQUIRED)
FIND_PACKAGE(SalomeOmniORBPy REQUIRED)
FIND_PACKAGE(SalomeLibXml2 REQUIRED)
FIND_PACKAGE(SalomeHDF5 REQUIRED COMPONENTS C)
FIND_PACKAGE(Eigen3 3.2.5 REQUIRED)
# Other KERNEL optionals:
IF(SALOME_BUILD_TESTS)

View File

@ -47,12 +47,37 @@ face5 = geompy.MakeFaceWithConstraints([geompy.GetSubShape(cut, [5]), geompy.Get
geompy.GetSubShape(cut, [11]), geompy.GetSubShape(cut, [3]),
geompy.GetSubShape(cut, [13]), geompy.GetSubShape(cut, [3])])
# create circle from 3 points
pCirc1 = geompy.MakeVertex(17.274575, 63.776413, 50.610737)
pCirc2 = geompy.MakeVertex(37.5, 49.081782, 127.552826)
pCirc3 = geompy.MakeVertex(62.5, 78.471044, 50.610737)
Circle_1 = geompy.MakeCircleThreePnt(pCirc1, pCirc2, pCirc3)
listE = []
listE.append(Circle_1)
# create list of points
listV = []
pV1 = geompy.MakeVertex(64.694631, 85.225425, 64.54915)
listV.append(pV1)
pV2 = geompy.MakeVertex(11.528956, 67.95085, 95.45085)
listV.append(pV2)
pV3 = geompy.MakeVertex(36.233192, 82.369878, 102.699525)
listV.append(pV3)
pV4 = geompy.MakeVertex(35.305369, 85.225425, 64.54915)
listV.append(pV4)
pV5 = geompy.MakeVertex(50, 75.355339, 115.355339)
listV.append(pV5)
# create face from edges and points
face6 = geompy.MakeWrappedFace(listE, listV, 1e-5)
# add objects in the study
id_face1 = geompy.addToStudy(face1,"Face1")
id_face2 = geompy.addToStudy(face2,"Face2")
id_face3 = geompy.addToStudy(face3,"Face3")
id_face4 = geompy.addToStudy(face4,"Face4")
id_face5 = geompy.addToStudy(face5,"Face5")
id_face6 = geompy.addToStudy(face5,"Face6")
# display the faces
gg.createAndDisplayGO(id_face1)
@ -70,3 +95,6 @@ gg.setTransparency(id_face4,0.2)
gg.createAndDisplayGO(id_face5)
gg.setDisplayMode(id_face5,1)
gg.setTransparency(id_face5,0.2)
gg.createAndDisplayGO(id_face6)
gg.setDisplayMode(id_face6,1)
gg.setTransparency(id_face6,0.2)

View File

@ -2066,6 +2066,17 @@ module GEOM
GEOM_Object MakeFaceFromSurface(in GEOM_Object theFace,
in GEOM_Object theWire);
/**
* \brief Create non planar face with list of edges and list of vertices
* \param theEdges list of Edges(must be closed but not nesessarily belong to the same plane) .
* \param theVertices list of vertices through which the result face must pass.
* \param theTolerance tolerance.
* \return New GEOM_Object, containing the created face.
*/
GEOM_Object MakeWrappedFace(in ListOfGO theEdges,
in ListOfGO theVertices,
in double theTolerance);
/*!
* \brief Create a face from a set of edges with the given constraints.
* \param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples):

View File

@ -25,6 +25,7 @@ INCLUDE_DIRECTORIES(
${PTHREAD_INCLUDE_DIR}
${KERNEL_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${PROJECT_SOURCE_DIR}/src/ShHealOper
${PROJECT_SOURCE_DIR}/src/GEOM
${PROJECT_SOURCE_DIR}/src/BlockFix
@ -187,6 +188,8 @@ SET(GEOMImpl_HEADERS
GEOMImpl_Types.hxx
GEOM_GEOMImpl.hxx
GEOMImpl_ICanonicalRecognition.hxx
GEOMImpl_WrappingDriver.hxx
GEOMImpl_IWrap.hxx
)
# --- sources ---
@ -266,6 +269,7 @@ SET(GEOMImpl_SOURCES
GEOMImpl_ShapeProximityDriver.cxx
GEOMImpl_FieldDriver.cxx
GEOMImpl_ICanonicalRecognition.cxx
GEOMImpl_WrappingDriver.cxx
)
# --- rules ---

View File

@ -85,6 +85,7 @@
#include <GEOMImpl_FieldDriver.hxx>
#include <GEOMImpl_ConformityDriver.hxx>
#include <GEOMImpl_ShapeProximityDriver.hxx>
#include <GEOMImpl_WrappingDriver.hxx>
//=============================================================================
/*!
@ -171,6 +172,9 @@ GEOMImpl_Gen::GEOMImpl_Gen()
// Field
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FieldDriver::GetID(), new GEOMImpl_FieldDriver());
// Wrapping
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_WrappingDriver::GetID(), new GEOMImpl_WrappingDriver());
/*@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@*/
SetEngine(this);

View File

@ -35,6 +35,7 @@
#include "GEOMImpl_ShapeDriver.hxx"
#include "GEOMImpl_GlueDriver.hxx"
#include "GEOMImpl_FillingDriver.hxx"
#include "GEOMImpl_WrappingDriver.hxx"
#include "GEOMImpl_IExtract.hxx"
#include "GEOMImpl_IVector.hxx"
@ -42,6 +43,7 @@
#include "GEOMImpl_IShapeExtend.hxx"
#include "GEOMImpl_IGlue.hxx"
#include "GEOMImpl_IFilling.hxx"
#include "GEOMImpl_IWrap.hxx"
#include "GEOMImpl_Block6Explorer.hxx"
#include "GEOMImpl_IHealingOperations.hxx"
@ -648,6 +650,99 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
return aShape;
}
//=============================================================================
/*!
* MakeWrappedFace
*/
//=============================================================================
Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWrappedFace
(std::list<Handle(GEOM_Object)> theEdges,
std::list<Handle(GEOM_Object)> theVertices,
const Standard_Real theTolerance)
{
SetErrorCode(KO);
//Add a new object
Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
//Add a new function
Handle(GEOM_Function) aFunction =
aShape->AddFunction(GEOMImpl_WrappingDriver::GetID(), WRAPPING_FACE);
if (aFunction.IsNull()) return NULL;
//Check if the function is set correctly
if (aFunction->GetDriverGUID() != GEOMImpl_WrappingDriver::GetID()) return NULL;
GEOMImpl_IWrap aCI (aFunction);
aCI.SetTolerance(theTolerance);
// Edges
Handle(TColStd_HSequenceOfTransient) anEdgesSeq = new TColStd_HSequenceOfTransient;
std::list<Handle(GEOM_Object)>::iterator it = theEdges.begin();
for (; it != theEdges.end(); it++) {
Handle(GEOM_Object) anEdge = (*it);
if ( anEdge.IsNull() || anEdge->GetValue().ShapeType() != TopAbs_EDGE ) {
SetErrorCode("NULL argument edge for the face construction");
return NULL;
}
Handle(GEOM_Function) aRefSh = anEdge->GetLastFunction();
anEdgesSeq->Append(aRefSh);
}
aCI.SetEdges(anEdgesSeq);
// Vertices
Handle(TColStd_HSequenceOfTransient) aVerticesSeq = new TColStd_HSequenceOfTransient;
it = theVertices.begin();
for (; it != theVertices.end(); it++) {
Handle(GEOM_Object) aVertex = (*it);
if ( aVertex.IsNull() || aVertex->GetValue().ShapeType() != TopAbs_VERTEX ) {
SetErrorCode("NULL argument vertex for the face construction");
return NULL;
}
Handle(GEOM_Function) aRefSh = aVertex->GetLastFunction();
aVerticesSeq->Append(aRefSh);
}
aCI.SetVertices(aVerticesSeq);
//Compute the face
try {
OCC_CATCH_SIGNALS;
if (!GetSolver()->ComputeFunction(aFunction)) {
SetErrorCode("Wrap driver failed");
return NULL;
}
}
catch (Standard_Failure& aFail) {
SetErrorCode(aFail.GetMessageString());
return NULL;
}
//Make a Python command
GEOM::TPythonDump pd (aFunction);
pd << aShape << " = geompy.MakeWrappedFace([";
// Edges
it = theEdges.begin();
if (it != theEdges.end()) {
pd << (*it++);
while (it != theEdges.end()) {
pd << ", " << (*it++);
}
}
pd << "], [";
// Vertices
it = theVertices.begin();
if (it != theVertices.end()) {
pd << (*it++);
while (it != theVertices.end()) {
pd << ", " << (*it++);
}
}
pd << "], " << theTolerance << ")";
SetErrorCode(OK);
return aShape;
}
//=============================================================================
/*!
* MakeFaceWithConstraints

View File

@ -104,6 +104,10 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
Standard_EXPORT Handle(GEOM_Object) MakeFaceFromSurface
(Handle(GEOM_Object) theFace,
Handle(GEOM_Object) theWire);
Standard_EXPORT Handle(GEOM_Object) MakeWrappedFace(std::list<Handle(GEOM_Object)> theEdges,
std::list<Handle(GEOM_Object)> theVertices,
const Standard_Real theTolerance);
Standard_EXPORT Handle(GEOM_Object) MakeFaceWithConstraints (std::list<Handle(GEOM_Object)> theConstraints);

View File

@ -0,0 +1,58 @@
// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// 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
//
//NOTE: This is an interface to a function for the Box creation.
//
#include "GEOM_Function.hxx"
class GEOMImpl_IWrap
{
public:
enum {
WRAP_ARG_EDGES = 1, // list of edges
WRAP_ARG_VERTICES = 2, // list of vertices
WRAP_TOLER = 3, // tolerance
};
GEOMImpl_IWrap(Handle(GEOM_Function) theFunction): _func(theFunction) {}
void SetEdges(const Handle(TColStd_HSequenceOfTransient)& theShapes)
{ _func->SetReferenceList(WRAP_ARG_EDGES, theShapes); }
Handle(TColStd_HSequenceOfTransient) GetEdges()
{ return _func->GetReferenceList(WRAP_ARG_EDGES); }
void SetVertices(const Handle(TColStd_HSequenceOfTransient)& theShapes)
{ _func->SetReferenceList(WRAP_ARG_VERTICES, theShapes); }
Handle(TColStd_HSequenceOfTransient) GetVertices()
{ return _func->GetReferenceList(WRAP_ARG_VERTICES); }
void SetTolerance(double theTol) { _func->SetReal(WRAP_TOLER, theTol); }
double GetTolerance() { return _func->GetReal(WRAP_TOLER); }
private:
Handle(GEOM_Function) _func;
};

View File

@ -327,6 +327,8 @@
#define SOLID_FACES 19
#define EXTRACTION 20
#define WRAPPING_FACE 1
#define ARCHIMEDE_TYPE 1
// Shape Healing operators

View File

@ -0,0 +1,452 @@
// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// 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 <GEOMImpl_WrappingDriver.hxx>
#include <GEOMAlgo_Splitter.hxx>
#include <GEOMUtils.hxx>
#include <GEOMImpl_ShapeDriver.hxx>
#include <GEOMImpl_IWrap.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOMImpl_Block6Explorer.hxx>
#include <GEOM_Object.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#if OCC_VERSION_LARGE < 0x07070000
#include <BRepAdaptor_HSurface.hxx>
#else
#include <BRepAdaptor_Surface.hxx>
#endif
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_BSplineSurface.hxx>
#include <GeomPlate_Surface.hxx>
#include <GeomPlate_BuildPlateSurface.hxx>
#include <GeomPlate_PointConstraint.hxx>
#include <GeomPlate_MakeApprox.hxx>
#include <GeomPlate_BuildAveragePlane.hxx>
#include <gp_Pnt.hxx>
#include <gp_Sphere.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Vertex.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <TColStd_HSequenceOfTransient.hxx>
#include <ShapeFix_Face.hxx>
#include <Standard_NullObject.hxx>
#include <numeric>
#include <vector>
#include <Eigen/Dense>
//=======================================================================
// function : GetID
// purpose :
//=======================================================================
const Standard_GUID &GEOMImpl_WrappingDriver::GetID()
{
static Standard_GUID aWrapDriver("FF1BBB71-729D-4E83-8232-78E74FC5637C");
return aWrapDriver;
}
//=======================================================================
// function : GEOMImpl_WrappingDriver
// purpose :
//=======================================================================
GEOMImpl_WrappingDriver::GEOMImpl_WrappingDriver()
{
}
//=======================================================================
// function : createPointsOnEdges
// purpose : create points on edges
//=======================================================================
static void createPointsOnEdges(const Handle(TColStd_HSequenceOfTransient) & theEdgesFuncs,
std::vector<gp_Pnt> &thePoints)
{
for (int i = 1; i <= theEdgesFuncs->Length(); i++)
{
Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(i));
TopoDS_Shape aShape_i = aRefShape->GetValue();
if (aShape_i.IsNull())
{
Standard_NullObject::Raise("Edge for face construction is null");
}
TopExp_Explorer exp(aShape_i, TopAbs_EDGE);
for (; exp.More(); exp.Next())
{
Standard_Real aFP, aLP, aP;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(exp.Current()), aFP, aLP);
if (!aCurve.IsNull())
{
for (int aPar = 1; aPar <= 9; aPar++)
{
aP = aFP + (aLP - aFP) * (aPar * 0.1);
gp_Pnt aPnt = aCurve->Value(aP);
thePoints.push_back(aPnt);
}
}
}
}
}
//================================================================================
// function : maxDistanceToFace
// purpose : finds max distanse between points and a face
//================================================================================
static Standard_Real maxDistanceToFace(const std::vector<gp_Pnt>& thePoints,
const TopoDS_Face& theFace,
const Standard_Real theTolerance)
{
Standard_Real U, V;
Standard_Real aMaxDist = 0.;
for(auto& aPnt : thePoints)
{
gp_Pnt aProj = GEOMUtils::ProjectPointOnFace(aPnt, theFace,U,V,theTolerance);
Standard_Real aDist = aProj.Distance(aPnt);
if(aDist > aMaxDist)
{
aMaxDist = aDist;
}
}
return aMaxDist;
}
//================================================================================
// function : divideSphericalShape
// purpose : divide spherical shape into two piece
// and choose that part that has the points
//================================================================================
static void divideSphericalShape(TopoDS_Shape &theShape,
const TopoDS_Wire &theWire,
const std::vector<gp_Pnt> &thePoints,
const Standard_Real theTolerance)
{
TopExp_Explorer anExp(theShape, TopAbs_FACE);
const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
TopoDS_Face aToolFace;
GEOMImpl_Block6Explorer::MakeFace(theWire, false, aToolFace);
if(!aToolFace.IsNull())
{
//split sphere and choose right part
GEOMAlgo_Splitter PS;
PS.AddArgument(aFace);
PS.AddTool(aToolFace);
PS.SetLimit(TopAbs_FACE);
PS.Perform();
TopoDS_Shape aResultShape = PS.Shape();
if(!aResultShape.IsNull())
{
anExp.Init(aResultShape, TopAbs_FACE);
for (; anExp.More(); anExp.Next())
{
Standard_Real aDist = maxDistanceToFace(thePoints, TopoDS::Face(anExp.Current()), theTolerance);
if(aDist < theTolerance)
{
theShape = TopoDS::Face(anExp.Current());
break;
}
}
}
}
}
//================================================================================
// function : makeFaceFromPointsAndWire
// purpose : Create face from set of points with the same approach as for
// geompy.makeSmoothingSurface. Cut resulting surface with a wire
//================================================================================
static TopoDS_Shape makeFaceFromPointsAndWire(const TopoDS_Wire &theWire,
const std::vector<gp_Pnt> &theAllPoints)
{
int nbPoints = theAllPoints.size();
Handle(TColgp_HArray1OfPnt) anArrayofPnt = new TColgp_HArray1OfPnt(1, nbPoints);
for (int i = 0; i < nbPoints; i++) {
gp_Pnt aP = theAllPoints[i];
anArrayofPnt->SetValue(i+1, aP);
}
// Try to build smoothing surface
GeomPlate_BuildAveragePlane gpbap(anArrayofPnt,anArrayofPnt->Length(),Precision::Confusion(),1,1);
Handle(Geom_Plane) plane(gpbap.Plane());
Standard_Real Umin, Umax, Vmin, Vmax;
gpbap.MinMaxBox(Umin,Umax,Vmin,Vmax);
TopoDS_Face aInitShape;
BRepBuilderAPI_MakeFace mf(plane,Umin,Umax,Vmin,Vmax,Precision::Confusion());
aInitShape = mf.Face();
GeomPlate_BuildPlateSurface aBuilder(3,10);
// ** Initialization of surface
#if OCC_VERSION_LARGE < 0x07070000
Handle(BRepAdaptor_HSurface) HSI = new BRepAdaptor_HSurface();
HSI->ChangeSurface().Initialize(aInitShape);
aBuilder.LoadInitSurface( BRep_Tool::Surface(HSI->ChangeSurface().Face()));
#else
Handle(BRepAdaptor_Surface) HSI = new BRepAdaptor_Surface();
HSI->Initialize(aInitShape);
aBuilder.LoadInitSurface( BRep_Tool::Surface(HSI->Face()) );
#endif
Standard_Integer j, j1, j2;
j1 = anArrayofPnt->Lower();
j2 = anArrayofPnt->Upper();
for (j=j1; j<=j2 ; j++)
{
gp_Pnt aPnt = anArrayofPnt->Value(j);
Handle(GeomPlate_PointConstraint) PCont = new GeomPlate_PointConstraint(aPnt,0);
aBuilder.Add(PCont);
}
aBuilder.Perform();
Handle(GeomPlate_Surface) gpPlate = aBuilder.Surface();
if(gpPlate.IsNull())
{
Standard_ConstructionError::Raise("Not possible to build a face with given input, GeomPlate_Surface failed");
}
Standard_Real seuil = Max(0.0001,10*aBuilder.G0Error());
GeomPlate_MakeApprox Mapp(gpPlate,0.0001,2,8,seuil);
Handle(Geom_Surface) aSurf(Mapp.Surface());
//cut surface with a face
TopoDS_Shape aShape;
BRepBuilderAPI_MakeFace aMkFace(aSurf, theWire);
if (aMkFace.IsDone())
{
aShape = aMkFace.Shape();
}
TopoDS_Face aFace = TopoDS::Face(aShape);
Handle(ShapeFix_Face) aFix = new ShapeFix_Face(aFace);
aFix->Perform();
aFix->FixOrientation();
aFace = aFix->Face();
return aFace;
}
//=======================================================================
// function : Execute
// purpose :
//=======================================================================
Standard_Integer GEOMImpl_WrappingDriver::Execute(Handle(TFunction_Logbook) & log) const
{
if (Label().IsNull())
return 0;
Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
GEOMImpl_IWrap aCI(aFunction);
Standard_Integer aType = aFunction->GetType();
TopoDS_Shape aShape;
if (aType == WRAPPING_FACE)
{
Handle(TColStd_HSequenceOfTransient) anEdges = aCI.GetEdges();
Handle(TColStd_HSequenceOfTransient) aVertices = aCI.GetVertices();
int nbEdge = anEdges->Length();
int nbVertices = aVertices->Length();
if (nbEdge < 1 || nbVertices < 1)
{
Standard_ConstructionError::Raise("No edges or vertices given");
}
Standard_Real aTolerance = aCI.GetTolerance();
if (aTolerance < Precision::Confusion())
aTolerance = Precision::Confusion();
std::vector<gp_Pnt> anAllPoints, aPoints;
createPointsOnEdges(anEdges, anAllPoints);
for (int i = 1; i <= aVertices->Length(); i++)
{
Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aVertices->Value(i));
TopoDS_Shape aShape_i = aRefShape->GetValue();
if (aShape_i.IsNull())
{
Standard_NullObject::Raise("Vertex for face construction is null");
}
TopExp_Explorer exp (aShape_i, TopAbs_VERTEX);
for (; exp.More(); exp.Next())
{
gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()));
anAllPoints.push_back(aP);
aPoints.push_back(aP);
}
}
if(anAllPoints.size() == 0)
{
Standard_NullObject::Raise("Shape creation imposible, no valid objects were given");
}
//create wire from edges
TopoDS_Wire aWire = GEOMImpl_ShapeDriver::MakeWireFromEdges(anEdges, aTolerance);
if(aWire.IsNull())
{
Standard_NullObject::Raise("Given edges does not create closed contour");
}
aShape = createWrappedFace(aWire, anAllPoints, aPoints, aTolerance);
}
if (aShape.IsNull())
return 0;
aFunction->SetValue(aShape);
log->SetTouched(Label());
return 1;
}
//================================================================================
/*!
* \brief Create wrapped face from vector of points and wire
*/
//================================================================================
TopoDS_Shape GEOMImpl_WrappingDriver::createWrappedFace(const TopoDS_Wire &theWire,
const std::vector<gp_Pnt> &theAllPoints,
const std::vector<gp_Pnt> &thePoints,
const Standard_Real theTolerance) const
{
TopoDS_Shape aShape;
gp_Pnt aCenter(0,0,0);
Standard_Real aRadius = 100;
if(isSphere(theAllPoints, aCenter, aRadius, theTolerance))
{
aShape = BRepPrimAPI_MakeSphere(aCenter, aRadius).Shape();
divideSphericalShape(aShape, theWire, thePoints, theTolerance);
return aShape;
}
aShape = makeFaceFromPointsAndWire(theWire, theAllPoints);
return aShape;
}
//================================================================================
/*!
* \brief Returns a name of creation operation and names and values of creation parameters
*/
//================================================================================
Standard_Boolean GEOMImpl_WrappingDriver::isSphere(const std::vector<gp_Pnt>& thePoints,
gp_Pnt& theCenter,
Standard_Real& theRadius,
const Standard_Real theTolerance)const
{
int aNumPoints = thePoints.size();
if(aNumPoints == 0)
{
return false;
}
// Create coefficient matrix A and right-hand side vector f
Eigen::MatrixXd A(aNumPoints, 4);
Eigen::VectorXd f(aNumPoints);
Standard_Real X(.0);
Standard_Real Y(.0);
Standard_Real Z(.0);
for (int i = 0; i < aNumPoints; ++i)
{
X = thePoints[i].X();
Y = thePoints[i].Y();
Z = thePoints[i].Z();
A(i, 0) = X * 2;
A(i, 1) = Y * 2;
A(i, 2) = Z * 2;
A(i, 3) = 1.0;
f(i) = X * X + Y * Y + Z * Z;
}
// Solve linear equations to get coefficients
Eigen::VectorXd c = A.colPivHouseholderQr().solve(f);
Standard_Real t = c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3];
theRadius = std::sqrt(t);
theCenter.SetCoord(c[0], c[1], c[2]);
//check that all points belong to the sphere within theTolerance
std::vector<Standard_Real> aDists;
for(const auto& aPnt : thePoints)
{
aDists.push_back(aPnt.Distance(theCenter));
}
if (!aDists.empty())
{
Standard_Real sumDistances = std::accumulate(aDists.begin(), aDists.end(), 0.0);
Standard_Real averageDistance = sumDistances / aDists.size();
if (std::fabs(averageDistance - theRadius) > theTolerance) {
return false;
}
}
return true;
}
//================================================================================
/*!
* \brief Returns a name of creation operation and names and values of creation parameters
*/
//================================================================================
bool GEOMImpl_WrappingDriver::
GetCreationInformation(std::string &theOperationName,
std::vector<GEOM_Param> &theParams)
{
if (Label().IsNull()) return 0;
Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
GEOMImpl_IWrap aCI( function );
Standard_Integer aType = function->GetType();
theOperationName = "WRAPPEDFACE";
switch ( aType ) {
case WRAPPING_FACE:
AddParam(theParams, "Edges", aCI.GetEdges());
AddParam(theParams, "Vertices", aCI.GetVertices());
AddParam(theParams, "Tolerance", aCI.GetTolerance());
break;
default:
return false;
}
return true;
}
IMPLEMENT_STANDARD_RTTIEXT(GEOMImpl_WrappingDriver, GEOM_BaseDriver)

View File

@ -0,0 +1,68 @@
// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// 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
//
// File : GEOMImpl_WrappingDriver.hxx
// Module : GEOMImpl
//
#ifndef _GEOMImpl_WrappingDriver_HeaderFile
#define _GEOMImpl_WrappingDriver_HeaderFile
#include <GEOM_BaseDriver.hxx>
class TopoDS_Wire;
class TopoDS_Face;
class TColgp_HArray1OfPnt;
DEFINE_STANDARD_HANDLE( GEOMImpl_WrappingDriver, GEOM_BaseDriver )
class GEOMImpl_WrappingDriver : public GEOM_BaseDriver {
public:
Standard_EXPORT GEOMImpl_WrappingDriver();
Standard_EXPORT ~GEOMImpl_WrappingDriver() {};
Standard_EXPORT virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
Standard_EXPORT virtual void Validate(Handle(TFunction_Logbook)&) const {}
Standard_EXPORT Standard_Boolean MustExecute(const Handle(TFunction_Logbook)&) const { return Standard_True; }
Standard_EXPORT static const Standard_GUID& GetID();
Standard_EXPORT virtual
bool GetCreationInformation(std::string& theOperationName,
std::vector<GEOM_Param>& params);
DEFINE_STANDARD_RTTIEXT(GEOMImpl_WrappingDriver,GEOM_BaseDriver)
private:
TopoDS_Shape createWrappedFace(const TopoDS_Wire& theWire,
const std::vector<gp_Pnt>& theAllPoints,
const std::vector<gp_Pnt>& thePoints,
const Standard_Real theTolerance)const;
Standard_Boolean isSphere(const std::vector<gp_Pnt>& thePoints,
gp_Pnt& theCenter,
Standard_Real& theRadius,
const Standard_Real theTolerance)const;
};
#endif

View File

@ -310,6 +310,47 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeFaceFromSurface
return GetObject(anObject);
}
//=============================================================================
/*!
* MakeWrappedFace
*/
//=============================================================================
GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeWrappedFace
(const GEOM::ListOfGO& theEdges,
const GEOM::ListOfGO& theVertices,
const CORBA::Double theTolerance)
{
GEOM::GEOM_Object_var aGEOMObject;
//Set a not done flag
GetOperations()->SetNotDone();
//Get the edges
std::list<Handle(::GEOM_Object)> anEdges;
for( CORBA::ULong ind = 0; ind < theEdges.length(); ind++ ) {
Handle(::GEOM_Object) anObject = GetObjectImpl( theEdges[ind] );
anEdges.push_back(anObject);
}
//Get the vertices
std::list<Handle(::GEOM_Object)> aVertices;
for( CORBA::ULong ind = 0; ind < theVertices.length(); ind++ ) {
Handle(::GEOM_Object) anObject = GetObjectImpl( theVertices[ind] );
aVertices.push_back(anObject);
}
//Create the Face
Handle(::GEOM_Object) anObject =
GetOperations()->MakeWrappedFace(anEdges, aVertices, theTolerance);
// enable warning status
if (anObject.IsNull())
return aGEOMObject._retn();
return GetObject(anObject);
}
//=============================================================================
/*!
* MakeFaceWithConstraints

View File

@ -67,6 +67,10 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i :
GEOM::GEOM_Object_ptr MakeFaceFromSurface(GEOM::GEOM_Object_ptr theFace,
GEOM::GEOM_Object_ptr theWire);
GEOM::GEOM_Object_ptr MakeWrappedFace(const GEOM::ListOfGO& theEdges,
const GEOM::ListOfGO& theVertices,
const CORBA::Double theTolerance);
GEOM::GEOM_Object_ptr MakeFaceWithConstraints (const GEOM::ListOfGO& theConstraints);
GEOM::GEOM_Object_ptr MakeShell (const GEOM::ListOfGO& theFacesAndShells);

View File

@ -4878,6 +4878,39 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
RaiseIfFailed("MakeFaceFromSurface", self.ShapesOp)
self._autoPublish(anObj, theName, "face")
return anObj
## Create a non-planar face from a list of closed edges and a list of vertices.
# @param theEdges list of Edges(must be closed but not nesessarily belong to the same plane).
# @param theVertices list of vertices through which the result face must pass.
# @param theTolerance tolerance
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created face.
#
# @ref tui_creation_face "Example"
@ManageTransactions("ShapesOp")
def MakeWrappedFace(self, theEdges, theVertices, theTolerance, theName=None):
"""
Create a non-planar face from a list of closed edges and a list of vertices.
Parameters:
theEdges list of Edges(must be closed but not nesessarily belong to the same plane).
theVertices list of vertices through which the result face must pass.
theTolerance tolerance
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created face.
"""
# Example: see GEOM_TestAll.py
anObj = self.ShapesOp.MakeWrappedFace(theEdges, theVertices, theTolerance)
RaiseIfFailed("MakeWrappedFace", self.ShapesOp)
self._autoPublish(anObj, theName, "face")
return anObj
## Create a face from a set of edges with the given constraints.
# @param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples):

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,60 @@
DBRep_DrawableShape
CASCADE Topology V1, (c) Matra-Datavision
Locations 0
Curve2ds 0
Curves 0
Polygon3D 0
PolygonOnTriangulations 0
Surfaces 0
Triangulations 0
TShapes 7
Ve
1e-07
30.9016994374947 95.1056516295154 60
0 0
0101101
*
Ve
1e-07
53.5826794978997 84.4327925502015 90
0 0
0101101
*
Ve
1e-07
95.1056516295154 30.9016994374947 75
0 0
0101101
*
Ve
1e-07
80.9016994374947 58.7785252292473 120
0 0
0101101
*
Ve
1e-07
92.9776485888251 36.8124552684678 135
0 0
0101101
*
Ve
1e-07
30.9016994374947 95.1056516295154 129
0 0
0101101
*
Co
1100000
+7 0 +6 0 +5 0 +4 0 +3 0 +2 0 *
+1 0

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,53 @@
DBRep_DrawableShape
CASCADE Topology V1, (c) Matra-Datavision
Locations 0
Curve2ds 0
Curves 0
Polygon3D 0
PolygonOnTriangulations 0
Surfaces 0
Triangulations 0
TShapes 6
Ve
1e-07
-98.2778854144335 12.9942378002121 13.1379991802029
0 0
0101101
*
Ve
1e-07
-62.4980389121083 48.4176397451153 61.2350168910961
0 0
0101101
*
Ve
1e-07
-91.4519040662823 -38.2576611431453 -13.1491675214732
0 0
0101101
*
Ve
1e-07
-78.3669668760696 -10.4350950638792 61.2350168910961
0 0
0101101
*
Ve
1e-07
-85.1638454334068 35.5349860871206 -38.5277068456318
0 0
0101101
*
Co
1100000
+6 0 +5 0 +4 0 +3 0 +2 0 *
+1 0

46
test/test_WrappedFace.py Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env python
import sys
import salome
salome.salome_init()
import GEOM
from salome.geom import geomBuilder
import math
from inspect import getfile
from os.path import abspath, dirname, join
import SALOMEDS
geompy = geomBuilder.New()
data_dir = abspath(join(dirname(getfile(lambda: None)), 'data'))
myInitFace = geompy.ImportBREP(join(data_dir, 'WrappedFace_sphere_face.brep'))
listE = geompy.ExtractShapes(myInitFace, geompy.ShapeType["EDGE"], True)
myVertices = geompy.ImportBREP(join(data_dir, 'WrappedFace_sphere_vertices.brep'))
lVertices = geompy.SubShapeAll(myVertices, geompy.ShapeType["VERTEX"])
wrappedFaceSphere = geompy.MakeWrappedFace(listE, lVertices, 0.01)
wrappedAreaSphere = geompy.BasicProperties(wrappedFaceSphere)[1]
eps = 1e-5
expectedArea = 47123.88980388897
print(wrappedAreaSphere)
assert(math.fabs(expectedArea - wrappedAreaSphere) < eps)
###########################################################################
myEdges = geompy.ImportBREP(join(data_dir, 'WrappedFace_bspline_edges.brep'))
listE2 = geompy.ExtractShapes(myEdges, geompy.ShapeType["EDGE"], True)
myVertices2 = geompy.ImportBREP(join(data_dir, 'WrappedFace_bspline_vertices.brep'))
lVertices2 = geompy.SubShapeAll(myVertices2, geompy.ShapeType["VERTEX"])
wrappedFace = geompy.MakeWrappedFace(listE2, lVertices2, 0.01)
wrappedArea = geompy.BasicProperties(wrappedFace)[1]
expectedArea = 15702.653817260858
print(wrappedArea)
assert(math.fabs(expectedArea - wrappedArea) < eps)

View File

@ -31,5 +31,6 @@ IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.3")
test_proximity_edge_edge.py
test_proximity_face_face.py
test_boolean_fuzzy.py
test_WrappedFace.py
)
ENDIF()