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_Projection_2D.hxx"
00030
00031 #include "StdMeshers_ProjectionSource2D.hxx"
00032 #include "StdMeshers_ProjectionUtils.hxx"
00033 #include "StdMeshers_FaceSide.hxx"
00034
00035 #include "SMDS_EdgePosition.hxx"
00036 #include "SMDS_FacePosition.hxx"
00037 #include "SMESHDS_Hypothesis.hxx"
00038 #include "SMESHDS_SubMesh.hxx"
00039 #include "SMESH_Block.hxx"
00040 #include "SMESH_Comment.hxx"
00041 #include "SMESH_Gen.hxx"
00042 #include "SMESH_Mesh.hxx"
00043 #include "SMESH_MesherHelper.hxx"
00044 #include "SMESH_Pattern.hxx"
00045 #include "SMESH_subMesh.hxx"
00046 #include "SMESH_subMeshEventListener.hxx"
00047
00048 #include "utilities.h"
00049
00050 #include <BRep_Tool.hxx>
00051 #include <Bnd_B2d.hxx>
00052 #include <TopExp.hxx>
00053 #include <TopExp_Explorer.hxx>
00054 #include <TopTools_ListIteratorOfListOfShape.hxx>
00055 #include <TopoDS.hxx>
00056 #include <gp_Ax2.hxx>
00057 #include <gp_Ax3.hxx>
00058
00059
00060 using namespace std;
00061
00062 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
00063
00064 typedef StdMeshers_ProjectionUtils TAssocTool;
00065
00066
00067
00068
00069
00070
00071 StdMeshers_Projection_2D::StdMeshers_Projection_2D(int hypId, int studyId, SMESH_Gen* gen)
00072 :SMESH_2D_Algo(hypId, studyId, gen)
00073 {
00074 _name = "Projection_2D";
00075 _shapeType = (1 << TopAbs_FACE);
00076
00077 _compatibleHypothesis.push_back("ProjectionSource2D");
00078 _sourceHypo = 0;
00079 }
00080
00081
00085
00086
00087 StdMeshers_Projection_2D::~StdMeshers_Projection_2D()
00088 {}
00089
00090
00091
00092
00093
00094
00095 bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh& theMesh,
00096 const TopoDS_Shape& theShape,
00097 SMESH_Hypothesis::Hypothesis_Status& theStatus)
00098 {
00099 list <const SMESHDS_Hypothesis * >::const_iterator itl;
00100
00101 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(theMesh, theShape);
00102 if ( hyps.size() == 0 )
00103 {
00104 theStatus = HYP_MISSING;
00105 return false;
00106 }
00107
00108 if ( hyps.size() > 1 )
00109 {
00110 theStatus = HYP_ALREADY_EXIST;
00111 return false;
00112 }
00113
00114 const SMESHDS_Hypothesis *theHyp = hyps.front();
00115
00116 string hypName = theHyp->GetName();
00117
00118 theStatus = HYP_OK;
00119
00120 if (hypName == "ProjectionSource2D")
00121 {
00122 _sourceHypo = static_cast<const StdMeshers_ProjectionSource2D *>(theHyp);
00123
00124
00125
00126 SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
00127 SMESH_Mesh* tgtMesh = & theMesh;
00128 if ( !srcMesh )
00129 srcMesh = tgtMesh;
00130
00131
00132 if ( _sourceHypo->HasVertexAssociation() )
00133 {
00134
00135 TopoDS_Shape edge = TAssocTool::GetEdgeByVertices
00136 ( srcMesh, _sourceHypo->GetSourceVertex(1), _sourceHypo->GetSourceVertex(2) );
00137 if ( edge.IsNull() ||
00138 !SMESH_MesherHelper::IsSubShape( edge, srcMesh ) ||
00139 !SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() ))
00140 {
00141 theStatus = HYP_BAD_PARAMETER;
00142 SCRUTE((edge.IsNull()));
00143 SCRUTE((SMESH_MesherHelper::IsSubShape( edge, srcMesh )));
00144 SCRUTE((SMESH_MesherHelper::IsSubShape( edge, _sourceHypo->GetSourceFace() )));
00145 }
00146 else
00147 {
00148
00149 edge = TAssocTool::GetEdgeByVertices
00150 ( tgtMesh, _sourceHypo->GetTargetVertex(1), _sourceHypo->GetTargetVertex(2) );
00151 if ( edge.IsNull() || !SMESH_MesherHelper::IsSubShape( edge, tgtMesh ))
00152 {
00153 theStatus = HYP_BAD_PARAMETER;
00154 SCRUTE((edge.IsNull()));
00155 SCRUTE((SMESH_MesherHelper::IsSubShape( edge, tgtMesh )));
00156 }
00157
00158 else if ( !_sourceHypo->IsCompoundSource() &&
00159 !SMESH_MesherHelper::IsSubShape( edge, theShape ))
00160 {
00161 theStatus = HYP_BAD_PARAMETER;
00162 SCRUTE((SMESH_MesherHelper::IsSubShape( edge, theShape )));
00163 }
00164 }
00165 }
00166
00167 if ( !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh ) ||
00168 ( srcMesh == tgtMesh && theShape == _sourceHypo->GetSourceFace() ))
00169 {
00170 theStatus = HYP_BAD_PARAMETER;
00171 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh )));
00172 SCRUTE((srcMesh == tgtMesh));
00173 SCRUTE(( theShape == _sourceHypo->GetSourceFace() ));
00174 }
00175 }
00176 else
00177 {
00178 theStatus = HYP_INCOMPATIBLE;
00179 }
00180 return ( theStatus == HYP_OK );
00181 }
00182
00183 namespace {
00184
00185
00191
00192
00193 bool isOldNode( const SMDS_MeshNode* node )
00194 {
00195
00196
00197 SMDS_ElemIteratorPtr invEdge = node->GetInverseElementIterator(SMDSAbs_Edge);
00198 bool isOld = invEdge->more();
00199 return isOld;
00200 }
00201
00202
00208
00209
00210 class MeshCleaner {
00211 SMESH_subMesh* sm;
00212 public:
00213 MeshCleaner( SMESH_subMesh* faceSubMesh ): sm(faceSubMesh) {}
00214 ~MeshCleaner() { Clean(sm); }
00215 void Release() { sm = 0; }
00216 static void Clean( SMESH_subMesh* sm, bool withSub=true )
00217 {
00218 if ( !sm ) return;
00219
00220
00221
00222
00223 SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
00224 SMESHDS_Mesh* mesh = sm->GetFather()->GetMeshDS();
00225 while ( nIt->more() ) {
00226 const SMDS_MeshNode* node = nIt->next();
00227 if ( !isOldNode( node ) )
00228 mesh->RemoveNode( node );
00229 }
00230
00231
00232
00233 if ( !withSub ) return;
00234 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
00235 while ( smIt->more() )
00236 Clean( smIt->next(), false );
00237
00238 }
00239 };
00240
00241
00250
00251
00252 bool getBoundaryNodes ( SMESH_subMesh* sm,
00253 const TopoDS_Face& face,
00254 map< double, const SMDS_MeshNode* > & u2nodes,
00255 set< const SMDS_MeshNode* > & seamNodes)
00256 {
00257 u2nodes.clear();
00258 seamNodes.clear();
00259 if ( !sm || !sm->GetSubMeshDS() )
00260 RETURN_BAD_RESULT("Null submesh");
00261
00262 SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
00263 switch ( sm->GetSubShape().ShapeType() ) {
00264
00265 case TopAbs_VERTEX: {
00266 while ( nIt->more() ) {
00267 const SMDS_MeshNode* node = nIt->next();
00268 if ( isOldNode( node ) ) continue;
00269 u2nodes.insert( make_pair( 0., node ));
00270 seamNodes.insert( node );
00271 return true;
00272 }
00273 break;
00274 }
00275 case TopAbs_EDGE: {
00276
00277
00278 const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
00279 if ( subSM.size() != 2 )
00280 RETURN_BAD_RESULT("there must be 2 submeshes of sub-vertices"
00281 " but we have " << subSM.size());
00282 SMESH_subMesh* smV1 = subSM.begin()->second;
00283 SMESH_subMesh* smV2 = subSM.rbegin()->second;
00284 if ( !smV1->IsMeshComputed() || !smV2->IsMeshComputed() )
00285 RETURN_BAD_RESULT("Empty vertex submeshes");
00286
00287
00288 nIt = smV1->GetSubMeshDS()->GetNodes();
00289 const SMDS_MeshNode* nV1 = 0;
00290 while ( nIt->more() && !nV1 ) {
00291 const SMDS_MeshNode* node = nIt->next();
00292 if ( !isOldNode( node ) ) nV1 = node;
00293 }
00294 if ( !nV1 )
00295 RETURN_BAD_RESULT("No new node found on V1");
00296
00297
00298 const SMDS_MeshNode* nE = 0;
00299 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
00300 SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face);
00301 while ( vElems->more() && !nE ) {
00302 const SMDS_MeshElement* elem = vElems->next();
00303 int nbNodes = elem->NbNodes();
00304 if ( elem->IsQuadratic() )
00305 nbNodes /= 2;
00306 int iV1 = elem->GetNodeIndex( nV1 );
00307
00308 int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
00309 if ( smDS->Contains( elem->GetNode( iE ) ))
00310 nE = elem->GetNode( iE );
00311 if ( !nE ) {
00312
00313 iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
00314 if ( smDS->Contains( elem->GetNode( iE )))
00315 nE = elem->GetNode( iE );
00316 }
00317 if ( nE && elem->IsQuadratic() ) {
00318 if ( Abs( iV1 - iE ) == 1 )
00319 nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
00320 else
00321 nE = elem->GetNode( elem->NbNodes() - 1 );
00322 }
00323 }
00324 if ( !nE )
00325 RETURN_BAD_RESULT("new node on edge not found");
00326
00327
00328 list< const SMDS_MeshNode* > bordNodes;
00329 list< const SMDS_MeshElement* > bordFaces;
00330 if ( !SMESH_MeshEditor::FindFreeBorder (nV1, nE, nV1, bordNodes, bordFaces ))
00331 RETURN_BAD_RESULT("free border of a face not found by nodes " <<
00332 nV1->GetID() << " " << nE->GetID() );
00333
00334
00335 SMESHDS_SubMesh* v2smDS = smV2->GetSubMeshDS();
00336 list< const SMDS_MeshNode* >::iterator bordIt = bordNodes.begin();
00337 bordIt++;
00338 for ( ; bordIt != bordNodes.end(); ++bordIt ) {
00339 const SMDS_MeshNode* node = *bordIt;
00340 if ( v2smDS->Contains( node ))
00341 break;
00342 if ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_EDGE )
00343 RETURN_BAD_RESULT("Bad node position type: node " << node->GetID() <<
00344 " pos type " << node->GetPosition()->GetTypeOfPosition());
00345 const SMDS_EdgePosition* pos =
00346 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00347 u2nodes.insert( make_pair( pos->GetUParameter(), node ));
00348 seamNodes.insert( node );
00349 }
00350 if ( u2nodes.size() != seamNodes.size() )
00351 RETURN_BAD_RESULT("Bad node params on edge " << sm->GetId() <<
00352 ", " << u2nodes.size() << " != " << seamNodes.size() );
00353 return true;
00354 }
00355 default:;
00356 }
00357 RETURN_BAD_RESULT ("Unexpected submesh type");
00358
00359 }
00360
00361
00366
00367
00368 bool projectPartner(const TopoDS_Face& tgtFace,
00369 const TopoDS_Face& srcFace,
00370 SMESH_Mesh * tgtMesh,
00371 SMESH_Mesh * srcMesh,
00372 const TAssocTool::TShapeShapeMap& shape2ShapeMap)
00373 {
00374 MESSAGE("projectPartner");
00375 const double tol = 1.e-7*srcMesh->GetMeshDS()->getMaxDim();
00376
00377 gp_Trsf trsf;
00378 if ( tgtFace.IsPartner( srcFace ))
00379 {
00380 gp_Trsf srcTrsf = srcFace.Location();
00381 gp_Trsf tgtTrsf = tgtFace.Location();
00382 trsf = srcTrsf.Inverted() * tgtTrsf;
00383 }
00384 else
00385 {
00386
00387
00388
00389 vector<gp_Pnt> srcPP, tgtPP;
00390 SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
00391 SMESH_subMeshIteratorPtr smIt = srcSM->getDependsOnIterator(false,false);
00392 srcSM = smIt->next();
00393 while ( smIt->more() && srcPP.size() < 3 )
00394 {
00395 srcSM = smIt->next();
00396 SMESHDS_SubMesh* srcSmds = srcSM->GetSubMeshDS();
00397 if ( !srcSmds ) continue;
00398 SMDS_NodeIteratorPtr nIt = srcSmds->GetNodes();
00399 while ( nIt->more() )
00400 {
00401 SMESH_TNodeXYZ p ( nIt->next());
00402 bool pOK = false;
00403 switch ( srcPP.size() )
00404 {
00405 case 0: pOK = true; break;
00406
00407 case 1: pOK = ( srcPP[0].SquareDistance( p ) > 10*tol ); break;
00408
00409 case 2:
00410 {
00411 gp_Vec p0p1( srcPP[0], srcPP[1] ), p0p( srcPP[0], p );
00412
00413 pOK = !p0p1.IsParallel( p0p, 3.14/20 );
00414 break;
00415 }
00416 }
00417 if ( !pOK )
00418 continue;
00419
00420
00421 pOK = false;
00422 gp_Pnt tgtP;
00423 const TopoDS_Shape& tgtShape = shape2ShapeMap( srcSM->GetSubShape() );
00424 if ( tgtShape.ShapeType() == TopAbs_VERTEX )
00425 {
00426 tgtP = BRep_Tool::Pnt( TopoDS::Vertex( tgtShape ));
00427 pOK = true;
00428
00429 }
00430 else if ( tgtPP.size() > 0 )
00431 {
00432 if ( SMESHDS_SubMesh* tgtSmds = tgtMesh->GetMeshDS()->MeshElements( tgtShape ))
00433 {
00434 double srcDist = srcPP[0].Distance( p );
00435 double eTol = BRep_Tool::Tolerance( TopoDS::Edge( tgtShape ));
00436 if (eTol < tol) eTol = tol;
00437 SMDS_NodeIteratorPtr nItT = tgtSmds->GetNodes();
00438 while ( nItT->more() && !pOK )
00439 {
00440 const SMDS_MeshNode* n = nItT->next();
00441 tgtP = SMESH_TNodeXYZ( n );
00442 pOK = ( fabs( srcDist - tgtPP[0].Distance( tgtP )) < 2*eTol );
00443
00444 }
00445 }
00446 }
00447 if ( !pOK )
00448 continue;
00449
00450 srcPP.push_back( p );
00451 tgtPP.push_back( tgtP );
00452 }
00453 }
00454 if ( srcPP.size() != 3 )
00455 return false;
00456
00457
00458 gp_Trsf fromTgtCS, toSrcCS;
00459 gp_Ax2 srcCS( srcPP[0], gp_Vec( srcPP[0], srcPP[1] ), gp_Vec( srcPP[0], srcPP[2]));
00460 gp_Ax2 tgtCS( tgtPP[0], gp_Vec( tgtPP[0], tgtPP[1] ), gp_Vec( tgtPP[0], tgtPP[2]));
00461 toSrcCS .SetTransformation( gp_Ax3( srcCS ));
00462 fromTgtCS.SetTransformation( gp_Ax3( tgtCS ));
00463 fromTgtCS.Invert();
00464
00465 trsf = fromTgtCS * toSrcCS;
00466 }
00467
00468
00469
00470 map<const SMDS_MeshNode* , const SMDS_MeshNode*> src2tgtNodes;
00471 map<const SMDS_MeshNode* , const SMDS_MeshNode*>::iterator srcN_tgtN;
00472
00473 for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() )
00474 {
00475 const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current() );
00476
00477 map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
00478 if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(),
00479 TopoDS::Edge( srcEdge.Current() ),
00480 true,
00481 srcNodes )
00482 ||
00483 !SMESH_Algo::GetSortedNodesOnEdge( tgtMesh->GetMeshDS(),
00484 TopoDS::Edge( tgtEdge ),
00485 true,
00486 tgtNodes )
00487 ||
00488 srcNodes.size() != tgtNodes.size())
00489 return false;
00490
00491 if ( !tgtEdge.IsPartner( srcEdge.Current() ))
00492 {
00493
00494 gp_Pnt p0S = SMESH_TNodeXYZ( (srcNodes.begin()) ->second);
00495 gp_Pnt p1S = SMESH_TNodeXYZ( (srcNodes.rbegin()) ->second);
00496 gp_Pnt p2S = SMESH_TNodeXYZ( (++srcNodes.begin())->second);
00497
00498 gp_Pnt p0T = SMESH_TNodeXYZ( (tgtNodes.begin()) ->second);
00499 gp_Pnt p1T = SMESH_TNodeXYZ( (tgtNodes.rbegin()) ->second);
00500 gp_Pnt p2T = SMESH_TNodeXYZ( (++tgtNodes.begin())->second);
00501
00502
00503 if ( p0T.SquareDistance( p0S.Transformed( trsf )) > tol ||
00504 p1T.SquareDistance( p1S.Transformed( trsf )) > tol ||
00505 p2T.SquareDistance( p2S.Transformed( trsf )) > tol )
00506 {
00507
00508
00509
00510
00511 return false;
00512 }
00513 }
00514
00515 map< double, const SMDS_MeshNode* >::iterator u_tn = tgtNodes.begin();
00516 map< double, const SMDS_MeshNode* >::iterator u_sn = srcNodes.begin();
00517 for ( ; u_tn != tgtNodes.end(); ++u_tn, ++u_sn)
00518 src2tgtNodes.insert( make_pair( u_sn->second, u_tn->second ));
00519 }
00520
00521
00522
00523
00524 SMESH_MesherHelper helper( *tgtMesh );
00525 helper.SetSubShape( tgtFace );
00526 helper.IsQuadraticSubMesh( tgtFace );
00527 helper.SetElementsOnShape( true );
00528
00529 SMESH_MesherHelper srcHelper( *srcMesh );
00530 srcHelper.SetSubShape( srcFace );
00531
00532 const SMDS_MeshNode* nullNode = 0;
00533
00534
00535 int tri1 = 1, tri2 = 2, quad1 = 1, quad3 = 3;
00536 if ( trsf.Form() != gp_Identity )
00537 std::swap( tri1, tri2 ), std::swap( quad1, quad3 );
00538
00539 SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
00540 SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
00541 vector< const SMDS_MeshNode* > tgtNodes;
00542 while ( elemIt->more() )
00543 {
00544 const SMDS_MeshElement* elem = elemIt->next();
00545 const int nbN = elem->NbCornerNodes();
00546 tgtNodes.resize( nbN );
00547 for ( int i = 0; i < nbN; ++i )
00548 {
00549 const SMDS_MeshNode* srcNode = elem->GetNode(i);
00550 srcN_tgtN = src2tgtNodes.insert( make_pair( srcNode, nullNode )).first;
00551 if ( srcN_tgtN->second == nullNode )
00552 {
00553
00554 gp_Pnt tgtP = gp_Pnt(srcNode->X(),srcNode->Y(),srcNode->Z()).Transformed( trsf );
00555 SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
00556 srcN_tgtN->second = n;
00557
00558 gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
00559 elem->GetNode( helper.WrapIndex(i+1,nbN)));
00560 n->SetPosition( new SMDS_FacePosition( srcUV.X(), srcUV.Y() ));
00561 }
00562 tgtNodes[i] = srcN_tgtN->second;
00563 }
00564
00565 switch ( nbN )
00566 {
00567 case 3: helper.AddFace(tgtNodes[0], tgtNodes[tri1], tgtNodes[tri2]); break;
00568 case 4: helper.AddFace(tgtNodes[0], tgtNodes[quad1], tgtNodes[2], tgtNodes[quad3]); break;
00569 }
00570 }
00571 return true;
00572
00573 }
00574
00575
00579
00580
00581 bool projectBy2DSimilarity(const TopoDS_Face& tgtFace,
00582 const TopoDS_Face& srcFace,
00583 SMESH_Mesh * tgtMesh,
00584 SMESH_Mesh * srcMesh,
00585 const TAssocTool::TShapeShapeMap& shape2ShapeMap)
00586 {
00587
00588
00589
00590 TError err;
00591 TSideVector srcWires =
00592 StdMeshers_FaceSide::GetFaceWires( srcFace, *srcMesh,false, err);
00593 if ( err && !err->IsOK() )
00594 return false;
00595
00596
00597 TSideVector tgtWires( srcWires.size() );
00598 for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
00599 {
00600 list< TopoDS_Edge > tgtEdges;
00601 StdMeshers_FaceSidePtr srcWire = srcWires[iW];
00602 for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
00603 tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ))));
00604
00605 tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
00606 true,
00607 false));
00608 if ( srcWires[iW]->GetUVPtStruct().size() !=
00609 tgtWires[iW]->GetUVPtStruct().size())
00610 return false;
00611 }
00612
00613
00614
00615 gp_Trsf2d trsf;
00616 {
00617
00618 const vector<UVPtStruct>& srcUVs = srcWires[0]->GetUVPtStruct();
00619 const vector<UVPtStruct>& tgtUVs = tgtWires[0]->GetUVPtStruct();
00620
00621
00622 gp_XY srcP0( srcUVs[0].u, srcUVs[0].v );
00623 gp_XY srcP1( srcUVs[1].u, srcUVs[1].v );
00624 gp_XY tgtP0( tgtUVs[0].u, tgtUVs[0].v );
00625 gp_XY tgtP1( tgtUVs[1].u, tgtUVs[1].v );
00626
00627
00628 gp_Trsf2d fromTgtCS, toSrcCS;
00629 gp_Ax2d srcCS( srcP0, gp_Vec2d( srcP0, srcP1 ));
00630 gp_Ax2d tgtCS( tgtP0, gp_Vec2d( tgtP0, tgtP1 ));
00631 toSrcCS .SetTransformation( srcCS );
00632 fromTgtCS.SetTransformation( tgtCS );
00633 fromTgtCS.Invert();
00634
00635 trsf = fromTgtCS * toSrcCS;
00636
00637
00638 const double tol = 1e-5 * gp_Vec2d( srcP0, srcP1 ).Magnitude();
00639 const int nbCheckPnt = Min( 10, srcUVs.size()-2 );
00640 const int dP = ( srcUVs.size()-2 ) / nbCheckPnt;
00641 for ( unsigned iP = 2; iP < srcUVs.size(); iP += dP )
00642 {
00643 gp_Pnt2d srcUV( srcUVs[iP].u, srcUVs[iP].v );
00644 gp_Pnt2d tgtUV( tgtUVs[iP].u, tgtUVs[iP].v );
00645 gp_Pnt2d tgtUV2 = srcUV.Transformed( trsf );
00646 if ( tgtUV.Distance( tgtUV2 ) > tol )
00647 return false;
00648 }
00649 }
00650
00651
00652
00653 typedef map<const SMDS_MeshNode* , const SMDS_MeshNode*, TIDCompare> TN2NMap;
00654 TN2NMap src2tgtNodes;
00655 TN2NMap::iterator srcN_tgtN;
00656
00657
00658 for ( unsigned iW = 0; iW < srcWires.size(); ++iW )
00659 {
00660 const vector<UVPtStruct>& srcUVs = srcWires[iW]->GetUVPtStruct();
00661 const vector<UVPtStruct>& tgtUVs = tgtWires[iW]->GetUVPtStruct();
00662 for ( unsigned i = 0; i < srcUVs.size(); ++i )
00663 src2tgtNodes.insert( make_pair( srcUVs[i].node, tgtUVs[i].node ));
00664 }
00665
00666
00667 SMESH_MesherHelper helper( *tgtMesh );
00668 helper.SetSubShape( tgtFace );
00669 helper.IsQuadraticSubMesh( tgtFace );
00670 helper.SetElementsOnShape( true );
00671 Handle(Geom_Surface) tgtSurface = BRep_Tool::Surface( tgtFace );
00672
00673 SMESH_MesherHelper srcHelper( *srcMesh );
00674 srcHelper.SetSubShape( srcFace );
00675
00676 const SMDS_MeshNode* nullNode = 0;
00677
00678 SMESHDS_SubMesh* srcSubDS = srcMesh->GetMeshDS()->MeshElements( srcFace );
00679 SMDS_ElemIteratorPtr elemIt = srcSubDS->GetElements();
00680 vector< const SMDS_MeshNode* > tgtNodes;
00681 bool uvOK;
00682 while ( elemIt->more() )
00683 {
00684 const SMDS_MeshElement* elem = elemIt->next();
00685 const int nbN = elem->NbCornerNodes();
00686 tgtNodes.resize( nbN );
00687 for ( int i = 0; i < nbN; ++i )
00688 {
00689 const SMDS_MeshNode* srcNode = elem->GetNode(i);
00690 srcN_tgtN = src2tgtNodes.insert( make_pair( srcNode, nullNode )).first;
00691 if ( srcN_tgtN->second == nullNode )
00692 {
00693
00694 gp_Pnt2d srcUV = srcHelper.GetNodeUV( srcFace, srcNode,
00695 elem->GetNode( helper.WrapIndex(i+1,nbN)), &uvOK);
00696
00697 gp_Pnt2d tgtUV = srcUV.Transformed( trsf );
00698 gp_Pnt tgtP = tgtSurface->Value( tgtUV.X(), tgtUV.Y() );
00699 SMDS_MeshNode* n = helper.AddNode( tgtP.X(), tgtP.Y(), tgtP.Z() );
00700 n->SetPosition( new SMDS_FacePosition( tgtUV.X(), tgtUV.Y() ));
00701 srcN_tgtN->second = n;
00702 }
00703 tgtNodes[i] = srcN_tgtN->second;
00704 }
00705
00706 switch ( nbN )
00707 {
00708 case 3: helper.AddFace(tgtNodes[0], tgtNodes[2], tgtNodes[1]); break;
00709 case 4: helper.AddFace(tgtNodes[0], tgtNodes[3], tgtNodes[2], tgtNodes[1]); break;
00710 }
00711 }
00712 return true;
00713
00714 }
00715
00716
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
00726 {
00727 MESSAGE("Projection_2D Compute");
00728 if ( !_sourceHypo )
00729 return false;
00730
00731 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
00732 SMESH_Mesh * tgtMesh = & theMesh;
00733 if ( !srcMesh )
00734 srcMesh = tgtMesh;
00735
00736 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00737
00738
00739
00740
00741
00742 TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
00743 TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
00744
00745 TAssocTool::TShapeShapeMap shape2ShapeMap;
00746 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
00747 if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
00748 shape2ShapeMap) ||
00749 !shape2ShapeMap.IsBound( tgtFace ))
00750 return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
00751
00752 TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD));
00753
00754
00755
00756
00757
00758 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
00759 SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace );
00760
00761 if ( tgtMesh == srcMesh ) {
00762 if ( !TAssocTool::MakeComputed( srcSubMesh ))
00763 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00764 }
00765 else {
00766 if ( !srcSubMesh->IsMeshComputed() )
00767 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00768 }
00769
00770
00771 if ( projectPartner( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap ))
00772 return true;
00773
00774 if ( projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap ))
00775 return true;
00776
00777
00778
00779
00780
00781 SMESH_MesherHelper helper( theMesh );
00782 helper.SetSubShape( tgtFace );
00783
00784
00785 Bnd_B2d uvBox;
00786 SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
00787 int nbFaceNodes = 0;
00788 for ( ; nbFaceNodes < 3 && faceIt->more(); ) {
00789 const SMDS_MeshElement* face = faceIt->next();
00790 SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
00791 while ( nodeIt->more() ) {
00792 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
00793 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
00794 nbFaceNodes++;
00795 uvBox.Add( helper.GetNodeUV( srcFace, node ));
00796 }
00797 }
00798 }
00799 const bool toProjectNodes =
00800 ( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN ));
00801
00802
00803 SMESH_Pattern mapper;
00804 mapper.Load( srcMesh, srcFace, toProjectNodes );
00805 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
00806 return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
00807
00808
00809
00810
00811 TopoDS_Vertex srcV1 = TopoDS::Vertex( mapper.GetSubShape( 1 ));
00812 if ( srcV1.IsNull() )
00813 RETURN_BAD_RESULT("Mesh is not bound to the face");
00814 if ( !shape2ShapeMap.IsBound( srcV1 ))
00815 RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() );
00816 TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1 ));
00817
00818 if ( !SMESH_MesherHelper::IsSubShape( srcV1, srcFace ))
00819 RETURN_BAD_RESULT("Wrong srcV1 " << srcV1.TShape().operator->());
00820 if ( !SMESH_MesherHelper::IsSubShape( tgtV1, tgtFace ))
00821 RETURN_BAD_RESULT("Wrong tgtV1 " << tgtV1.TShape().operator->());
00822
00823
00824 bool reverse = false;
00825 list< TopoDS_Edge > tgtEdges, srcEdges;
00826 list< int > nbEdgesInWires;
00827 SMESH_Block::GetOrderedEdges( tgtFace, tgtV1, tgtEdges, nbEdgesInWires);
00828 SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires);
00829 if ( nbEdgesInWires.front() > 1 )
00830 {
00831 TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
00832 TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
00833 reverse = ( ! srcE1.IsSame( srcE1bis ));
00834 }
00835 else if ( nbEdgesInWires.front() == 1 )
00836 {
00837
00838
00839 }
00840 else
00841 {
00842 RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
00843 }
00844
00845
00846
00847
00848
00849
00850
00851 mapper.Apply( tgtFace, tgtV1, reverse );
00852 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
00853 return error("Can't apply source mesh pattern to the face");
00854
00855
00856
00857 const bool toCreatePolygons = false, toCreatePolyedrs = false;
00858 mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
00859 if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
00860 return error("Can't make mesh by source mesh pattern");
00861
00862
00863
00864 MeshCleaner cleaner( tgtSubMesh );
00865
00866
00867
00868
00869
00870
00871 SMESH_MeshEditor editor( tgtMesh );
00872 SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
00873
00874
00875
00876
00877 SMESH_subMeshIteratorPtr smIt = tgtSubMesh->getDependsOnIterator(false,false);
00878 while ( smIt->more() )
00879 {
00880 SMESH_subMesh* sm = smIt->next();
00881 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
00882
00883
00884
00885 bool isSeam = helper.IsRealSeam( sm->GetId() );
00886
00887 enum { NEW_NODES = 0, OLD_NODES };
00888 map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
00889 map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
00890 set< const SMDS_MeshNode* > seamNodes;
00891
00892
00893 if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
00894 RETURN_BAD_RESULT("getBoundaryNodes() failed");
00895
00896 SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
00897 while ( nIt->more() )
00898 {
00899 const SMDS_MeshNode* node = nIt->next();
00900 bool isOld = isOldNode( node );
00901
00902 if ( !isOld && isSeam ) {
00903 if ( seamNodes.find( node ) != seamNodes.end())
00904 continue;
00905 }
00906
00907
00908 map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES];
00909 switch ( node->GetPosition()->GetTypeOfPosition() )
00910 {
00911 case SMDS_TOP_VERTEX: {
00912 pos2nodes.insert( make_pair( 0, node ));
00913 break;
00914 }
00915 case SMDS_TOP_EDGE: {
00916 const SMDS_EdgePosition* pos =
00917 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00918 pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
00919 break;
00920 }
00921 default:
00922 RETURN_BAD_RESULT("Wrong node position type: "<<
00923 node->GetPosition()->GetTypeOfPosition());
00924 }
00925 }
00926 if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() )
00927 {
00928 if ( u2nodesMaps[ NEW_NODES ].size() == 0 &&
00929 sm->GetSubShape().ShapeType() == TopAbs_EDGE &&
00930 helper.IsDegenShape( sm->GetId() ) )
00931
00932
00933 continue;
00934
00935 RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<<
00936 u2nodesMaps[ OLD_NODES ].size() << " != " <<
00937 u2nodesMaps[ NEW_NODES ].size());
00938 }
00939 if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) {
00940 RETURN_BAD_RESULT("Different nb of old and seam nodes " <<
00941 u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
00942 }
00943
00944 u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
00945 u_newNode = u2nodesMaps[ NEW_NODES ].begin();
00946 newEnd = u2nodesMaps[ NEW_NODES ].end();
00947 u_newOnSeam = u2nodesOnSeam.begin();
00948 for ( ; u_newNode != newEnd; ++u_newNode, ++u_oldNode ) {
00949 groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
00950 groupsOfNodes.back().push_back( u_oldNode->second );
00951 groupsOfNodes.back().push_back( u_newNode->second );
00952 if ( isSeam )
00953 groupsOfNodes.back().push_back( (u_newOnSeam++)->second );
00954 }
00955 }
00956
00957
00958
00959 int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
00960 editor.MergeNodes( groupsOfNodes );
00961 int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
00962 if ( nbFaceBeforeMerge != nbFaceAtferMerge )
00963 return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
00964
00965
00966
00967
00968
00969 TopoDS_Face face = tgtFace;
00970 if ( !theMesh.IsMainShape( tgtFace ))
00971 {
00972
00973 TopoDS_Shape mainShape = meshDS->ShapeToMesh();
00974 switch ( mainShape.ShapeType() ) {
00975 case TopAbs_SHELL:
00976 case TopAbs_SOLID: break;
00977 default:
00978 TopTools_ListIteratorOfListOfShape ancestIt = theMesh.GetAncestors( face );
00979 for ( ; ancestIt.More(); ancestIt.Next() ) {
00980 TopAbs_ShapeEnum type = ancestIt.Value().ShapeType();
00981 if ( type == TopAbs_SOLID ) {
00982 mainShape = ancestIt.Value();
00983 break;
00984 } else if ( type == TopAbs_SHELL ) {
00985 mainShape = ancestIt.Value();
00986 }
00987 }
00988 }
00989
00990 TopExp_Explorer exp( mainShape, TopAbs_FACE );
00991 for ( ; exp.More(); exp.Next() ) {
00992 if ( tgtFace.IsSame( exp.Current() )) {
00993 face = TopoDS::Face( exp.Current() );
00994 break;
00995 }
00996 }
00997 }
00998
00999 if ( SMESH_Algo::IsReversedSubMesh( face, meshDS ))
01000 {
01001 SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();
01002 while ( eIt->more() ) {
01003 const SMDS_MeshElement* e = eIt->next();
01004 if ( e->GetType() == SMDSAbs_Face && !editor.Reorient( e ))
01005 RETURN_BAD_RESULT("Pb of SMESH_MeshEditor::Reorient()");
01006 }
01007 }
01008
01009 cleaner.Release();
01010
01011 return true;
01012 }
01013
01014
01015
01016
01017
01018
01019
01020 bool StdMeshers_Projection_2D::Evaluate(SMESH_Mesh& theMesh,
01021 const TopoDS_Shape& theShape,
01022 MapShapeNbElems& aResMap)
01023 {
01024 if ( !_sourceHypo )
01025 return false;
01026
01027 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
01028 SMESH_Mesh * tgtMesh = & theMesh;
01029 if ( !srcMesh )
01030 srcMesh = tgtMesh;
01031
01032
01033
01034
01035
01036 TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
01037 TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
01038
01039 TAssocTool::TShapeShapeMap shape2ShapeMap;
01040 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
01041 if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
01042 shape2ShapeMap) ||
01043 !shape2ShapeMap.IsBound( tgtFace ))
01044 return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
01045
01046 TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD));
01047
01048
01049
01050
01051
01052 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
01053
01054 if ( !srcSubMesh->IsMeshComputed() )
01055 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
01056
01057
01058 std::vector<int> aVec(SMDSEntity_Last);
01059 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
01060
01061 aVec[SMDSEntity_Node] = srcSubMesh->GetSubMeshDS()->NbNodes();
01062
01063
01064 SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
01065 while ( elemIt->more() ) {
01066 const SMDS_MeshElement* E = elemIt->next();
01067 if( E->NbNodes()==3 ) {
01068 aVec[SMDSEntity_Triangle]++;
01069 }
01070 else if( E->NbNodes()==4 ) {
01071 aVec[SMDSEntity_Quadrangle]++;
01072 }
01073 else if( E->NbNodes()==6 && E->IsQuadratic() ) {
01074 aVec[SMDSEntity_Quad_Triangle]++;
01075 }
01076 else if( E->NbNodes()==8 && E->IsQuadratic() ) {
01077 aVec[SMDSEntity_Quad_Quadrangle]++;
01078 }
01079 else {
01080 aVec[SMDSEntity_Polygon]++;
01081 }
01082 }
01083
01084 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01085 aResMap.insert(std::make_pair(sm,aVec));
01086
01087 return true;
01088 }
01089
01090
01091
01101
01102
01103 void StdMeshers_Projection_2D::SetEventListener(SMESH_subMesh* subMesh)
01104 {
01105 TAssocTool::SetEventListener( subMesh,
01106 _sourceHypo->GetSourceFace(),
01107 _sourceHypo->GetSourceMesh() );
01108 }