[bos #29471] [EDF] (2022-T1) Advanced geometry features: iterate through holes of a face

This commit is contained in:
Alexey Sozinov 2022-04-07 13:43:09 +03:00 committed by jfa
parent e6d054cfcd
commit de644ac6fe
16 changed files with 500 additions and 0 deletions

View File

@ -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
*/

View File

@ -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 @@*/
};
};

View File

@ -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
)

View File

@ -65,6 +65,7 @@
#include <GEOMImpl_FilletDriver.hxx>
#include <GEOMImpl_Fillet1dDriver.hxx>
#include <GEOMImpl_Fillet2dDriver.hxx>
#include <GEOMImpl_PatchFaceDriver.hxx>
#include <GEOMImpl_TranslateDriver.hxx>
#include <GEOMImpl_RotateDriver.hxx>
#include <GEOMImpl_MirrorDriver.hxx>
@ -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());

View File

@ -23,6 +23,10 @@
#include <GEOMImpl_IMeasureOperations.hxx>
#include <GEOMImpl_IMeasure.hxx>
#include <GEOMImpl_MeasureDriver.hxx>
#include <GEOMImpl_IPatchFace.hxx>
#include <GEOMImpl_PatchFaceDriver.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOMUtils.hxx>
@ -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

View File

@ -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

View File

@ -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 <TColStd_HSequenceOfTransient.hxx>
#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;
};

View File

@ -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 <GEOMImpl_PatchFaceDriver.hxx>
#include <GEOMImpl_IPatchFace.hxx>
#include <GEOMImpl_Types.hxx>
#include <GEOM_Function.hxx>
#include <GEOMUtils.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepTools.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopAbs.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <StdFail_NotDone.hxx>
//=======================================================================
//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<GEOM_Param>& /*theParams*/)
{
return false;
}
IMPLEMENT_STANDARD_RTTIEXT(GEOMImpl_PatchFaceDriver, GEOM_BaseDriver)

View File

@ -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 <GEOM_BaseDriver.hxx>
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<GEOM_Param>& params);
DEFINE_STANDARD_RTTIEXT(GEOMImpl_PatchFaceDriver,GEOM_BaseDriver)
};
#endif

View File

@ -123,6 +123,8 @@
#define GEOM_CURVATURE_VEC 59
#define GEOM_PATCH_FACE 60
//GEOM_Function types
#define COPY_WITH_REF 1

View File

@ -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();
}
//=============================================================================
/*!

View File

@ -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,

View File

@ -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<GEOM::ListOfGO>* aListPtr = new GEOM_List_i<GEOM::ListOfGO>(*(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,

View File

@ -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;

View File

@ -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.
#

View File

@ -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))