-// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015 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
#include <Bnd_B3d.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2d_Line.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
#include <Geom_Curve.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
Prism_3D::TPrismTopo prism;
myPropagChains = 0;
+ bool selectBottom = meshedFaces.empty();
if ( nbSolids == 1 )
{
+ TopoDS_Shape solid = TopExp_Explorer( theShape, TopAbs_SOLID ).Current();
if ( !meshedFaces.empty() )
prism.myBottom = meshedFaces.front();
- return ( initPrism( prism, TopExp_Explorer( theShape, TopAbs_SOLID ).Current() ) &&
+ return ( initPrism( prism, solid, selectBottom ) &&
compute( prism ));
}
{
prism.Clear();
prism.myBottom = face;
- if ( !initPrism( prism, solid ) ||
+ if ( !initPrism( prism, solid, selectBottom ) ||
!compute( prism ))
return false;
while ( const TopoDS_Shape* f = faceIt->next() )
{
const TopoDS_Face& candidateF = TopoDS::Face( *f );
+ if ( candidateF.IsSame( wFace )) continue;
+ // select a source FACE: prismIt->myBottom or prismIt->myTop
+ TopoDS_Face sourceF = prismIt->myBottom;
+ for ( TopExp_Explorer v( prismIt->myTop, TopAbs_VERTEX ); v.More(); v.Next() )
+ if ( myHelper->IsSubShape( v.Current(), candidateF )) {
+ sourceF = prismIt->myTop;
+ break;
+ }
prism.Clear();
- prism.myBottom = candidateF;
+ prism.myBottom = candidateF;
mySetErrorToSM = false;
if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
- myHelper->IsSubShape( candidateF, solid ) &&
+ myHelper ->IsSubShape( candidateF, solid ) &&
!myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
- initPrism( prism, solid ) &&
+ initPrism( prism, solid, /*selectBottom=*/false ) &&
!myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
- project2dMesh( prismIt->myBottom, candidateF))
+ !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
+ project2dMesh( sourceF, prism.myBottom ))
{
mySetErrorToSM = true;
if ( !compute( prism ))
{
meshedFaces.push_front( prism.myTop );
meshedFaces.push_front( prism.myBottom );
+ selectBottom = false;
}
meshedPrism.push_back( prism );
meshedSolids.Add( solid );
if ( meshedFaces.empty() )
{
meshedFaces.splice( meshedFaces.end(), suspectSourceFaces );
+ selectBottom = true;
}
// find FACEs with local 1D hyps, which has to be computed by now,
{
if ( !meshedFaces.empty() ) meshedFaces.pop_back();
meshedFaces.push_back( face ); // lower priority
+ selectBottom = true;
prevNbFaces = nbFaces;
}
}
faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
if ( !faceSM->IsEmpty() ) {
meshedFaces.push_front( face ); // higher priority
+ selectBottom = true;
break;
}
else {
meshedFaces.push_front( prism.myBottom );
meshedPrism.push_back( prism );
meshedSolids.Add( solid.Current() );
+ selectBottom = true;
}
mySetErrorToSM = true;
}
return error( err );
}
}
- return true;
+ return error( COMPERR_OK );
}
//================================================================================
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
const TopoDS_Edge & topE = topSide->Edge( 0 );
if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
- return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom )));
+ return toSM( error( TCom("Wrong source face: #") << shapeID( thePrism.myBottom )));
}
return true;
if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
+ // Assure the bottom is meshed
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ if (( botSM->IsEmpty() ) &&
+ ( ! botSM->GetAlgo() ||
+ ! _gen->Compute( *botSM->GetFather(), botSM->GetSubShape(), /*shapeOnly=*/true )))
+ return error( COMPERR_BAD_INPUT_MESH,
+ TCom( "No mesher defined to compute the face #")
+ << shapeID( thePrism.myBottom ));
+
// Make all side FACEs of thePrism meshed with quads
if ( !computeWalls( thePrism ))
return false;
// Analyse mesh and geometry to find all block sub-shapes and submeshes
- // (after fixing IPAL52499 myBlock is used only as a holder of boundary nodes
- // and location of internal nodes is computed by StdMeshers_Sweeper)
+ // (after fixing IPAL52499 myBlock is used as a holder of boundary nodes
+ // and for 2D projection in hard cases where StdMeshers_Projection_2D fails;
+ // location of internal nodes is usually computed by StdMeshers_Sweeper)
if ( !myBlock.Init( myHelper, thePrism ))
return toSM( error( myBlock.GetError()));
// Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes
+ myUseBlock = false;
myBotToColumnMap.clear();
if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false;
// use transformation (issue 0020680, IPAL0052499)
StdMeshers_Sweeper sweeper;
+ double tol;
+ bool allowHighBndError;
- // load boundary nodes
- bool dummy;
- list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
- for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+ if ( !myUseBlock )
{
- int edgeID = meshDS->ShapeToIndex( *edge );
- TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*>
- ( myBlock.GetParam2ColumnMap( edgeID, dummy ));
- TParam2ColumnMap::iterator u2colIt = u2col->begin();
- for ( ; u2colIt != u2col->end(); ++u2colIt )
- sweeper.myBndColumns.push_back( & u2colIt->second );
- }
- // load node columns inside the bottom face
- TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
- for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
- sweeper.myIntColumns.push_back( & bot_column->second );
+ // load boundary nodes into sweeper
+ bool dummy;
+ list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
+ for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+ {
+ int edgeID = meshDS->ShapeToIndex( *edge );
+ TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*>
+ ( myBlock.GetParam2ColumnMap( edgeID, dummy ));
+ TParam2ColumnMap::iterator u2colIt = u2col->begin();
+ for ( ; u2colIt != u2col->end(); ++u2colIt )
+ sweeper.myBndColumns.push_back( & u2colIt->second );
+ }
+ // load node columns inside the bottom face
+ TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
+ for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
+ sweeper.myIntColumns.push_back( & bot_column->second );
- const double tol = getSweepTolerance( thePrism );
+ tol = getSweepTolerance( thePrism );
+ allowHighBndError = !isSimpleBottom( thePrism );
+ }
- if ( sweeper.ComputeNodes( *myHelper, tol ))
+ if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol, allowHighBndError ))
{
}
else // use block approach
// clear data
myBotToColumnMap.clear();
myBlock.Clear();
-
+
+ // update state of sub-meshes (mostly in order to erase improper errors)
+ SMESH_subMesh* sm = myHelper->GetMesh()->GetSubMesh( thePrism.myShape3D );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ sm->GetComputeError().reset();
+ sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+ }
+
return true;
}
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
const TopoDS_Face& face = (*quad)->face;
- SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+ SMESH_subMesh* fSM = mesh->GetSubMesh( face );
if ( ! fSM->IsMeshComputed() )
{
// Top EDGEs must be projections from the bottom ones
NSProjUtils::TShapeShapeMap shape2ShapeMap;
const bool sameTopo =
NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
- thePrism.myTop, myHelper->GetMesh(),
- shape2ShapeMap);
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap);
if ( !sameTopo )
for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
{
for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
{
NSProjUtils::InsertAssociation( botSide->Edge( iE ),
- topSide->Edge( iE ), shape2ShapeMap );
+ topSide->Edge( iE ), shape2ShapeMap );
NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
- myHelper->IthVertex( 0, topSide->Edge( iE )),
- shape2ShapeMap );
+ myHelper->IthVertex( 0, topSide->Edge( iE )),
+ shape2ShapeMap );
}
}
else
vt.IsSame( sideT->LastVertex() ))
{
NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
- topSide->Edge( 0 ), shape2ShapeMap );
+ topSide->Edge( 0 ), shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
}
vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
vt.IsSame( sideT->LastVertex() ))
{
NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
- topSide->Edge( topSide->NbEdges()-1 ),
- shape2ShapeMap );
+ topSide->Edge( topSide->NbEdges()-1 ),
+ shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
}
}
// Find matching nodes of top and bottom faces
n2nMapPtr = & n2nMap;
if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
- thePrism.myTop, myHelper->GetMesh(),
- shape2ShapeMap, n2nMap ))
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap, n2nMap ))
{
if ( sameTopo )
return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
continue; // wall columns are contained in myBlock
// create node column
Prism_3D::TNode bN( botNode );
- TNode2ColumnMap::iterator bN_col =
+ TNode2ColumnMap::iterator bN_col =
myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
TNodeColumn & column = bN_col->second;
column.resize( zSize );
{
return true;
}
+ NSProjUtils::TNodeNodeMap& n2nMap =
+ (NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap();
+ n2nMap.clear();
+
+ myUseBlock = true;
SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( topSMDS && topSMDS->NbElements() > 0 )
- topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+ {
+ //topSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+ for ( SMDS_ElemIteratorPtr eIt = topSMDS->GetElements(); eIt->more(); )
+ meshDS->RemoveFreeElement( eIt->next(), topSMDS, /*fromGroups=*/false );
+ for ( SMDS_NodeIteratorPtr nIt = topSMDS->GetNodes(); nIt->more(); )
+ meshDS->RemoveFreeNode( nIt->next(), topSMDS, /*fromGroups=*/false );
+ }
const TopoDS_Face& botFace = thePrism.myBottom; // oriented within
const TopoDS_Face& topFace = thePrism.myTop; // the 3D SHAPE
column.front() = botNode;
column.back() = topNode;
+ n2nMap.insert( n2nMap.end(), make_pair( botNode, topNode ));
+
if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
}
case 3: {
newFace = myHelper->AddFace(nodes[0], nodes[1], nodes[2]);
break;
- }
+ }
case 4: {
newFace = myHelper->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
break;
- }
+ }
default:
newFace = meshDS->AddPolygonalFace( nodes );
}
meshDS->SetMeshElementOnShape( newFace, topFaceID );
}
- myHelper->SetElementsOnShape( oldSetElemsOnShape );
+ myHelper->SetElementsOnShape( oldSetElemsOnShape );
+
+ // Check the projected mesh
+
+ if ( thePrism.myNbEdgesInWires.size() > 1 && // there are holes
+ topHelper.IsDistorted2D( topSM, /*checkUV=*/false ))
+ {
+ SMESH_MeshEditor editor( topHelper.GetMesh() );
+
+ // smooth in 2D or 3D?
+ TopLoc_Location loc;
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( topFace, loc );
+ bool isPlanar = GeomLib_IsPlanarSurface( surface ).IsPlanar();
+
+ bool isFixed = false;
+ set<const SMDS_MeshNode*> fixedNodes;
+ for ( int iAttemp = 0; !isFixed && iAttemp < 10; ++iAttemp )
+ {
+ TIDSortedElemSet faces;
+ for ( faceIt = topSMDS->GetElements(); faceIt->more(); )
+ faces.insert( faces.end(), faceIt->next() );
+
+ SMESH_MeshEditor::SmoothMethod algo =
+ iAttemp ? SMESH_MeshEditor::CENTROIDAL : SMESH_MeshEditor::LAPLACIAN;
+
+ // smoothing
+ editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
+ /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
+
+ isFixed = !topHelper.IsDistorted2D( topSM, /*checkUV=*/true );
+ }
+ if ( !isFixed )
+ return toSM( error( TCom("Projection from face #") << botSM->GetId()
+ << " to face #" << topSM->GetId()
+ << " failed: inverted elements created"));
+ }
return true;
}
return 0.1 * Sqrt ( minDist );
}
+//=======================================================================
+//function : isSimpleQuad
+//purpose : check if the bottom FACE is meshable with nice qudrangles,
+// if so the block aproach can work rather fast.
+// This is a temporary mean caused by problems in StdMeshers_Sweeper
+//=======================================================================
+
+bool StdMeshers_Prism_3D::isSimpleBottom( const Prism_3D::TPrismTopo& thePrism )
+{
+ // analyse angles between edges
+ double nbConcaveAng = 0, nbConvexAng = 0;
+ TopoDS_Face reverseBottom = TopoDS::Face( thePrism.myBottom.Reversed() ); // see initPrism()
+ TopoDS_Vertex commonV;
+ const list< TopoDS_Edge >& botEdges = thePrism.myBottomEdges;
+ list< TopoDS_Edge >::const_iterator edge = botEdges.begin();
+ while ( edge != botEdges.end() )
+ {
+ if ( SMESH_Algo::isDegenerated( *edge ))
+ return false;
+ TopoDS_Edge e1 = *edge++;
+ TopoDS_Edge e2 = ( edge == botEdges.end() ? botEdges.front() : *edge );
+ if ( ! TopExp::CommonVertex( e1, e2, commonV ))
+ {
+ e2 = botEdges.front();
+ if ( ! TopExp::CommonVertex( e1, e2, commonV ))
+ break;
+ }
+ double angle = myHelper->GetAngle( e1, e2, reverseBottom, commonV );
+ if ( angle < -5 * M_PI/180 )
+ if ( ++nbConcaveAng > 1 )
+ return false;
+ if ( angle > 85 * M_PI/180 )
+ if ( ++nbConvexAng > 4 )
+ return false;
+ }
+ return true;
+}
+
//=======================================================================
//function : project2dMesh
//purpose : Project mesh faces from a source FACE of one prism (theSrcFace)
bool ok = projector2D->Compute( *myHelper->GetMesh(), theTgtFace );
SMESH_subMesh* tgtSM = myHelper->GetMesh()->GetSubMesh( theTgtFace );
+ if ( !ok && tgtSM->GetSubMeshDS() ) {
+ //tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESHDS_SubMesh* tgtSMDS = tgtSM->GetSubMeshDS();
+ for ( SMDS_ElemIteratorPtr eIt = tgtSMDS->GetElements(); eIt->more(); )
+ meshDS->RemoveFreeElement( eIt->next(), tgtSMDS, /*fromGroups=*/false );
+ for ( SMDS_NodeIteratorPtr nIt = tgtSMDS->GetNodes(); nIt->more(); )
+ meshDS->RemoveFreeNode( nIt->next(), tgtSMDS, /*fromGroups=*/false );
+ }
tgtSM->ComputeStateEngine ( SMESH_subMesh::CHECK_COMPUTE_STATE );
tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
for ( iE = 0; iE < *nbE; ++e, ++iE )
if ( SMESH_Algo::isDegenerated( *e ))
{
- ee.erase( e );
+ e = --ee.erase( e );
--(*nbE);
--iE;
}
//=======================================================================
bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
- const TopoDS_Shape& shape3D)
+ const TopoDS_Shape& theShape3D,
+ const bool selectBottom)
{
- myHelper->SetSubShape( shape3D );
+ myHelper->SetSubShape( theShape3D );
- SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D );
+ SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( theShape3D );
if ( !mainSubMesh ) return toSM( error(COMPERR_BAD_INPUT_MESH,"Null submesh of shape3D"));
// detect not-quad FACE sub-meshes of the 3D SHAPE
list< SMESH_subMesh* > notQuadGeomSubMesh;
list< SMESH_subMesh* > notQuadElemSubMesh;
+ list< SMESH_subMesh* > meshedSubMesh;
int nbFaces = 0;
//
SMESH_subMesh* anyFaceSM = 0;
if ( nbWires != 1 || nbEdgesInWires.front() != 4 )
notQuadGeomSubMesh.push_back( sm );
- // look for not quadrangle mesh elements
- if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() )
- if ( !myHelper->IsSameElemGeometry( smDS, SMDSGeom_QUADRANGLE ))
+ // look for a not structured sub-mesh
+ if ( !sm->IsEmpty() )
+ {
+ meshedSubMesh.push_back( sm );
+ if ( !myHelper->IsSameElemGeometry( sm->GetSubMeshDS(), SMDSGeom_QUADRANGLE ) ||
+ !myHelper->IsStructured ( sm ))
notQuadElemSubMesh.push_back( sm );
+ }
}
int nbNotQuadMeshed = notQuadElemSubMesh.size();
// use thePrism.myBottom
if ( !thePrism.myBottom.IsNull() )
{
- if ( botSM ) {
+ if ( botSM ) { // <-- not quad geom or mesh on botSM
if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
std::swap( botSM, topSM );
- if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom ))
- return toSM( error( COMPERR_BAD_INPUT_MESH,
- "Incompatible non-structured sub-meshes"));
+ if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
+ if ( !selectBottom )
+ return toSM( error( COMPERR_BAD_INPUT_MESH,
+ "Incompatible non-structured sub-meshes"));
+ std::swap( botSM, topSM );
+ thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
+ }
}
}
- else {
+ else if ( !selectBottom ) {
botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
}
}
- else if ( !botSM ) // find a proper bottom
+ if ( !botSM ) // find a proper bottom
{
- // composite walls or not prism shape
- for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() )
+ bool savedSetErrorToSM = mySetErrorToSM;
+ mySetErrorToSM = false; // ingore errors in initPrism()
+
+ // search among meshed FACEs
+ list< SMESH_subMesh* >::iterator sm = meshedSubMesh.begin();
+ for ( ; !botSM && sm != meshedSubMesh.end(); ++sm )
+ {
+ thePrism.Clear();
+ botSM = *sm;
+ thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
+ if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false ))
+ botSM = NULL;
+ }
+ // search among all FACEs
+ for ( TopExp_Explorer f( theShape3D, TopAbs_FACE ); !botSM && f.More(); f.Next() )
{
int minNbFaces = 2 + myHelper->Count( f.Current(), TopAbs_EDGE, false);
- if ( nbFaces >= minNbFaces)
- {
- thePrism.Clear();
- thePrism.myBottom = TopoDS::Face( f.Current() );
- if ( initPrism( thePrism, shape3D ))
- return true;
- }
- return toSM( error( COMPERR_BAD_SHAPE ));
+ if ( nbFaces < minNbFaces) continue;
+ thePrism.Clear();
+ thePrism.myBottom = TopoDS::Face( f.Current() );
+ botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ if ( !initPrism( thePrism, theShape3D, /*selectBottom=*/false ))
+ botSM = NULL;
}
+ mySetErrorToSM = savedSetErrorToSM;
+ return botSM ? true : toSM( error( COMPERR_BAD_SHAPE ));
}
// find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
}
}
- thePrism.myShape3D = shape3D;
+ thePrism.myShape3D = theShape3D;
if ( thePrism.myBottom.IsNull() )
thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
- thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myBottom ));
- thePrism.myTop. Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myTop ));
+ thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myBottom ));
+ thePrism.myTop. Orientation( myHelper->GetSubShapeOri( theShape3D, thePrism.myTop ));
// Get ordered bottom edges
TopoDS_Face reverseBottom = // to have order of top EDGEs as in the top FACE
thePrism.myNbEdgesInWires, V000 );
// Get Wall faces corresponding to the ordered bottom edges and the top FACE
- if ( !getWallFaces( thePrism, nbFaces ))
+ if ( !getWallFaces( thePrism, nbFaces )) // it also sets thePrism.myTop
return false; //toSM( error(COMPERR_BAD_SHAPE, "Can't find side faces"));
if ( topSM )
TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() );
if ( s.ShapeType() != TopAbs_EDGE )
s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() );
- if ( s.ShapeType() == TopAbs_EDGE )
+ if ( !s.IsNull() && s.ShapeType() == TopAbs_EDGE )
edge = TopoDS::Edge( s );
}
if ( !edge.IsNull() )
//================================================================================
bool StdMeshers_Sweeper::ComputeNodes( SMESH_MesherHelper& helper,
- const double tol)
+ const double tol,
+ const bool allowHighBndError)
{
const size_t zSize = myBndColumns[0]->size();
const size_t zSrc = 0, zTgt = zSize-1;
bndErrorIsSmall = ( sumError < tol );
}
+ if ( !bndErrorIsSmall && !allowHighBndError )
+ return false;
+
// compute final points on the central layer
std::vector< double > int2BndDist( myBndColumns.size() ); // work array of applyBoundaryError()
double r = zS / ( zSize - 1.);