using namespace std;
#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
-#define SHOWYXZ(msg, xyz) // {\
-// gp_Pnt p (xyz); \
-// cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
-// }
+#define gpXYZ(n) SMESH_TNodeXYZ(n)
+
#ifdef _DEBUG_
#define DBGOUT(msg) //cout << msg << endl;
+#define SHOWYXZ(msg, xyz) \
+ // { gp_Pnt p (xyz); \
+ // cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl; }
#else
#define DBGOUT(msg)
+#define SHOWYXZ(msg, xyz)
#endif
-namespace TAssocTool = StdMeshers_ProjectionUtils;
+namespace NSProjUtils = StdMeshers_ProjectionUtils;
typedef SMESH_Comment TCom;
fatherAlgo->GetGen() );
return algo;
}
+ const NSProjUtils::TNodeNodeMap& GetNodesMap()
+ {
+ return _src2tgtNodes;
+ }
};
//=======================================================================
/*!
( sm->NbElements() > 0 ) &&
( !theHelper.IsSameElemGeometry( sm, SMDSGeom_QUADRANGLE ) ))
{
- faceFound;
+ faceFound = true;
break;
}
if ( !faceFound )
quad->face = TopoDS::Face( face );
- return isComposite;
+ return !isComposite;
}
//================================================================================
*/
//================================================================================
- double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
- {
- return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
- }
+ // double normAngle(const TopoDS_Edge & E1, const TopoDS_Edge & E2, const TopoDS_Face & F)
+ // {
+ // return SMESH_MesherHelper::GetAngle( E1, E2, F ) / ( 0.5 * M_PI );
+ // }
//================================================================================
/*!
{
_name = "Prism_3D";
_shapeType = (1 << TopAbs_SOLID); // 1 bit per shape type
- _onlyUnaryInput = false; // accept all SOLIDs at once
+ _onlyUnaryInput = false; // mesh all SOLIDs at once
_requireDiscreteBoundary = false; // mesh FACEs and EDGEs by myself
_supportSubmeshes = true; // "source" FACE must be meshed by other algo
_neededLowerHyps[ 1 ] = true; // suppress warning on hiding a global 1D algo
for ( ; exp.More(); exp.Next() ) {
++nbFace;
const TopoDS_Shape& face = exp.Current();
- nbEdge = TAssocTool::Count( face, TopAbs_EDGE, 0 );
- nbWire = TAssocTool::Count( face, TopAbs_WIRE, 0 );
+ nbEdge = NSProjUtils::Count( face, TopAbs_EDGE, 0 );
+ nbWire = NSProjUtils::Count( face, TopAbs_WIRE, 0 );
if ( nbEdge!= 4 || nbWire!= 1 ) {
if ( !notQuadFaces.empty() ) {
- if ( TAssocTool::Count( notQuadFaces.back(), TopAbs_EDGE, 0 ) != nbEdge ||
- TAssocTool::Count( notQuadFaces.back(), TopAbs_WIRE, 0 ) != nbWire )
+ if ( NSProjUtils::Count( notQuadFaces.back(), TopAbs_EDGE, 0 ) != nbEdge ||
+ NSProjUtils::Count( notQuadFaces.back(), TopAbs_WIRE, 0 ) != nbWire )
RETURN_BAD_RESULT("Different not quad faces");
}
notQuadFaces.push_back( face );
RETURN_BAD_RESULT("Bad nb not quad faces: " << notQuadFaces.size());
// check total nb faces
- nbEdge = TAssocTool::Count( notQuadFaces.back(), TopAbs_EDGE, 0 );
+ nbEdge = NSProjUtils::Count( notQuadFaces.back(), TopAbs_EDGE, 0 );
if ( nbFace != nbEdge + 2 )
RETURN_BAD_RESULT("Bad nb of faces: " << nbFace << " but must be " << nbEdge + 2);
}
meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces );
Prism_3D::TPrismTopo prism;
+ myPropagChains = 0;
if ( nbSolids == 1 )
{
if ( !quadList.back() )
return toSM( error(TCom("Side face #") << shapeID( face )
<< " not meshable with quadrangles"));
- if ( ! setBottomEdge( *edge, quadList.back(), face ))
- ; //return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
+ bool isCompositeBase = ! setBottomEdge( *edge, quadList.back(), face );
+ if ( isCompositeBase )
+ {
+ // it's OK if all EDGEs of the bottom side belongs to the bottom FACE
+ StdMeshers_FaceSidePtr botSide = quadList.back()->side[ QUAD_BOTTOM_SIDE ];
+ for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+ if ( !myHelper->IsSubShape( botSide->Edge(iE), thePrism.myBottom ))
+ return toSM( error(TCom("Composite 'horizontal' edges are not supported")));
+ }
if ( faceMap.Add( face ))
thePrism.myWallQuads.push_back( quadList );
break;
// find wall FACEs adjacent to each of thePrism.myWallQuads by the top side EDGE
if ( totalNbFaces - faceMap.Extent() > 2 )
{
+ const int nbFoundWalls = faceMap.Extent();
for ( size_t i = 0; i < thePrism.myWallQuads.size(); ++i )
{
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
}
}
}
+ if ( nbFoundWalls == faceMap.Extent() )
+ return toSM( error("Failed to find wall faces"));
+
}
} // while ( totalNbFaces - faceMap.Extent() > 2 )
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)
if ( !myBlock.Init( myHelper, thePrism ))
return toSM( error( myBlock.GetError()));
// Try to get gp_Trsf to get all nodes from bottom ones
vector<gp_Trsf> trsf;
gp_Trsf bottomToTopTrsf;
- if ( !myBlock.GetLayersTransformation( trsf, thePrism ))
- trsf.clear();
- else if ( !trsf.empty() )
- bottomToTopTrsf = trsf.back();
+ // if ( !myBlock.GetLayersTransformation( trsf, thePrism ))
+ // trsf.clear();
+ // else if ( !trsf.empty() )
+ // bottomToTopTrsf = trsf.back();
// To compute coordinates of a node inside a block, it is necessary to know
// 1. normalized parameters of the node by which
// Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes
myBotToColumnMap.clear();
- if ( !assocOrProjBottom2Top( bottomToTopTrsf ) ) // it also fills myBotToColumnMap
+ if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false;
// Create nodes inside the block
- // try to use transformation (issue 0020680)
- if ( !trsf.empty() )
+ // use transformation (issue 0020680, IPAL0052499)
+ StdMeshers_Sweeper sweeper;
+
+ // load boundary nodes
+ bool dummy;
+ list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
+ for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
{
- // loop on nodes inside the bottom face
- TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
- for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
- {
- const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode
- if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
- continue; // node is not inside face
+ 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 );
- // column nodes; middle part of the column are zero pointers
- TNodeColumn& column = bot_column->second;
- TNodeColumn::iterator columnNodes = column.begin();
- for ( int z = 0; columnNodes != column.end(); ++columnNodes, ++z)
- {
- const SMDS_MeshNode* & node = *columnNodes;
- if ( node ) continue; // skip bottom or top node
+ const double tol = getSweepTolerance( thePrism );
- gp_XYZ coords = tBotNode.GetCoords();
- trsf[z-1].Transforms( coords );
- node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
- meshDS->SetNodeInVolume( node, volumeID );
- }
- } // loop on bottom nodes
+ if ( sweeper.ComputeNodes( *myHelper, tol ))
+ {
}
else // use block approach
{
{
const Prism_3D::TNode& tBotNode = bot_column->first; // bottom TNode
if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
- continue; // node is not inside the FACE
+ continue; // node is not inside the FACE
// column nodes; middle part of the column are zero pointers
TNodeColumn& column = bot_column->second;
// create a node
node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
meshDS->SetNodeInVolume( node, volumeID );
+
+ if ( _computeCanceled )
+ return false;
}
} // loop on bottom nodes
}
TProjction1dAlgo* projector1D = TProjction1dAlgo::instance( this );
StdMeshers_Quadrangle_2D* quadAlgo = TQuadrangleAlgo::instance( this, myHelper );
- SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
- hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
- hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
+ // SMESH_HypoFilter hyp1dFilter( SMESH_HypoFilter::IsAlgo(),/*not=*/true);
+ // hyp1dFilter.And( SMESH_HypoFilter::HasDim( 1 ));
+ // hyp1dFilter.And( SMESH_HypoFilter::IsMoreLocalThan( thePrism.myShape3D, *mesh ));
// Discretize equally 'vertical' EDGEs
// -----------------------------------
// find source FACE sides for projection: either already computed ones or
// the 'most composite' ones
- multimap< int, int > wgt2quad;
- for ( size_t iW = 0; iW != thePrism.myWallQuads.size(); ++iW )
+ const size_t nbWalls = thePrism.myWallQuads.size();
+ vector< int > wgt( nbWalls, 0 ); // "weight" of a wall
+ for ( size_t iW = 0; iW != nbWalls; ++iW )
{
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
- int wgt = 0; // "weight"
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
StdMeshers_FaceSidePtr lftSide = (*quad)->side[ QUAD_LEFT_SIDE ];
for ( int i = 0; i < lftSide->NbEdges(); ++i )
{
- ++wgt;
+ ++wgt[ iW ];
const TopoDS_Edge& E = lftSide->Edge(i);
if ( mesh->GetSubMesh( E )->IsMeshComputed() )
- wgt += 10;
- else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
- wgt += 100;
+ {
+ wgt[ iW ] += 100;
+ wgt[ myHelper->WrapIndex( iW+1, nbWalls)] += 10;
+ wgt[ myHelper->WrapIndex( iW-1, nbWalls)] += 10;
+ }
+ // else if ( mesh->GetHypothesis( E, hyp1dFilter, true )) // local hypothesis!
+ // wgt += 100;
}
}
- wgt2quad.insert( make_pair( wgt, iW ));
-
// in quadratic mesh, pass ignoreMediumNodes to quad sides
if ( myHelper->GetIsQuadratic() )
{
(*quad)->side[ i ].grid->SetIgnoreMediumNodes( true );
}
}
+ multimap< int, int > wgt2quad;
+ for ( size_t iW = 0; iW != nbWalls; ++iW )
+ wgt2quad.insert( make_pair( wgt[ iW ], iW ));
// Project 'vertical' EDGEs, from left to right
multimap< int, int >::reverse_iterator w2q = wgt2quad.rbegin();
{
const TopoDS_Edge& tgtE = rgtSide->Edge(i);
SMESH_subMesh* tgtSM = mesh->GetSubMesh( tgtE );
- if (( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+ if ( !( isTgtEdgeComputed[ i ] = tgtSM->IsMeshComputed() )) {
+ tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
+ tgtSM->ComputeStateEngine ( SMESH_subMesh::COMPUTE );
+ }
+ if ( tgtSM->IsMeshComputed() ) {
++nbTgtMeshed;
nbTgtSegments += tgtSM->GetSubMeshDS()->NbElements();
}
{
if ( nbTgtSegments != nbSrcSegments )
{
- for ( int i = 0; i < lftSide->NbEdges(); ++i )
- addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+ bool badMeshRemoved = false;
+ // remove just computed segments
for ( int i = 0; i < rgtSide->NbEdges(); ++i )
- addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
- return toSM( error( TCom("Different nb of segment on logically vertical edges #")
- << shapeID( lftSide->Edge(0) ) << " and #"
- << shapeID( rgtSide->Edge(0) ) << ": "
- << nbSrcSegments << " != " << nbTgtSegments ));
+ if ( !isTgtEdgeComputed[ i ])
+ {
+ const TopoDS_Edge& tgtE = rgtSide->Edge(i);
+ SMESH_subMesh* tgtSM = mesh->GetSubMesh( tgtE );
+ tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+ badMeshRemoved = true;
+ nbTgtMeshed--;
+ }
+ if ( !badMeshRemoved )
+ {
+ for ( int i = 0; i < lftSide->NbEdges(); ++i )
+ addBadInputElements( meshDS->MeshElements( lftSide->Edge( i )));
+ for ( int i = 0; i < rgtSide->NbEdges(); ++i )
+ addBadInputElements( meshDS->MeshElements( rgtSide->Edge( i )));
+ return toSM( error( TCom("Different nb of segment on logically vertical edges #")
+ << shapeID( lftSide->Edge(0) ) << " and #"
+ << shapeID( rgtSide->Edge(0) ) << ": "
+ << nbSrcSegments << " != " << nbTgtSegments ));
+ }
+ }
+ else // if ( nbTgtSegments == nbSrcSegments )
+ {
+ continue;
}
- continue;
}
// Compute 'vertical projection'
if ( nbTgtMeshed == 0 )
// new nodes are on different EDGEs; put one of them on VERTEX
const int edgeIndex = rgtSide->EdgeIndex( srcNodeStr[ iN-1 ].normParam );
const double vertexParam = rgtSide->LastParameter( edgeIndex );
- const gp_Pnt p = BRep_Tool::Pnt( rgtSide->LastVertex( edgeIndex ));
+ TopoDS_Vertex vertex = rgtSide->LastVertex( edgeIndex );
+ const SMDS_MeshNode* vn = SMESH_Algo::VertexNode( vertex, meshDS );
+ const gp_Pnt p = BRep_Tool::Pnt( vertex );
const int isPrev = ( Abs( srcNodeStr[ iN-1 ].normParam - vertexParam ) <
Abs( srcNodeStr[ iN ].normParam - vertexParam ));
meshDS->UnSetNodeOnShape( newNodes[ iN-isPrev ] );
- meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], rgtSide->LastVertex( edgeIndex ));
+ meshDS->SetNodeOnVertex ( newNodes[ iN-isPrev ], vertex );
meshDS->MoveNode ( newNodes[ iN-isPrev ], p.X(), p.Y(), p.Z() );
id2type.first = newNodes[ iN-(1-isPrev) ]->getshapeId();
+ if ( vn )
+ {
+ SMESH_MeshEditor::TListOfListOfNodes lln( 1, list< const SMDS_MeshNode* >() );
+ lln.back().push_back ( vn );
+ lln.back().push_front( newNodes[ iN-isPrev ] ); // to keep
+ SMESH_MeshEditor( mesh ).MergeNodes( lln );
+ }
}
SMDS_MeshElement* newEdge = myHelper->AddEdge( newNodes[ iN-1 ], newNodes[ iN ] );
meshDS->SetMeshElementOnShape( newEdge, id2type.first );
Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin();
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
- // Top EDGEs must be projections from the bottom ones
- // to compute stuctured quad mesh on wall FACEs
- // ---------------------------------------------------
+ const TopoDS_Face& face = (*quad)->face;
+ SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+ if ( ! fSM->IsMeshComputed() )
{
+ // Top EDGEs must be projections from the bottom ones
+ // to compute stuctured quad mesh on wall FACEs
+ // ---------------------------------------------------
const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0);
const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE ].grid->Edge(0);
SMESH_subMesh* botSM = mesh->GetSubMesh( botE );
}
}
tgtSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
- }
- // Compute quad mesh on wall FACEs
- // -------------------------------
- const TopoDS_Face& face = (*quad)->face;
- SMESH_subMesh* fSM = mesh->GetSubMesh( face );
- if ( ! fSM->IsMeshComputed() )
- {
+
+ // Compute quad mesh on wall FACEs
+ // -------------------------------
+
// make all EDGES meshed
fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE );
if ( !fSM->SubMeshesComputed() )
TopoDS_Edge StdMeshers_Prism_3D::findPropagationSource( const TopoDS_Edge& E )
{
- for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
- if ( myPropagChains[i].Contains( E ))
- return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
+ if ( myPropagChains )
+ for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i )
+ if ( myPropagChains[i].Contains( E ))
+ return TopoDS::Edge( myPropagChains[i].FindKey( 1 ));
return TopoDS_Edge();
}
*/
//================================================================================
-bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf )
+bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf,
+ const Prism_3D::TPrismTopo& thePrism)
{
- SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
- SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ SMESH_subMesh * topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( !botSMDS || botSMDS->NbElements() == 0 )
{
- _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape() );
+ _gen->Compute( *myHelper->GetMesh(), botSM->GetSubShape(), /*aShapeOnly=*/true );
botSMDS = botSM->GetSubMeshDS();
if ( !botSMDS || botSMDS->NbElements() == 0 )
return toSM( error(TCom("No elements on face #") << botSM->GetId() ));
}
bool needProject = !topSM->IsMeshComputed();
- if ( !needProject &&
+ if ( !needProject &&
(botSMDS->NbElements() != topSMDS->NbElements() ||
botSMDS->NbNodes() != topSMDS->NbNodes()))
{
<<" and #"<< topSM->GetId() << " seems different" ));
///RETURN_BAD_RESULT("Need to project but not allowed");
+ NSProjUtils::TNodeNodeMap n2nMap;
+ const NSProjUtils::TNodeNodeMap* n2nMapPtr = & n2nMap;
if ( needProject )
{
- return projectBottomToTop( bottomToTopTrsf );
+ if ( !projectBottomToTop( bottomToTopTrsf, thePrism ))
+ return false;
+ n2nMapPtr = & TProjction2dAlgo::instance( this )->GetNodesMap();
}
- TopoDS_Face botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE ));
- TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
- // associate top and bottom faces
- TAssocTool::TShapeShapeMap shape2ShapeMap;
- if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
- topFace, myBlock.Mesh(),
- shape2ShapeMap) )
- return toSM( error(TCom("Topology of faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
+ if ( !n2nMapPtr || n2nMapPtr->size() < botSMDS->NbNodes() )
+ {
+ // associate top and bottom faces
+ NSProjUtils::TShapeShapeMap shape2ShapeMap;
+ const bool sameTopo =
+ NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap);
+ if ( !sameTopo )
+ for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
+ {
+ const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ];
+ StdMeshers_FaceSidePtr botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ];
+ StdMeshers_FaceSidePtr topSide = quadList.back ()->side[ QUAD_TOP_SIDE ];
+ if ( botSide->NbEdges() == topSide->NbEdges() )
+ {
+ for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( iE ),
+ topSide->Edge( iE ), shape2ShapeMap );
+ NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
+ myHelper->IthVertex( 0, topSide->Edge( iE )),
+ shape2ShapeMap );
+ }
+ }
+ else
+ {
+ TopoDS_Vertex vb, vt;
+ StdMeshers_FaceSidePtr sideB, sideT;
+ vb = myHelper->IthVertex( 0, botSide->Edge( 0 ));
+ vt = myHelper->IthVertex( 0, topSide->Edge( 0 ));
+ sideB = quadList.front()->side[ QUAD_LEFT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
+ topSide->Edge( 0 ), shape2ShapeMap );
+ NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
+ vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 ));
+ sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ];
+ sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ];
+ if ( vb.IsSame( sideB->FirstVertex() ) &&
+ vt.IsSame( sideT->LastVertex() ))
+ {
+ NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
+ topSide->Edge( topSide->NbEdges()-1 ),
+ shape2ShapeMap );
+ NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
+ }
+ }
+ }
- // Find matching nodes of top and bottom faces
- TNodeNodeMap n2nMap;
- if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
- topFace, myBlock.Mesh(),
- shape2ShapeMap, n2nMap ))
- return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
- <<" and #"<< topSM->GetId() << " seems different" ));
+ // Find matching nodes of top and bottom faces
+ n2nMapPtr = & n2nMap;
+ if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap, n2nMap ))
+ {
+ if ( sameTopo )
+ return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ else
+ return toSM( error(TCom("Topology of faces #") << botSM->GetId()
+ <<" and #"<< topSM->GetId() << " seems different" ));
+ }
+ }
// Fill myBotToColumnMap
int zSize = myBlock.VerticalSize();
- //TNode prevTNode;
- TNodeNodeMap::iterator bN_tN = n2nMap.begin();
- for ( ; bN_tN != n2nMap.end(); ++bN_tN )
+ TNodeNodeMap::const_iterator bN_tN = n2nMapPtr->begin();
+ for ( ; bN_tN != n2nMapPtr->end(); ++bN_tN )
{
const SMDS_MeshNode* botNode = bN_tN->first;
const SMDS_MeshNode* topNode = bN_tN->second;
//================================================================================
/*!
- * \brief Remove quadrangles from the top face and
- * create triangles there by projection from the bottom
+ * \brief Remove faces from the top face and re-create them by projection from the bottom
* \retval bool - a success or not
*/
//================================================================================
-bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf )
+bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottomToTopTrsf,
+ const Prism_3D::TPrismTopo& thePrism )
{
- SMESHDS_Mesh* meshDS = myBlock.MeshDS();
- SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
- SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+ if ( project2dMesh( thePrism.myBottom, thePrism.myTop ))
+ {
+ return true;
+ }
+
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
+ SMESH_subMesh * topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( topSMDS && topSMDS->NbElements() > 0 )
topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
- const TopoDS_Face& botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE )); // oriented within
- const TopoDS_Face& topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE )); // the 3D SHAPE
- int topFaceID = meshDS->ShapeToIndex( topFace );
+ const TopoDS_Face& botFace = thePrism.myBottom; // oriented within
+ const TopoDS_Face& topFace = thePrism.myTop; // the 3D SHAPE
+ int topFaceID = meshDS->ShapeToIndex( thePrism.myTop );
SMESH_MesherHelper botHelper( *myHelper->GetMesh() );
botHelper.SetSubShape( botFace );
column.resize( zSize );
column.front() = botNode;
column.back() = topNode;
+
+ if ( _computeCanceled )
+ return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
}
// Create top faces
return true;
}
+//=======================================================================
+//function : getSweepTolerance
+//purpose : Compute tolerance to pass to StdMeshers_Sweeper
+//=======================================================================
+
+double StdMeshers_Prism_3D::getSweepTolerance( const Prism_3D::TPrismTopo& thePrism )
+{
+ SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
+ SMESHDS_SubMesh * sm[2] = { meshDS->MeshElements( thePrism.myBottom ),
+ meshDS->MeshElements( thePrism.myTop ) };
+ double minDist = 1e100;
+
+ vector< SMESH_TNodeXYZ > nodes;
+ for ( int iSM = 0; iSM < 2; ++iSM )
+ {
+ if ( !sm[ iSM ]) continue;
+
+ SMDS_ElemIteratorPtr fIt = sm[ iSM ]->GetElements();
+ while ( fIt->more() )
+ {
+ const SMDS_MeshElement* face = fIt->next();
+ const int nbNodes = face->NbCornerNodes();
+ SMDS_ElemIteratorPtr nIt = face->nodesIterator();
+
+ nodes.resize( nbNodes + 1 );
+ for ( int iN = 0; iN < nbNodes; ++iN )
+ nodes[ iN ] = nIt->next();
+ nodes.back() = nodes[0];
+
+ // loop on links
+ double dist2;
+ for ( int iN = 0; iN < nbNodes; ++iN )
+ {
+ if ( nodes[ iN ]._node->GetPosition()->GetDim() < 2 &&
+ nodes[ iN+1 ]._node->GetPosition()->GetDim() < 2 )
+ {
+ // it's a boundary link; measure distance of other
+ // nodes to this link
+ gp_XYZ linkDir = nodes[ iN ] - nodes[ iN+1 ];
+ double linkLen = linkDir.Modulus();
+ bool isDegen = ( linkLen < numeric_limits<double>::min() );
+ if ( !isDegen ) linkDir /= linkLen;
+ for ( int iN2 = 0; iN2 < nbNodes; ++iN2 ) // loop on other nodes
+ {
+ if ( nodes[ iN2 ] == nodes[ iN ] ||
+ nodes[ iN2 ] == nodes[ iN+1 ]) continue;
+ if ( isDegen )
+ {
+ dist2 = ( nodes[ iN ] - nodes[ iN2 ]).SquareModulus();
+ }
+ else
+ {
+ dist2 = linkDir.CrossSquareMagnitude( nodes[ iN ] - nodes[ iN2 ]);
+ }
+ if ( dist2 > numeric_limits<double>::min() )
+ minDist = Min ( minDist, dist2 );
+ }
+ }
+ // measure length link
+ else if ( nodes[ iN ]._node < nodes[ iN+1 ]._node ) // not to measure same link twice
+ {
+ dist2 = ( nodes[ iN ] - nodes[ iN+1 ]).SquareModulus();
+ if ( dist2 > numeric_limits<double>::min() )
+ minDist = Min ( minDist, dist2 );
+ }
+ }
+ }
+ }
+ return 0.1 * Sqrt ( minDist );
+}
+
//=======================================================================
//function : project2dMesh
//purpose : Project mesh faces from a source FACE of one prism (theSrcFace)
if ( E.IsSame( Edge( i ))) return i;
return -1;
}
+ bool IsSideFace( const TopoDS_Shape& face ) const
+ {
+ if ( _faces->Contains( face )) // avoid returning true for a prism top FACE
+ return ( !_face.IsNull() || !( face.IsSame( _faces->FindKey( _faces->Extent() ))));
+ return false;
+ }
};
//--------------------------------------------------------------------------------
/*!
TEdgeWithNeighborsVec& botEdges = faceEdgesVec[ iF ];
if ( botEdges.empty() )
- {
if ( !getEdges( botF, botEdges, /*noHoles=*/false ))
break;
- if ( allFaces.Extent()-1 <= (int) botEdges.size() )
- continue; // all faces are adjacent to botF - no top FACE
- }
+ if ( allFaces.Extent()-1 <= (int) botEdges.size() )
+ continue; // all faces are adjacent to botF - no top FACE
+
// init data of side FACEs
vector< PrismSide > sides( botEdges.size() );
for ( int iS = 0; iS < botEdges.size(); ++iS )
}
bool isOK = true; // ok for a current botF
- bool isAdvanced = true;
- int nbFoundSideFaces = 0;
+ bool isAdvanced = true; // is new data found in a current loop
+ int nbFoundSideFaces = 0;
for ( int iLoop = 0; isOK && isAdvanced; ++iLoop )
{
isAdvanced = false;
{
PrismSide& side = sides[ iS ];
if ( side._face.IsNull() )
- continue;
+ continue; // probably the prism top face is the last of side._faces
+
if ( side._topEdge.IsNull() )
{
// find vertical EDGEs --- EGDEs shared with neighbor side FACEs
if ( side._isCheckedEdge[ iE ] ) continue;
const TopoDS_Edge& vertE = side.Edge( iE );
const TopoDS_Shape& neighborF = getAnotherFace( side._face, vertE, facesOfEdge );
- bool isEdgeShared = adjSide->_faces->Contains( neighborF );
+ bool isEdgeShared = adjSide->IsSideFace( neighborF );
if ( isEdgeShared )
{
isAdvanced = true;
{
if ( side._leftSide->_faces->Contains( f ))
{
- stop = true;
+ stop = true; // probably f is the prism top face
side._leftSide->_face.Nullify();
side._leftSide->_topEdge.Nullify();
}
if ( side._rightSide->_faces->Contains( f ))
{
- stop = true;
+ stop = true; // probably f is the prism top face
side._rightSide->_face.Nullify();
side._rightSide->_topEdge.Nullify();
}
side._topEdge.Nullify();
continue;
}
- side._face = TopoDS::Face( f );
- int faceID = allFaces.FindIndex( side._face );
+ side._face = TopoDS::Face( f );
+ int faceID = allFaces.FindIndex( side._face );
side._edges = & faceEdgesVec[ faceID ];
if ( side._edges->empty() )
if ( !getEdges( side._face, * side._edges, /*noHoles=*/true ))
myWallQuads.clear();
}
+ //================================================================================
+ /*!
+ * \brief Set upside-down
+ */
+ //================================================================================
+
+ void TPrismTopo::SetUpsideDown()
+ {
+ std::swap( myBottom, myTop );
+ myBottomEdges.clear();
+ std::reverse( myBottomEdges.begin(), myBottomEdges.end() );
+ for ( size_t i = 0; i < myWallQuads.size(); ++i )
+ {
+ myWallQuads[i].reverse();
+ TQuadList::iterator q = myWallQuads[i].begin();
+ for ( ; q != myWallQuads[i].end(); ++q )
+ {
+ (*q)->shift( 2, /*keepUnitOri=*/true );
+ }
+ myBottomEdges.push_back( myWallQuads[i].front()->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0) );
+ }
+ }
+
} // namespace Prism_3D
//================================================================================
SMESH_subMesh * botSM = 0;
SMESH_subMesh * topSM = 0;
- if ( hasNotQuad ) // can chose a bottom FACE
+ if ( hasNotQuad ) // can choose a bottom FACE
{
if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front();
else botSM = notQuadGeomSubMesh.front();
thePrism.myShape3D = shape3D;
if ( thePrism.myBottom.IsNull() )
thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
- thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( shape3D,
- thePrism.myBottom ));
+ thePrism.myBottom.Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myBottom ));
+ thePrism.myTop. Orientation( myHelper->GetSubShapeOri( shape3D, thePrism.myTop ));
+
// Get ordered bottom edges
TopoDS_Face reverseBottom = // to have order of top EDGEs as in the top FACE
TopoDS::Face( thePrism.myBottom.Reversed() );
"Non-quadrilateral faces are not opposite"));
}
+ if ( thePrism.myBottomEdges.size() > thePrism.myWallQuads.size() )
+ {
+ // composite bottom sides => set thePrism upside-down
+ thePrism.SetUpsideDown();
+ }
+
return true;
}
}
if ( !edge.IsNull() )
{
- double u1 = myHelper.GetNodeU( edge, nn[0] );
- double u3 = myHelper.GetNodeU( edge, nn[2] );
+ double u1 = myHelper.GetNodeU( edge, nn[0], nn[2] );
+ double u3 = myHelper.GetNodeU( edge, nn[2], nn[0] );
double u = u1 * ( 1 - hR ) + u3 * hR;
TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( edge,loc,f,l );
double r = ( U - i1->first ) / ( i2->first - i1->first );
return i1->second * ( 1 - r ) + i2->second * r;
}
+
+//================================================================================
+/*!
+ * \brief Projects internal nodes using transformation found by boundary nodes
+ */
+//================================================================================
+
+bool StdMeshers_Sweeper::projectIntPoints(const vector< gp_XYZ >& fromBndPoints,
+ const vector< gp_XYZ >& toBndPoints,
+ const vector< gp_XYZ >& fromIntPoints,
+ vector< gp_XYZ >& toIntPoints,
+ NSProjUtils::TrsfFinder3D& trsf,
+ vector< gp_XYZ > * bndError)
+{
+ // find transformation
+ if ( trsf.IsIdentity() && !trsf.Solve( fromBndPoints, toBndPoints ))
+ return false;
+
+ // compute internal points using the found trsf
+ for ( size_t iP = 0; iP < fromIntPoints.size(); ++iP )
+ {
+ toIntPoints[ iP ] = trsf.Transform( fromIntPoints[ iP ]);
+ }
+
+ // compute boundary error
+ if ( bndError )
+ {
+ bndError->resize( fromBndPoints.size() );
+ gp_XYZ fromTrsf;
+ for ( size_t iP = 0; iP < fromBndPoints.size(); ++iP )
+ {
+ fromTrsf = trsf.Transform( fromBndPoints[ iP ] );
+ (*bndError)[ iP ] = toBndPoints[ iP ] - fromTrsf;
+ }
+ }
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Add boundary error to ineternal points
+ */
+//================================================================================
+
+void StdMeshers_Sweeper::applyBoundaryError(const vector< gp_XYZ >& bndPoints,
+ const vector< gp_XYZ >& bndError1,
+ const vector< gp_XYZ >& bndError2,
+ const double r,
+ vector< gp_XYZ >& intPoints,
+ vector< double >& int2BndDist)
+{
+ // fix each internal point
+ const double eps = 1e-100;
+ for ( size_t iP = 0; iP < intPoints.size(); ++iP )
+ {
+ gp_XYZ & intPnt = intPoints[ iP ];
+
+ // compute distance from intPnt to each boundary node
+ double int2BndDistSum = 0;
+ for ( size_t iBnd = 0; iBnd < bndPoints.size(); ++iBnd )
+ {
+ int2BndDist[ iBnd ] = 1 / (( intPnt - bndPoints[ iBnd ]).SquareModulus() + eps );
+ int2BndDistSum += int2BndDist[ iBnd ];
+ }
+
+ // apply bndError
+ for ( size_t iBnd = 0; iBnd < bndPoints.size(); ++iBnd )
+ {
+ intPnt += bndError1[ iBnd ] * ( 1 - r ) * int2BndDist[ iBnd ] / int2BndDistSum;
+ intPnt += bndError2[ iBnd ] * r * int2BndDist[ iBnd ] / int2BndDistSum;
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Creates internal nodes of the prism
+ */
+//================================================================================
+
+bool StdMeshers_Sweeper::ComputeNodes( SMESH_MesherHelper& helper,
+ const double tol)
+{
+ const size_t zSize = myBndColumns[0]->size();
+ const size_t zSrc = 0, zTgt = zSize-1;
+ if ( zSize < 3 ) return true;
+
+ vector< vector< gp_XYZ > > intPntsOfLayer( zSize ); // node coodinates to compute
+ // set coordinates of src and tgt nodes
+ for ( size_t z = 0; z < intPntsOfLayer.size(); ++z )
+ intPntsOfLayer[ z ].resize( myIntColumns.size() );
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zSrc ][ iP ] = intPoint( iP, zSrc );
+ intPntsOfLayer[ zTgt ][ iP ] = intPoint( iP, zTgt );
+ }
+
+ // compute coordinates of internal nodes by projecting (transfroming) src and tgt
+ // nodes towards the central layer
+
+ vector< NSProjUtils::TrsfFinder3D > trsfOfLayer( zSize );
+ vector< vector< gp_XYZ > > bndError( zSize );
+
+ // boundary points used to compute an affine transformation from a layer to a next one
+ vector< gp_XYZ > fromSrcBndPnts( myBndColumns.size() ), fromTgtBndPnts( myBndColumns.size() );
+ vector< gp_XYZ > toSrcBndPnts ( myBndColumns.size() ), toTgtBndPnts ( myBndColumns.size() );
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ fromSrcBndPnts[ iP ] = bndPoint( iP, zSrc );
+ fromTgtBndPnts[ iP ] = bndPoint( iP, zTgt );
+ }
+
+ size_t zS = zSrc + 1;
+ size_t zT = zTgt - 1;
+ for ( ; zS < zT; ++zS, --zT ) // vertical loop on layers
+ {
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ if (! projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ intPntsOfLayer[ zS-1 ], intPntsOfLayer[ zS ],
+ trsfOfLayer [ zS-1 ], & bndError[ zS-1 ]))
+ return false;
+ if (! projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ intPntsOfLayer[ zT+1 ], intPntsOfLayer[ zT ],
+ trsfOfLayer [ zT+1 ], & bndError[ zT+1 ]))
+ return false;
+
+ // if ( zT == zTgt - 1 )
+ // {
+ // for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ // {
+ // gp_XYZ fromTrsf = trsfOfLayer [ zT+1].Transform( fromTgtBndPnts[ iP ] );
+ // cout << "mesh.AddNode( "
+ // << fromTrsf.X() << ", "
+ // << fromTrsf.Y() << ", "
+ // << fromTrsf.Z() << ") " << endl;
+ // }
+ // for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ // cout << "mesh.AddNode( "
+ // << intPntsOfLayer[ zT ][ iP ].X() << ", "
+ // << intPntsOfLayer[ zT ][ iP ].Y() << ", "
+ // << intPntsOfLayer[ zT ][ iP ].Z() << ") " << endl;
+ // }
+
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromSrcBndPnts.swap( toSrcBndPnts );
+ }
+
+ // Compute two projections of internal points to the central layer
+ // in order to evaluate an error of internal points
+
+ bool centerIntErrorIsSmall;
+ vector< gp_XYZ > centerSrcIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > centerTgtIntPnts( myIntColumns.size() );
+
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ if (! projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ intPntsOfLayer[ zS-1 ], centerSrcIntPnts,
+ trsfOfLayer [ zS-1 ], & bndError[ zS-1 ]))
+ return false;
+ if (! projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ intPntsOfLayer[ zT+1 ], centerTgtIntPnts,
+ trsfOfLayer [ zT+1 ], & bndError[ zT+1 ]))
+ return false;
+
+ // evaluate an error of internal points on the central layer
+ centerIntErrorIsSmall = true;
+ if ( zS == zT ) // odd zSize
+ {
+ for ( size_t iP = 0; ( iP < myIntColumns.size() && centerIntErrorIsSmall ); ++iP )
+ centerIntErrorIsSmall =
+ (centerSrcIntPnts[ iP ] - centerTgtIntPnts[ iP ]).SquareModulus() < tol*tol;
+ }
+ else // even zSize
+ {
+ for ( size_t iP = 0; ( iP < myIntColumns.size() && centerIntErrorIsSmall ); ++iP )
+ centerIntErrorIsSmall =
+ (intPntsOfLayer[ zS-1 ][ iP ] - centerTgtIntPnts[ iP ]).SquareModulus() < tol*tol;
+ }
+
+ // Evaluate an error of boundary points
+
+ bool bndErrorIsSmall = true;
+ for ( size_t iP = 0; ( iP < myBndColumns.size() && bndErrorIsSmall ); ++iP )
+ {
+ double sumError = 0;
+ for ( size_t z = 1; z < zS; ++z ) // loop on layers
+ sumError += ( bndError[ z-1 ][ iP ].Modulus() +
+ bndError[ zSize-z ][ iP ].Modulus() );
+
+ bndErrorIsSmall = ( sumError < tol );
+ }
+
+ // compute final points on the central layer
+ std::vector< double > int2BndDist( myBndColumns.size() ); // work array of applyBoundaryError()
+ double r = zS / ( zSize - 1.);
+ if ( zS == zT )
+ {
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zS ][ iP ] =
+ ( 1 - r ) * centerSrcIntPnts[ iP ] + r * centerTgtIntPnts[ iP ];
+ }
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ }
+ }
+ else
+ {
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ intPntsOfLayer[ zS ][ iP ] =
+ r * intPntsOfLayer[ zS ][ iP ] + ( 1 - r ) * centerSrcIntPnts[ iP ];
+ intPntsOfLayer[ zT ][ iP ] =
+ r * intPntsOfLayer[ zT ][ iP ] + ( 1 - r ) * centerTgtIntPnts[ iP ];
+ }
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, bndError[ zT+1 ], bndError[ zT-1 ], r,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+ }
+
+ //centerIntErrorIsSmall = true;
+ //bndErrorIsSmall = true;
+ if ( !centerIntErrorIsSmall )
+ {
+ // Compensate the central error; continue adding projection
+ // by going from central layer to the source and target ones
+
+ vector< gp_XYZ >& fromSrcIntPnts = centerSrcIntPnts;
+ vector< gp_XYZ >& fromTgtIntPnts = centerTgtIntPnts;
+ vector< gp_XYZ > toSrcIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > toTgtIntPnts( myIntColumns.size() );
+ vector< gp_XYZ > srcBndError( myBndColumns.size() );
+ vector< gp_XYZ > tgtBndError( myBndColumns.size() );
+
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromSrcBndPnts.swap( toSrcBndPnts );
+
+ for ( ++zS, --zT; zS < zTgt; ++zS, --zT ) // vertical loop on layers
+ {
+ // invert transformation
+ if ( !trsfOfLayer[ zS+1 ].Invert() )
+ trsfOfLayer[ zS+1 ] = NSProjUtils::TrsfFinder3D(); // to recompute
+ if ( !trsfOfLayer[ zT-1 ].Invert() )
+ trsfOfLayer[ zT-1 ] = NSProjUtils::TrsfFinder3D();
+
+ // project internal nodes and compute bnd error
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ projectIntPoints( fromSrcBndPnts, toSrcBndPnts,
+ fromSrcIntPnts, toSrcIntPnts,
+ trsfOfLayer[ zS+1 ], & srcBndError );
+ projectIntPoints( fromTgtBndPnts, toTgtBndPnts,
+ fromTgtIntPnts, toTgtIntPnts,
+ trsfOfLayer[ zT-1 ], & tgtBndError );
+
+ // if ( zS == zTgt - 1 )
+ // {
+ // cout << "mesh2 = smesh.Mesh()" << endl;
+ // for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ // {
+ // gp_XYZ fromTrsf = trsfOfLayer [ zS+1].Transform( fromSrcBndPnts[ iP ] );
+ // cout << "mesh2.AddNode( "
+ // << fromTrsf.X() << ", "
+ // << fromTrsf.Y() << ", "
+ // << fromTrsf.Z() << ") " << endl;
+ // }
+ // for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ // cout << "mesh2.AddNode( "
+ // << toSrcIntPnts[ iP ].X() << ", "
+ // << toSrcIntPnts[ iP ].Y() << ", "
+ // << toSrcIntPnts[ iP ].Z() << ") " << endl;
+ // }
+
+ // sum up 2 projections
+ r = zS / ( zSize - 1.);
+ vector< gp_XYZ >& zSIntPnts = intPntsOfLayer[ zS ];
+ vector< gp_XYZ >& zTIntPnts = intPntsOfLayer[ zT ];
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ zSIntPnts[ iP ] = r * zSIntPnts[ iP ] + ( 1 - r ) * toSrcIntPnts[ iP ];
+ zTIntPnts[ iP ] = r * zTIntPnts[ iP ] + ( 1 - r ) * toTgtIntPnts[ iP ];
+ }
+
+ // compensate bnd error
+ if ( !bndErrorIsSmall )
+ {
+ applyBoundaryError( toSrcBndPnts, srcBndError, bndError[ zS+1 ], r,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, tgtBndError, bndError[ zT-1 ], r,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+
+ fromSrcBndPnts.swap( toSrcBndPnts );
+ fromSrcIntPnts.swap( toSrcIntPnts );
+ fromTgtBndPnts.swap( toTgtBndPnts );
+ fromTgtIntPnts.swap( toTgtIntPnts );
+ }
+ } // if ( !centerIntErrorIsSmall )
+
+ else if ( !bndErrorIsSmall )
+ {
+ zS = zSrc + 1;
+ zT = zTgt - 1;
+ for ( ; zS < zT; ++zS, --zT ) // vertical loop on layers
+ {
+ for ( size_t iP = 0; iP < myBndColumns.size(); ++iP )
+ {
+ toSrcBndPnts[ iP ] = bndPoint( iP, zS );
+ toTgtBndPnts[ iP ] = bndPoint( iP, zT );
+ }
+ // compensate bnd error
+ applyBoundaryError( toSrcBndPnts, bndError[ zS-1 ], bndError[ zS-1 ], 0.5,
+ intPntsOfLayer[ zS ], int2BndDist );
+ applyBoundaryError( toTgtBndPnts, bndError[ zT+1 ], bndError[ zT+1 ], 0.5,
+ intPntsOfLayer[ zT ], int2BndDist );
+ }
+ }
+
+ // cout << "centerIntErrorIsSmall = " << centerIntErrorIsSmall<< endl;
+ // cout << "bndErrorIsSmall = " << bndErrorIsSmall<< endl;
+
+ // Create nodes
+ for ( size_t iP = 0; iP < myIntColumns.size(); ++iP )
+ {
+ vector< const SMDS_MeshNode* > & nodeCol = *myIntColumns[ iP ];
+ for ( size_t z = zSrc + 1; z < zTgt; ++z ) // vertical loop on layers
+ {
+ const gp_XYZ & xyz = intPntsOfLayer[ z ][ iP ];
+ if ( !( nodeCol[ z ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() )))
+ return false;
+ }
+ }
+
+ return true;
+}