-// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//================================================================================
SMESH_MesherHelper::SMESH_MesherHelper(SMESH_Mesh& theMesh)
- : myParIndex(0), myMesh(&theMesh), myShapeID(0), myCreateQuadratic(false)
+ : myParIndex(0), myMesh(&theMesh), myShapeID(0), myCreateQuadratic(false),
+ myFixNodeParameters(false)
{
myPar1[0] = myPar2[0] = myPar1[1] = myPar2[1] = 0;
mySetElemOnShape = ( ! myMesh->HasShapeToMesh() );
{
SMESHDS_Mesh* meshDS = GetMeshDS();
// we can create quadratic elements only if all elements
- // created on subshapes of given shape are quadratic
+ // created on sub-shapes of given shape are quadratic
// also we have to fill myTLinkNodeMap
myCreateQuadratic = true;
mySeamShapeIds.clear();
myDegenShapeIds.clear();
TopAbs_ShapeEnum subType( aSh.ShapeType()==TopAbs_FACE ? TopAbs_EDGE : TopAbs_FACE );
+ if ( aSh.ShapeType()==TopAbs_COMPOUND )
+ {
+ TopoDS_Iterator subIt( aSh );
+ if ( subIt.More() )
+ subType = ( subIt.Value().ShapeType()==TopAbs_FACE ) ? TopAbs_EDGE : TopAbs_FACE;
+ }
SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge );
+
int nbOldLinks = myTLinkNodeMap.size();
if ( !myMesh->HasShapeToMesh() )
TopLoc_Location loc;
Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc );
- if ( surface->IsUPeriodic() || surface->IsVPeriodic() )
+ if ( surface->IsUPeriodic() || surface->IsVPeriodic() ||
+ surface->IsUClosed() || surface->IsVClosed() )
{
//while ( surface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface )))
//surface = Handle(Geom_RectangularTrimmedSurface)::DownCast( surface )->BasisSurface();
//function : GetNodeUVneedInFaceNode
//purpose : Check if inFaceNode argument is necessary for call GetNodeUV(F,..)
// Return true if the face is periodic.
-// If F is Null, answer about subshape set through IsQuadraticSubMesh() or
+// If F is Null, answer about sub-shape set through IsQuadraticSubMesh() or
// * SetSubShape()
//=======================================================================
((SMESH_MesherHelper*)this)->myNodePosShapesValidity.insert( make_pair( shapeID, ok));
}
+//=======================================================================
+//function : ToFixNodeParameters
+//purpose : Enables fixing node parameters on EDGEs and FACEs in
+// GetNodeU(...,check=true), GetNodeUV(...,check=true), CheckNodeUV() and
+// CheckNodeU() in case if a node lies on a shape set via SetSubShape().
+// Default is False
+//=======================================================================
+
+void SMESH_MesherHelper::ToFixNodeParameters(bool toFix)
+{
+ myFixNodeParameters = toFix;
+}
+
+
//=======================================================================
//function : GetUVOnSeam
//purpose : Select UV on either of 2 pcurves of a seam edge, closest to the given UV
return false;
}
// store the fixed UV on the face
- if ( myShape.IsSame(F) && shapeID == myShapeID )
+ if ( myShape.IsSame(F) && shapeID == myShapeID && myFixNodeParameters )
const_cast<SMDS_MeshNode*>(n)->SetPosition
( SMDS_PositionPtr( new SMDS_FacePosition( U, V )));
}
return false;
}
// store the fixed U on the edge
- if ( myShape.IsSame(E) && shapeID == myShapeID )
+ if ( myShape.IsSame(E) && shapeID == myShapeID && myFixNodeParameters )
const_cast<SMDS_MeshNode*>(n)->SetPosition
( SMDS_PositionPtr( new SMDS_EdgePosition( U )));
}
return true;
}
+//=======================================================================
+//function : GetMediumPos
+//purpose : Return index and type of the shape (EDGE or FACE only) to
+// set a medium node on
+//=======================================================================
+
+std::pair<int, TopAbs_ShapeEnum> SMESH_MesherHelper::GetMediumPos(const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2)
+{
+ TopAbs_ShapeEnum shapeType = TopAbs_SHAPE;
+ int shapeID = -1;
+ TopoDS_Shape shape;
+
+ if (( myShapeID == n1->getshapeId() || myShapeID == n2->getshapeId() ) && myShapeID > 0 )
+ {
+ shapeType = myShape.ShapeType();
+ shapeID = myShapeID;
+ }
+ else if ( n1->getshapeId() == n2->getshapeId() )
+ {
+ shapeID = n2->getshapeId();
+ shape = GetSubShapeByNode( n1, GetMeshDS() );
+ }
+ else
+ {
+ const SMDS_TypeOfPosition Pos1 = n1->GetPosition()->GetTypeOfPosition();
+ const SMDS_TypeOfPosition Pos2 = n2->GetPosition()->GetTypeOfPosition();
+
+ if ( Pos1 == SMDS_TOP_3DSPACE || Pos2 == SMDS_TOP_3DSPACE )
+ {
+ }
+ else if ( Pos1 == SMDS_TOP_FACE || Pos2 == SMDS_TOP_FACE )
+ {
+ if ( Pos1 != SMDS_TOP_FACE || Pos2 != SMDS_TOP_FACE )
+ {
+ if ( Pos1 != SMDS_TOP_FACE ) std::swap( n1,n2 );
+ TopoDS_Shape F = GetSubShapeByNode( n1, GetMeshDS() );
+ TopoDS_Shape S = GetSubShapeByNode( n2, GetMeshDS() );
+ if ( IsSubShape( S, F ))
+ {
+ shapeType = TopAbs_FACE;
+ shapeID = n1->getshapeId();
+ }
+ }
+ }
+ else if ( Pos1 == SMDS_TOP_EDGE && Pos2 == SMDS_TOP_EDGE )
+ {
+ TopoDS_Shape E1 = GetSubShapeByNode( n1, GetMeshDS() );
+ TopoDS_Shape E2 = GetSubShapeByNode( n2, GetMeshDS() );
+ shape = GetCommonAncestor( E1, E2, *myMesh, TopAbs_FACE );
+ }
+ else if ( Pos1 == SMDS_TOP_VERTEX && Pos2 == SMDS_TOP_VERTEX )
+ {
+ TopoDS_Shape V1 = GetSubShapeByNode( n1, GetMeshDS() );
+ TopoDS_Shape V2 = GetSubShapeByNode( n2, GetMeshDS() );
+ shape = GetCommonAncestor( V1, V2, *myMesh, TopAbs_EDGE );
+ if ( shape.IsNull() ) shape = GetCommonAncestor( V1, V2, *myMesh, TopAbs_FACE );
+ }
+ else // VERTEX and EDGE
+ {
+ if ( Pos1 != SMDS_TOP_VERTEX ) std::swap( n1,n2 );
+ TopoDS_Shape V = GetSubShapeByNode( n1, GetMeshDS() );
+ TopoDS_Shape E = GetSubShapeByNode( n2, GetMeshDS() );
+ if ( IsSubShape( V, E ))
+ shape = E;
+ else
+ shape = GetCommonAncestor( V, E, *myMesh, TopAbs_FACE );
+ }
+ }
+
+ if ( !shape.IsNull() )
+ {
+ if ( shapeID < 1 )
+ shapeID = GetMeshDS()->ShapeToIndex( shape );
+ shapeType = shape.ShapeType();
+ }
+ return make_pair( shapeID, shapeType );
+}
+
//=======================================================================
//function : GetMediumNode
//purpose : Return existing or create new medium nodes between given ones
// get type of shape for the new medium node
int faceID = -1, edgeID = -1;
- const SMDS_PositionPtr Pos1 = n1->GetPosition();
- const SMDS_PositionPtr Pos2 = n2->GetPosition();
-
TopoDS_Edge E; double u [2];
TopoDS_Face F; gp_XY uv[2];
bool uvOK[2] = { false, false };
- if( myShape.IsNull() )
- {
- if( Pos1->GetTypeOfPosition()==SMDS_TOP_FACE ) {
- faceID = n1->getshapeId();
- }
- else if( Pos2->GetTypeOfPosition()==SMDS_TOP_FACE ) {
- faceID = n2->getshapeId();
- }
+ pair<int, TopAbs_ShapeEnum> pos = GetMediumPos( n1, n2 );
- if( Pos1->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
- edgeID = n1->getshapeId();
- }
- if( Pos2->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
- edgeID = n2->getshapeId();
- }
- }
// get positions of the given nodes on shapes
- TopAbs_ShapeEnum shapeType = myShape.IsNull() ? TopAbs_SHAPE : myShape.ShapeType();
- if ( faceID>0 || shapeType == TopAbs_FACE)
+ if ( pos.second == TopAbs_FACE )
{
- if( myShape.IsNull() )
- F = TopoDS::Face(meshDS->IndexToShape(faceID));
- else {
- F = TopoDS::Face(myShape);
- faceID = myShapeID;
- }
+ F = TopoDS::Face(meshDS->IndexToShape( faceID = pos.first ));
uv[0] = GetNodeUV(F,n1,n2, force3d ? 0 : &uvOK[0]);
uv[1] = GetNodeUV(F,n2,n1, force3d ? 0 : &uvOK[1]);
}
- else if (edgeID>0 || shapeType == TopAbs_EDGE)
+ else if ( pos.second == TopAbs_EDGE )
{
+ const SMDS_PositionPtr Pos1 = n1->GetPosition();
+ const SMDS_PositionPtr Pos2 = n2->GetPosition();
if ( Pos1->GetTypeOfPosition()==SMDS_TOP_EDGE &&
Pos2->GetTypeOfPosition()==SMDS_TOP_EDGE &&
- n1->getshapeId() != n2->getshapeId() ) // issue 0021006
- return getMediumNodeOnComposedWire(n1,n2,force3d);
-
- if( myShape.IsNull() )
- E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
- else {
- E = TopoDS::Edge(myShape);
- edgeID = myShapeID;
+ n1->getshapeId() != n2->getshapeId() )
+ {
+ // issue 0021006
+ return getMediumNodeOnComposedWire(n1,n2,force3d);
}
+ E = TopoDS::Edge(meshDS->IndexToShape( edgeID = pos.first ));
u[0] = GetNodeU(E,n1,n2, force3d ? 0 : &uvOK[0]);
u[1] = GetNodeU(E,n2,n1, force3d ? 0 : &uvOK[1]);
}
- if(!force3d)
+
+ if ( !force3d & uvOK[0] && uvOK[1] )
{
// we try to create medium node using UV parameters of
// nodes, else - medium between corresponding 3d points
if( ! F.IsNull() )
{
- if ( uvOK[0] && uvOK[1] )
+ //if ( uvOK[0] && uvOK[1] )
{
if ( IsDegenShape( n1->getshapeId() )) {
if ( myParIndex & U_periodic ) uv[0].SetCoord( 1, uv[1].Coord( 1 ));
//purpose : Creates a node
//=======================================================================
-SMDS_MeshNode* SMESH_MesherHelper::AddNode(double x, double y, double z, int ID)
+SMDS_MeshNode* SMESH_MesherHelper::AddNode(double x, double y, double z, int ID,
+ double u, double v)
{
SMESHDS_Mesh * meshDS = GetMeshDS();
SMDS_MeshNode* node = 0;
node = meshDS->AddNode( x, y, z );
if ( mySetElemOnShape && myShapeID > 0 ) {
switch ( myShape.ShapeType() ) {
- case TopAbs_SOLID: meshDS->SetNodeInVolume( node, myShapeID); break;
- case TopAbs_SHELL: meshDS->SetNodeInVolume( node, myShapeID); break;
- case TopAbs_FACE: meshDS->SetNodeOnFace( node, myShapeID); break;
- case TopAbs_EDGE: meshDS->SetNodeOnEdge( node, myShapeID); break;
- case TopAbs_VERTEX: meshDS->SetNodeOnVertex( node, myShapeID); break;
+ case TopAbs_SOLID: meshDS->SetNodeInVolume( node, myShapeID); break;
+ case TopAbs_SHELL: meshDS->SetNodeInVolume( node, myShapeID); break;
+ case TopAbs_FACE: meshDS->SetNodeOnFace( node, myShapeID, u, v); break;
+ case TopAbs_EDGE: meshDS->SetNodeOnEdge( node, myShapeID, u); break;
+ case TopAbs_VERTEX: meshDS->SetNodeOnVertex( node, myShapeID); break;
default: ;
}
}
for ( int i = 0; i < nodes.size(); ++i )
{
const SMDS_MeshNode* n1 = nodes[i];
- const SMDS_MeshNode* n2 = nodes[(i+1)/nodes.size()];
+ const SMDS_MeshNode* n2 = nodes[(i+1)%nodes.size()];
const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
newNodes.push_back( n1 );
newNodes.push_back( n12 );
return elem;
}
+//=======================================================================
+//function : AddVolume
+//purpose : Creates LINEAR!!!!!!!!! octahedron
+//=======================================================================
+
+SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
+ const SMDS_MeshNode* n2,
+ const SMDS_MeshNode* n3,
+ const SMDS_MeshNode* n4,
+ const SMDS_MeshNode* n5,
+ const SMDS_MeshNode* n6,
+ const SMDS_MeshNode* n7,
+ const SMDS_MeshNode* n8,
+ const SMDS_MeshNode* n9,
+ const SMDS_MeshNode* n10,
+ const SMDS_MeshNode* n11,
+ const SMDS_MeshNode* n12,
+ const int id,
+ bool force3d)
+{
+ SMESHDS_Mesh * meshDS = GetMeshDS();
+ SMDS_MeshVolume* elem = 0;
+ if(id)
+ elem = meshDS->AddVolumeWithID(n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,id);
+ else
+ elem = meshDS->AddVolume(n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12);
+ if ( mySetElemOnShape && myShapeID > 0 )
+ meshDS->SetMeshElementOnShape( elem, myShapeID );
+ return elem;
+}
+
//=======================================================================
//function : AddPolyhedralVolume
//purpose : Creates polyhedron. In quadratic mesh, adds medium nodes
return elem;
}
+namespace
+{
+ //================================================================================
+ /*!
+ * \brief Check if a node belongs to any face of sub-mesh
+ */
+ //================================================================================
+
+ bool isNodeInSubMesh( const SMDS_MeshNode* n, const SMESHDS_SubMesh* sm )
+ {
+ SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator( SMDSAbs_Face );
+ while ( fIt->more() )
+ if ( sm->Contains( fIt->next() ))
+ return true;
+ return false;
+ }
+}
+
//=======================================================================
//function : LoadNodeColumns
//purpose : Load nodes bound to face into a map of node columns
SMESHDS_Mesh* theMesh,
SMESH_ProxyMesh* theProxyMesh)
{
+ return LoadNodeColumns(theParam2ColumnMap,
+ theFace,
+ std::list<TopoDS_Edge>(1,theBaseEdge),
+ theMesh,
+ theProxyMesh);
+}
+
+//=======================================================================
+//function : LoadNodeColumns
+//purpose : Load nodes bound to face into a map of node columns
+//=======================================================================
+
+bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
+ const TopoDS_Face& theFace,
+ const std::list<TopoDS_Edge>& theBaseSide,
+ SMESHDS_Mesh* theMesh,
+ SMESH_ProxyMesh* theProxyMesh)
+{
+ // get a right submesh of theFace
+
const SMESHDS_SubMesh* faceSubMesh = 0;
if ( theProxyMesh )
{
if ( !faceSubMesh || faceSubMesh->NbElements() == 0 )
return false;
- // get nodes on theBaseEdge sorted by param on edge and initialize theParam2ColumnMap with them
-
- map< double, const SMDS_MeshNode*> sortedBaseNodes;
- if ( !SMESH_Algo::GetSortedNodesOnEdge( theMesh, theBaseEdge,/*noMedium=*/true, sortedBaseNodes)
- || sortedBaseNodes.size() < 2 )
- return false;
+ // get data of edges for normalization of params
- int nbRows = faceSubMesh->NbElements() / ( sortedBaseNodes.size()-1 ) + 1;
- map< double, const SMDS_MeshNode*>::iterator u_n = sortedBaseNodes.begin();
- double f = u_n->first, range = sortedBaseNodes.rbegin()->first - f;
- for ( ; u_n != sortedBaseNodes.end(); u_n++ )
+ vector< double > length;
+ double fullLen = 0;
+ list<TopoDS_Edge>::const_iterator edge;
{
- double par = ( u_n->first - f ) / range;
- vector<const SMDS_MeshNode*>& nCol = theParam2ColumnMap[ par ];
- nCol.resize( nbRows );
- nCol[0] = u_n->second;
+ for ( edge = theBaseSide.begin(); edge != theBaseSide.end(); ++edge )
+ {
+ double len = std::max( 1e-10, SMESH_Algo::EdgeLength( *edge ));
+ fullLen += len;
+ length.push_back( len );
+ }
}
- TParam2ColumnMap::iterator par_nVec_2, par_nVec_1 = theParam2ColumnMap.begin();
- if ( theProxyMesh )
+
+ // get nodes on theBaseEdge sorted by param on edge and initialize theParam2ColumnMap with them
+ edge = theBaseSide.begin();
+ for ( int iE = 0; edge != theBaseSide.end(); ++edge, ++iE )
{
- for ( ; par_nVec_1 != theParam2ColumnMap.end(); ++par_nVec_1 )
+ map< double, const SMDS_MeshNode*> sortedBaseNodes;
+ SMESH_Algo::GetSortedNodesOnEdge( theMesh, *edge,/*noMedium=*/true, sortedBaseNodes);
+ if ( sortedBaseNodes.empty() ) continue;
+
+ map< double, const SMDS_MeshNode*>::iterator u_n = sortedBaseNodes.begin();
+ if ( theProxyMesh ) // from sortedBaseNodes remove nodes not shared by faces of faceSubMesh
{
- const SMDS_MeshNode* & n = par_nVec_1->second[0];
- n = theProxyMesh->GetProxyNode( n );
+ const SMDS_MeshNode* n1 = sortedBaseNodes.begin()->second;
+ const SMDS_MeshNode* n2 = sortedBaseNodes.rbegin()->second;
+ bool allNodesAreProxy = ( n1 != theProxyMesh->GetProxyNode( n1 ) &&
+ n2 != theProxyMesh->GetProxyNode( n2 ));
+ if ( allNodesAreProxy )
+ for ( u_n = sortedBaseNodes.begin(); u_n != sortedBaseNodes.end(); u_n++ )
+ u_n->second = theProxyMesh->GetProxyNode( u_n->second );
+
+ if ( u_n = sortedBaseNodes.begin(), !isNodeInSubMesh( u_n->second, faceSubMesh ))
+ {
+ while ( ++u_n != sortedBaseNodes.end() && !isNodeInSubMesh( u_n->second, faceSubMesh ));
+ sortedBaseNodes.erase( sortedBaseNodes.begin(), u_n );
+ }
+ else if ( u_n = --sortedBaseNodes.end(), !isNodeInSubMesh( u_n->second, faceSubMesh ))
+ {
+ while ( u_n != sortedBaseNodes.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh ));
+ sortedBaseNodes.erase( ++u_n, sortedBaseNodes.end() );
+ }
+ if ( sortedBaseNodes.empty() ) continue;
+ }
+
+ double f, l;
+ BRep_Tool::Range( *edge, f, l );
+ if ( edge->Orientation() == TopAbs_REVERSED ) std::swap( f, l );
+ const double coeff = 1. / ( l - f ) * length[iE] / fullLen;
+ const double prevPar = theParam2ColumnMap.empty() ? 0 : theParam2ColumnMap.rbegin()->first;
+ for ( u_n = sortedBaseNodes.begin(); u_n != sortedBaseNodes.end(); u_n++ )
+ {
+ double par = prevPar + coeff * ( u_n->first - f );
+ TParam2ColumnMap::iterator u2nn =
+ theParam2ColumnMap.insert( theParam2ColumnMap.end(), make_pair( par, TNodeColumn()));
+ u2nn->second.push_back( u_n->second );
}
}
+ if ( theParam2ColumnMap.empty() )
+ return false;
+
+
+ int nbRows = 1 + faceSubMesh->NbElements() / ( theParam2ColumnMap.size()-1 );
// fill theParam2ColumnMap column by column by passing from nodes on
// theBaseEdge up via mesh faces on theFace
+ TParam2ColumnMap::iterator par_nVec_1, par_nVec_2;
par_nVec_2 = theParam2ColumnMap.begin();
par_nVec_1 = par_nVec_2++;
TIDSortedElemSet emptySet, avoidSet;
{
vector<const SMDS_MeshNode*>& nCol1 = par_nVec_1->second;
vector<const SMDS_MeshNode*>& nCol2 = par_nVec_2->second;
+ nCol1.resize( nbRows );
+ nCol2.resize( nbRows );
int i1, i2, iRow = 0;
const SMDS_MeshNode *n1 = nCol1[0], *n2 = nCol2[0];
}
avoidSet.insert( face );
}
- if ( iRow + 1 < nbRows ) // compact if necessary
- nCol1.resize( iRow + 1 ), nCol2.resize( iRow + 1 );
+ // set a real height
+ nCol1.resize( iRow + 1 );
+ nCol2.resize( iRow + 1 );
}
return theParam2ColumnMap.size() > 1 && theParam2ColumnMap.begin()->second.size() > 1;
}
return PShapeIteratorPtr( new TAncestorsIterator( mesh.GetAncestors(shape), ancestorType));
}
+//=======================================================================
+//function : GetCommonAncestor
+//purpose : Find a common ancestors of two shapes of the given type
+//=======================================================================
+
+TopoDS_Shape SMESH_MesherHelper::GetCommonAncestor(const TopoDS_Shape& shape1,
+ const TopoDS_Shape& shape2,
+ const SMESH_Mesh& mesh,
+ TopAbs_ShapeEnum ancestorType)
+{
+ TopoDS_Shape commonAnc;
+ if ( !shape1.IsNull() && !shape2.IsNull() )
+ {
+ PShapeIteratorPtr ancIt = GetAncestors( shape1, mesh, ancestorType );
+ while ( const TopoDS_Shape* anc = ancIt->next() )
+ if ( IsSubShape( shape2, *anc ))
+ {
+ commonAnc = *anc;
+ break;
+ }
+ }
+ return commonAnc;
+}
+
//#include <Perf_Meter.hxx>
//=======================================================================
gp_XYZ mid1 = _qlink->MiddlePnt();
gp_XYZ mid2 = _qfaces[0]->_sides[ iOpp ]->MiddlePnt();
double faceSize2 = (mid1-mid2).SquareModulus();
- isStraight = _qlink->_nodeMove.SquareMagnitude() < 1/3./3. * faceSize2;
+ isStraight = _qlink->_nodeMove.SquareMagnitude() < 1/10./10. * faceSize2;
}
return isStraight;
}
if ( getenv("NO_FixQuadraticElements") )
return;
- // 0. Apply algorithm to solids or geom faces
+ // 0. Apply algorithm to SOLIDs or FACEs
// ----------------------------------------------
if ( myShape.IsNull() ) {
if ( !myMesh->HasShapeToMesh() ) return;
SMESH_MesherHelper h(*myMesh);
h.SetSubShape( fIt.Key() );
h.FixQuadraticElements(true);
+ h.ToFixNodeParameters(true);
}
//perf_print_all_meters(1);
return;
const SMDS_MeshElement* vol = elemIt->next();
if ( !vol->IsQuadratic() || !volTool.Set( vol ))
return;
+ double volMinSize2 = -1.;
for ( int iF = 0; iF < volTool.NbFaces(); ++iF ) // loop on faces of volume
{
int nbN = volTool.NbFaceNodes( iF );
QLink link( faceNodes[iN], faceNodes[iN+2], faceNodes[iN+1] );
pLink = links.insert( link ).first;
faceLinks[ iN/2 ] = & *pLink;
- if ( !isCurved )
- isCurved = !link.IsStraight();
- if ( link.MediumPos() == SMDS_TOP_3DSPACE && !link.IsStraight() )
- return; // already fixed
+
+ if ( link.MediumPos() == SMDS_TOP_3DSPACE )
+ {
+ if ( !link.IsStraight() )
+ return; // already fixed
+ }
+ else if ( !isCurved )
+ {
+ if ( volMinSize2 < 0 ) volMinSize2 = volTool.MinLinearSize2();
+ isCurved = !isStraightLink( volMinSize2, link._nodeMove.SquareMagnitude() );
+ }
}
// store QFace
pFace = faces.insert( QFace( faceLinks )).first;