Fix regressions caused by improvements

This commit is contained in:
eap 2015-08-05 20:59:31 +03:00
parent afb2a8e781
commit 7084b4f979
9 changed files with 162 additions and 111 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -53,8 +53,12 @@ the opposite border.
In practice the borders to sew often coincide and in this case it is In practice the borders to sew often coincide and in this case it is
difficult to specify the first and the last nodes of a border since difficult to specify the first and the last nodes of a border since
they coincide with the first and the last nodes of the other they coincide with the first and the last nodes of the other
border. To cope with this, manually \ref merging_nodes_page to fuse border. To cope with this,
each pair of coincident nodes into one. \ref merging_nodes_page "merge" coincident nodes into one
beforehand. Two figures below illustrate this approach.
\image html sew_using_merge.png "Merge coincident nodes which are difficult to distinguish"
<br>
\image html sew_after_merge.png "After merging nodes it is easy to specify border nodes"
The sewing algorithm is as follows: The sewing algorithm is as follows:
<ol> <ol>

View File

@ -46,8 +46,6 @@ using namespace std;
SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index) SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
{ {
myParent = parent; myParent = parent;
myElements.clear();
myNodes.clear();
myIndex = index; myIndex = index;
myUnusedIdNodes = 0; myUnusedIdNodes = 0;
myUnusedIdElements = 0; myUnusedIdElements = 0;
@ -65,61 +63,54 @@ SMESHDS_SubMesh::~SMESHDS_SubMesh()
//======================================================================= //=======================================================================
//function : AddElement //function : AddElement
//purpose : //purpose :
//======================================================================= //=======================================================================
void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME) void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
{ {
if (!IsComplexSubmesh()) if (!IsComplexSubmesh())
{
if ( ME->GetType() == SMDSAbs_Node )
{ {
if ( ME->GetType() == SMDSAbs_Node ) AddNode( static_cast< const SMDS_MeshNode* >( ME ));
return;
}
int oldShapeId = ME->getshapeId();
if ( oldShapeId > 0 )
{
if (oldShapeId != myIndex)
{ {
AddNode( static_cast< const SMDS_MeshNode* >( ME )); throw SALOME_Exception
(LOCALIZED("add element in subshape already belonging to a subshape"));
}
int idInSubShape = ME->getIdInShape();
if (idInSubShape >= 0)
{
MESSAGE("add element in subshape already belonging to that subshape "
<< ME->GetID() << " " << oldShapeId << " " << idInSubShape);
// check if ok: do nothing if ok
if (idInSubShape >= myElements.size())
{
throw SALOME_Exception(LOCALIZED("out of bounds"));
}
if (ME != myElements[idInSubShape])
{
throw SALOME_Exception(LOCALIZED("not the same element"));
}
return; return;
} }
int oldShapeId = ME->getshapeId();
if ( oldShapeId > 0 )
{
if (oldShapeId != myIndex)
{
MESSAGE("add element in subshape already belonging to another subshape "
<< ME->GetID() << " " << oldShapeId << " " << myIndex);
throw SALOME_Exception(LOCALIZED("add element in subshape already belonging to a subshape"));
}
else
{
int idInSubShape = ME->getIdInShape();
if (idInSubShape >= 0)
{
MESSAGE("add element in subshape already belonging to that subshape "
<< ME->GetID() << " " << oldShapeId << " " << idInSubShape);
// check if ok: do nothing if ok
if (idInSubShape >= myElements.size())
{
MESSAGE("out of bounds " << idInSubShape << " " << myElements.size());
throw SALOME_Exception(LOCALIZED("out of bounds"));
}
if (ME != myElements[idInSubShape])
{
MESSAGE("not the same element");
throw SALOME_Exception(LOCALIZED("not the same element"));
}
MESSAGE("already done, OK, nothing to do");
return;
}
}
}
SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
elem->setShapeId(myIndex);
elem->setIdInShape(myElements.size());
myElements.push_back(ME);
} }
SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
elem->setShapeId(myIndex);
elem->setIdInShape(myElements.size());
myElements.push_back(ME);
}
} }
//======================================================================= //=======================================================================
//function : RemoveElement //function : RemoveElement
//purpose : //purpose :
//======================================================================= //=======================================================================
bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted) bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
@ -183,7 +174,7 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
//======================================================================= //=======================================================================
//function : RemoveNode //function : RemoveNode
//purpose : //purpose :
//======================================================================= //=======================================================================
bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted) bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
@ -385,29 +376,52 @@ bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
if (!ME) if (!ME)
return false; return false;
if (IsComplexSubmesh()) if ( IsComplexSubmesh() )
{ {
set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin(); set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
for (; aSubIt != mySubMeshes.end(); aSubIt++) for (; aSubIt != mySubMeshes.end(); aSubIt++)
if ((*aSubIt)->Contains(ME)) if ((*aSubIt)->Contains(ME))
return true; return true;
return false; return false;
} }
if (ME->GetType() == SMDSAbs_Node) if (ME->GetType() == SMDSAbs_Node)
{ {
int idInShape = ME->getIdInShape(); int idInShape = ME->getIdInShape();
if ((idInShape >= 0) && (idInShape < myNodes.size())) if ((idInShape >= 0) && (idInShape < myNodes.size()))
if (myNodes[idInShape] == ME) if (myNodes[idInShape] == ME)
return true; return true;
} }
else else
{ {
int idInShape = ME->getIdInShape(); int idInShape = ME->getIdInShape();
if ((idInShape >= 0) && (idInShape < myElements.size())) if ((idInShape >= 0) && (idInShape < myElements.size()))
if (myElements[idInShape] == ME) if (myElements[idInShape] == ME)
return true; return true;
} }
return false;
}
//=======================================================================
//function : IsQuadratic
//purpose : Return true if my 1st element is quadratic
//=======================================================================
bool SMESHDS_SubMesh::IsQuadratic() const
{
if ( IsComplexSubmesh() )
{
set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
for (; aSubIt != mySubMeshes.end(); aSubIt++)
if ((*aSubIt)->IsQuadratic())
return true;
return false;
}
for ( size_t i = 0; i < myElements.size(); ++i )
if ( myElements[i] )
return myElements[i]->IsQuadratic();
return false; return false;
} }

View File

@ -67,19 +67,20 @@ class SMESHDS_EXPORT SMESHDS_SubMesh
virtual int NbNodes() const; virtual int NbNodes() const;
virtual SMDS_NodeIteratorPtr GetNodes() const; virtual SMDS_NodeIteratorPtr GetNodes() const;
virtual bool Contains(const SMDS_MeshElement * ME) const; // check if elem or node is in virtual bool Contains(const SMDS_MeshElement * ME) const; // check if elem or node is in
virtual bool IsQuadratic() const;
// clear the contents // clear the contents
virtual void Clear(); virtual void Clear();
int getSize(); int getSize();
void compactList(); void compactList();
SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); } SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); }
int GetID() const { return myIndex; } int GetID() const { return myIndex; }
private: private:
SMESHDS_Mesh * myParent; SMESHDS_Mesh * myParent;
std::vector<const SMDS_MeshElement*> myElements; std::vector<const SMDS_MeshElement*> myElements;
std::vector<const SMDS_MeshNode*> myNodes; std::vector<const SMDS_MeshNode*> myNodes;
int myUnusedIdNodes; int myUnusedIdNodes;
int myUnusedIdElements; int myUnusedIdElements;

View File

@ -287,8 +287,11 @@ class Mesh_Algorithm:
if not "ViscousLayers" in self.GetCompatibleHypothesis(): if not "ViscousLayers" in self.GetCompatibleHypothesis():
raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName() raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ): if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
import GEOM faceIDs = []
faceIDs = [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces] for shape in faces:
ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] )
for f in ff:
faceIDs.append( self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f))
faces = faceIDs faces = faceIDs
hyp = self.Hypothesis("ViscousLayers", hyp = self.Hypothesis("ViscousLayers",
[thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore], [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
@ -320,7 +323,12 @@ class Mesh_Algorithm:
if not "ViscousLayers2D" in self.GetCompatibleHypothesis(): if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName() raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ): if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ] edgeIDs = []
for shape in edges:
ee = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["EDGE"])
for e in ee:
edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e ))
edges = edgeIDs
hyp = self.Hypothesis("ViscousLayers2D", hyp = self.Hypothesis("ViscousLayers2D",
[thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore], [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
toAdd=False) toAdd=False)

View File

@ -311,7 +311,9 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this ); StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
SMESH_MesherHelper helper( *myProxyMesh->GetMesh() ); SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
fHelper.SetSubShape( myFace );
bool paramOK; bool paramOK;
double eps = 1e-100; double eps = 1e-100;
@ -346,7 +348,8 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
const double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param const double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
if ( node ) // nodes on internal vertices may be missing if ( node ) // nodes on internal vertices may be missing
{ {
if ( vertexNodes.insert( node ).second ) if ( vertexNodes.insert( node ).second ||
fHelper.IsRealSeam( node->getshapeId() ))
u2node.insert( u2node.end(), make_pair( prevNormPar, node )); u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
} }
else if ( iE == 0 ) else if ( iE == 0 )
@ -373,12 +376,12 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
u2nodeVec.clear(); u2nodeVec.clear();
double paramSize = myLast[iE] - myFirst[iE]; double paramSize = myLast[iE] - myFirst[iE];
double r = myNormPar[iE] - prevNormPar; double r = myNormPar[iE] - prevNormPar;
helper.SetSubShape( myEdge[iE] ); eHelper.SetSubShape( myEdge[iE] );
helper.ToFixNodeParameters( true ); eHelper.ToFixNodeParameters( true );
if ( !myIsUniform[iE] ) if ( !myIsUniform[iE] )
for ( size_t i = 0; i < nodes.size(); ++i ) for ( size_t i = 0; i < nodes.size(); ++i )
{ {
double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK ); double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
double aLenU = GCPnts_AbscissaPoint::Length( me->myC3dAdaptor[iE], myFirst[iE], u ); double aLenU = GCPnts_AbscissaPoint::Length( me->myC3dAdaptor[iE], myFirst[iE], u );
if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6" if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
{ {
@ -391,7 +394,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
if ( u2nodeVec.empty() ) if ( u2nodeVec.empty() )
for ( size_t i = 0; i < nodes.size(); ++i ) for ( size_t i = 0; i < nodes.size(); ++i )
{ {
double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK ); double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
// paramSize is signed so orientation is taken into account // paramSize is signed so orientation is taken into account
double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize; double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
u2nodeVec.push_back( make_pair( normPar, nodes[i] )); u2nodeVec.push_back( make_pair( normPar, nodes[i] ));
@ -401,10 +404,11 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst,
} }
} // loop on myEdge's } // loop on myEdge's
if ( u2node.empty() ) return myPoints;
// Add 2nd VERTEX node for a last EDGE // Add 2nd VERTEX node for a last EDGE
if ( !proxySubMesh.back() )
{ {
if ( u2node.empty() ) return myPoints;
const SMDS_MeshNode* node; const SMDS_MeshNode* node;
if ( IsClosed() ) if ( IsClosed() )
node = u2node.begin()->second; node = u2node.begin()->second;
@ -576,7 +580,9 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
if ( NbEdges() == 0 ) return resultNodes; if ( NbEdges() == 0 ) return resultNodes;
SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
SMESH_MesherHelper helper(*myProxyMesh->GetMesh()); SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
fHelper.SetSubShape( myFace );
bool paramOK = true; bool paramOK = true;
// Sort nodes of all edges putting them into a map // Sort nodes of all edges putting them into a map
@ -606,7 +612,8 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
// Add 1st vertex node of a current EDGE // Add 1st vertex node of a current EDGE
const SMDS_MeshNode* node = VertexNode( iE ); const SMDS_MeshNode* node = VertexNode( iE );
if ( node ) { // nodes on internal vertices may be missing if ( node ) { // nodes on internal vertices may be missing
if ( vertexNodes.insert( node ).second ) if ( vertexNodes.insert( node ).second ||
fHelper.IsRealSeam( node->getshapeId() ))
u2node.insert( make_pair( prevNormPar, node )); u2node.insert( make_pair( prevNormPar, node ));
} }
else if ( iE == 0 ) else if ( iE == 0 )
@ -632,11 +639,11 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
{ {
double paramSize = myLast[iE] - myFirst[iE]; double paramSize = myLast[iE] - myFirst[iE];
double r = myNormPar[iE] - prevNormPar; double r = myNormPar[iE] - prevNormPar;
helper.SetSubShape( myEdge[iE] ); eHelper.SetSubShape( myEdge[iE] );
helper.ToFixNodeParameters( true ); eHelper.ToFixNodeParameters( true );
for ( size_t i = 0; i < nodes.size(); ++i ) for ( size_t i = 0; i < nodes.size(); ++i )
{ {
double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK ); double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
// paramSize is signed so orientation is taken into account // paramSize is signed so orientation is taken into account
double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize; double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
u2node.insert( u2node.end(), make_pair( normPar, nodes[i] )); u2node.insert( u2node.end(), make_pair( normPar, nodes[i] ));
@ -707,9 +714,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t i,
if ( inlude1stVertex ) if ( inlude1stVertex )
{ {
const SMDS_MeshNode* n0 = VertexNode( i ); if ( const SMDS_MeshNode* n0 = VertexNode( i ))
if ( !n0 ) return false; nodes.push_back( n0 );
nodes.push_back( n0 );
} }
if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 )) if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 ))
@ -764,9 +770,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t i,
if ( inludeLastVertex ) if ( inludeLastVertex )
{ {
const SMDS_MeshNode* n1 = VertexNode( i+1 ); if ( const SMDS_MeshNode* n1 = VertexNode( i+1 ))
if ( !n1 ) return false; nodes.push_back( n1 );
nodes.push_back( n1 );
} }
return true; return true;
} }
@ -943,27 +948,43 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
me->myNbSegments = 0; me->myNbSegments = 0;
me->myMissingVertexNodes = false; me->myMissingVertexNodes = false;
vector<const SMDS_MeshNode*> nodes;
for ( int i = 0; i < NbEdges(); ++i ) for ( int i = 0; i < NbEdges(); ++i )
{ {
if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) { if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) ))
int nbN = sm->NbNodes(); {
if ( sm->NbElements() > 0 ) { if ( sm->NbNodes() == sm->NbElements() - 1 )
nbN = sm->NbElements() - 1; // nodes can be moved to other shapes by MergeNodes() {
if ( !myIgnoreMediumNodes && me->myNbPonits += sm->NbNodes();
sm->GetElements()->next()->IsQuadratic() ) if ( myIgnoreMediumNodes && sm->IsQuadratic() )
nbN += sm->NbElements(); me->myNbPonits -= sm->NbElements();
}
else // nodes can be moved to other shapes by MergeNodes()
{
nodes.clear();
GetEdgeNodes( i, nodes, /*v1=*/false, /*v2=*/false );
me->myNbPonits += nodes.size();
} }
me->myNbPonits += nbN;
me->myNbSegments += sm->NbElements(); me->myNbSegments += sm->NbElements();
} }
} }
SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
helper.SetSubShape( myFace );
std::set< const SMDS_MeshNode* > vNodes; std::set< const SMDS_MeshNode* > vNodes;
for ( int i = 0; i <= NbEdges(); ++i ) for ( int i = 0; i <= NbEdges(); ++i ) // nb VERTEXes is more than NbEdges() if !IsClosed()
if ( const SMDS_MeshNode* n = VertexNode( i )) if ( const SMDS_MeshNode* n = VertexNode( i ))
vNodes.insert( n ); {
if ( !vNodes.insert( n ).second &&
helper.IsRealSeam( n->getshapeId() ) &&
i < NbEdges())
me->myNbPonits++;
}
else else
{
me->myMissingVertexNodes = true; me->myMissingVertexNodes = true;
}
me->myNbPonits += vNodes.size(); me->myNbPonits += vNodes.size();
if ( IsClosed() ) if ( IsClosed() )

View File

@ -513,18 +513,18 @@ namespace {
if ( !tgtNodes.empty() ) if ( !tgtNodes.empty() )
{ {
vector< const SMDS_MeshNode* >::iterator tn = tgtNodes.begin(); vector< const SMDS_MeshNode* >::iterator tn = tgtNodes.begin();
if ( srcWire->Edge(iE).Orientation() == tgtWire->Edge(iE).Orientation() ) //if ( srcWire->Edge(iE).Orientation() == tgtWire->Edge(iE).Orientation() )
{ {
vector< const SMDS_MeshNode* >::iterator sn = srcNodes.begin(); vector< const SMDS_MeshNode* >::iterator sn = srcNodes.begin();
for ( ; tn != tgtNodes.end(); ++tn, ++sn) for ( ; tn != tgtNodes.end(); ++tn, ++sn)
src2tgtNodes.insert( make_pair( *sn, *tn )); src2tgtNodes.insert( make_pair( *sn, *tn ));
} }
else // else
{ // {
vector< const SMDS_MeshNode* >::reverse_iterator sn = srcNodes.rbegin(); // vector< const SMDS_MeshNode* >::reverse_iterator sn = srcNodes.rbegin();
for ( ; tn != tgtNodes.end(); ++tn, ++sn) // for ( ; tn != tgtNodes.end(); ++tn, ++sn)
src2tgtNodes.insert( make_pair( *sn, *tn )); // src2tgtNodes.insert( make_pair( *sn, *tn ));
} // }
is1DComputed = true; is1DComputed = true;
} }
} }

View File

@ -4276,9 +4276,12 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
return error(COMPERR_BAD_SHAPE, return error(COMPERR_BAD_SHAPE,
TComm("Face must have 4 sides but not ") << faceSide.NbEdges() ); TComm("Face must have 4 sides but not ") << faceSide.NbEdges() );
const int nbSegments = Max( faceSide.NbPoints()-1, faceSide.NbSegments() ); if ( theConsiderMesh )
if ( nbSegments < nbCorners ) {
return error(COMPERR_BAD_INPUT_MESH, TComm("Too few boundary nodes: ") << nbSegments); const int nbSegments = Max( faceSide.NbPoints()-1, faceSide.NbSegments() );
if ( nbSegments < nbCorners )
return error(COMPERR_BAD_INPUT_MESH, TComm("Too few boundary nodes: ") << nbSegments);
}
if ( nbCorners == 3 ) if ( nbCorners == 3 )
{ {