From de644ac6fe44325aaa8ce9c1aa729dd9189eea6e Mon Sep 17 00:00:00 2001 From: Alexey Sozinov Date: Thu, 7 Apr 2022 13:43:09 +0300 Subject: [PATCH] [bos #29471] [EDF] (2022-T1) Advanced geometry features: iterate through holes of a face --- idl/GEOM_Gen.idl | 10 ++ idl/GEOM_Superv.idl | 5 + src/GEOMImpl/CMakeLists.txt | 3 + src/GEOMImpl/GEOMImpl_Gen.cxx | 2 + src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx | 72 ++++++++++ src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx | 1 + src/GEOMImpl/GEOMImpl_IPatchFace.hxx | 47 +++++++ src/GEOMImpl/GEOMImpl_PatchFaceDriver.cxx | 140 +++++++++++++++++++ src/GEOMImpl/GEOMImpl_PatchFaceDriver.hxx | 49 +++++++ src/GEOMImpl/GEOMImpl_Types.hxx | 2 + src/GEOM_I/GEOM_IMeasureOperations_i.cc | 26 ++++ src/GEOM_I/GEOM_IMeasureOperations_i.hh | 2 + src/GEOM_I_Superv/GEOM_Superv_i.cc | 30 ++++ src/GEOM_I_Superv/GEOM_Superv_i.hh | 7 + src/GEOM_SWIG/geomBuilder.py | 33 +++++ test/test_patch_face_01.py | 71 ++++++++++ 16 files changed, 500 insertions(+) create mode 100644 src/GEOMImpl/GEOMImpl_IPatchFace.hxx create mode 100644 src/GEOMImpl/GEOMImpl_PatchFaceDriver.cxx create mode 100644 src/GEOMImpl/GEOMImpl_PatchFaceDriver.hxx create mode 100644 test/test_patch_face_01.py diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index b83b75d28..98b0086b9 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -4660,6 +4660,16 @@ module GEOM */ double GetAngleBtwVectors (in GEOM_Object theShape1, in GEOM_Object theShape2); + /*! + * \brief The function takes a single face with holes and returns a list of faces, + * first of them is the original face without holes, and the other faces are placed + * on the same surface as the original face but bounded by each hole wire. + * If the original face has no holes, it will be returned as an output + * \param theShape face, to perform operation. + * \return ListOfGO, containing the result original face and faces from holes. + */ + ListOfGO PatchFace(in GEOM_Object theShape); + /*! * \brief Get point coordinates */ diff --git a/idl/GEOM_Superv.idl b/idl/GEOM_Superv.idl index 0b59d2672..0ae258e6c 100644 --- a/idl/GEOM_Superv.idl +++ b/idl/GEOM_Superv.idl @@ -675,6 +675,11 @@ module GEOM in string theFileName, in double theDeflection ); + //-----------------------------------------------------------// + // Measure Operations // + //-----------------------------------------------------------// + GEOM_List PatchFace(in GEOM_Object theShape); + /*@@ insert new functions before this line @@ do not remove this line @@*/ }; }; diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index 26d37c40f..43faf7ab8 100644 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -93,6 +93,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_IDisk.hxx GEOMImpl_IFace.hxx GEOMImpl_ILine.hxx + GEOMImpl_IPatchFace.hxx GEOMImpl_IPlane.hxx GEOMImpl_IMarker.hxx GEOMImpl_ITranslate.hxx @@ -178,6 +179,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_HealingDriver.hxx GEOMImpl_FillingDriver.hxx GEOMImpl_GlueDriver.hxx + GEOMImpl_PatchFaceDriver.hxx GEOMImpl_Types.hxx GEOM_GEOMImpl.hxx ) @@ -253,6 +255,7 @@ SET(GEOMImpl_SOURCES GEOMImpl_HealingDriver.cxx GEOMImpl_FillingDriver.cxx GEOMImpl_GlueDriver.cxx + GEOMImpl_PatchFaceDriver.cxx GEOMImpl_FieldDriver.cxx ) diff --git a/src/GEOMImpl/GEOMImpl_Gen.cxx b/src/GEOMImpl/GEOMImpl_Gen.cxx index e61e220a8..867f7b9eb 100644 --- a/src/GEOMImpl/GEOMImpl_Gen.cxx +++ b/src/GEOMImpl/GEOMImpl_Gen.cxx @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +162,7 @@ GEOMImpl_Gen::GEOMImpl_Gen() // Measurements TFunction_DriverTable::Get()->AddDriver(GEOMImpl_MeasureDriver::GetID(), new GEOMImpl_MeasureDriver()); + TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PatchFaceDriver::GetID(), new GEOMImpl_PatchFaceDriver()); // Field TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FieldDriver::GetID(), new GEOMImpl_FieldDriver()); diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index ff539a6c9..aa141c288 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -23,6 +23,10 @@ #include #include #include + +#include +#include + #include #include @@ -2358,6 +2362,74 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Objec } +//============================================================================= +/*! + * PatchFace + */ + //============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE); + Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL; + + GEOMImpl_IPatchFace aPI(aFunction); + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aPI.SetShape(aRefShape); + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + + // Perform + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("patch face driver failed"); + return NULL; + } + + // Get result compound and collect all faces into result sequence + TopoDS_Shape aResCompound = aFunction->GetValue(); + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aResCompound, anIndices); + + Handle(TColStd_HArray1OfInteger) anArray; + for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next()) + { + TopoDS_Shape aValue = anExpW.Value(); + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); + + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray); + if (!anObj.IsNull()) + { + aSeq->Append(anObj); + } + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aSeq; + } + + //Make a Python command + GEOM::TPythonDump(aFunction, true) + << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")"; + + SetErrorCode(OK); + return aSeq; +} + //============================================================================= /*! * CurveCurvatureByParam diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx index 2d2002613..827f695ff 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx @@ -198,6 +198,7 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations { Standard_EXPORT Standard_Real GetAngleBtwVectors (Handle(GEOM_Object) theVec1, Handle(GEOM_Object) theVec2); + Standard_EXPORT Handle(TColStd_HSequenceOfTransient) PatchFace(Handle(GEOM_Object) theShape); // Methods for receiving radiuses of curvature of curves and surfaces // in the given point diff --git a/src/GEOMImpl/GEOMImpl_IPatchFace.hxx b/src/GEOMImpl/GEOMImpl_IPatchFace.hxx new file mode 100644 index 000000000..2058d7c05 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IPatchFace.hxx @@ -0,0 +1,47 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 patch face. +// +#include "GEOM_Function.hxx" + +#include + +#define PATCHFACE_ARG_FACE 1 + +class GEOMImpl_IPatchFace +{ + public: + + GEOMImpl_IPatchFace(Handle(GEOM_Function) theFunction): _func(theFunction) {} + + void SetShape(Handle(GEOM_Function) theRef) + { + _func->SetReference(PATCHFACE_ARG_FACE, theRef); + } + + Handle(GEOM_Function) GetShape() + { + return _func->GetReference(PATCHFACE_ARG_FACE); + } + + private: + + Handle(GEOM_Function) _func; +}; diff --git a/src/GEOMImpl/GEOMImpl_PatchFaceDriver.cxx b/src/GEOMImpl/GEOMImpl_PatchFaceDriver.cxx new file mode 100644 index 000000000..4aa496c63 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PatchFaceDriver.cxx @@ -0,0 +1,140 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& GEOMImpl_PatchFaceDriver::GetID() +{ + static Standard_GUID aPatchFaceDriver("6E0A4C17-9E56-4739-8C67-B37C01C47ED6"); + return aPatchFaceDriver; +} + + +//======================================================================= +//function : GEOMImpl_PatchFaceDriver +//purpose : +//======================================================================= +GEOMImpl_PatchFaceDriver::GEOMImpl_PatchFaceDriver() +{ +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer GEOMImpl_PatchFaceDriver::Execute(Handle(TFunction_Logbook)& log) const +{ + if (Label().IsNull()) return 0; + Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + GEOMImpl_IPatchFace aCI(aFunction); + + Handle(GEOM_Function) aRefShape = aCI.GetShape(); + if (aRefShape.IsNull()) return 0; + + TopoDS_Shape aFaceShape = aRefShape->GetValue(); + + TopoDS_Compound aCompound; + if (aFaceShape.ShapeType() == TopAbs_FACE) + { + if (aFaceShape.Orientation() == TopAbs_Orientation::TopAbs_REVERSED) + aFaceShape.Reverse(); + + // Colect all Wires from face + TopTools_ListOfShape aWires; + TopoDS_Wire anOuterWire = BRepTools::OuterWire(TopoDS::Face(aFaceShape)); + aWires.Append(anOuterWire); + for (TopExp_Explorer anExpW(aFaceShape, TopAbs_WIRE); anExpW.More(); anExpW.Next()) + { + TopoDS_Wire aWire = TopoDS::Wire(anExpW.Current()); + if (anOuterWire.IsSame(aWire)) + continue; + + aWire.Reverse(); + aWires.Append(aWire); + } + + BRep_Builder aBrepBuilder; + TopLoc_Location aLocation; + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aFaceShape), aLocation); + + // Create result compound from all faces + aBrepBuilder.MakeCompound(aCompound); + TopTools_ListIteratorOfListOfShape anIterWires(aWires); + for (; anIterWires.More(); anIterWires.Next()) + { + // Create face on surface from wire + TopoDS_Face aFace; + aBrepBuilder.MakeFace(aFace, aSurface, aLocation, 1.e-7); + aBrepBuilder.Add(aFace, anIterWires.Value()); + + // Add created face to compound + aBrepBuilder.Add(aCompound, aFace); + } + } + else + { + Standard_ConstructionError::Raise("Wrong arguments: a face must be given"); + } + + if (aCompound.IsNull()) return 0; + + aFunction->SetValue(aCompound); + log->SetTouched(Label()); + + return 1; +} + +//================================================================================ +/*! + * \brief Returns a name of creation operation and names and values of creation parameters + */ + //================================================================================ + +bool GEOMImpl_PatchFaceDriver:: +GetCreationInformation(std::string& /*theOperationName*/, + std::vector& /*theParams*/) +{ + return false; +} + +IMPLEMENT_STANDARD_RTTIEXT(GEOMImpl_PatchFaceDriver, GEOM_BaseDriver) diff --git a/src/GEOMImpl/GEOMImpl_PatchFaceDriver.hxx b/src/GEOMImpl/GEOMImpl_PatchFaceDriver.hxx new file mode 100644 index 000000000..7bc6af413 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PatchFaceDriver.hxx @@ -0,0 +1,49 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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_PatchFaceDriver.hxx +// Module : GEOMImpl +// +#ifndef _GEOMImpl_PatchFaceDriver_HeaderFile +#define _GEOMImpl_PatchFaceDriver_HeaderFile + +#include + +DEFINE_STANDARD_HANDLE(GEOMImpl_PatchFaceDriver, GEOM_BaseDriver ) + +class GEOMImpl_PatchFaceDriver : public GEOM_BaseDriver { + +public: + + Standard_EXPORT GEOMImpl_PatchFaceDriver(); + 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 ~GEOMImpl_PatchFaceDriver() {}; + + Standard_EXPORT virtual + bool GetCreationInformation(std::string& theOperationName, + std::vector& params); + + DEFINE_STANDARD_RTTIEXT(GEOMImpl_PatchFaceDriver,GEOM_BaseDriver) +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index faa8f9953..af37b6dcf 100644 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -123,6 +123,8 @@ #define GEOM_CURVATURE_VEC 59 +#define GEOM_PATCH_FACE 60 + //GEOM_Function types #define COPY_WITH_REF 1 diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.cc b/src/GEOM_I/GEOM_IMeasureOperations_i.cc index ccc759c3e..0c09e09c4 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.cc +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.cc @@ -1072,6 +1072,32 @@ CORBA::Double GEOM_IMeasureOperations_i::GetAngleBtwVectors (GEOM::GEOM_Object_p return GetOperations()->GetAngleBtwVectors(aShape1, aShape2); } +//============================================================================= +/*! +* PatchFace +*/ +//============================================================================= +GEOM::ListOfGO* GEOM_IMeasureOperations_i::PatchFace(GEOM::GEOM_Object_ptr theShape) +{ + GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO; + + //Get the reference shape + Handle(::GEOM_Object) aShapeRef = GetObjectImpl(theShape); + if (aShapeRef.IsNull()) return aSeq._retn(); + + // Perform patch face operation + Handle(TColStd_HSequenceOfTransient) aHSeq = + GetOperations()->PatchFace(aShapeRef); + if (!GetOperations()->IsDone() || aHSeq.IsNull()) + return aSeq._retn(); + + Standard_Integer aLength = aHSeq->Length(); + aSeq->length(aLength); + for (Standard_Integer i = 1; i <= aLength; i++) + aSeq[i - 1] = GetObject(Handle(::GEOM_Object)::DownCast(aHSeq->Value(i))); + + return aSeq._retn(); +} //============================================================================= /*! diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.hh b/src/GEOM_I/GEOM_IMeasureOperations_i.hh index 30b89faeb..6a5aa39ee 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.hh +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.hh @@ -142,6 +142,8 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i : CORBA::Double GetAngleBtwVectors (GEOM::GEOM_Object_ptr theShape1, GEOM::GEOM_Object_ptr theShape2); + GEOM::ListOfGO* PatchFace(GEOM::GEOM_Object_ptr theShape); + // Methods for receiving radiuses of curvature of curves and surfaces // in the given point CORBA::Double CurveCurvatureByParam (GEOM::GEOM_Object_ptr theCurve, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index adb77cca4..7c3f7299e 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -61,6 +61,7 @@ GEOM_Superv_i::GEOM_Superv_i(CORBA::ORB_ptr orb, myBlocksOp = GEOM::GEOM_IBlocksOperations::_nil(); myCurvesOp = GEOM::GEOM_ICurvesOperations::_nil(); myLocalOp = GEOM::GEOM_ILocalOperations::_nil(); + myMeasureOp = GEOM::GEOM_IMeasureOperations::_nil(); myGroupOp = GEOM::GEOM_IGroupOperations::_nil(); } @@ -299,6 +300,20 @@ void GEOM_Superv_i::getLocalOp() } } +//============================================================================= +// getMeasureOp: +//============================================================================= +void GEOM_Superv_i::getMeasureOp() +{ + if (CORBA::is_nil(myGeomEngine)) + setGeomEngine(); + // get GEOM_IMeasureOperations interface + if (CORBA::is_nil(myMeasureOp)) + { + myMeasureOp = myGeomEngine->GetIMeasureOperations(); + } +} + //============================================================================= // getGroupOp: //============================================================================= @@ -3743,6 +3758,21 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeSmoothingSurface (GEOM::GEOM_List_ptr t return NULL; } +//============================================================================= +// PatchFace: +//============================================================================= +GEOM::GEOM_List_ptr GEOM_Superv_i::PatchFace(GEOM::GEOM_Object_ptr theShape) +{ + beginService(" GEOM_Superv_i::PatchFace"); + MESSAGE("GEOM_Superv_i::PatchFace"); + getLocalOp(); + + GEOM::ListOfGO* aList = myMeasureOp->PatchFace(theShape); + GEOM_List_i* aListPtr = new GEOM_List_i(*(aList)); + endService(" GEOM_Superv_i::PatchFace"); + return aListPtr->_this(); +} + /*@@ insert new functions before this line @@ do not remove this line @@*/ GEOM_Superv_i_With_Session::GEOM_Superv_i_With_Session(CORBA::ORB_ptr orb, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.hh b/src/GEOM_I_Superv/GEOM_Superv_i.hh index caaa9fe64..e35a40aaf 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.hh +++ b/src/GEOM_I_Superv/GEOM_Superv_i.hh @@ -69,6 +69,7 @@ public: void getBlocksOp(); void getCurvesOp(); void getLocalOp(); + void getMeasureOp(); void getGroupOp(); void getAdvancedOp(); void getSTLPluginOp(); @@ -780,6 +781,11 @@ public: CORBA::Double theH, GEOM::pattern thePattern); GEOM::GEOM_Object_ptr MakeSmoothingSurface (GEOM::GEOM_List_ptr thelPoints); + + //-----------------------------------------------------------// + // Measure Operations // + //-----------------------------------------------------------// + GEOM::GEOM_List_ptr PatchFace(GEOM::GEOM_Object_ptr theShape); /*@@ insert new functions before this line @@ do not remove this line @@*/ protected: @@ -797,6 +803,7 @@ private: GEOM::GEOM_IBlocksOperations_var myBlocksOp; GEOM::GEOM_ICurvesOperations_var myCurvesOp; GEOM::GEOM_ILocalOperations_var myLocalOp; + GEOM::GEOM_IMeasureOperations_var myMeasureOp; GEOM::GEOM_IGroupOperations_var myGroupOp; GEOM::IAdvancedOperations_var myAdvancedOp; GEOM::ISTLOperations_var mySTLOp; diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 9c8ad7f7c..e80d9f60a 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -11784,6 +11784,39 @@ class geomBuilder(GEOM._objref_GEOM_Gen): return aKindTuple + ## The function takes a single face with holes and returns a list of faces, + # first of them is the original face without holes, and the other faces are placed + # on the same surface as the original face but bounded by each hole wire. + # If the original face has no holes, it will be returned as an output + # @param theShape Face to perform operation on. + # + # @return GEOM.ListOfGO, list created faces, where first of them is the original face without holes + @ManageTransactions("MeasuOp") + def PatchFace(self, theShape): + """ + The function takes a single face with holes and returns a list of faces, + first of them is the original face without holes, and the other faces are placed + on the same surface as the original face but bounded by each hole wire. + If the original face has no holes, it will be returned as an output + + Parameters: + theShape Face to perform operation on. + + Returns: + GEOM.ListOfGO, list created faces, where first of them is the original face without holes + + Example of usage: + Circle_1 = geompy.MakeCircle(None, None, 190) + Circle_2 = geompy.MakeCircle(None, None, 100) + Face_1 = geompy.MakeFaceWires([Circle_1], 1) + Face_2 = geompy.MakeFaceWires([Circle_2], 1) + Cut_1 = geompy.MakeCutList(Face_1, [Face_2], True) + faces = geompy.PatchFace(Cut_1) + """ + aList = self.MeasuOp.PatchFace(theShape) + RaiseIfFailed("PatchFace", self.MeasuOp) + return aList + ## Returns the string that describes if the shell is good for solid. # This is a support method for MakeSolid. # diff --git a/test/test_patch_face_01.py b/test/test_patch_face_01.py new file mode 100644 index 000000000..1d0d288b4 --- /dev/null +++ b/test/test_patch_face_01.py @@ -0,0 +1,71 @@ +# Check patch face functionality + +def CheckFacesOnHoles( faces ): + """ + check that none of the faces in the list have holes + param faces - list of faces + return bool - *True* if all faces not have hole; *False* otherwise + """ + for face in faces: + newFaces = geompy.PatchFace(face) + if len(newFaces) != 1: + return False + return True + +def CompareAreaAfterPatchFace( originalFace, patchFaceResult, eps=1e-06 ): + """ + Specific function for check result of PatchFace operation. + Check that area of original face equal area first face from list (face by outer wire of original face) + minus the areas of the rest elements from list (holes) + param originalFace - original face + param patchFaceResult - list of faces result PatchFace operation. + First element - face from outer wire of original face, + other elements - faces from holes on original face + param eps - defines tolerance for comparison + return bool - *True* if area of original face is equal of area face[0] minus area of holes; *False* otherwise + """ + areaOfHoles = 0. + for index in range(1, len(patchFaceResult)): + areaOfHoles += geompy.BasicProperties(patchFaceResult[index])[1] + return geompy.BasicProperties(originalFace)[1] - (geompy.BasicProperties(patchFaceResult[0])[1] - areaOfHoles) <= eps + +import math +import salome +salome.salome_init_without_session() +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New() + +# Create shape +vz = geompy.MakeVectorDXDYDZ(0, 0, 1) +pyz = geompy.MakeVertex(0, -150, 100) + +geomObj = geompy.MakeMarker(0, 0, 0, 1, 0, 0, 0, 1, 0) +sk = geompy.Sketcher2D() +sk.addPoint(30.0000000, 50.0000000) +sk.addArcAbsolute(70.0000000, 20.0000000) +sk.addSegmentAbsolute(0.0000000, 0.0000000) +sk.close() +sketch = sk.wire(geomObj) +face_1 = geompy.MakeFaceWires([sketch], 1) +multiTranslation = geompy.MakeMultiTranslation1D(face_1, None, 105, 3) +[face_2,face_3,face_4] = geompy.ExtractShapes(multiTranslation, geompy.ShapeType["FACE"], True) +scale_1 = geompy.MakeScaleTransform(face_3, None, 0.3) +scale_2 = geompy.MakeScaleTransform(face_4, None, 0.3) + +translation_1 = geompy.MakeTranslation(scale_1, -10, 25, 0) +translation_2 = geompy.MakeTranslation(scale_2, -25, 20, 0) + +rotation_1 = geompy.MakeRotation(translation_1, vz, -19*math.pi/180.0) +rotation_2 = geompy.MakeRotation(translation_2, vz, 15*math.pi/180.0) + +cut = geompy.MakeCutList(face_1, [rotation_2, rotation_1], True) + +#Perform oepration +faces = geompy.PatchFace(cut) + +# Check, that result faces haven't holes +assert(CheckFacesOnHoles(faces)) + +#Check area +assert(CompareAreaAfterPatchFace(cut, faces))