00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "StdMeshers_Prism_3D.hxx"
00030
00031 #include "StdMeshers_ProjectionUtils.hxx"
00032 #include "SMESH_MesherHelper.hxx"
00033 #include "SMDS_VolumeTool.hxx"
00034 #include "SMDS_VolumeOfNodes.hxx"
00035 #include "SMDS_EdgePosition.hxx"
00036 #include "SMESH_Comment.hxx"
00037
00038 #include "utilities.h"
00039
00040 #include <BRep_Tool.hxx>
00041 #include <Bnd_B3d.hxx>
00042 #include <Geom2dAdaptor_Curve.hxx>
00043 #include <Geom2d_Line.hxx>
00044 #include <Geom_Curve.hxx>
00045 #include <TopExp.hxx>
00046 #include <TopExp_Explorer.hxx>
00047 #include <TopTools_ListIteratorOfListOfShape.hxx>
00048 #include <TopTools_MapOfShape.hxx>
00049 #include <TopTools_SequenceOfShape.hxx>
00050 #include <TopoDS.hxx>
00051 #include <gp_Ax2.hxx>
00052 #include <gp_Ax3.hxx>
00053
00054 using namespace std;
00055
00056 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
00057 #define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
00058 #define SHOWYXZ(msg, xyz) // {\
00059 // gp_Pnt p (xyz); \
00060 // cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
00061 // }
00062
00063 typedef StdMeshers_ProjectionUtils TAssocTool;
00064 typedef SMESH_Comment TCom;
00065
00066 enum { ID_BOT_FACE = SMESH_Block::ID_Fxy0,
00067 ID_TOP_FACE = SMESH_Block::ID_Fxy1,
00068 BOTTOM_EDGE = 0, TOP_EDGE, V0_EDGE, V1_EDGE,
00069 NB_WALL_FACES = 4 };
00070
00071 namespace {
00072
00073
00082
00083
00084 TParam2ColumnIt getColumn( const TParam2ColumnMap* columnsMap,
00085 const double parameter )
00086 {
00087 TParam2ColumnIt u_col = columnsMap->upper_bound( parameter );
00088 if ( u_col != columnsMap->begin() )
00089 --u_col;
00090 return u_col;
00091 }
00092
00093
00102
00103
00104 double getRAndNodes( const TNodeColumn* column,
00105 const double param,
00106 const SMDS_MeshNode* & node1,
00107 const SMDS_MeshNode* & node2)
00108 {
00109 if ( param >= 1.0 || column->size() == 1) {
00110 node1 = node2 = column->back();
00111 return 0;
00112 }
00113
00114 int i = int( param * ( column->size() - 1 ));
00115 double u0 = double( i )/ double( column->size() - 1 );
00116 double r = ( param - u0 ) * ( column->size() - 1 );
00117
00118 node1 = (*column)[ i ];
00119 node2 = (*column)[ i + 1];
00120 return r;
00121 }
00122
00123
00130
00131
00132 void splitParams( const int nbParts,
00133 const TParam2ColumnMap* columnsMap,
00134 vector< double > & params)
00135 {
00136 params.clear();
00137 params.reserve( nbParts + 1 );
00138 TParam2ColumnIt last_par_col = --columnsMap->end();
00139 double par = columnsMap->begin()->first;
00140 double parLast = last_par_col->first;
00141 params.push_back( par );
00142 for ( int i = 0; i < nbParts - 1; ++ i )
00143 {
00144 double partSize = ( parLast - par ) / double ( nbParts - i );
00145 TParam2ColumnIt par_col = getColumn( columnsMap, par + partSize );
00146 if ( par_col->first == par ) {
00147 ++par_col;
00148 if ( par_col == last_par_col ) {
00149 while ( i < nbParts - 1 )
00150 params.push_back( par + partSize * i++ );
00151 break;
00152 }
00153 }
00154 par = par_col->first;
00155 params.push_back( par );
00156 }
00157 params.push_back( parLast );
00158 }
00159
00160
00164
00165
00166 gp_Ax2 getLayerCoordSys(const int z,
00167 const vector< const TNodeColumn* >& columns,
00168 int& xColumn)
00169 {
00170
00171 gp_XYZ O(0,0,0);
00172 int vertexCol = -1;
00173 for ( int i = 0; i < columns.size(); ++i )
00174 {
00175 O += gpXYZ( (*columns[ i ])[ z ]);
00176 if ( vertexCol < 0 &&
00177 columns[ i ]->front()->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
00178 vertexCol = i;
00179 }
00180 O /= columns.size();
00181
00182
00183 gp_Vec Z(0,0,0);
00184 int iPrev = columns.size()-1;
00185 for ( int i = 0; i < columns.size(); ++i )
00186 {
00187 gp_Vec v1( O, gpXYZ( (*columns[ iPrev ])[ z ]));
00188 gp_Vec v2( O, gpXYZ( (*columns[ i ] )[ z ]));
00189 Z += v1 ^ v2;
00190 iPrev = i;
00191 }
00192
00193 if ( vertexCol >= 0 )
00194 {
00195 O = gpXYZ( (*columns[ vertexCol ])[ z ]);
00196 }
00197 if ( xColumn < 0 || xColumn >= columns.size() )
00198 {
00199
00200 double maxDist = 0;
00201 for ( int i = 0; i < columns.size(); ++i )
00202 {
00203 double dist = ( O - gpXYZ((*columns[ i ])[ z ])).SquareModulus();
00204 if ( dist > maxDist )
00205 {
00206 xColumn = i;
00207 maxDist = dist;
00208 }
00209 }
00210 }
00211
00212
00213 gp_Vec X( O, gpXYZ( (*columns[ xColumn ])[ z ]));
00214
00215 return gp_Ax2( O, Z, X);
00216 }
00217
00218
00223
00224
00225 int removeQuasiQuads(list< SMESH_subMesh* >& notQuadSubMesh)
00226 {
00227 int oldNbSM = notQuadSubMesh.size();
00228 SMESHDS_Mesh* mesh = notQuadSubMesh.front()->GetFather()->GetMeshDS();
00229 list< SMESH_subMesh* >::iterator smIt = notQuadSubMesh.begin();
00230 #define __NEXT_SM { ++smIt; continue; }
00231 while ( smIt != notQuadSubMesh.end() )
00232 {
00233 SMESH_subMesh* faceSm = *smIt;
00234 SMESHDS_SubMesh* faceSmDS = faceSm->GetSubMeshDS();
00235 int nbQuads = faceSmDS->NbElements();
00236 if ( nbQuads == 0 ) __NEXT_SM;
00237
00238
00239 list< TopoDS_Edge > orderedEdges;
00240 list< int > nbEdgesInWires;
00241 TopoDS_Vertex V000;
00242 int nbWires = SMESH_Block::GetOrderedEdges( TopoDS::Face( faceSm->GetSubShape() ),
00243 V000, orderedEdges, nbEdgesInWires );
00244 if ( nbWires != 1 || nbEdgesInWires.front() <= 4 )
00245 __NEXT_SM;
00246
00247
00248 list<int> nbSegOnEdge;
00249 list< TopoDS_Edge >::iterator edge = orderedEdges.begin();
00250 for ( ; edge != orderedEdges.end(); ++edge )
00251 {
00252 if ( SMESHDS_SubMesh* edgeSmDS = mesh->MeshElements( *edge ))
00253 nbSegOnEdge.push_back( edgeSmDS->NbElements() );
00254 else
00255 nbSegOnEdge.push_back(0);
00256 }
00257
00258
00259 int nbEdges = nbEdgesInWires.front();
00260 list<int>::iterator nbSegIt = nbSegOnEdge.begin();
00261 for ( edge = orderedEdges.begin(); edge != orderedEdges.end(); )
00262 {
00263 const TopoDS_Edge& e1 = *edge++;
00264 const TopoDS_Edge& e2 = ( edge == orderedEdges.end() ? orderedEdges.front() : *edge );
00265 if ( SMESH_Algo::IsContinuous( e1, e2 ))
00266 {
00267
00268 TopoDS_Vertex vCommon = TopExp::LastVertex( e1, true );
00269 const SMDS_MeshNode* vNode = SMESH_Algo::VertexNode( vCommon, mesh );
00270 int nbF = 0;
00271 if ( vNode )
00272 {
00273 SMDS_ElemIteratorPtr fIt = vNode->GetInverseElementIterator(SMDSAbs_Face);
00274 while ( fIt->more() )
00275 nbF += faceSmDS->Contains( fIt->next() );
00276 }
00277 list<int>::iterator nbSegIt1 = nbSegIt++;
00278 if ( !vNode || nbF == 2 )
00279 {
00280
00281 if ( nbSegIt == nbSegOnEdge.end() ) nbSegIt = nbSegOnEdge.begin();
00282 *nbSegIt += *nbSegIt1;
00283 nbSegOnEdge.erase( nbSegIt1 );
00284 --nbEdges;
00285 }
00286 }
00287 else
00288 {
00289 ++nbSegIt;
00290 }
00291 }
00292 vector<int> nbSegVec( nbSegOnEdge.begin(), nbSegOnEdge.end());
00293 if ( nbSegVec.size() == 4 &&
00294 nbSegVec[0] == nbSegVec[2] &&
00295 nbSegVec[1] == nbSegVec[3] &&
00296 nbSegVec[0] * nbSegVec[1] == nbQuads
00297 )
00298 smIt = notQuadSubMesh.erase( smIt );
00299 else
00300 __NEXT_SM;
00301 }
00302
00303 return oldNbSM - notQuadSubMesh.size();
00304 }
00305 }
00306
00307
00308
00309
00310
00311
00312 StdMeshers_Prism_3D::StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen)
00313 :SMESH_3D_Algo(hypId, studyId, gen)
00314 {
00315 _name = "Prism_3D";
00316 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);
00317 myProjectTriangles = false;
00318 }
00319
00320
00324
00325
00326 StdMeshers_Prism_3D::~StdMeshers_Prism_3D()
00327 {}
00328
00329
00330
00331
00332
00333
00334 bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh& aMesh,
00335 const TopoDS_Shape& aShape,
00336 SMESH_Hypothesis::Hypothesis_Status& aStatus)
00337 {
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 aStatus = SMESH_Hypothesis::HYP_OK;
00373 return true;
00374 }
00375
00376
00377
00378
00379
00380
00381 bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
00382 {
00383 SMESH_MesherHelper helper( theMesh );
00384 myHelper = &helper;
00385
00386 myHelper->IsQuadraticSubMesh( theShape );
00387
00388
00389 if ( !myBlock.Init( myHelper, theShape ))
00390 return error( myBlock.GetError());
00391
00392 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
00393
00394 int volumeID = meshDS->ShapeToIndex( theShape );
00395
00396
00397
00398
00399
00400
00401
00402 myShapeXYZ.resize( myBlock.NbSubShapes() );
00403 for ( int iV = SMESH_Block::ID_FirstV; iV < SMESH_Block::ID_FirstE; ++iV ) {
00404 myBlock.VertexPoint( iV, myShapeXYZ[ iV ]);
00405 SHOWYXZ("V point " <<iV << " ", myShapeXYZ[ iV ]);
00406 }
00407
00408
00409
00410 myBotToColumnMap.clear();
00411 if ( !assocOrProjBottom2Top() )
00412 return false;
00413
00414
00415
00416
00417
00418 vector<gp_Trsf> trsf;
00419 if ( myBlock.GetLayersTransformation(trsf))
00420 {
00421
00422 TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
00423 for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
00424 {
00425 const TNode& tBotNode = bot_column->first;
00426 if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
00427 continue;
00428
00429
00430 TNodeColumn& column = bot_column->second;
00431 TNodeColumn::iterator columnNodes = column.begin();
00432 for ( int z = 0; columnNodes != column.end(); ++columnNodes, ++z)
00433 {
00434 const SMDS_MeshNode* & node = *columnNodes;
00435 if ( node ) continue;
00436
00437 gp_XYZ coords = tBotNode.GetCoords();
00438 trsf[z-1].Transforms( coords );
00439 node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
00440 meshDS->SetNodeInVolume( node, volumeID );
00441 }
00442 }
00443 }
00444 else
00445 {
00446
00447 TNode prevBNode;
00448 TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
00449 for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
00450 {
00451 const TNode& tBotNode = bot_column->first;
00452 if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
00453 continue;
00454
00455
00456 TNodeColumn& column = bot_column->second;
00457
00458
00459 gp_XYZ paramHint(-1,-1,-1);
00460 if ( prevBNode.IsNeighbor( tBotNode ))
00461 paramHint = prevBNode.GetParams();
00462 if ( !myBlock.ComputeParameters( tBotNode.GetCoords(), tBotNode.ChangeParams(),
00463 ID_BOT_FACE, paramHint ))
00464 return error(TCom("Can't compute normalized parameters for node ")
00465 << tBotNode.myNode->GetID() << " on the face #"
00466 << myBlock.SubMesh( ID_BOT_FACE )->GetId() );
00467 prevBNode = tBotNode;
00468
00469 myShapeXYZ[ ID_BOT_FACE ] = tBotNode.GetCoords();
00470 gp_XYZ botParams = tBotNode.GetParams();
00471
00472
00473 myShapeXYZ[ ID_TOP_FACE ] = gpXYZ( column.back() );
00474 gp_XYZ topParams = botParams;
00475 topParams.SetZ( 1 );
00476 if ( column.size() > 2 ) {
00477 gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ];
00478 if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE, topParams ))
00479 return error(TCom("Can't compute normalized parameters ")
00480 << "for node " << column.back()->GetID()
00481 << " on the face #"<< column.back()->getshapeId() );
00482 }
00483
00484
00485 TNodeColumn::iterator columnNodes = column.begin();
00486 for ( int z = 0; columnNodes != column.end(); ++columnNodes, ++z)
00487 {
00488 const SMDS_MeshNode* & node = *columnNodes;
00489 if ( node ) continue;
00490
00491
00492 double rz = (double) z / (double) ( column.size() - 1 );
00493 gp_XYZ params = botParams * ( 1 - rz ) + topParams * rz;
00494
00495
00496 const int nbSideFaces = 4;
00497 int sideFaceIDs[nbSideFaces] = { SMESH_Block::ID_Fx0z,
00498 SMESH_Block::ID_Fx1z,
00499 SMESH_Block::ID_F0yz,
00500 SMESH_Block::ID_F1yz };
00501 for ( int iF = 0; iF < nbSideFaces; ++iF )
00502 if ( !setFaceAndEdgesXYZ( sideFaceIDs[ iF ], params, z ))
00503 return false;
00504
00505
00506 gp_XYZ coords;
00507 if ( !SMESH_Block::ShellPoint( params, myShapeXYZ, coords ))
00508 return error("Can't compute coordinates by normalized parameters");
00509
00510 SHOWYXZ("TOPFacePoint ",myShapeXYZ[ ID_TOP_FACE]);
00511 SHOWYXZ("BOT Node "<< tBotNode.myNode->GetID(),gpXYZ(tBotNode.myNode));
00512 SHOWYXZ("ShellPoint ",coords);
00513
00514
00515 node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
00516 meshDS->SetNodeInVolume( node, volumeID );
00517 }
00518 }
00519 }
00520
00521
00522
00523 SMESHDS_SubMesh* smDS = myBlock.SubMeshDS( ID_BOT_FACE );
00524 if ( !smDS ) return error(COMPERR_BAD_INPUT_MESH, "Null submesh");
00525
00526
00527 SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
00528 while ( faceIt->more() )
00529 {
00530 const SMDS_MeshElement* face = faceIt->next();
00531 if ( !face || face->GetType() != SMDSAbs_Face )
00532 continue;
00533 int nbNodes = face->NbNodes();
00534 if ( face->IsQuadratic() )
00535 nbNodes /= 2;
00536
00537
00538 vector< const TNodeColumn* > columns( nbNodes );
00539 for ( int i = 0; i < nbNodes; ++i )
00540 {
00541 const SMDS_MeshNode* n = face->GetNode( i );
00542 if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
00543 TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n );
00544 if ( bot_column == myBotToColumnMap.end() )
00545 return error(TCom("No nodes found above node ") << n->GetID() );
00546 columns[ i ] = & bot_column->second;
00547 }
00548 else {
00549 columns[ i ] = myBlock.GetNodeColumn( n );
00550 if ( !columns[ i ] )
00551 return error(TCom("No side nodes found above node ") << n->GetID() );
00552 }
00553 }
00554
00555 AddPrisms( columns, myHelper );
00556
00557 }
00558
00559
00560 myBotToColumnMap.clear();
00561 myBlock.Clear();
00562
00563 return true;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 bool StdMeshers_Prism_3D::Evaluate(SMESH_Mesh& theMesh,
00573 const TopoDS_Shape& theShape,
00574 MapShapeNbElems& aResMap)
00575 {
00576
00577 vector < SMESH_subMesh * >meshFaces;
00578 TopTools_SequenceOfShape aFaces;
00579 int NumBase = 0, i = 0, NbQFs = 0;
00580 for (TopExp_Explorer exp(theShape, TopAbs_FACE); exp.More(); exp.Next()) {
00581 i++;
00582 aFaces.Append(exp.Current());
00583 SMESH_subMesh *aSubMesh = theMesh.GetSubMesh(exp.Current());
00584 meshFaces.push_back(aSubMesh);
00585 MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i-1]);
00586 if( anIt==aResMap.end() ) {
00587 SMESH_ComputeErrorPtr& smError = aSubMesh->GetComputeError();
00588 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
00589 return false;
00590 }
00591 std::vector<int> aVec = (*anIt).second;
00592 int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
00593 int nbqua = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
00594 if( nbtri==0 && nbqua>0 ) {
00595 NbQFs++;
00596 }
00597 if( nbtri>0 ) {
00598 NumBase = i;
00599 }
00600 }
00601
00602 if(NbQFs<4) {
00603 std::vector<int> aResVec(SMDSEntity_Last);
00604 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
00605 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
00606 aResMap.insert(std::make_pair(sm,aResVec));
00607 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
00608 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
00609 return false;
00610 }
00611
00612 if(NumBase==0) NumBase = 1;
00613
00614
00615 int nb1d = 0;
00616 TopTools_MapOfShape Edges1;
00617 for (TopExp_Explorer exp(aFaces.Value(NumBase), TopAbs_EDGE); exp.More(); exp.Next()) {
00618 Edges1.Add(exp.Current());
00619 SMESH_subMesh *sm = theMesh.GetSubMesh(exp.Current());
00620 if( sm ) {
00621 MapShapeNbElemsItr anIt = aResMap.find(sm);
00622 if( anIt == aResMap.end() ) continue;
00623 std::vector<int> aVec = (*anIt).second;
00624 nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
00625 }
00626 }
00627
00628 int OppNum = 0;
00629 for(i=1; i<=6; i++) {
00630 if(i==NumBase) continue;
00631 bool IsOpposite = true;
00632 for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) {
00633 if( Edges1.Contains(exp.Current()) ) {
00634 IsOpposite = false;
00635 break;
00636 }
00637 }
00638 if(IsOpposite) {
00639 OppNum = i;
00640 break;
00641 }
00642 }
00643
00644 int nb2d = 0;
00645 for(i=1; i<=6; i++) {
00646 if( i==OppNum || i==NumBase ) continue;
00647 MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] );
00648 if( anIt == aResMap.end() ) continue;
00649 std::vector<int> aVec = (*anIt).second;
00650 nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
00651 }
00652
00653 MapShapeNbElemsItr anIt = aResMap.find( meshFaces[NumBase-1] );
00654 std::vector<int> aVec = (*anIt).second;
00655 bool IsQuadratic = (aVec[SMDSEntity_Quad_Triangle]>aVec[SMDSEntity_Triangle]) ||
00656 (aVec[SMDSEntity_Quad_Quadrangle]>aVec[SMDSEntity_Quadrangle]);
00657 int nb2d_face0_3 = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
00658 int nb2d_face0_4 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
00659 int nb0d_face0 = aVec[SMDSEntity_Node];
00660 int nb1d_face0_int = ( nb2d_face0_3*3 + nb2d_face0_4*4 - nb1d ) / 2;
00661
00662 std::vector<int> aResVec(SMDSEntity_Last);
00663 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
00664 if(IsQuadratic) {
00665 aResVec[SMDSEntity_Quad_Penta] = nb2d_face0_3 * ( nb2d/nb1d );
00666 aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0_4 * ( nb2d/nb1d );
00667 aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d;
00668 }
00669 else {
00670 aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 );
00671 aResVec[SMDSEntity_Penta] = nb2d_face0_3 * ( nb2d/nb1d );
00672 aResVec[SMDSEntity_Hexa] = nb2d_face0_4 * ( nb2d/nb1d );
00673 }
00674 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
00675 aResMap.insert(std::make_pair(sm,aResVec));
00676
00677 return true;
00678 }
00679
00680
00681
00687
00688
00689 void StdMeshers_Prism_3D::AddPrisms( vector<const TNodeColumn*> & columns,
00690 SMESH_MesherHelper* helper)
00691 {
00692 SMESHDS_Mesh * meshDS = helper->GetMeshDS();
00693 int shapeID = helper->GetSubShapeID();
00694
00695 int nbNodes = columns.size();
00696 int nbZ = columns[0]->size();
00697 if ( nbZ < 2 ) return;
00698
00699
00700 bool isForward = true;
00701 SMDS_VolumeTool vTool;
00702 int z = 1;
00703 switch ( nbNodes ) {
00704 case 3: {
00705 const SMDS_MeshNode* botNodes[3] = { (*columns[0])[z-1],
00706 (*columns[1])[z-1],
00707 (*columns[2])[z-1] };
00708 const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z],
00709 (*columns[1])[z],
00710 (*columns[2])[z] };
00711 SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2],
00712 topNodes[0], topNodes[1], topNodes[2]);
00713 vTool.Set( &tmpVol );
00714 isForward = vTool.IsForward();
00715 break;
00716 }
00717 case 4: {
00718 const SMDS_MeshNode* botNodes[4] = { (*columns[0])[z-1], (*columns[1])[z-1],
00719 (*columns[2])[z-1], (*columns[3])[z-1] };
00720 const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z],
00721 (*columns[2])[z], (*columns[3])[z] };
00722 SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
00723 topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
00724 vTool.Set( &tmpVol );
00725 isForward = vTool.IsForward();
00726 break;
00727 }
00728 }
00729
00730
00731 for ( z = 1; z < nbZ; ++z )
00732 {
00733 SMDS_MeshElement* vol = 0;
00734 switch ( nbNodes ) {
00735
00736 case 3: {
00737 const SMDS_MeshNode* botNodes[3] = { (*columns[0])[z-1],
00738 (*columns[1])[z-1],
00739 (*columns[2])[z-1] };
00740 const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z],
00741 (*columns[1])[z],
00742 (*columns[2])[z] };
00743 if ( isForward )
00744 vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2],
00745 topNodes[0], topNodes[1], topNodes[2]);
00746 else
00747 vol = helper->AddVolume( topNodes[0], topNodes[1], topNodes[2],
00748 botNodes[0], botNodes[1], botNodes[2]);
00749 break;
00750 }
00751 case 4: {
00752 const SMDS_MeshNode* botNodes[4] = { (*columns[0])[z-1], (*columns[1])[z-1],
00753 (*columns[2])[z-1], (*columns[3])[z-1] };
00754 const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z],
00755 (*columns[2])[z], (*columns[3])[z] };
00756 if ( isForward )
00757 vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
00758 topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
00759 else
00760 vol = helper->AddVolume( topNodes[0], topNodes[1], topNodes[2], topNodes[3],
00761 botNodes[0], botNodes[1], botNodes[2], botNodes[3]);
00762 break;
00763 }
00764 default:
00765
00766 vector<const SMDS_MeshNode*> nodes( 2*nbNodes + 4*nbNodes);
00767 vector<int> quantities( 2 + nbNodes, 4 );
00768 quantities[0] = quantities[1] = nbNodes;
00769 columns.resize( nbNodes + 1 );
00770 columns[ nbNodes ] = columns[ 0 ];
00771 for ( int i = 0; i < nbNodes; ++i ) {
00772 nodes[ i ] = (*columns[ i ])[z-1];
00773 nodes[ i+nbNodes ] = (*columns[ i ])[z ];
00774
00775 int di = 2*nbNodes + 4*i - 1;
00776 nodes[ di ] = (*columns[i ])[z-1];
00777 nodes[ di+1 ] = (*columns[i+1])[z-1];
00778 nodes[ di+2 ] = (*columns[i+1])[z ];
00779 nodes[ di+3 ] = (*columns[i ])[z ];
00780 }
00781 vol = meshDS->AddPolyhedralVolume( nodes, quantities );
00782 }
00783 if ( vol && shapeID > 0 )
00784 meshDS->SetMeshElementOnShape( vol, shapeID );
00785 }
00786 }
00787
00788
00795
00796
00797 bool StdMeshers_Prism_3D::assocOrProjBottom2Top()
00798 {
00799 SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
00800 SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
00801
00802 SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
00803 SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
00804
00805 if ( !botSMDS || botSMDS->NbElements() == 0 )
00806 return error(TCom("No elememts on face #") << botSM->GetId());
00807
00808 bool needProject = false;
00809 if ( !topSMDS ||
00810 botSMDS->NbElements() != topSMDS->NbElements() ||
00811 botSMDS->NbNodes() != topSMDS->NbNodes())
00812 {
00813 MESSAGE("nb elem bot " << botSMDS->NbElements() << " top " << topSMDS->NbElements());
00814 MESSAGE("nb node bot " << botSMDS->NbNodes() << " top " << topSMDS->NbNodes());
00815 if ( myBlock.HasNotQuadElemOnTop() )
00816 return error(TCom("Mesh on faces #") << botSM->GetId()
00817 <<" and #"<< topSM->GetId() << " seems different" );
00818 needProject = true;
00819 }
00820
00821 if ( 0 )
00822 return error(TCom("Mesh on faces #") << botSM->GetId()
00823 <<" and #"<< topSM->GetId() << " seems different" );
00825
00826 if ( needProject )
00827 {
00828 return projectBottomToTop();
00829 }
00830
00831 TopoDS_Face botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE ));
00832 TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
00833
00834 TAssocTool::TShapeShapeMap shape2ShapeMap;
00835 if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
00836 topFace, myBlock.Mesh(),
00837 shape2ShapeMap) )
00838 return error(TCom("Topology of faces #") << botSM->GetId()
00839 <<" and #"<< topSM->GetId() << " seems different" );
00840
00841
00842 TNodeNodeMap n2nMap;
00843 if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
00844 topFace, myBlock.Mesh(),
00845 shape2ShapeMap, n2nMap ))
00846 return error(TCom("Mesh on faces #") << botSM->GetId()
00847 <<" and #"<< topSM->GetId() << " seems different" );
00848
00849
00850
00851 int zSize = myBlock.VerticalSize();
00852
00853 TNodeNodeMap::iterator bN_tN = n2nMap.begin();
00854 for ( ; bN_tN != n2nMap.end(); ++bN_tN )
00855 {
00856 const SMDS_MeshNode* botNode = bN_tN->first;
00857 const SMDS_MeshNode* topNode = bN_tN->second;
00858 if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE )
00859 continue;
00860
00861 TNode bN( botNode );
00862 TNode2ColumnMap::iterator bN_col =
00863 myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
00864 TNodeColumn & column = bN_col->second;
00865 column.resize( zSize );
00866 column.front() = botNode;
00867 column.back() = topNode;
00868 }
00869 return true;
00870 }
00871
00872
00878
00879
00880 bool StdMeshers_Prism_3D::projectBottomToTop()
00881 {
00882 SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
00883 SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
00884
00885 SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
00886 SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
00887
00888 if ( topSMDS )
00889 topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
00890
00891 SMESHDS_Mesh* meshDS = myBlock.MeshDS();
00892 int shapeID = myHelper->GetSubShapeID();
00893 int topFaceID = meshDS->ShapeToIndex( topSM->GetSubShape() );
00894
00895
00896
00897 int zSize = myBlock.VerticalSize();
00898 TNode prevTNode;
00899 SMDS_NodeIteratorPtr nIt = botSMDS->GetNodes();
00900 while ( nIt->more() )
00901 {
00902 const SMDS_MeshNode* botNode = nIt->next();
00903 if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE )
00904 continue;
00905
00906 TNode bN( botNode );
00907 gp_XYZ paramHint(-1,-1,-1);
00908 if ( prevTNode.IsNeighbor( bN ))
00909 paramHint = prevTNode.GetParams();
00910 if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(),
00911 ID_BOT_FACE, paramHint ))
00912 return error(TCom("Can't compute normalized parameters for node ")
00913 << botNode->GetID() << " on the face #"<< botSM->GetId() );
00914 prevTNode = bN;
00915
00916 gp_XYZ topXYZ; gp_XY topUV;
00917 if ( !myBlock.FacePoint( ID_TOP_FACE, bN.GetParams(), topXYZ ) ||
00918 !myBlock.FaceUV ( ID_TOP_FACE, bN.GetParams(), topUV ))
00919 return error(TCom("Can't compute coordinates "
00920 "by normalized parameters on the face #")<< topSM->GetId() );
00921 SMDS_MeshNode * topNode = meshDS->AddNode( topXYZ.X(),topXYZ.Y(),topXYZ.Z() );
00922 meshDS->SetNodeOnFace( topNode, topFaceID, topUV.X(), topUV.Y() );
00923
00924 TNode2ColumnMap::iterator bN_col =
00925 myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
00926 TNodeColumn & column = bN_col->second;
00927 column.resize( zSize );
00928 column.front() = botNode;
00929 column.back() = topNode;
00930 }
00931
00932
00933
00934
00935 SMDS_ElemIteratorPtr faceIt = botSMDS->GetElements();
00936 while ( faceIt->more() )
00937 {
00938 const SMDS_MeshElement* face = faceIt->next();
00939 if ( !face || face->GetType() != SMDSAbs_Face )
00940 continue;
00941 int nbNodes = face->NbNodes();
00942 if ( face->IsQuadratic() )
00943 nbNodes /= 2;
00944
00945
00946 vector< const SMDS_MeshNode* > nodes( nbNodes );
00947 for ( int i = 0; i < nbNodes; ++i )
00948 {
00949 const SMDS_MeshNode* n = face->GetNode( nbNodes - i - 1 );
00950 if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
00951 TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n );
00952 if ( bot_column == myBotToColumnMap.end() )
00953 return error(TCom("No nodes found above node ") << n->GetID() );
00954 nodes[ i ] = bot_column->second.back();
00955 }
00956 else {
00957 const TNodeColumn* column = myBlock.GetNodeColumn( n );
00958 if ( !column )
00959 return error(TCom("No side nodes found above node ") << n->GetID() );
00960 nodes[ i ] = column->back();
00961 }
00962 }
00963
00964 SMDS_MeshElement* newFace = 0;
00965 switch ( nbNodes ) {
00966
00967 case 3: {
00968 newFace = myHelper->AddFace(nodes[0], nodes[1], nodes[2]);
00969 break;
00970 }
00971 case 4: {
00972 newFace = myHelper->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
00973 break;
00974 }
00975 default:
00976 newFace = meshDS->AddPolygonalFace( nodes );
00977 }
00978 if ( newFace && shapeID > 0 )
00979 meshDS->SetMeshElementOnShape( newFace, shapeID );
00980 }
00981
00982 return true;
00983 }
00984
00985
00992
00993
00994 bool StdMeshers_Prism_3D::setFaceAndEdgesXYZ( const int faceID, const gp_XYZ& params, int z )
00995 {
00996
00997 enum { BASE = 0, TOP, LEFT, RIGHT };
00998 vector< int > edgeVec;
00999 SMESH_Block::GetFaceEdgesIDs( faceID, edgeVec );
01000
01001 myBlock.EdgePoint( edgeVec[ BASE ], params, myShapeXYZ[ edgeVec[ BASE ]]);
01002 myBlock.EdgePoint( edgeVec[ TOP ], params, myShapeXYZ[ edgeVec[ TOP ]]);
01003
01004 SHOWYXZ("\nparams ", params);
01005 SHOWYXZ("TOP is " <<edgeVec[ TOP ], myShapeXYZ[ edgeVec[ TOP]]);
01006 SHOWYXZ("BASE is "<<edgeVec[ BASE], myShapeXYZ[ edgeVec[ BASE]]);
01007
01008 if ( faceID == SMESH_Block::ID_Fx0z || faceID == SMESH_Block::ID_Fx1z )
01009 {
01010 myBlock.EdgePoint( edgeVec[ LEFT ], params, myShapeXYZ[ edgeVec[ LEFT ]]);
01011 myBlock.EdgePoint( edgeVec[ RIGHT ], params, myShapeXYZ[ edgeVec[ RIGHT ]]);
01012
01013 SHOWYXZ("VER "<<edgeVec[ LEFT], myShapeXYZ[ edgeVec[ LEFT]]);
01014 SHOWYXZ("VER "<<edgeVec[ RIGHT], myShapeXYZ[ edgeVec[ RIGHT]]);
01015 }
01016 myBlock.FacePoint( faceID, params, myShapeXYZ[ faceID ]);
01017 SHOWYXZ("FacePoint "<<faceID, myShapeXYZ[ faceID]);
01018
01019 return true;
01020 }
01021
01022
01026
01027
01028 bool TNode::IsNeighbor( const TNode& other ) const
01029 {
01030 if ( !other.myNode || !myNode ) return false;
01031
01032 SMDS_ElemIteratorPtr fIt = other.myNode->GetInverseElementIterator(SMDSAbs_Face);
01033 while ( fIt->more() )
01034 if ( fIt->next()->GetNodeIndex( myNode ) >= 0 )
01035 return true;
01036 return false;
01037 }
01038
01039
01043
01044
01045 StdMeshers_PrismAsBlock::StdMeshers_PrismAsBlock()
01046 {
01047 mySide = 0;
01048 }
01049
01050 StdMeshers_PrismAsBlock::~StdMeshers_PrismAsBlock()
01051 {
01052 Clear();
01053 }
01054 void StdMeshers_PrismAsBlock::Clear()
01055 {
01056 myHelper = 0;
01057 myShapeIDMap.Clear();
01058 myError.reset();
01059
01060 if ( mySide ) {
01061 delete mySide; mySide = 0;
01062 }
01063 myParam2ColumnMaps.clear();
01064 myShapeIndex2ColumnMap.clear();
01065 }
01066
01067
01074
01075
01076 bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper,
01077 const TopoDS_Shape& shape3D)
01078 {
01079 if ( mySide ) {
01080 delete mySide; mySide = 0;
01081 }
01082 vector< TSideFace* > sideFaces( NB_WALL_FACES, 0 );
01083 vector< pair< double, double> > params ( NB_WALL_FACES );
01084 mySide = new TSideFace( sideFaces, params );
01085
01086 myHelper = helper;
01087 SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
01088
01089 SMESH_Block::init();
01090 myShapeIDMap.Clear();
01091 myShapeIndex2ColumnMap.clear();
01092
01093 int wallFaceIds[ NB_WALL_FACES ] = {
01094 SMESH_Block::ID_Fx0z, SMESH_Block::ID_F1yz,
01095 SMESH_Block::ID_Fx1z, SMESH_Block::ID_F0yz
01096 };
01097
01098 myError = SMESH_ComputeError::New();
01099
01100
01101
01102
01103
01104
01105 list< SMESH_subMesh* > notQuadGeomSubMesh;
01106 list< SMESH_subMesh* > notQuadElemSubMesh;
01107 int nbFaces = 0;
01108
01109 SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D );
01110 if ( !mainSubMesh ) return error(COMPERR_BAD_INPUT_MESH,"Null submesh of shape3D");
01111
01112
01113 SMESH_subMeshIteratorPtr smIt = mainSubMesh->getDependsOnIterator(false,false);
01114 while ( smIt->more() )
01115 {
01116 SMESH_subMesh* sm = smIt->next();
01117 const TopoDS_Shape& face = sm->GetSubShape();
01118 if ( face.ShapeType() != TopAbs_FACE )
01119 continue;
01120 nbFaces++;
01121
01122
01123 list< TopoDS_Edge > orderedEdges;
01124 list< int > nbEdgesInWires;
01125 TopoDS_Vertex V000;
01126 int nbWires = GetOrderedEdges( TopoDS::Face( face ),
01127 V000, orderedEdges, nbEdgesInWires );
01128 if ( nbWires != 1 || nbEdgesInWires.front() != 4 )
01129 notQuadGeomSubMesh.push_back( sm );
01130
01131
01132 if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) {
01133 bool hasNotQuad = false;
01134 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
01135 while ( eIt->more() && !hasNotQuad ) {
01136 const SMDS_MeshElement* elem = eIt->next();
01137 if ( elem->GetType() == SMDSAbs_Face ) {
01138 int nbNodes = elem->NbNodes();
01139 if ( elem->IsQuadratic() )
01140 nbNodes /= 2;
01141 hasNotQuad = ( nbNodes != 4 );
01142 }
01143 }
01144 if ( hasNotQuad )
01145 notQuadElemSubMesh.push_back( sm );
01146 }
01147 else {
01148 return error(COMPERR_BAD_INPUT_MESH,TCom("Not meshed face #")<<sm->GetId());
01149 }
01150
01151 if ( notQuadGeomSubMesh.back() != sm &&
01152 notQuadElemSubMesh.back() != sm )
01153 {
01154
01155 vector< int > nbEdges;
01156 nbEdges.reserve( nbEdgesInWires.front() );
01157 for ( list< TopoDS_Edge >::iterator edge = orderedEdges.begin();
01158 edge != orderedEdges.end(); ++edge )
01159 {
01160 if ( SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edge ))
01161 nbEdges.push_back ( smDS->NbElements() );
01162 else
01163 nbEdges.push_back ( 0 );
01164 }
01165 int nbQuads = sm->GetSubMeshDS()->NbElements();
01166 if ( nbEdges[0] * nbEdges[1] != nbQuads ||
01167 nbEdges[0] != nbEdges[2] ||
01168 nbEdges[1] != nbEdges[3] )
01169 notQuadElemSubMesh.push_back( sm );
01170 }
01171 }
01172
01173
01174
01175
01176
01177
01178
01179 SMESH_subMesh * botSM = 0;
01180 SMESH_subMesh * topSM = 0;
01181
01182 int nbNotQuad = notQuadGeomSubMesh.size();
01183 int nbNotQuadMeshed = notQuadElemSubMesh.size();
01184 bool hasNotQuad = ( nbNotQuad || nbNotQuadMeshed );
01185
01186
01187 if ( nbNotQuadMeshed > 2 )
01188 {
01189 return error(COMPERR_BAD_INPUT_MESH,
01190 TCom("More than 2 faces with not quadrangle elements: ")
01191 <<nbNotQuadMeshed);
01192 }
01193 int nbQuasiQuads = 0;
01194 if ( nbNotQuad > 0 && nbNotQuad != 2 )
01195 {
01196
01197
01198 nbQuasiQuads = removeQuasiQuads( notQuadGeomSubMesh );
01199 nbNotQuad -= nbQuasiQuads;
01200 if ( nbNotQuad > 0 && nbNotQuad != 2 )
01201 return error(COMPERR_BAD_SHAPE,
01202 TCom("More than 2 not quadrilateral faces: ")
01203 <<nbNotQuad);
01204 }
01205
01206
01207 if ( hasNotQuad )
01208 {
01209 if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front();
01210 else botSM = notQuadGeomSubMesh.front();
01211 if ( nbNotQuadMeshed > 1 ) topSM = notQuadElemSubMesh.back();
01212 else if ( nbNotQuad > 1 ) topSM = notQuadGeomSubMesh.back();
01213 }
01214
01215 if ( nbNotQuad == 2 && nbNotQuadMeshed > 0 ) {
01216 bool ok = false;
01217 if ( nbNotQuadMeshed == 1 )
01218 ok = ( find( notQuadGeomSubMesh.begin(),
01219 notQuadGeomSubMesh.end(), botSM ) != notQuadGeomSubMesh.end() );
01220 else
01221 ok = ( notQuadGeomSubMesh == notQuadElemSubMesh );
01222 if ( !ok )
01223 return error(COMPERR_BAD_INPUT_MESH, "Side face meshed with not quadrangle elements");
01224 }
01225
01226 myNotQuadOnTop = ( nbNotQuadMeshed > 1 );
01227 MESSAGE("myNotQuadOnTop " << myNotQuadOnTop << " nbNotQuadMeshed " << nbNotQuadMeshed);
01228
01229
01230
01231 if ( nbNotQuad == 0 )
01232 {
01233
01234
01235
01236 TopoDS_Vertex Vbot, Vtop;
01237 if ( nbNotQuadMeshed > 0 )
01238 {
01239 TopTools_IndexedMapOfShape edgeMap;
01240 TopExp::MapShapes( botSM->GetSubShape(), TopAbs_EDGE, edgeMap );
01241
01242 Vbot = TopExp::FirstVertex( TopoDS::Edge( edgeMap( 1 )));
01243
01244 TopTools_ListIteratorOfListOfShape ancestIt = Mesh()->GetAncestors( Vbot );
01245 for ( ; Vtop.IsNull() && ancestIt.More(); ancestIt.Next() )
01246 {
01247 const TopoDS_Shape & ancestor = ancestIt.Value();
01248 if ( ancestor.ShapeType() == TopAbs_EDGE && !edgeMap.FindIndex( ancestor ))
01249 {
01250 TopoDS_Vertex V1, V2;
01251 TopExp::Vertices( TopoDS::Edge( ancestor ), V1, V2);
01252 if ( Vbot.IsSame ( V1 )) Vtop = V2;
01253 else if ( Vbot.IsSame ( V2 )) Vtop = V1;
01254
01255 TopExp_Explorer exp( shape3D, TopAbs_VERTEX );
01256 for ( ; exp.More(); exp.Next() )
01257 if ( Vtop.IsSame( exp.Current() ))
01258 break;
01259 if ( !exp.More() )
01260 Vtop.Nullify();
01261 }
01262 }
01263 }
01264
01265 TopoDS_Shell shell;
01266 TopExp_Explorer exp( shape3D, TopAbs_SHELL );
01267 int nbShell = 0;
01268 for ( ; exp.More(); exp.Next(), ++nbShell )
01269 shell = TopoDS::Shell( exp.Current() );
01270
01271
01272
01273
01274 if ( !SMESH_Block::FindBlockShapes( shell, Vbot, Vtop, myShapeIDMap )) {
01275 if ( !hasNotQuad )
01276 return error(COMPERR_BAD_SHAPE, "Can't detect top and bottom of a prism");
01277 }
01278 else {
01279 if ( !botSM ) botSM = Mesh()->GetSubMeshContaining( myShapeIDMap( ID_BOT_FACE ));
01280 if ( !topSM ) topSM = Mesh()->GetSubMeshContaining( myShapeIDMap( ID_TOP_FACE ));
01281 }
01282
01283 }
01284
01285
01286
01287 if ( nbNotQuadMeshed == 2 )
01288 {
01289
01290
01291
01292
01293
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 TopoDS_Vertex V000;
01305 double minVal = DBL_MAX, minX, val;
01306 for ( TopExp_Explorer exp( botSM->GetSubShape(), TopAbs_VERTEX );
01307 exp.More(); exp.Next() )
01308 {
01309 const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() );
01310 gp_Pnt P = BRep_Tool::Pnt( v );
01311 val = P.X() + P.Y() + P.Z();
01312 if ( val < minVal || ( val == minVal && P.X() < minX )) {
01313 V000 = v;
01314 minVal = val;
01315 minX = P.X();
01316 }
01317 }
01318
01319
01320 list< TopoDS_Edge > orderedEdges;
01321 list< int > nbEInW;
01322 SMESH_Block::GetOrderedEdges( TopoDS::Face( botSM->GetSubShape().Reversed() ),
01323 V000, orderedEdges, nbEInW );
01324
01325
01326
01327
01328 list< TopoDS_Face > wallFaces;
01329 if ( !GetWallFaces( Mesh(), shape3D, botSM->GetSubShape(), orderedEdges, nbEInW, wallFaces))
01330 return error(COMPERR_BAD_SHAPE, "Can't find side faces");
01331
01332
01333
01334 {
01335 list< TopoDS_Face >::iterator faceIt = wallFaces.begin();
01336 for ( ; faceIt != wallFaces.end(); ++faceIt )
01337 {
01338 bool hasCommon = false;
01339 for (TopExp_Explorer edge(*faceIt, TopAbs_EDGE); !hasCommon && edge.More(); edge.Next())
01340 if ( helper->IsSubShape( edge.Current(), topSM->GetSubShape() ))
01341 hasCommon = true;
01342 if ( !hasCommon )
01343 return error(COMPERR_BAD_SHAPE);
01344 }
01345 }
01346
01347
01348
01349
01350 myParam2ColumnMaps.clear();
01351 myParam2ColumnMaps.resize( orderedEdges.size() );
01352
01353 int iE, nbEdges = nbEInW.front();
01354 vector< double > edgeLength( nbEdges );
01355 map< double, int > len2edgeMap;
01356
01357 list< TopoDS_Edge >::iterator edgeIt = orderedEdges.begin();
01358 list< TopoDS_Face >::iterator faceIt = wallFaces.begin();
01359 for ( iE = 0; iE < nbEdges; ++edgeIt, ++faceIt )
01360 {
01361 TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
01362 if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
01363 return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
01364 << "on a side face #" << MeshDS()->ShapeToIndex( *faceIt ));
01365
01366 SHOWYXZ("\np1 F "<<iE, gpXYZ(faceColumns.begin()->second.front() ));
01367 SHOWYXZ("p2 F "<<iE, gpXYZ(faceColumns.rbegin()->second.front() ));
01368 SHOWYXZ("V First "<<iE, BRep_Tool::Pnt( TopExp::FirstVertex(*edgeIt,true )));
01369
01370 edgeLength[ iE ] = SMESH_Algo::EdgeLength( *edgeIt );
01371
01372 if ( nbEdges < NB_WALL_FACES )
01373 {
01374 SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edgeIt);
01375 if ( !smDS )
01376 return error(COMPERR_BAD_INPUT_MESH, TCom("Null submesh on the edge #")
01377 << MeshDS()->ShapeToIndex( *edgeIt ));
01378
01379 edgeLength[ iE ] *= smDS->NbNodes() + edgeLength[ iE ] / ( 1000 + iE );
01380 len2edgeMap[ edgeLength[ iE ]] = iE;
01381 }
01382 ++iE;
01383 }
01384
01385
01386 for ( ; edgeIt != orderedEdges.end() ; ++edgeIt, ++faceIt )
01387 {
01388 TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
01389 if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
01390 return error(COMPERR_BAD_INPUT_MESH, TCom("Can't find regular quadrangle mesh ")
01391 << "on a side face #" << MeshDS()->ShapeToIndex( *faceIt ));
01392
01393 int id = MeshDS()->ShapeToIndex( *edgeIt );
01394 bool isForward = true;
01395 myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
01396
01397
01398 const SMDS_MeshNode* n0 = faceColumns.begin()->second.front();
01399 id = n0->getshapeId();
01400 myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
01401
01402 const SMDS_MeshNode* n1 = faceColumns.rbegin()->second.front();
01403 id = n1->getshapeId();
01404 myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
01405
01406
01407
01408 ++iE;
01409 }
01410
01411
01412
01413
01414 if ( nbEdges <= NB_WALL_FACES )
01415 {
01416 map< int, int > iE2nbSplit;
01417 if ( nbEdges != NB_WALL_FACES )
01418 {
01419 if ( len2edgeMap.size() != nbEdges )
01420 RETURN_BAD_RESULT("Uniqueness of edge lengths not assured");
01421 map< double, int >::reverse_iterator maxLen_i = len2edgeMap.rbegin();
01422 map< double, int >::reverse_iterator midLen_i = ++len2edgeMap.rbegin();
01423 double maxLen = maxLen_i->first;
01424 double midLen = ( len2edgeMap.size() == 1 ) ? 0 : midLen_i->first;
01425 switch ( nbEdges ) {
01426 case 1:
01427 iE2nbSplit.insert( make_pair( 0, 4 )); break;
01428 case 2:
01429 if ( maxLen / 3 > midLen / 2 ) {
01430 iE2nbSplit.insert( make_pair( maxLen_i->second, 3 ));
01431 }
01432 else {
01433 iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
01434 iE2nbSplit.insert( make_pair( midLen_i->second, 2 ));
01435 }
01436 break;
01437 case 3:
01438
01439 iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
01440 }
01441 }
01442
01443 faceIt = wallFaces.begin();
01444 edgeIt = orderedEdges.begin();
01445 int iSide = 0;
01446 for ( iE = 0; iE < nbEdges; ++edgeIt, ++faceIt )
01447 {
01448
01449 map< int, int >::iterator i_nb = iE2nbSplit.find( iE );
01450 if ( i_nb != iE2nbSplit.end() ) {
01451
01452 int nbSplit = i_nb->second;
01453 vector< double > params;
01454 splitParams( nbSplit, &myParam2ColumnMaps[ iE ], params );
01455 bool isForward = ( edgeIt->Orientation() == TopAbs_FORWARD );
01456 for ( int i = 0; i < nbSplit; ++i ) {
01457 double f = ( isForward ? params[ i ] : params[ nbSplit - i-1 ]);
01458 double l = ( isForward ? params[ i+1 ] : params[ nbSplit - i ]);
01459 TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
01460 *faceIt, *edgeIt,
01461 &myParam2ColumnMaps[ iE ], f, l );
01462 mySide->SetComponent( iSide++, comp );
01463 }
01464 }
01465 else {
01466 TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
01467 *faceIt, *edgeIt,
01468 &myParam2ColumnMaps[ iE ]);
01469 mySide->SetComponent( iSide++, comp );
01470 }
01471 ++iE;
01472 }
01473 }
01474 else {
01475
01476
01477 int nbExraFaces = nbEdges - 3;
01478 int iSide = 0, iE;
01479 double u0 = 0, sumLen = 0;
01480 for ( iE = 0; iE < nbExraFaces; ++iE )
01481 sumLen += edgeLength[ iE ];
01482
01483 vector< TSideFace* > components( nbExraFaces );
01484 vector< pair< double, double> > params( nbExraFaces );
01485 faceIt = wallFaces.begin();
01486 edgeIt = orderedEdges.begin();
01487 for ( iE = 0; iE < nbExraFaces; ++edgeIt, ++faceIt )
01488 {
01489 components[ iE ] = new TSideFace( myHelper, wallFaceIds[ iSide ],
01490 *faceIt, *edgeIt,
01491 &myParam2ColumnMaps[ iE ]);
01492 double u1 = u0 + edgeLength[ iE ] / sumLen;
01493 params[ iE ] = make_pair( u0 , u1 );
01494 u0 = u1;
01495 ++iE;
01496 }
01497 mySide->SetComponent( iSide++, new TSideFace( components, params ));
01498
01499
01500 for ( ; iE < nbEdges; ++faceIt, ++edgeIt )
01501 {
01502 TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
01503 *faceIt, *edgeIt,
01504 &myParam2ColumnMaps[ iE ]);
01505 mySide->SetComponent( iSide++, comp );
01506 ++iE;
01507 }
01508 }
01509
01510
01511
01512
01513
01514 TopoDS_Face botF = TopoDS::Face( botSM->GetSubShape() );
01515 TopoDS_Face topF = TopoDS::Face( topSM->GetSubShape() );
01516
01517 vector< int > botEdgeIdVec;
01518 SMESH_Block::GetFaceEdgesIDs( ID_BOT_FACE, botEdgeIdVec );
01519
01520 bool isForward[NB_WALL_FACES] = { true, true, true, true };
01521 Adaptor2d_Curve2d* botPcurves[NB_WALL_FACES];
01522 Adaptor2d_Curve2d* topPcurves[NB_WALL_FACES];
01523
01524 for ( int iF = 0; iF < NB_WALL_FACES; ++iF )
01525 {
01526 TSideFace * sideFace = mySide->GetComponent( iF );
01527 if ( !sideFace )
01528 RETURN_BAD_RESULT("NULL TSideFace");
01529 int fID = sideFace->FaceID();
01530
01531
01532 if ( sideFace->InsertSubShapes( myShapeIDMap ) != 8 &&
01533 !sideFace->IsComplex())
01534 MESSAGE( ": Warning : InsertSubShapes() < 8 on side " << iF );
01535
01536
01537 Adaptor2d_Curve2d* pcurves[NB_WALL_FACES];
01538 if ( !sideFace->GetPCurves( pcurves ))
01539 RETURN_BAD_RESULT("TSideFace::GetPCurves() failed");
01540
01541 SMESH_Block::TFace& tFace = myFace[ fID - ID_FirstF ];
01542 tFace.Set( fID, sideFace->Surface(), pcurves, isForward );
01543
01544 SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), sideFace->Value(0,0));
01545
01546 vector< int > edgeIdVec;
01547 SMESH_Block::GetFaceEdgesIDs( fID, edgeIdVec );
01548 for ( int isMax = 0; isMax < 2; ++isMax ) {
01549 {
01550 int eID = edgeIdVec[ isMax ];
01551 SMESH_Block::TEdge& tEdge = myEdge[ eID - ID_FirstE ];
01552 tEdge.Set( eID, sideFace->HorizCurve(isMax), true);
01553 SHOWYXZ(eID<<" HOR"<<isMax<<"(0)", sideFace->HorizCurve(isMax)->Value(0));
01554 SHOWYXZ(eID<<" HOR"<<isMax<<"(1)", sideFace->HorizCurve(isMax)->Value(1));
01555 }
01556 {
01557 int eID = edgeIdVec[ isMax+2 ];
01558 SMESH_Block::TEdge& tEdge = myEdge[ eID - ID_FirstE ];
01559 tEdge.Set( eID, sideFace->VertiCurve(isMax), true);
01560 SHOWYXZ(eID<<" VER"<<isMax<<"(0)", sideFace->VertiCurve(isMax)->Value(0));
01561 SHOWYXZ(eID<<" VER"<<isMax<<"(1)", sideFace->VertiCurve(isMax)->Value(1));
01562
01563
01564 vector< int > vertexIdVec;
01565 SMESH_Block::GetEdgeVertexIDs( eID, vertexIdVec );
01566 myPnt[ vertexIdVec[0] - ID_FirstV ] = tEdge.GetCurve()->Value(0).XYZ();
01567 myPnt[ vertexIdVec[1] - ID_FirstV ] = tEdge.GetCurve()->Value(1).XYZ();
01568 }
01569 }
01570
01571 for ( iE = 0; iE < NB_WALL_FACES; ++iE ) {
01572 if ( edgeIdVec[ BOTTOM_EDGE ] == botEdgeIdVec[ iE ] ) {
01573 botPcurves[ iE ] = sideFace->HorizPCurve( false, botF );
01574 topPcurves[ iE ] = sideFace->HorizPCurve( true, topF );
01575 break;
01576 }
01577 }
01578
01579 }
01580
01581 {
01582 SMESH_Block::TFace& tFace = myFace[ ID_BOT_FACE - ID_FirstF ];
01583 tFace.Set( ID_BOT_FACE, new BRepAdaptor_Surface( botF ), botPcurves, isForward );
01584 SMESH_Block::Insert( botF, ID_BOT_FACE, myShapeIDMap );
01585 }
01586 {
01587 SMESH_Block::TFace& tFace = myFace[ ID_TOP_FACE - ID_FirstF ];
01588 tFace.Set( ID_TOP_FACE, new BRepAdaptor_Surface( topF ), topPcurves, isForward );
01589 SMESH_Block::Insert( topF, ID_TOP_FACE, myShapeIDMap );
01590 }
01591
01592
01593
01594
01595 list< TSideFace* > fList;
01596 list< TSideFace* >::iterator fListIt;
01597 fList.push_back( mySide );
01598 for ( fListIt = fList.begin(); fListIt != fList.end(); ++fListIt)
01599 {
01600 int nb = (*fListIt)->NbComponents();
01601 for ( int i = 0; i < nb; ++i ) {
01602 if ( TSideFace* comp = (*fListIt)->GetComponent( i ))
01603 fList.push_back( comp );
01604 }
01605 if ( TParam2ColumnMap* cols = (*fListIt)->GetColumns()) {
01606
01607 int id = MeshDS()->ShapeToIndex( (*fListIt)->BaseEdge() );
01608 bool isForward = (*fListIt)->IsForward();
01609 myShapeIndex2ColumnMap[ id ] = make_pair( cols, isForward );
01610
01611
01612 const SMDS_MeshNode* n0 = cols->begin()->second.front();
01613 id = n0->getshapeId();
01614 myShapeIndex2ColumnMap[ id ] = make_pair( cols, isForward );
01615
01616 const SMDS_MeshNode* n1 = cols->rbegin()->second.front();
01617 id = n1->getshapeId();
01618 myShapeIndex2ColumnMap[ id ] = make_pair( cols, !isForward );
01619 }
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631 return true;
01632 }
01633
01634
01640
01641
01642 const TNodeColumn* StdMeshers_PrismAsBlock::GetNodeColumn(const SMDS_MeshNode* node) const
01643 {
01644 int sID = node->getshapeId();
01645
01646 map<int, pair< TParam2ColumnMap*, bool > >::const_iterator col_frw =
01647 myShapeIndex2ColumnMap.find( sID );
01648 if ( col_frw != myShapeIndex2ColumnMap.end() ) {
01649 const TParam2ColumnMap* cols = col_frw->second.first;
01650 TParam2ColumnIt u_col = cols->begin();
01651 for ( ; u_col != cols->end(); ++u_col )
01652 if ( u_col->second[ 0 ] == node )
01653 return & u_col->second;
01654 }
01655 return 0;
01656 }
01657
01658
01659
01660
01661
01662
01663
01664
01665 bool StdMeshers_PrismAsBlock::GetLayersTransformation(vector<gp_Trsf> & trsf) const
01666 {
01667 const int zSize = VerticalSize();
01668 if ( zSize < 3 ) return true;
01669 trsf.resize( zSize - 2 );
01670
01671
01672
01673 vector< const TNodeColumn* > columns;
01674 {
01675 const TopoDS_Shape& baseFace = Shape(ID_BOT_FACE);
01676 list< TopoDS_Edge > orderedEdges;
01677 list< int > nbEdgesInWires;
01678 GetOrderedEdges( TopoDS::Face( baseFace ), TopoDS_Vertex(), orderedEdges, nbEdgesInWires );
01679 bool isReverse;
01680 list< TopoDS_Edge >::iterator edgeIt = orderedEdges.begin();
01681 for ( int iE = 0; iE < nbEdgesInWires.front(); ++iE, ++edgeIt )
01682 {
01683 if ( BRep_Tool::Degenerated( *edgeIt )) continue;
01684 const TParam2ColumnMap& u2colMap =
01685 GetParam2ColumnMap( myHelper->GetMeshDS()->ShapeToIndex( *edgeIt ), isReverse );
01686 isReverse = ( edgeIt->Orientation() == TopAbs_REVERSED );
01687 double f = u2colMap.begin()->first, l = u2colMap.rbegin()->first;
01688 if ( isReverse ) swap ( f, l );
01689 const int nbCol = 5;
01690 for ( int i = 0; i < nbCol; ++i )
01691 {
01692 double u = f + i/double(nbCol) * ( l - f );
01693 const TNodeColumn* col = & getColumn( & u2colMap, u )->second;
01694 if ( columns.empty() || col != columns.back() )
01695 columns.push_back( col );
01696 }
01697 }
01698 }
01699
01700
01701
01702 double tol2;
01703 {
01704 Bnd_B3d bndBox;
01705 for ( int i = 0; i < columns.size(); ++i )
01706 bndBox.Add( gpXYZ( columns[i]->front() ));
01707 tol2 = bndBox.SquareExtent() * 1e-5;
01708 }
01709
01710
01711
01712 int xCol = -1;
01713 gp_Trsf fromCsZ, toCs0;
01714 gp_Ax3 cs0 = getLayerCoordSys(0, columns, xCol );
01715
01716 toCs0.SetTransformation( cs0 );
01717 for ( int z = 1; z < zSize-1; ++z )
01718 {
01719 gp_Ax3 csZ = getLayerCoordSys(z, columns, xCol );
01720
01721 fromCsZ.SetTransformation( csZ );
01722 fromCsZ.Invert();
01723 gp_Trsf& t = trsf[ z-1 ];
01724 t = fromCsZ * toCs0;
01725
01726
01727
01728 for ( int i = 0; i < columns.size(); ++i )
01729 {
01730 gp_Pnt p0 = gpXYZ( (*columns[i])[0] );
01731 gp_Pnt pz = gpXYZ( (*columns[i])[z] );
01732 t.Transforms( p0.ChangeCoord() );
01733 if ( p0.SquareDistance( pz ) > tol2 )
01734 return false;
01735 }
01736 }
01737 return true;
01738 }
01739
01740
01749
01750
01751 bool StdMeshers_PrismAsBlock::IsForwardEdge(SMESHDS_Mesh* meshDS,
01752 const TParam2ColumnMap& columnsMap,
01753 const TopoDS_Edge & bottomEdge,
01754 const int sideFaceID)
01755 {
01756 bool isForward = false;
01757 if ( SMESH_MesherHelper::IsClosedEdge( bottomEdge ))
01758 {
01759 isForward = ( bottomEdge.Orientation() == TopAbs_FORWARD );
01760 }
01761 else
01762 {
01763 const TNodeColumn& firstCol = columnsMap.begin()->second;
01764 const SMDS_MeshNode* bottomNode = firstCol[0];
01765 TopoDS_Shape firstVertex = SMESH_MesherHelper::GetSubShapeByNode( bottomNode, meshDS );
01766 isForward = ( firstVertex.IsSame( TopExp::FirstVertex( bottomEdge, true )));
01767 }
01768
01769 if ( sideFaceID == ID_Fx1z || sideFaceID == ID_F0yz )
01770 isForward = !isForward;
01771 return isForward;
01772 }
01773
01774
01783
01784
01785 bool StdMeshers_PrismAsBlock::GetWallFaces( SMESH_Mesh* mesh,
01786 const TopoDS_Shape & mainShape,
01787 const TopoDS_Shape & bottomFace,
01788 std::list< TopoDS_Edge >& bottomEdges,
01789 std::list< int > & nbEInW,
01790 std::list< TopoDS_Face >& wallFaces)
01791 {
01792 wallFaces.clear();
01793
01794 TopTools_IndexedMapOfShape faceMap;
01795 TopExp::MapShapes( mainShape, TopAbs_FACE, faceMap );
01796
01797 list< TopoDS_Edge >::iterator edge = bottomEdges.begin();
01798 std::list< int >::iterator nbE = nbEInW.begin();
01799 int iE = 0;
01800 while ( edge != bottomEdges.end() )
01801 {
01802 ++iE;
01803 if ( BRep_Tool::Degenerated( *edge ))
01804 {
01805 edge = bottomEdges.erase( edge );
01806 --iE;
01807 --(*nbE);
01808 }
01809 else
01810 {
01811 PShapeIteratorPtr fIt = myHelper->GetAncestors( *edge, *mesh, TopAbs_FACE );
01812 while ( fIt->more() )
01813 {
01814 const TopoDS_Shape* face = fIt->next();
01815 if ( !bottomFace.IsSame( *face ) &&
01816 faceMap.FindIndex( *face ))
01817 {
01818 wallFaces.push_back( TopoDS::Face( *face ));
01819 break;
01820 }
01821 }
01822 ++edge;
01823 }
01824 if ( iE == *nbE )
01825 {
01826 iE = 0;
01827 ++nbE;
01828 }
01829 }
01830 return ( wallFaces.size() == bottomEdges.size() );
01831 }
01832
01833
01842
01843
01844 StdMeshers_PrismAsBlock::TSideFace::TSideFace(SMESH_MesherHelper* helper,
01845 const int faceID,
01846 const TopoDS_Face& face,
01847 const TopoDS_Edge& baseEdge,
01848 TParam2ColumnMap* columnsMap,
01849 const double first,
01850 const double last):
01851 myID( faceID ),
01852 myParamToColumnMap( columnsMap ),
01853 myBaseEdge( baseEdge ),
01854 myHelper( helper )
01855 {
01856 mySurface.Initialize( face );
01857 myParams.resize( 1 );
01858 myParams[ 0 ] = make_pair( first, last );
01859 myIsForward = StdMeshers_PrismAsBlock::IsForwardEdge( myHelper->GetMeshDS(),
01860 *myParamToColumnMap,
01861 myBaseEdge, myID );
01862 }
01863
01864
01868
01869
01870 StdMeshers_PrismAsBlock::TSideFace::
01871 TSideFace(const vector< TSideFace* >& components,
01872 const vector< pair< double, double> > & params)
01873 :myID( components[0] ? components[0]->myID : 0 ),
01874 myParamToColumnMap( 0 ),
01875 myParams( params ),
01876 myIsForward( true ),
01877 myComponents( components ),
01878 myHelper( components[0] ? components[0]->myHelper : 0 )
01879 {}
01880
01885
01886
01887 StdMeshers_PrismAsBlock::TSideFace::TSideFace( const TSideFace& other )
01888 {
01889 myID = other.myID;
01890 mySurface = other.mySurface;
01891 myBaseEdge = other.myBaseEdge;
01892 myParams = other.myParams;
01893 myIsForward = other.myIsForward;
01894 myHelper = other.myHelper;
01895 myParamToColumnMap = other.myParamToColumnMap;
01896
01897 myComponents.resize( other.myComponents.size());
01898 for (int i = 0 ; i < myComponents.size(); ++i )
01899 myComponents[ i ] = new TSideFace( *other.myComponents[ i ]);
01900 }
01901
01902
01906
01907
01908 StdMeshers_PrismAsBlock::TSideFace::~TSideFace()
01909 {
01910 for (int i = 0 ; i < myComponents.size(); ++i )
01911 if ( myComponents[ i ] )
01912 delete myComponents[ i ];
01913 }
01914
01915
01921
01922
01923 Adaptor3d_Curve* StdMeshers_PrismAsBlock::TSideFace::VertiCurve(const bool isMax) const
01924 {
01925 if ( !myComponents.empty() ) {
01926 if ( isMax )
01927 return myComponents.back()->VertiCurve(isMax);
01928 else
01929 return myComponents.front()->VertiCurve(isMax);
01930 }
01931 double f = myParams[0].first, l = myParams[0].second;
01932 if ( !myIsForward ) std::swap( f, l );
01933 return new TVerticalEdgeAdaptor( myParamToColumnMap, isMax ? l : f );
01934 }
01935
01936
01942
01943
01944 Adaptor3d_Curve* StdMeshers_PrismAsBlock::TSideFace::HorizCurve(const bool isTop) const
01945 {
01946 return new THorizontalEdgeAdaptor( this, isTop );
01947 }
01948
01949
01955
01956
01957 bool StdMeshers_PrismAsBlock::TSideFace::GetPCurves(Adaptor2d_Curve2d* pcurv[4]) const
01958 {
01959 int iEdge[ 4 ] = { BOTTOM_EDGE, TOP_EDGE, V0_EDGE, V1_EDGE };
01960
01961 for ( int i = 0 ; i < 4 ; ++i ) {
01962 Handle(Geom2d_Line) line;
01963 switch ( iEdge[ i ] ) {
01964 case TOP_EDGE:
01965 line = new Geom2d_Line( gp_Pnt2d( 0, 1 ), gp::DX2d() ); break;
01966 case BOTTOM_EDGE:
01967 line = new Geom2d_Line( gp::Origin2d(), gp::DX2d() ); break;
01968 case V0_EDGE:
01969 line = new Geom2d_Line( gp::Origin2d(), gp::DY2d() ); break;
01970 case V1_EDGE:
01971 line = new Geom2d_Line( gp_Pnt2d( 1, 0 ), gp::DY2d() ); break;
01972 }
01973 pcurv[ i ] = new Geom2dAdaptor_Curve( line, 0, 1 );
01974 }
01975 return true;
01976 }
01977
01978
01985
01986
01987 Adaptor2d_Curve2d*
01988 StdMeshers_PrismAsBlock::TSideFace::HorizPCurve(const bool isTop,
01989 const TopoDS_Face& horFace) const
01990 {
01991 return new TPCurveOnHorFaceAdaptor( this, isTop, horFace );
01992 }
01993
01994
02001
02002
02003 StdMeshers_PrismAsBlock::TSideFace*
02004 StdMeshers_PrismAsBlock::TSideFace::GetComponent(const double U,double & localU) const
02005 {
02006 localU = U;
02007 if ( myComponents.empty() )
02008 return const_cast<TSideFace*>( this );
02009
02010 int i;
02011 for ( i = 0; i < myComponents.size(); ++i )
02012 if ( U < myParams[ i ].second )
02013 break;
02014 if ( i >= myComponents.size() )
02015 i = myComponents.size() - 1;
02016
02017 double f = myParams[ i ].first, l = myParams[ i ].second;
02018 localU = ( U - f ) / ( l - f );
02019 return myComponents[ i ];
02020 }
02021
02022
02030
02031
02032 double StdMeshers_PrismAsBlock::TSideFace::GetColumns(const double U,
02033 TParam2ColumnIt & col1,
02034 TParam2ColumnIt & col2) const
02035 {
02036 double u = U, r = 0;
02037 if ( !myComponents.empty() ) {
02038 TSideFace * comp = GetComponent(U,u);
02039 return comp->GetColumns( u, col1, col2 );
02040 }
02041
02042 if ( !myIsForward )
02043 u = 1 - u;
02044 double f = myParams[0].first, l = myParams[0].second;
02045 u = f + u * ( l - f );
02046
02047 col1 = col2 = getColumn( myParamToColumnMap, u );
02048 if ( ++col2 == myParamToColumnMap->end() ) {
02049 --col2;
02050 r = 0.5;
02051 }
02052 else {
02053 double uf = col1->first;
02054 double ul = col2->first;
02055 r = ( u - uf ) / ( ul - uf );
02056 }
02057 return r;
02058 }
02059
02060
02067
02068
02069 gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
02070 const Standard_Real V) const
02071 {
02072 if ( !myComponents.empty() ) {
02073 double u;
02074 TSideFace * comp = GetComponent(U,u);
02075 return comp->Value( u, V );
02076 }
02077
02078 TParam2ColumnIt u_col1, u_col2;
02079 double vR, hR = GetColumns( U, u_col1, u_col2 );
02080
02081 const SMDS_MeshNode* n1 = 0;
02082 const SMDS_MeshNode* n2 = 0;
02083 const SMDS_MeshNode* n3 = 0;
02084 const SMDS_MeshNode* n4 = 0;
02085
02086
02087
02088
02089
02090
02091 const double tol = 1e-3;
02092 if ( V < tol || V+tol >= 1. )
02093 {
02094 n1 = V < tol ? u_col1->second.front() : u_col1->second.back();
02095 n3 = V < tol ? u_col2->second.front() : u_col2->second.back();
02096 TopoDS_Edge edge;
02097 if ( V < tol )
02098 {
02099 edge = myBaseEdge;
02100 }
02101 else
02102 {
02103 TopoDS_Shape s = myHelper->GetSubShapeByNode( n1, myHelper->GetMeshDS() );
02104 if ( s.ShapeType() != TopAbs_EDGE )
02105 s = myHelper->GetSubShapeByNode( n3, myHelper->GetMeshDS() );
02106 if ( s.ShapeType() == TopAbs_EDGE )
02107 edge = TopoDS::Edge( s );
02108 }
02109 if ( !edge.IsNull() )
02110 {
02111 double u1 = myHelper->GetNodeU( edge, n1 );
02112 double u3 = myHelper->GetNodeU( edge, n3 );
02113 double u = u1 * ( 1 - hR ) + u3 * hR;
02114 TopLoc_Location loc; double f,l;
02115 Handle(Geom_Curve) curve = BRep_Tool::Curve( edge,loc,f,l );
02116 return curve->Value( u ).Transformed( loc );
02117 }
02118 }
02119
02120
02121 vR = getRAndNodes( & u_col1->second, V, n1, n2 );
02122 vR = getRAndNodes( & u_col2->second, V, n3, n4 );
02123
02124 gp_XY uv1 = myHelper->GetNodeUV( mySurface.Face(), n1, n4);
02125 gp_XY uv2 = myHelper->GetNodeUV( mySurface.Face(), n2, n3);
02126 gp_XY uv12 = uv1 * ( 1 - vR ) + uv2 * vR;
02127
02128 gp_XY uv3 = myHelper->GetNodeUV( mySurface.Face(), n3, n2);
02129 gp_XY uv4 = myHelper->GetNodeUV( mySurface.Face(), n4, n1);
02130 gp_XY uv34 = uv3 * ( 1 - vR ) + uv4 * vR;
02131
02132 gp_XY uv = uv12 * ( 1 - hR ) + uv34 * hR;
02133
02134 gp_Pnt p = mySurface.Value( uv.X(), uv.Y() );
02135 return p;
02136 }
02137
02138
02139
02145
02146
02147 TopoDS_Edge StdMeshers_PrismAsBlock::TSideFace::GetEdge(const int iEdge) const
02148 {
02149 if ( !myComponents.empty() ) {
02150 switch ( iEdge ) {
02151 case V0_EDGE : return myComponents.front()->GetEdge( iEdge );
02152 case V1_EDGE : return myComponents.back() ->GetEdge( iEdge );
02153 default: return TopoDS_Edge();
02154 }
02155 }
02156 TopoDS_Shape edge;
02157 const SMDS_MeshNode* node = 0;
02158 SMESHDS_Mesh * meshDS = myHelper->GetMesh()->GetMeshDS();
02159 TNodeColumn* column;
02160
02161 switch ( iEdge ) {
02162 case TOP_EDGE:
02163 case BOTTOM_EDGE:
02164 column = & (( ++myParamToColumnMap->begin())->second );
02165 node = ( iEdge == TOP_EDGE ) ? column->back() : column->front();
02166 edge = myHelper->GetSubShapeByNode ( node, meshDS );
02167 if ( edge.ShapeType() == TopAbs_VERTEX ) {
02168 column = & ( myParamToColumnMap->begin()->second );
02169 node = ( iEdge == TOP_EDGE ) ? column->back() : column->front();
02170 }
02171 break;
02172 case V0_EDGE:
02173 case V1_EDGE: {
02174 bool back = ( iEdge == V1_EDGE );
02175 if ( !myIsForward ) back = !back;
02176 if ( back )
02177 column = & ( myParamToColumnMap->rbegin()->second );
02178 else
02179 column = & ( myParamToColumnMap->begin()->second );
02180 if ( column->size() > 0 )
02181 edge = myHelper->GetSubShapeByNode( (*column)[ 1 ], meshDS );
02182 if ( edge.IsNull() || edge.ShapeType() == TopAbs_VERTEX )
02183 node = column->front();
02184 break;
02185 }
02186 default:;
02187 }
02188 if ( !edge.IsNull() && edge.ShapeType() == TopAbs_EDGE )
02189 return TopoDS::Edge( edge );
02190
02191
02192 TopoDS_Shape V1 = edge;
02193 TopoDS_Shape V2 = myHelper->GetSubShapeByNode( node, meshDS );
02194 if ( V2.ShapeType() == TopAbs_VERTEX && !V2.IsSame( V1 ))
02195 {
02196 TopTools_ListIteratorOfListOfShape ancestIt =
02197 myHelper->GetMesh()->GetAncestors( V1 );
02198 for ( ; ancestIt.More(); ancestIt.Next() )
02199 {
02200 const TopoDS_Shape & ancestor = ancestIt.Value();
02201 if ( ancestor.ShapeType() == TopAbs_EDGE )
02202 for ( TopExp_Explorer e( ancestor, TopAbs_VERTEX ); e.More(); e.Next() )
02203 if ( V2.IsSame( e.Current() ))
02204 return TopoDS::Edge( ancestor );
02205 }
02206 }
02207 return TopoDS_Edge();
02208 }
02209
02210
02216
02217
02218 int StdMeshers_PrismAsBlock::TSideFace::InsertSubShapes(TBlockShapes& shapeMap) const
02219 {
02220 int nbInserted = 0;
02221
02222
02223 vector< int > edgeIdVec;
02224 SMESH_Block::GetFaceEdgesIDs( myID, edgeIdVec );
02225
02226 for ( int i = BOTTOM_EDGE; i <=V1_EDGE ; ++i ) {
02227 TopoDS_Edge e = GetEdge( i );
02228 if ( !e.IsNull() ) {
02229 nbInserted += SMESH_Block::Insert( e, edgeIdVec[ i ], shapeMap);
02230 }
02231 }
02232
02233
02234
02235 TParam2ColumnIt col1, col2 ;
02236 vector< int > vertIdVec;
02237
02238
02239 SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ V0_EDGE ], vertIdVec);
02240 GetColumns(0, col1, col2 );
02241 const SMDS_MeshNode* node0 = col1->second.front();
02242 const SMDS_MeshNode* node1 = col1->second.back();
02243 TopoDS_Shape v0 = myHelper->GetSubShapeByNode( node0, myHelper->GetMeshDS());
02244 TopoDS_Shape v1 = myHelper->GetSubShapeByNode( node1, myHelper->GetMeshDS());
02245 if ( v0.ShapeType() == TopAbs_VERTEX ) {
02246 nbInserted += SMESH_Block::Insert( v0, vertIdVec[ 0 ], shapeMap);
02247 }
02248 if ( v1.ShapeType() == TopAbs_VERTEX ) {
02249 nbInserted += SMESH_Block::Insert( v1, vertIdVec[ 1 ], shapeMap);
02250 }
02251
02252
02253 SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ V1_EDGE ], vertIdVec);
02254 GetColumns(1, col1, col2 );
02255 node0 = col2->second.front();
02256 node1 = col2->second.back();
02257 v0 = myHelper->GetSubShapeByNode( node0, myHelper->GetMeshDS());
02258 v1 = myHelper->GetSubShapeByNode( node1, myHelper->GetMeshDS());
02259 if ( v0.ShapeType() == TopAbs_VERTEX ) {
02260 nbInserted += SMESH_Block::Insert( v0, vertIdVec[ 0 ], shapeMap);
02261 }
02262 if ( v1.ShapeType() == TopAbs_VERTEX ) {
02263 nbInserted += SMESH_Block::Insert( v1, vertIdVec[ 1 ], shapeMap);
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310 return nbInserted;
02311 }
02312
02313
02317
02318
02319 void StdMeshers_PrismAsBlock::TSideFace::dumpNodes(int nbNodes) const
02320 {
02321 #ifdef _DEBUG_
02322 cout << endl << "NODES OF FACE "; SMESH_Block::DumpShapeID( myID, cout ) << endl;
02323 THorizontalEdgeAdaptor* hSize0 = (THorizontalEdgeAdaptor*) HorizCurve(0);
02324 cout << "Horiz side 0: "; hSize0->dumpNodes(nbNodes); cout << endl;
02325 THorizontalEdgeAdaptor* hSize1 = (THorizontalEdgeAdaptor*) HorizCurve(1);
02326 cout << "Horiz side 1: "; hSize1->dumpNodes(nbNodes); cout << endl;
02327 TVerticalEdgeAdaptor* vSide0 = (TVerticalEdgeAdaptor*) VertiCurve(0);
02328 cout << "Verti side 0: "; vSide0->dumpNodes(nbNodes); cout << endl;
02329 TVerticalEdgeAdaptor* vSide1 = (TVerticalEdgeAdaptor*) VertiCurve(1);
02330 cout << "Verti side 1: "; vSide1->dumpNodes(nbNodes); cout << endl;
02331 delete hSize0; delete hSize1; delete vSide0; delete vSide1;
02332 #endif
02333 }
02334
02335
02341
02342
02343 StdMeshers_PrismAsBlock::TVerticalEdgeAdaptor::
02344 TVerticalEdgeAdaptor( const TParam2ColumnMap* columnsMap, const double parameter)
02345 {
02346 myNodeColumn = & getColumn( columnsMap, parameter )->second;
02347 }
02348
02349
02355
02356
02357 gp_Pnt StdMeshers_PrismAsBlock::TVerticalEdgeAdaptor::Value(const Standard_Real U) const
02358 {
02359 const SMDS_MeshNode* n1;
02360 const SMDS_MeshNode* n2;
02361 double r = getRAndNodes( myNodeColumn, U, n1, n2 );
02362 return gpXYZ(n1) * ( 1 - r ) + gpXYZ(n2) * r;
02363 }
02364
02365
02369
02370
02371 void StdMeshers_PrismAsBlock::TVerticalEdgeAdaptor::dumpNodes(int nbNodes) const
02372 {
02373 #ifdef _DEBUG_
02374 for ( int i = 0; i < nbNodes && i < myNodeColumn->size(); ++i )
02375 cout << (*myNodeColumn)[i]->GetID() << " ";
02376 if ( nbNodes < myNodeColumn->size() )
02377 cout << myNodeColumn->back()->GetID();
02378 #endif
02379 }
02380
02381
02387
02388
02389 gp_Pnt StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::Value(const Standard_Real U) const
02390 {
02391 return mySide->TSideFace::Value( U, myV );
02392 }
02393
02394
02398
02399
02400 void StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::dumpNodes(int nbNodes) const
02401 {
02402 #ifdef _DEBUG_
02403
02404 const TSideFace* side = mySide;
02405 double u = 0;
02406 if ( mySide->IsComplex() )
02407 side = mySide->GetComponent(0,u);
02408
02409 TParam2ColumnIt col, col2;
02410 TParam2ColumnMap* u2cols = side->GetColumns();
02411 side->GetColumns( u , col, col2 );
02412
02413 int j, i = myV ? mySide->ColumnHeight()-1 : 0;
02414
02415 const SMDS_MeshNode* n = 0;
02416 const SMDS_MeshNode* lastN
02417 = side->IsForward() ? u2cols->rbegin()->second[ i ] : u2cols->begin()->second[ i ];
02418 for ( j = 0; j < nbNodes && n != lastN; ++j )
02419 {
02420 n = col->second[ i ];
02421 cout << n->GetID() << " ";
02422 if ( side->IsForward() )
02423 ++col;
02424 else
02425 --col;
02426 }
02427
02428
02429 u = 1;
02430 if ( mySide->IsComplex() )
02431 side = mySide->GetComponent(1,u);
02432
02433 side->GetColumns( u , col, col2 );
02434 if ( n != col->second[ i ] )
02435 cout << col->second[ i ]->GetID();
02436 #endif
02437 }
02438
02444
02445
02446 gp_Pnt2d StdMeshers_PrismAsBlock::TPCurveOnHorFaceAdaptor::Value(const Standard_Real U) const
02447 {
02448 TParam2ColumnIt u_col1, u_col2;
02449 double r = mySide->GetColumns( U, u_col1, u_col2 );
02450 gp_XY uv1 = mySide->GetNodeUV( myFace, u_col1->second[ myZ ]);
02451 gp_XY uv2 = mySide->GetNodeUV( myFace, u_col2->second[ myZ ]);
02452 return uv1 * ( 1 - r ) + uv2 * r;
02453 }