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 #include "SMESH_Pattern.hxx"
00028
00029 #include <BRepAdaptor_Curve.hxx>
00030 #include <BRepTools.hxx>
00031 #include <BRepTools_WireExplorer.hxx>
00032 #include <BRep_Tool.hxx>
00033 #include <Bnd_Box.hxx>
00034 #include <Bnd_Box2d.hxx>
00035 #include <ElSLib.hxx>
00036 #include <Extrema_ExtPC.hxx>
00037 #include <Extrema_GenExtPS.hxx>
00038 #include <Extrema_POnSurf.hxx>
00039 #include <Geom2d_Curve.hxx>
00040 #include <GeomAdaptor_Surface.hxx>
00041 #include <Geom_Curve.hxx>
00042 #include <Geom_Surface.hxx>
00043 #include <Precision.hxx>
00044 #include <TopAbs_ShapeEnum.hxx>
00045 #include <TopExp.hxx>
00046 #include <TopExp_Explorer.hxx>
00047 #include <TopLoc_Location.hxx>
00048 #include <TopTools_ListIteratorOfListOfShape.hxx>
00049 #include <TopoDS.hxx>
00050 #include <TopoDS_Edge.hxx>
00051 #include <TopoDS_Face.hxx>
00052 #include <TopoDS_Iterator.hxx>
00053 #include <TopoDS_Shell.hxx>
00054 #include <TopoDS_Vertex.hxx>
00055 #include <TopoDS_Wire.hxx>
00056 #include <gp_Ax2.hxx>
00057 #include <gp_Lin2d.hxx>
00058 #include <gp_Pnt2d.hxx>
00059 #include <gp_Trsf.hxx>
00060 #include <gp_XY.hxx>
00061 #include <gp_XYZ.hxx>
00062
00063 #include "SMDS_EdgePosition.hxx"
00064 #include "SMDS_FacePosition.hxx"
00065 #include "SMDS_MeshElement.hxx"
00066 #include "SMDS_MeshFace.hxx"
00067 #include "SMDS_MeshNode.hxx"
00068 #include "SMDS_VolumeTool.hxx"
00069 #include "SMESHDS_Group.hxx"
00070 #include "SMESHDS_Mesh.hxx"
00071 #include "SMESHDS_SubMesh.hxx"
00072 #include "SMESH_Block.hxx"
00073 #include "SMESH_Mesh.hxx"
00074 #include "SMESH_MesherHelper.hxx"
00075 #include "SMESH_subMesh.hxx"
00076
00077 #include <Basics_Utils.hxx>
00078 #include "utilities.h"
00079
00080 using namespace std;
00081
00082 typedef map< const SMDS_MeshElement*, int > TNodePointIDMap;
00083
00084 #define smdsNode( elem ) static_cast<const SMDS_MeshNode*>( elem )
00085
00086
00087
00088
00089
00090
00091 SMESH_Pattern::SMESH_Pattern ()
00092 {
00093 }
00094
00095
00096
00097
00098
00099 static inline int getInt( const char * theSring )
00100 {
00101 if ( *theSring < '0' || *theSring > '9' )
00102 return -1;
00103
00104 char *ptr;
00105 int val = strtol( theSring, &ptr, 10 );
00106 if ( ptr == theSring ||
00107
00108 (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
00109 return -1;
00110
00111 return val;
00112 }
00113
00114
00115
00116
00117
00118
00119 static inline double getDouble( const char * theSring )
00120 {
00121 char *ptr;
00122 return strtod( theSring, &ptr );
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 static int readLine (list <const char*> & theFields,
00132 const char* & theLineBeg,
00133 const bool theClearFields )
00134 {
00135 if ( theClearFields )
00136 theFields.clear();
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 int nbRead = 0;
00155 bool stopReading = false;
00156 do {
00157 bool goOn = true;
00158 bool isNumber = false;
00159 switch ( *theLineBeg )
00160 {
00161 case ' ':
00162 case '\t':
00163 case 13:
00164 break;
00165
00166 case '\n':
00167 stopReading = ( nbRead > 0 );
00168 break;
00169
00170 case '!':
00171 do theLineBeg++;
00172 while ( *theLineBeg != '\n' && *theLineBeg != '\0' );
00173 goOn = false;
00174 break;
00175
00176 case '\0':
00177 return nbRead;
00178
00179 case '-':
00180 case '+':
00181 case '.':
00182 isNumber = true;
00183 default:
00184 isNumber = isNumber || ( *theLineBeg >= '0' && *theLineBeg <= '9' );
00185 if ( isNumber ) {
00186 theFields.push_back( theLineBeg );
00187 nbRead++;
00188 do theLineBeg++;
00189 while (*theLineBeg != ' ' &&
00190 *theLineBeg != '\n' &&
00191 *theLineBeg != '\0');
00192 goOn = false;
00193 }
00194 else
00195 return 0;
00196 }
00197
00198 if ( goOn )
00199 theLineBeg++;
00200
00201 } while ( !stopReading );
00202
00203 return nbRead;
00204 }
00205
00206
00207
00208
00209
00210
00211 bool SMESH_Pattern::Load (const char* theFileContents)
00212 {
00213 MESSAGE("Load( file ) ");
00214
00215 Kernel_Utils::Localizer loc;
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 Clear();
00230
00231 const char* lineBeg = theFileContents;
00232 list <const char*> fields;
00233 const bool clearFields = true;
00234
00235
00236
00237 if ( readLine( fields, lineBeg, clearFields ) != 1 ) {
00238 MESSAGE("Error reading NB_POINTS");
00239 return setErrorCode( ERR_READ_NB_POINTS );
00240 }
00241 int nbPoints = getInt( fields.front() );
00242
00243
00244
00245
00246 int dim = readLine( fields, lineBeg, clearFields );
00247 if ( dim == 2 )
00248 myIs2D = true;
00249 else if ( dim == 3 )
00250 myIs2D = false;
00251 else {
00252 MESSAGE("Error reading points: wrong nb of coordinates");
00253 return setErrorCode( ERR_READ_POINT_COORDS );
00254 }
00255 if ( nbPoints <= dim ) {
00256 MESSAGE(" Too few points ");
00257 return setErrorCode( ERR_READ_TOO_FEW_POINTS );
00258 }
00259
00260
00261 int iPoint;
00262 for ( iPoint = 1; iPoint < nbPoints; iPoint++ )
00263 if ( readLine( fields, lineBeg, !clearFields ) != dim ) {
00264 MESSAGE("Error reading points : wrong nb of coordinates ");
00265 return setErrorCode( ERR_READ_POINT_COORDS );
00266 }
00267
00268 myPoints.resize( nbPoints );
00269 list <const char*>::iterator fIt = fields.begin();
00270 for ( iPoint = 0; iPoint < nbPoints; iPoint++ )
00271 {
00272 TPoint & p = myPoints[ iPoint ];
00273 for ( int iCoord = 1; iCoord <= dim; iCoord++, fIt++ )
00274 {
00275 double coord = getDouble( *fIt );
00276 if ( !myIs2D && ( coord < 0.0 || coord > 1.0 )) {
00277 MESSAGE("Error reading 3D points, value should be in [0,1]: " << coord);
00278 Clear();
00279 return setErrorCode( ERR_READ_3D_COORD );
00280 }
00281 p.myInitXYZ.SetCoord( iCoord, coord );
00282 if ( myIs2D )
00283 p.myInitUV.SetCoord( iCoord, coord );
00284 }
00285 }
00286
00287
00288 if ( myIs2D )
00289 {
00290 if ( readLine( fields, lineBeg, clearFields ) == 0 ) {
00291 MESSAGE("Error: missing key-points");
00292 Clear();
00293 return setErrorCode( ERR_READ_NO_KEYPOINT );
00294 }
00295 set<int> idSet;
00296 for ( fIt = fields.begin(); fIt != fields.end(); fIt++ )
00297 {
00298 int pointIndex = getInt( *fIt );
00299 if ( pointIndex >= nbPoints || pointIndex < 0 ) {
00300 MESSAGE("Error: invalid point index " << pointIndex );
00301 Clear();
00302 return setErrorCode( ERR_READ_BAD_INDEX );
00303 }
00304 if ( idSet.insert( pointIndex ).second )
00305 myKeyPointIDs.push_back( pointIndex );
00306 }
00307 }
00308
00309
00310
00311 while ( readLine( fields, lineBeg, clearFields ))
00312 {
00313 myElemPointIDs.push_back( TElemDef() );
00314 TElemDef& elemPoints = myElemPointIDs.back();
00315 for ( fIt = fields.begin(); fIt != fields.end(); fIt++ )
00316 {
00317 int pointIndex = getInt( *fIt );
00318 if ( pointIndex >= nbPoints || pointIndex < 0 ) {
00319 MESSAGE("Error: invalid point index " << pointIndex );
00320 Clear();
00321 return setErrorCode( ERR_READ_BAD_INDEX );
00322 }
00323 elemPoints.push_back( pointIndex );
00324 }
00325
00326 bool Ok = true;
00327 switch ( elemPoints.size() ) {
00328 case 3: if ( !myIs2D ) Ok = false; break;
00329 case 4: break;
00330 case 5:
00331 case 6:
00332 case 8: if ( myIs2D ) Ok = false; break;
00333 default: Ok = false;
00334 }
00335 if ( !Ok ) {
00336 MESSAGE("Error: wrong nb of nodes in element " << elemPoints.size() );
00337 Clear();
00338 return setErrorCode( ERR_READ_ELEM_POINTS );
00339 }
00340 }
00341 if ( myElemPointIDs.empty() ) {
00342 MESSAGE("Error: no elements");
00343 Clear();
00344 return setErrorCode( ERR_READ_NO_ELEMS );
00345 }
00346
00347 findBoundaryPoints();
00348
00349 return setErrorCode( ERR_OK );
00350 }
00351
00352
00353
00354
00355
00356
00357 bool SMESH_Pattern::Save (ostream& theFile)
00358 {
00359 MESSAGE(" ::Save(file) " );
00360
00361 Kernel_Utils::Localizer loc;
00362
00363 if ( !IsLoaded() ) {
00364 MESSAGE(" Pattern not loaded ");
00365 return setErrorCode( ERR_SAVE_NOT_LOADED );
00366 }
00367
00368 theFile << "!!! SALOME Mesh Pattern file" << endl;
00369 theFile << "!!!" << endl;
00370 theFile << "!!! Nb of points:" << endl;
00371 theFile << myPoints.size() << endl;
00372
00373
00374 const int width = 8;
00375
00376
00377
00378
00379
00380 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
00381 for ( int i = 0; pVecIt != myPoints.end(); pVecIt++, i++ ) {
00382 const gp_XYZ & xyz = (*pVecIt).myInitXYZ;
00383 theFile << " " << setw( width ) << xyz.X() << " " << setw( width ) << xyz.Y();
00384 if ( !myIs2D ) theFile << " " << setw( width ) << xyz.Z();
00385 theFile << " !- " << i << endl;
00386 }
00387
00388 if ( myIs2D ) {
00389 theFile << "!!! Indices of " << myKeyPointIDs.size() << " key-points:" << endl;
00390 list< int >::const_iterator kpIt = myKeyPointIDs.begin();
00391 for ( ; kpIt != myKeyPointIDs.end(); kpIt++ )
00392 theFile << " " << *kpIt;
00393 if ( !myKeyPointIDs.empty() )
00394 theFile << endl;
00395 }
00396
00397 theFile << "!!! Indices of points of " << myElemPointIDs.size() << " elements:" << endl;
00398 list<TElemDef >::const_iterator epIt = myElemPointIDs.begin();
00399 for ( ; epIt != myElemPointIDs.end(); epIt++ )
00400 {
00401 const TElemDef & elemPoints = *epIt;
00402 TElemDef::const_iterator iIt = elemPoints.begin();
00403 for ( ; iIt != elemPoints.end(); iIt++ )
00404 theFile << " " << *iIt;
00405 theFile << endl;
00406 }
00407
00408 theFile << endl;
00409
00410 return setErrorCode( ERR_OK );
00411 }
00412
00413
00414
00415
00416
00417
00418 template<typename T> struct TSizeCmp {
00419 bool operator ()( const list < T > & l1, const list < T > & l2 )
00420 const { return l1.size() < l2.size(); }
00421 };
00422
00423 template<typename T> void sortBySize( list< list < T > > & theListOfList )
00424 {
00425 if ( theListOfList.size() > 2 ) {
00426 TSizeCmp< T > SizeCmp;
00427 theListOfList.sort( SizeCmp );
00428 }
00429 }
00430
00431
00432
00433
00434
00435
00436 static gp_XY project (const SMDS_MeshNode* theNode,
00437 Extrema_GenExtPS & theProjectorPS)
00438 {
00439 gp_Pnt P( theNode->X(), theNode->Y(), theNode->Z() );
00440 theProjectorPS.Perform( P );
00441 if ( !theProjectorPS.IsDone() ) {
00442 MESSAGE( "SMESH_Pattern: point projection FAILED");
00443 return gp_XY(0.,0.);
00444 }
00445 double u, v, minVal = DBL_MAX;
00446 for ( int i = theProjectorPS.NbExt(); i > 0; i-- )
00447 if ( theProjectorPS.Value( i ) < minVal ) {
00448 minVal = theProjectorPS.Value( i );
00449 theProjectorPS.Point( i ).Parameter( u, v );
00450 }
00451 return gp_XY( u, v );
00452 }
00453
00454
00455
00456
00457
00458
00459 template <class TFaceIterator> bool areNodesBound( TFaceIterator & faceItr )
00460 {
00461 while ( faceItr->more() )
00462 {
00463 SMDS_ElemIteratorPtr nIt = faceItr->next()->nodesIterator();
00464 while ( nIt->more() )
00465 {
00466 const SMDS_MeshNode* node = smdsNode( nIt->next() );
00467 if (node->getshapeId() <1) {
00468 return false;
00469 }
00470 }
00471 }
00472 return true;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482 static bool isMeshBoundToShape(SMESHDS_Mesh * aMeshDS,
00483 SMESHDS_SubMesh * aFaceSubmesh,
00484 const bool isMainShape)
00485 {
00486 if ( isMainShape ) {
00487
00488 if ( aMeshDS->NbFaces() != aFaceSubmesh->NbElements() )
00489 return false;
00490 }
00491
00492
00493 if ( aFaceSubmesh ) {
00494 SMDS_ElemIteratorPtr fIt = aFaceSubmesh->GetElements();
00495 return areNodesBound( fIt );
00496 }
00497 SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
00498 return areNodesBound( fIt );
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508 bool SMESH_Pattern::Load (SMESH_Mesh* theMesh,
00509 const TopoDS_Face& theFace,
00510 bool theProject)
00511 {
00512 MESSAGE(" ::Load(face) " );
00513 Clear();
00514 myIs2D = true;
00515
00516 SMESHDS_Mesh * aMeshDS = theMesh->GetMeshDS();
00517 SMESHDS_SubMesh * fSubMesh = aMeshDS->MeshElements( theFace );
00518 const bool isQuadMesh = aMeshDS->GetMeshInfo().NbFaces( ORDER_QUADRATIC );
00519 SMESH_MesherHelper helper( *theMesh );
00520 helper.SetSubShape( theFace );
00521
00522 int nbNodes = ( !fSubMesh ? 0 : fSubMesh->NbNodes() );
00523 int nbElems = ( !fSubMesh ? 0 : fSubMesh->NbElements() );
00524 if ( nbElems == 0 && aMeshDS->NbFaces() == 0 )
00525 {
00526 MESSAGE( "No elements bound to the face");
00527 return setErrorCode( ERR_LOAD_EMPTY_SUBMESH );
00528 }
00529
00530 TopoDS_Face face = TopoDS::Face( theFace.Oriented( TopAbs_FORWARD ));
00531
00532
00533 bool isClosed = helper.HasSeam();
00534 TopoDS_Vertex bidon;
00535 list<TopoDS_Edge> eList;
00536 list<TopoDS_Edge>::iterator elIt;
00537 SMESH_Block::GetOrderedEdges( face, bidon, eList, myNbKeyPntInBoundary );
00538
00539
00540 bool isMainShape = theMesh->IsMainShape( face );
00541 bool needProject = !isMeshBoundToShape( aMeshDS, fSubMesh, isMainShape );
00542 bool canProject = ( nbElems ? true : isMainShape );
00543 if ( isClosed )
00544 canProject = false;
00545
00546 if ( ( theProject || needProject ) && !canProject )
00547 return setErrorCode( ERR_LOADF_CANT_PROJECT );
00548
00549 Extrema_GenExtPS projector;
00550 GeomAdaptor_Surface aSurface( BRep_Tool::Surface( face ));
00551 if ( theProject || needProject )
00552 projector.Initialize( aSurface, 20,20, 1e-5,1e-5 );
00553
00554 int iPoint = 0;
00555 TNodePointIDMap nodePointIDMap;
00556 TNodePointIDMap closeNodePointIDMap;
00557
00558 if ( needProject )
00559 {
00560 MESSAGE("Project the submesh");
00561
00562
00563
00564
00565
00566 list< const SMDS_MeshElement* > faces;
00567 if ( nbElems > 0 ) {
00568 SMDS_ElemIteratorPtr fIt = fSubMesh->GetElements();
00569 while ( fIt->more() ) {
00570 const SMDS_MeshElement* f = fIt->next();
00571 if ( f && f->GetType() == SMDSAbs_Face )
00572 faces.push_back( f );
00573 }
00574 }
00575 else {
00576 SMDS_FaceIteratorPtr fIt = aMeshDS->facesIterator();
00577 while ( fIt->more() )
00578 faces.push_back( fIt->next() );
00579 }
00580
00581
00582 list< const SMDS_MeshElement* >::iterator fIt = faces.begin();
00583 for ( ; fIt != faces.end(); ++fIt )
00584 {
00585 myElemPointIDs.push_back( TElemDef() );
00586 TElemDef& elemPoints = myElemPointIDs.back();
00587 int nbNodes = (*fIt)->NbCornerNodes();
00588 for ( int i = 0;i < nbNodes; ++i )
00589 {
00590 const SMDS_MeshElement* node = (*fIt)->GetNode( i );
00591 TNodePointIDMap::iterator nIdIt = nodePointIDMap.insert( make_pair( node, -1 )).first;
00592 if ( nIdIt->second == -1 )
00593 {
00594 elemPoints.push_back( iPoint );
00595 nIdIt->second = iPoint++;
00596 }
00597 else
00598 elemPoints.push_back( (*nIdIt).second );
00599 }
00600 }
00601 myPoints.resize( iPoint );
00602
00603
00604 TNodePointIDMap::iterator nIdIt = nodePointIDMap.begin();
00605 for ( ; nIdIt != nodePointIDMap.end(); nIdIt++ )
00606 {
00607 const SMDS_MeshNode* node = smdsNode( (*nIdIt).first );
00608 TPoint * p = & myPoints[ (*nIdIt).second ];
00609 p->myInitUV = project( node, projector );
00610 p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 );
00611 }
00612
00613 TopExp_Explorer vExp( face, TopAbs_VERTEX );
00614 set<int> foundIndices;
00615 for ( ; vExp.More(); vExp.Next() ) {
00616 const TopoDS_Vertex v = TopoDS::Vertex( vExp.Current() );
00617 gp_Pnt2d uv = BRep_Tool::Parameters( v, face );
00618 double minDist = DBL_MAX;
00619 int index;
00620 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
00621 for ( iPoint = 0; pVecIt != myPoints.end(); pVecIt++, iPoint++ ) {
00622 double dist = uv.SquareDistance( (*pVecIt).myInitUV );
00623 if ( dist < minDist ) {
00624 minDist = dist;
00625 index = iPoint;
00626 }
00627 }
00628 if ( foundIndices.insert( index ).second )
00629 myKeyPointIDs.push_back( index );
00630 }
00631 myIsBoundaryPointsFound = false;
00632
00633 }
00634 else
00635 {
00636
00637
00638
00639
00640
00641
00642
00643 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ ) {
00644 int nbV = myShapeIDMap.Extent();
00645 myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
00646 bool added = ( nbV < myShapeIDMap.Extent() );
00647 if ( !added ) {
00648
00649 myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ).Reversed());
00650 ++nbNodes;
00651 }
00652 if ( SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( *elIt ))
00653 nbNodes += eSubMesh->NbNodes() + 1;
00654 }
00655
00656 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
00657 myShapeIDMap.Add( *elIt );
00658
00659 myShapeIDMap.Add( face );
00660
00661 myPoints.resize( nbNodes );
00662
00663
00664
00665 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
00666 {
00667 TopoDS_Edge & edge = *elIt;
00668 list< TPoint* > & ePoints = getShapePoints( edge );
00669 double f, l;
00670 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( edge, face, f, l );
00671 bool isForward = ( edge.Orientation() == TopAbs_FORWARD );
00672
00673 TopoDS_Shape v1 = TopExp::FirstVertex( edge, true );
00674 TopoDS_Shape v2 = TopExp::LastVertex( edge, true );
00675
00676
00677 v2.Reverse();
00678
00679
00680 if ( isClosed ) {
00681 if ( helper.IsSeamShape( edge ) ) {
00682 if ( helper.IsRealSeam( edge ) && !isForward ) {
00683
00684 v1.Reverse();
00685 v2.Reverse();
00686 }
00687 }
00688 else {
00689 for ( int is2 = 0; is2 < 2; ++is2 ) {
00690 TopoDS_Shape & v = is2 ? v2 : v1;
00691 if ( helper.IsRealSeam( v ) ) {
00692
00693 TopoDS_Edge seam;
00694 list<TopoDS_Edge>::iterator eIt2 = elIt;
00695 if ( is2 )
00696 seam = ( ++eIt2 == eList.end() ? eList.front() : *eIt2 );
00697 else
00698 seam = ( eIt2 == eList.begin() ? eList.back() : *(--eIt2) );
00699 if ( seam.Orientation() == TopAbs_REVERSED )
00700 v.Reverse();
00701 }
00702 }
00703 }
00704 }
00705
00706
00707 list< TPoint* > * vPoint = & getShapePoints( v1 );
00708 if ( vPoint->empty() )
00709 {
00710 SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v1 );
00711 if ( vSubMesh && vSubMesh->NbNodes() ) {
00712 myKeyPointIDs.push_back( iPoint );
00713 SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes();
00714 const SMDS_MeshNode* node = nIt->next();
00715 if ( v1.Orientation() == TopAbs_REVERSED )
00716 closeNodePointIDMap.insert( make_pair( node, iPoint ));
00717 else
00718 nodePointIDMap.insert( make_pair( node, iPoint ));
00719
00720 TPoint* keyPoint = &myPoints[ iPoint++ ];
00721 vPoint->push_back( keyPoint );
00722 if ( theProject )
00723 keyPoint->myInitUV = project( node, projector );
00724 else
00725 keyPoint->myInitUV = C2d->Value( isForward ? f : l ).XY();
00726 keyPoint->myInitXYZ.SetCoord (keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0);
00727 }
00728 }
00729 if ( !vPoint->empty() )
00730 ePoints.push_back( vPoint->front() );
00731
00732
00733 SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edge );
00734 if ( eSubMesh && eSubMesh->NbNodes() )
00735 {
00736
00737 typedef map < double, const SMDS_MeshNode* > TParamNodeMap;
00738 TParamNodeMap paramNodeMap;
00739 int nbMeduimNodes = 0;
00740 SMDS_NodeIteratorPtr nIt = eSubMesh->GetNodes();
00741 while ( nIt->more() )
00742 {
00743 const SMDS_MeshNode* node = nIt->next();
00744 if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face )) {
00745 ++nbMeduimNodes;
00746 continue;
00747 }
00748 const SMDS_EdgePosition* epos =
00749 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
00750 double u = epos->GetUParameter();
00751 paramNodeMap.insert( make_pair( u, node ));
00752 }
00753 if ( paramNodeMap.size() != eSubMesh->NbNodes() ) {
00754
00755 Extrema_ExtPC proj;
00756 BRepAdaptor_Curve aCurve( edge );
00757 proj.Initialize( aCurve, f, l );
00758 paramNodeMap.clear();
00759 nIt = eSubMesh->GetNodes();
00760 for ( int iNode = 0; nIt->more(); ++iNode ) {
00761 const SMDS_MeshNode* node = nIt->next();
00762 if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face ))
00763 continue;
00764 proj.Perform( gp_Pnt( node->X(), node->Y(), node->Z()));
00765 double u = 0;
00766 if ( proj.IsDone() ) {
00767 for ( int i = 1, nb = proj.NbExt(); i <= nb; ++i )
00768 if ( proj.IsMin( i )) {
00769 u = proj.Point( i ).Parameter();
00770 break;
00771 }
00772 } else {
00773 u = isForward ? iNode : eSubMesh->NbNodes() - iNode;
00774 }
00775 paramNodeMap.insert( make_pair( u, node ));
00776 }
00777
00778
00779 if ( paramNodeMap.size() != eSubMesh->NbNodes() - nbMeduimNodes )
00780 return setErrorCode(ERR_UNEXPECTED);
00781 }
00782
00783
00784 bool isSeam = helper.IsRealSeam( edge );
00785 double du = l - f;
00786 TParamNodeMap::iterator unIt = paramNodeMap.begin();
00787 TParamNodeMap::reverse_iterator unRIt = paramNodeMap.rbegin();
00788 while ( unIt != paramNodeMap.end() )
00789 {
00790 TPoint* p = & myPoints[ iPoint ];
00791 ePoints.push_back( p );
00792 const SMDS_MeshNode* node = isForward ? (*unIt).second : (*unRIt).second;
00793 if ( isSeam && !isForward )
00794 closeNodePointIDMap.insert( make_pair( node, iPoint ));
00795 else
00796 nodePointIDMap.insert ( make_pair( node, iPoint ));
00797
00798 if ( theProject )
00799 p->myInitUV = project( node, projector );
00800 else {
00801 double u = isForward ? (*unIt).first : (*unRIt).first;
00802 p->myInitU = isForward ? (( u - f ) / du ) : ( 1.0 - ( u - f ) / du );
00803 p->myInitUV = C2d->Value( u ).XY();
00804 }
00805 p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 );
00806 unIt++; unRIt++;
00807 iPoint++;
00808 }
00809 }
00810
00811 vPoint = & getShapePoints( v2 );
00812 if ( vPoint->empty() )
00813 {
00814 SMESHDS_SubMesh * vSubMesh = aMeshDS->MeshElements( v2 );
00815 if ( vSubMesh && vSubMesh->NbNodes() ) {
00816 myKeyPointIDs.push_back( iPoint );
00817 SMDS_NodeIteratorPtr nIt = vSubMesh->GetNodes();
00818 const SMDS_MeshNode* node = nIt->next();
00819 if ( v2.Orientation() == TopAbs_REVERSED )
00820 closeNodePointIDMap.insert( make_pair( node, iPoint ));
00821 else
00822 nodePointIDMap.insert( make_pair( node, iPoint ));
00823
00824 TPoint* keyPoint = &myPoints[ iPoint++ ];
00825 vPoint->push_back( keyPoint );
00826 if ( theProject )
00827 keyPoint->myInitUV = project( node, projector );
00828 else
00829 keyPoint->myInitUV = C2d->Value( isForward ? l : f ).XY();
00830 keyPoint->myInitXYZ.SetCoord( keyPoint->myInitUV.X(), keyPoint->myInitUV.Y(), 0 );
00831 }
00832 }
00833 if ( !vPoint->empty() )
00834 ePoints.push_back( vPoint->front() );
00835
00836
00837 if ( theProject )
00838 {
00839 double totalDist = 0;
00840 list< TPoint* >::iterator pIt = ePoints.begin();
00841 TPoint* prevP = *pIt;
00842 prevP->myInitU = totalDist;
00843 for ( pIt++; pIt != ePoints.end(); pIt++ ) {
00844 TPoint* p = *pIt;
00845 totalDist += ( p->myInitUV - prevP->myInitUV ).Modulus();
00846 p->myInitU = totalDist;
00847 prevP = p;
00848 }
00849 if ( totalDist > DBL_MIN)
00850 for ( pIt = ePoints.begin(); pIt != ePoints.end(); pIt++ ) {
00851 TPoint* p = *pIt;
00852 p->myInitU /= totalDist;
00853 }
00854 }
00855 }
00856
00857
00858
00859 if ( fSubMesh && fSubMesh->NbElements() )
00860 {
00861 list< TPoint* > & fPoints = getShapePoints( face );
00862 SMDS_NodeIteratorPtr nIt = fSubMesh->GetNodes();
00863 while ( nIt->more() )
00864 {
00865 const SMDS_MeshNode* node = nIt->next();
00866 if ( isQuadMesh && helper.IsMedium( node, SMDSAbs_Face ))
00867 continue;
00868 nodePointIDMap.insert( make_pair( node, iPoint ));
00869 TPoint* p = &myPoints[ iPoint++ ];
00870 fPoints.push_back( p );
00871 if ( theProject )
00872 p->myInitUV = project( node, projector );
00873 else {
00874 const SMDS_FacePosition* pos =
00875 static_cast<const SMDS_FacePosition*>(node->GetPosition());
00876 p->myInitUV.SetCoord( pos->GetUParameter(), pos->GetVParameter() );
00877 }
00878 p->myInitXYZ.SetCoord( p->myInitUV.X(), p->myInitUV.Y(), 0 );
00879 }
00880
00881 TNodePointIDMap::iterator n_id, not_found = closeNodePointIDMap.end();
00882 SMDS_ElemIteratorPtr elemIt = fSubMesh->GetElements();
00883 while ( elemIt->more() )
00884 {
00885 const SMDS_MeshElement* elem = elemIt->next();
00886 SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
00887 myElemPointIDs.push_back( TElemDef() );
00888 TElemDef& elemPoints = myElemPointIDs.back();
00889
00890 while ( nIt->more() )
00891 {
00892 const SMDS_MeshNode* node = smdsNode( nIt->next() );
00893 n_id = nodePointIDMap.find( node );
00894 if ( n_id == nodePointIDMap.end() )
00895 continue;
00896 iPoint = n_id->second;
00897
00898 if ( helper.IsRealSeam( node->getshapeId() ) &&
00899 ( n_id = closeNodePointIDMap.find( node )) != not_found )
00900 {
00901 TPoint & p1 = myPoints[ iPoint ];
00902 TPoint & p2 = myPoints[ n_id->second ];
00903
00904 SMDS_ElemIteratorPtr nIt2 = elem->nodesIterator();
00905 const SMDS_MeshNode* notSeamNode = 0;
00906
00907 while ( nIt2->more() && !notSeamNode ) {
00908 const SMDS_MeshNode* n = smdsNode( nIt2->next() );
00909 if ( !helper.IsSeamShape( n->getshapeId() ))
00910 notSeamNode = n;
00911 }
00912 gp_Pnt2d uv = helper.GetNodeUV( theFace, node, notSeamNode );
00913 double dist1 = uv.SquareDistance( p1.myInitUV );
00914 double dist2 = uv.SquareDistance( p2.myInitUV );
00915 if ( dist2 < dist1 )
00916 iPoint = n_id->second;
00917 }
00918 elemPoints.push_back( iPoint );
00919 }
00920 }
00921 }
00922 myPoints.resize( nodePointIDMap.size() + closeNodePointIDMap.size() );
00923
00924 myIsBoundaryPointsFound = true;
00925 }
00926
00927
00928
00929 Bnd_Box2d bndBox;
00930 vector< TPoint >::iterator pVecIt = myPoints.begin();
00931 for ( ; pVecIt != myPoints.end(); pVecIt++ )
00932 bndBox.Add( gp_Pnt2d( (*pVecIt).myInitUV ));
00933 double minU, minV, maxU, maxV;
00934 bndBox.Get( minU, minV, maxU, maxV );
00935 double dU = maxU - minU, dV = maxV - minV;
00936 if ( dU <= DBL_MIN || dV <= DBL_MIN ) {
00937 Clear();
00938 bndBox.SetVoid();
00939
00940 TopExp_Explorer vExp( face, TopAbs_VERTEX );
00941 for ( ; vExp.More(); vExp.Next() ) {
00942 gp_Pnt2d uv = BRep_Tool::Parameters( TopoDS::Vertex( vExp.Current() ), face );
00943 bndBox.Add( uv );
00944 }
00945 bndBox.Get( minU, minV, maxU, maxV );
00946 dU = maxU - minU, dV = maxV - minV;
00947 if ( dU <= DBL_MIN || dV <= DBL_MIN )
00948
00949 return setErrorCode( ERR_LOADF_NARROW_FACE );
00950 else
00951
00952 return setErrorCode( ERR_LOADF_CANT_PROJECT );
00953 }
00954 double ratio = dU / dV, maxratio = 3, scale;
00955 int iCoord = 0;
00956 if ( ratio > maxratio ) {
00957 scale = ratio / maxratio;
00958 iCoord = 2;
00959 }
00960 else if ( ratio < 1./maxratio ) {
00961 scale = maxratio / ratio;
00962 iCoord = 1;
00963 }
00964 if ( iCoord ) {
00965 SCRUTE( scale );
00966 for ( pVecIt = myPoints.begin(); pVecIt != myPoints.end(); pVecIt++ ) {
00967 TPoint & p = *pVecIt;
00968 p.myInitUV.SetCoord( iCoord, p.myInitUV.Coord( iCoord ) * scale );
00969 p.myInitXYZ.SetCoord( p.myInitUV.X(), p.myInitUV.Y(), 0 );
00970 }
00971 }
00972 if ( myElemPointIDs.empty() ) {
00973 MESSAGE( "No elements bound to the face");
00974 return setErrorCode( ERR_LOAD_EMPTY_SUBMESH );
00975 }
00976
00977 return setErrorCode( ERR_OK );
00978 }
00979
00980
00981
00982
00983
00984
00985 void SMESH_Pattern::computeUVOnEdge (const TopoDS_Edge& theEdge,
00986 const list< TPoint* > & ePoints )
00987 {
00988 bool isForward = ( theEdge.Orientation() == TopAbs_FORWARD );
00989 double f, l;
00990 Handle(Geom2d_Curve) C2d =
00991 BRep_Tool::CurveOnSurface( theEdge, TopoDS::Face( myShape ), f, l );
00992
00993 ePoints.back()->myInitU = 1.0;
00994 list< TPoint* >::const_iterator pIt = ePoints.begin();
00995 for ( pIt++; pIt != ePoints.end(); pIt++ )
00996 {
00997 TPoint* point = *pIt;
00998
00999 double du = ( isForward ? point->myInitU : 1 - point->myInitU );
01000 point->myU = ( f * ( 1 - du ) + l * du );
01001
01002 point->myUV = C2d->Value( point->myU ).XY();
01003 }
01004 }
01005
01006
01007
01008
01009
01010
01011 static bool intersectIsolines(const gp_XY& uv11, const gp_XY& uv12, const double r1,
01012 const gp_XY& uv21, const gp_XY& uv22, const double r2,
01013 gp_XY& resUV,
01014 bool& isDeformed)
01015 {
01016 gp_XY loc1 = uv11 * ( 1 - r1 ) + uv12 * r1;
01017 gp_XY loc2 = uv21 * ( 1 - r2 ) + uv22 * r2;
01018 resUV = 0.5 * ( loc1 + loc2 );
01019
01020
01021 double d1 = (uv11-uv12).Modulus();
01022 double d2 = (uv21-uv22).Modulus();
01023
01024 double delta = min( d1, d2 ) / 10.;
01025 isDeformed = ( loc1 - loc2 ).SquareModulus() > delta * delta;
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 if ( isDeformed ) {
01050 MESSAGE("intersectIsolines(), d1 = " << d1 << ", d2 = " << d2 << ", delta = " << delta <<
01051 ", " << (loc1 - loc2).SquareModulus() << " > " << delta * delta);
01052 }
01053 return true;
01054 }
01055
01056
01057
01058
01059
01060
01061 bool SMESH_Pattern::compUVByIsoIntersection (const list< list< TPoint* > >& theBndPoints,
01062 const gp_XY& theInitUV,
01063 gp_XY& theUV,
01064 bool & theIsDeformed )
01065 {
01066
01067
01068 gp_XY uv1[2], uv2[2];
01069 double ratio[2];
01070 const double zero = DBL_MIN;
01071 for ( int iIso = 0; iIso < 2; iIso++ )
01072 {
01073
01074
01075
01076 gp_XY UV[2], initUV[2];
01077 int nbUV = 0, iCoord = iIso + 1;
01078 double initParam = theInitUV.Coord( iCoord );
01079
01080 list< list< TPoint* > >::const_iterator bndIt = theBndPoints.begin();
01081 for ( ; bndIt != theBndPoints.end(); bndIt++ )
01082 {
01083 const list< TPoint* > & bndPoints = * bndIt;
01084 TPoint* prevP = bndPoints.back();
01085 list< TPoint* >::const_iterator pIt = bndPoints.begin();
01086 bool coincPrev = false;
01087
01088 for ( ; pIt != bndPoints.end(); pIt++ )
01089 {
01090 double paramDiff = initParam - (*pIt)->myInitUV.Coord( iCoord );
01091 double prevParamDiff = initParam - prevP->myInitUV.Coord( iCoord );
01092 double sumOfDiff = Abs(prevParamDiff) + Abs(paramDiff);
01093 if (!coincPrev &&
01094 sumOfDiff > zero &&
01095 prevParamDiff * paramDiff <= zero )
01096 {
01097
01098 double r = Abs(prevParamDiff) / sumOfDiff;
01099 gp_XY uvInit = (*pIt)->myInitUV * r + prevP->myInitUV * ( 1 - r );
01100 int i = nbUV++;
01101 if ( i >= 2 ) {
01102
01103 gp_XY vec0 = initUV[0] - theInitUV;
01104 gp_XY vec1 = initUV[1] - theInitUV;
01105 gp_XY vec = uvInit - theInitUV;
01106 bool isBetween = ( vec0 * vec1 < 0 );
01107 double dist0 = vec0.SquareModulus();
01108 double dist1 = vec1.SquareModulus();
01109 double dist = vec .SquareModulus();
01110 if ( !isBetween || dist < dist0 || dist < dist1 ) {
01111 i = ( dist0 < dist1 ? 1 : 0 );
01112 if ( isBetween && vec.Dot( i ? vec1 : vec0 ) < 0 )
01113 i = 3;
01114 }
01115 }
01116 if ( i < 2 ) {
01117 initUV[ i ] = uvInit;
01118 UV[ i ] = (*pIt)->myUV * r + prevP->myUV * ( 1 - r );
01119 }
01120 coincPrev = ( Abs(paramDiff) <= zero );
01121 }
01122 else
01123 coincPrev = false;
01124 prevP = *pIt;
01125 }
01126 }
01127 if ( nbUV < 2 || (UV[0]-UV[1]).SquareModulus() <= DBL_MIN*DBL_MIN ) {
01128 MESSAGE(" consequent edge-points not found, nb UV found: " << nbUV <<
01129 ", for point: " << theInitUV.X() <<" " << theInitUV.Y() );
01130 return setErrorCode( ERR_APPLF_BAD_TOPOLOGY );
01131 }
01132
01133
01134
01135 double r =
01136 (initUV[0]-theInitUV).Modulus() / (initUV[0]-initUV[1]).Modulus();
01137
01138
01139 uv1[ iIso ] = UV[0];
01140 uv2[ iIso ] = UV[1];
01141 ratio[ iIso ] = r;
01142 }
01143 if ( !intersectIsolines( uv1[0], uv2[0], ratio[0],
01144 uv1[1], uv2[1], ratio[1], theUV, theIsDeformed )) {
01145 MESSAGE(" Cant intersect isolines for a point "<<theInitUV.X()<<", "<<theInitUV.Y());
01146 return setErrorCode( ERR_APPLF_BAD_TOPOLOGY );
01147 }
01148
01149 return true;
01150 }
01151
01152
01153
01154
01155
01156
01157 struct TIsoNode {
01158 bool myIsMovable;
01159 gp_XY myInitUV;
01160 gp_XY myUV;
01161 double myRatio[2];
01162 gp_Dir2d myDir[2];
01163 TIsoNode* myNext[4];
01164 TIsoNode* myBndNodes[4];
01165 TIsoNode(double initU, double initV):
01166 myInitUV( initU, initV ), myUV( 1e100, 1e100 ), myIsMovable(true)
01167 { myNext[0] = myNext[1] = myNext[2] = myNext[3] = 0; }
01168 bool IsUVComputed() const
01169 { return myUV.X() != 1e100; }
01170 bool IsMovable() const
01171 { return myIsMovable && myNext[0] && myNext[1] && myNext[2] && myNext[3]; }
01172 void SetNotMovable()
01173 { myIsMovable = false; }
01174 void SetBoundaryNode(TIsoNode* node, int iDir, int i)
01175 { myBndNodes[ iDir + i * 2 ] = node; }
01176 TIsoNode* GetBoundaryNode(int iDir, int i)
01177 { return myBndNodes[ iDir + i * 2 ]; }
01178 void SetNext(TIsoNode* node, int iDir, int isForward)
01179 { myNext[ iDir + isForward * 2 ] = node; }
01180 TIsoNode* GetNext(int iDir, int isForward)
01181 { return myNext[ iDir + isForward * 2 ]; }
01182 };
01183
01184
01185
01186
01187
01188
01189 static inline TIsoNode* getNextNode(const TIsoNode* node, int dir )
01190 {
01191 TIsoNode* n = node->myNext[ dir ];
01192 if ( n && !n->IsUVComputed() ) {
01193 n = 0;
01194
01195
01196 }
01197 return n;
01198 }
01199
01200
01201
01202
01203
01204
01205 enum { CHECK_NEW_IN, CHECK_NEW_OK, FIX_OLD };
01206
01207 static bool checkQuads (const TIsoNode* node,
01208 gp_XY& newUV,
01209 const bool reversed,
01210 const int crit = FIX_OLD,
01211 double fixSize = 0.)
01212 {
01213 gp_XY oldUV = node->myUV, oldUVFixed[4], oldUVImpr[4];
01214 int nbOldFix = 0, nbOldImpr = 0;
01215 double newBadRate = 0, oldBadRate = 0;
01216 bool newIsOk = true, newIsIn = true, oldIsIn = true, oldIsOk = true;
01217 int i, dir1 = 0, dir2 = 3;
01218 for ( ; dir1 < 4; dir1++, dir2++ )
01219 {
01220 if ( dir2 > 3 ) dir2 = 0;
01221 TIsoNode* n[3];
01222
01223
01224 n[0] = getNextNode( node, dir1 );
01225 n[2] = getNextNode( node, dir2 );
01226 if ( !n[0] || !n[2] ) continue;
01227 n[1] = getNextNode( n[0], dir2 );
01228 if ( !n[1] ) n[1] = getNextNode( n[2], dir1 );
01229 bool isTriangle = ( !n[1] );
01230 if ( reversed ) {
01231 TIsoNode* tmp = n[0]; n[0] = n[2]; n[2] = tmp;
01232 }
01233
01234
01235
01236
01237
01238
01239
01240 if ( !isTriangle &&
01241 ((( n[0]->myUV - n[1]->myUV ).SquareModulus() <= DBL_MIN ) ||
01242 (( n[2]->myUV - n[1]->myUV ).SquareModulus() <= DBL_MIN )))
01243 isTriangle = true;
01244 if ( isTriangle &&
01245 ( n[0]->myUV - n[2]->myUV ).SquareModulus() <= DBL_MIN )
01246 continue;
01247
01248
01249 double minDiag = fixSize;
01250 if ( minDiag == 0. ) {
01251 double maxLen2 = ( node->myUV - n[0]->myUV ).SquareModulus();
01252 if ( !isTriangle ) {
01253 maxLen2 = Max( maxLen2, ( n[0]->myUV - n[1]->myUV ).SquareModulus() );
01254 maxLen2 = Max( maxLen2, ( n[1]->myUV - n[2]->myUV ).SquareModulus() );
01255 }
01256 maxLen2 = Max( maxLen2, ( n[2]->myUV - node->myUV ).SquareModulus() );
01257 minDiag = sqrt( maxLen2 ) * PI / 60.;
01258 }
01259
01260
01261
01262
01263
01264
01265 bool newIn[3] = { true, true, true }, newOk[3] = { true, true, true };
01266 bool wasIn[3] = { true, true, true }, wasOk[3] = { true, true, true };
01267 gp_Vec2d moveVec[3], outVec[3];
01268 for ( i = isTriangle ? 2 : 0; i < 3; i++ )
01269 {
01270 bool isDiag = ( i == 2 );
01271 if ( isDiag && newOk[0] && newOk[1] && !isTriangle )
01272 break;
01273 gp_Vec2d sideDir;
01274 if ( isDiag )
01275 sideDir = gp_Vec2d( n[0]->myUV, n[2]->myUV );
01276 else
01277 sideDir = gp_Vec2d( n[i]->myUV, n[i+1]->myUV );
01278
01279 gp_Vec2d outDir( sideDir.Y(), -sideDir.X() );
01280 outDir.Normalize();
01281 gp_Vec2d newDir( n[i]->myUV, newUV );
01282 gp_Vec2d oldDir( n[i]->myUV, oldUV );
01283 outVec[i] = outDir;
01284 if ( newIsOk ) newOk[i] = ( outDir * newDir < -minDiag );
01285 if ( newIsIn ) newIn[i] = ( outDir * newDir < 0 );
01286 if ( crit == FIX_OLD ) {
01287 wasIn[i] = ( outDir * oldDir < 0 );
01288 wasOk[i] = ( outDir * oldDir < -minDiag );
01289 if ( !newOk[i] )
01290 newBadRate += outDir * newDir;
01291 if ( !wasOk[i] )
01292 oldBadRate += outDir * oldDir;
01293
01294 if ( !wasOk[i] ) {
01295 double oldDist = - outDir * oldDir;
01296
01297
01298 moveVec[i] = ( oldDist - minDiag ) * outDir;
01299 }
01300 }
01301 }
01302
01303
01304 bool convex = true;
01305 if ( !isTriangle )
01306 convex = ( outVec[0] * gp_Vec2d( n[1]->myUV, n[2]->myUV ) < 0 );
01307
01308 bool isNewOk = ( newOk[0] && newOk[1] ) || ( newOk[2] && convex );
01309 bool isNewIn = ( newIn[0] && newIn[1] ) || ( newIn[2] && convex );
01310 newIsOk = ( newIsOk && isNewOk );
01311 newIsIn = ( newIsIn && isNewIn );
01312
01313 if ( crit != FIX_OLD ) {
01314 if ( crit == CHECK_NEW_OK && !newIsOk ) break;
01315 if ( crit == CHECK_NEW_IN && !newIsIn ) break;
01316 continue;
01317 }
01318
01319 bool isOldIn = ( wasIn[0] && wasIn[1] ) || ( wasIn[2] && convex );
01320 bool isOldOk = ( wasOk[0] && wasOk[1] ) || ( wasOk[2] && convex );
01321 oldIsIn = ( oldIsIn && isOldIn );
01322 oldIsOk = ( oldIsOk && isOldIn );
01323
01324
01325 if ( !isOldIn ) {
01326
01327
01328
01329 gp_XY uv;
01330 if ( convex || isTriangle ) {
01331 uv = 0.5 * ( n[0]->myUV + n[2]->myUV ) - minDiag * outVec[2].XY();
01332 }
01333 else {
01334 gp_Vec2d out = outVec[0].Normalized() + outVec[1].Normalized();
01335 double outSize = out.Magnitude();
01336 if ( outSize > DBL_MIN )
01337 out /= outSize;
01338 else
01339 out.SetCoord( -outVec[1].Y(), outVec[1].X() );
01340 uv = n[1]->myUV - minDiag * out.XY();
01341 }
01342 oldUVFixed[ nbOldFix++ ] = uv;
01343
01344 }
01345 else if ( !isOldOk ) {
01346
01347
01348 gp_XY uv1, uv2 = node->myUV;
01349 for ( i = isTriangle ? 2 : 0; i < 3; i++ )
01350 if ( wasOk[i] )
01351 moveVec[ i ].SetCoord( 1, 2e100);
01352 while ( !isOldOk ) {
01353
01354 int i, iMin = 4;
01355 double minMove2 = 1e100;
01356 for ( i = isTriangle ? 2 : 0; i < 3; i++ )
01357 {
01358 if ( moveVec[i].Coord(1) < 1e100 ) {
01359 double move2 = moveVec[i].SquareMagnitude();
01360 if ( move2 < minMove2 ) {
01361 minMove2 = move2;
01362 iMin = i;
01363 }
01364 }
01365 }
01366 if ( iMin == 4 ) {
01367 break;
01368 }
01369
01370 uv1 = node->myUV + moveVec[ iMin ].XY();
01371 uv2 += moveVec[ iMin ].XY();
01372 moveVec[ iMin ].SetCoord( 1, 2e100);
01373
01374 for ( i = isTriangle ? 2 : 0; i < 3; i++ )
01375 wasOk[i] = ( outVec[i] * gp_Vec2d( n[i]->myUV, uv1 ) < -minDiag );
01376 isOldOk = ( wasOk[0] && wasOk[1] ) || ( wasOk[2] && convex );
01377 if ( isOldOk )
01378 oldUVImpr[ nbOldImpr++ ] = uv1;
01379 else {
01380
01381 for ( i = isTriangle ? 2 : 0; i < 3; i++ )
01382 wasOk[i] = ( outVec[i] * gp_Vec2d( n[i]->myUV, uv2 ) < -minDiag );
01383 isOldOk = ( wasOk[0] && wasOk[1] ) || ( wasOk[2] && convex );
01384 if ( isOldOk )
01385 oldUVImpr[ nbOldImpr++ ] = uv2;
01386 }
01387 }
01388 }
01389
01390 }
01391
01392 if ( crit == CHECK_NEW_OK )
01393 return newIsOk;
01394 if ( crit == CHECK_NEW_IN )
01395 return newIsIn;
01396
01397 if ( newIsOk )
01398 return true;
01399
01400 if ( oldIsOk )
01401 newUV = oldUV;
01402 else {
01403 if ( oldIsIn && nbOldImpr ) {
01404
01405
01406 gp_XY uv = oldUVImpr[ 0 ];
01407 for ( int i = 1; i < nbOldImpr; i++ )
01408 uv += oldUVImpr[ i ];
01409 uv /= nbOldImpr;
01410 if ( checkQuads( node, uv, reversed, CHECK_NEW_OK )) {
01411 newUV = uv;
01412 return false;
01413 }
01414 else {
01415
01416 }
01417 }
01418 if ( !oldIsIn && nbOldFix ) {
01419
01420
01421 gp_XY uv = oldUVFixed[ 0 ];
01422 for ( int i = 1; i < nbOldFix; i++ )
01423 uv += oldUVFixed[ i ];
01424 uv /= nbOldFix;
01425 if ( checkQuads( node, uv, reversed, CHECK_NEW_IN )) {
01426 newUV = uv;
01427 return false;
01428 }
01429 else {
01430
01431 }
01432 }
01433 if ( newIsIn && oldIsIn )
01434 newUV = ( newBadRate < oldBadRate ) ? newUV : oldUV;
01435 else if ( !newIsIn )
01436 newUV = oldUV;
01437 }
01438
01439 return false;
01440 }
01441
01442
01443
01444
01445
01446
01447
01448 bool SMESH_Pattern::
01449 compUVByElasticIsolines(const list< list< TPoint* > >& theBndPoints,
01450 const list< TPoint* >& thePntToCompute)
01451 {
01452 return false;
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 set< double > paramSet[ 2 ];
01465 list< list< TPoint* > >::const_iterator pListIt;
01466 list< TPoint* >::const_iterator pIt;
01467 for ( pListIt = theBndPoints.begin(); pListIt != theBndPoints.end(); pListIt++ ) {
01468 const list< TPoint* > & pList = * pListIt;
01469 for ( pIt = pList.begin(); pIt != pList.end(); pIt++ ) {
01470 paramSet[0].insert( (*pIt)->myInitUV.X() );
01471 paramSet[1].insert( (*pIt)->myInitUV.Y() );
01472 }
01473 }
01474 for ( pIt = thePntToCompute.begin(); pIt != thePntToCompute.end(); pIt++ ) {
01475 paramSet[0].insert( (*pIt)->myInitUV.X() );
01476 paramSet[1].insert( (*pIt)->myInitUV.Y() );
01477 }
01478
01479 int iDir;
01480 double tol[ 2 ];
01481 for ( iDir = 0; iDir < 2; iDir++ )
01482 {
01483 set< double > & params = paramSet[ iDir ];
01484 double range = ( *params.rbegin() - *params.begin() );
01485 double toler = range / 1e6;
01486 tol[ iDir ] = toler;
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 }
01501
01502
01503
01504 list < TIsoNode > nodes;
01505 typedef list < TIsoNode *> TIsoLine;
01506 map < double, TIsoLine > isoMap[ 2 ];
01507
01508 set< double > & params0 = paramSet[ 0 ];
01509 set< double >::iterator par0It = params0.begin();
01510 for ( ; par0It != params0.end(); par0It++ )
01511 {
01512 TIsoLine & isoLine0 = isoMap[0][ *par0It ];
01513 set< double > & params1 = paramSet[ 1 ];
01514 set< double >::iterator par1It = params1.begin();
01515 for ( ; par1It != params1.end(); par1It++ )
01516 {
01517 nodes.push_back( TIsoNode( *par0It, *par1It ) );
01518 isoLine0.push_back( & nodes.back() );
01519 isoMap[1][ *par1It ].push_back( & nodes.back() );
01520 }
01521 }
01522
01523
01524
01525
01526 Bnd_Box2d uvBnd;
01527 list< list< TPoint* > >::const_iterator bndIt = theBndPoints.begin();
01528 list< TIsoNode* > bndNodes;
01529 for ( ; bndIt != theBndPoints.end(); bndIt++ )
01530 {
01531 const list< TPoint* > & bndPoints = * bndIt;
01532 TPoint* prevP = bndPoints.back();
01533 list< TPoint* >::const_iterator pIt = bndPoints.begin();
01534
01535 for ( ; pIt != bndPoints.end(); pIt++ )
01536 {
01537 TPoint* point = *pIt;
01538 for ( iDir = 0; iDir < 2; iDir++ )
01539 {
01540 const int iCoord = iDir + 1;
01541 const int iOtherCoord = 2 - iDir;
01542 double par1 = prevP->myInitUV.Coord( iCoord );
01543 double par2 = point->myInitUV.Coord( iCoord );
01544 double parDif = par2 - par1;
01545 if ( Abs( parDif ) <= DBL_MIN )
01546 continue;
01547
01548 double toler = tol[ 1 - iDir ];
01549 double minPar = Min ( par1, par2 );
01550 double maxPar = Max ( par1, par2 );
01551 map < double, TIsoLine >& isos = isoMap[ iDir ];
01552 map < double, TIsoLine >::iterator isoIt = isos.begin();
01553 for ( ; isoIt != isos.end(); isoIt++ )
01554 {
01555 double isoParam = (*isoIt).first;
01556 if ( isoParam < minPar || isoParam > maxPar )
01557 continue;
01558 double r = ( isoParam - par1 ) / parDif;
01559 gp_XY uv = ( 1 - r ) * prevP->myUV + r * point->myUV;
01560 gp_XY initUV = ( 1 - r ) * prevP->myInitUV + r * point->myInitUV;
01561 double otherPar = initUV.Coord( iOtherCoord );
01562
01563 TIsoLine & isoLine = (*isoIt).second;
01564 double nodePar;
01565 TIsoLine::iterator nIt = isoLine.begin();
01566 for ( ; nIt != isoLine.end(); nIt++ ) {
01567 nodePar = (*nIt)->myInitUV.Coord( iOtherCoord );
01568 if ( nodePar >= otherPar )
01569 break;
01570 }
01571 TIsoNode * node;
01572 if ( Abs( nodePar - otherPar ) <= toler )
01573 node = ( nIt == isoLine.end() ) ? isoLine.back() : (*nIt);
01574 else {
01575 nodes.push_back( TIsoNode( initUV.X(), initUV.Y() ) );
01576 node = & nodes.back();
01577 isoLine.insert( nIt, node );
01578 }
01579 node->SetNotMovable();
01580 node->myUV = uv;
01581 uvBnd.Add( gp_Pnt2d( uv ));
01582
01583
01584 gp_XY tgt( point->myUV - prevP->myUV );
01585 if ( ::IsEqual( r, 1. ))
01586 node->myDir[ 0 ] = tgt;
01587 else if ( ::IsEqual( r, 0. ))
01588 node->myDir[ 1 ] = tgt;
01589 else
01590 node->myDir[ 1 ] = node->myDir[ 0 ] = tgt;
01591
01592 if ( bndIt == theBndPoints.begin() && ::IsEqual( r, 1. ))
01593 if ( bndNodes.empty() || bndNodes.back() != node )
01594 bndNodes.push_back( node );
01595 }
01596 }
01597 prevP = point;
01598 }
01599 }
01600
01601
01602
01603
01604 double leastX = DBL_MAX;
01605 TIsoNode * leftNode;
01606 list < TIsoNode >::iterator nodeIt = nodes.begin();
01607 for ( ; nodeIt != nodes.end(); nodeIt++ ) {
01608 TIsoNode & node = *nodeIt;
01609 if ( node.IsUVComputed() && node.myUV.X() < leastX ) {
01610 leastX = node.myUV.X();
01611 leftNode = &node;
01612 }
01613
01614
01615
01616
01617
01618
01619 }
01620 bool reversed = ( leftNode->myDir[0].Y() + leftNode->myDir[1].Y() > 0 );
01621
01622
01623
01624
01625
01626
01627
01628 for ( iDir = 0; iDir < 2; iDir++ )
01629 {
01630 const int iCoord = 2 - iDir;
01631 map < double, TIsoLine >& isos = isoMap[ iDir ];
01632 map < double, TIsoLine >::iterator isoIt = isos.begin();
01633 for ( ; isoIt != isos.end(); isoIt++ )
01634 {
01635 TIsoLine & isoLine = (*isoIt).second;
01636 bool firstCompNodeFound = false;
01637 TIsoLine::iterator lastCompNodePos, nPrevIt, nIt, nNextIt, nIt2;
01638 nPrevIt = nIt = nNextIt = isoLine.begin();
01639 nIt++;
01640 nNextIt++; nNextIt++;
01641 while ( nIt != isoLine.end() )
01642 {
01643
01644 TIsoNode* node = *nIt, * prevNode = *nPrevIt;
01645 if ( !firstCompNodeFound && prevNode->IsUVComputed() ) {
01646 firstCompNodeFound = true;
01647 lastCompNodePos = nPrevIt;
01648 }
01649 if ( firstCompNodeFound ) {
01650 node->SetNext( prevNode, iDir, 0 );
01651 prevNode->SetNext( node, iDir, 1 );
01652 }
01653
01654 if ( nNextIt != isoLine.end() ) {
01655 double par1 = prevNode->myInitUV.Coord( iCoord );
01656 double par2 = node->myInitUV.Coord( iCoord );
01657 double par3 = (*nNextIt)->myInitUV.Coord( iCoord );
01658 node->myRatio[ iDir ] = ( par2 - par1 ) / ( par3 - par1 );
01659 }
01660
01661 if ( node->IsUVComputed() )
01662 lastCompNodePos = nIt;
01663 else if ( firstCompNodeFound && nNextIt != isoLine.end() ) {
01664 TIsoNode* bndNode1 = *lastCompNodePos, *bndNode2 = 0;
01665 for ( nIt2 = nNextIt; nIt2 != isoLine.end(); nIt2++ )
01666 if ( (*nIt2)->IsUVComputed() )
01667 break;
01668 if ( nIt2 != isoLine.end() ) {
01669 bndNode2 = *nIt2;
01670 node->SetBoundaryNode( bndNode1, iDir, 0 );
01671 node->SetBoundaryNode( bndNode2, iDir, 1 );
01672
01673
01674
01675
01676
01677
01678
01679 }
01680 else {
01682 node->SetBoundaryNode( 0, iDir, 0 );
01683 node->SetBoundaryNode( 0, iDir, 1 );
01684 }
01685 }
01686 nIt++; nPrevIt++;
01687 if ( nNextIt != isoLine.end() ) nNextIt++;
01688
01689 if ( !firstCompNodeFound )
01690 isoLine.pop_front();
01691 }
01692
01693
01694
01695
01696 isoLine.erase( ++lastCompNodePos, isoLine.end() );
01697 }
01698 }
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796 list< TIsoNode* > startNodes;
01797 list< TIsoNode* >::iterator nIt = bndNodes.end();
01798 TIsoNode* node = *(--nIt);
01799 TIsoNode* prevNode = *(--nIt);
01800 for ( nIt = bndNodes.begin(); nIt != bndNodes.end(); nIt++ )
01801 {
01802 TIsoNode* nextNode = *nIt;
01803 gp_Vec2d initTgt1( prevNode->myInitUV, node->myInitUV );
01804 gp_Vec2d initTgt2( node->myInitUV, nextNode->myInitUV );
01805 double initAngle = initTgt1.Angle( initTgt2 );
01806 double angle = node->myDir[0].Angle( node->myDir[1] );
01807 if ( reversed ) angle = -angle;
01808 if ( initAngle > angle && initAngle - angle > PI / 2.1 ) {
01809
01810 TIsoNode* nClose = 0;
01811 list< TIsoNode* > testNodes;
01812 testNodes.push_back( node );
01813 list< TIsoNode* >::iterator it = testNodes.begin();
01814 for ( ; !nClose && it != testNodes.end(); it++ )
01815 {
01816 for (int i = 0; i < 4; i++ )
01817 {
01818 nClose = (*it)->myNext[ i ];
01819 if ( nClose ) {
01820 if ( !nClose->IsUVComputed() )
01821 break;
01822 else {
01823 testNodes.push_back( nClose );
01824 nClose = 0;
01825 }
01826 }
01827 }
01828 }
01829 startNodes.push_back( nClose );
01830
01831
01832
01833
01834
01835
01836
01837 }
01838 prevNode = node;
01839 node = nextNode;
01840 }
01841
01842
01843
01844 list < TIsoNode* > internNodes;
01845 bool needIteration = true;
01846 if ( startNodes.empty() ) {
01847 MESSAGE( " Starting UV by compUVByIsoIntersection()");
01848 needIteration = false;
01849 map < double, TIsoLine >& isos = isoMap[ 0 ];
01850 map < double, TIsoLine >::iterator isoIt = isos.begin();
01851 for ( ; isoIt != isos.end(); isoIt++ )
01852 {
01853 TIsoLine & isoLine = (*isoIt).second;
01854 TIsoLine::iterator nIt = isoLine.begin();
01855 for ( ; !needIteration && nIt != isoLine.end(); nIt++ )
01856 {
01857 TIsoNode* node = *nIt;
01858 if ( !node->IsUVComputed() && node->IsMovable() ) {
01859 internNodes.push_back( node );
01860
01861 if ( !compUVByIsoIntersection(theBndPoints, node->myInitUV,
01862 node->myUV, needIteration ))
01863 node->myUV = node->myInitUV;
01864 }
01865 }
01866 }
01867 if ( needIteration )
01868 for ( nIt = bndNodes.begin(); nIt != bndNodes.end(); nIt++ )
01869 {
01870 TIsoNode* node = *nIt, *nClose = 0;
01871 list< TIsoNode* > testNodes;
01872 testNodes.push_back( node );
01873 list< TIsoNode* >::iterator it = testNodes.begin();
01874 for ( ; !nClose && it != testNodes.end(); it++ )
01875 {
01876 for (int i = 0; i < 4; i++ )
01877 {
01878 nClose = (*it)->myNext[ i ];
01879 if ( nClose ) {
01880 if ( !nClose->IsUVComputed() && nClose->IsMovable() )
01881 break;
01882 else {
01883 testNodes.push_back( nClose );
01884 nClose = 0;
01885 }
01886 }
01887 }
01888 }
01889 startNodes.push_back( nClose );
01890 }
01891 }
01892
01893 double aMin[2], aMax[2], step[2];
01894 uvBnd.Get( aMin[0], aMin[1], aMax[0], aMax[1] );
01895 double minUvSize = Min ( aMax[0]-aMin[0], aMax[1]-aMin[1] );
01896 step[0] = minUvSize / paramSet[ 0 ].size() / 10;
01897 step[1] = minUvSize / paramSet[ 1 ].size() / 10;
01898
01899
01900 for ( nIt = startNodes.begin(); nIt != startNodes.end(); nIt++ )
01901 {
01902 TIsoNode *node = *nIt;
01903 if ( node->IsUVComputed() || !node->IsMovable() )
01904 continue;
01905 gp_XY newUV( 0, 0 ), sumDir( 0, 0 );
01906 int nbComp = 0, nbPrev = 0;
01907 for ( iDir = 0; iDir < 2; iDir++ )
01908 {
01909 TIsoNode* prevNode1 = 0, *prevNode2 = 0;
01910 TIsoNode* n = node->GetNext( iDir, 0 );
01911 if ( n->IsUVComputed() )
01912 prevNode1 = n;
01913 else
01914 startNodes.push_back( n );
01915 n = node->GetNext( iDir, 1 );
01916 if ( n->IsUVComputed() )
01917 prevNode2 = n;
01918 else
01919 startNodes.push_back( n );
01920 if ( !prevNode1 ) {
01921 prevNode1 = prevNode2;
01922 prevNode2 = 0;
01923 }
01924 if ( prevNode1 ) nbPrev++;
01925 if ( prevNode2 ) nbPrev++;
01926 if ( prevNode1 ) {
01927 gp_XY dir;
01928 double prevPar = prevNode1->myInitUV.Coord( 2 - iDir );
01929 double par = node->myInitUV.Coord( 2 - iDir );
01930 bool isEnd = ( prevPar > par );
01931
01932
01933 TIsoNode* bndNode = node->GetBoundaryNode( iDir, isEnd );
01934 if ( !bndNode ) {
01935 MESSAGE("Why we are here?");
01936 continue;
01937 }
01938 gp_XY tgt( bndNode->myDir[0].XY() + bndNode->myDir[1].XY() );
01939 dir.SetCoord( 1, tgt.Y() * ( reversed ? 1 : -1 ));
01940 dir.SetCoord( 2, tgt.X() * ( reversed ? -1 : 1 ));
01941
01942
01943
01944
01945
01946
01947
01948 if ( prevNode2 ) {
01949
01950 gp_XY & uv1 = prevNode1->myUV;
01951 gp_XY & uv2 = prevNode2->myUV;
01952
01953
01954
01955
01956 double r = node->myRatio[ iDir ];
01957 newUV += uv1 * ( 1 - r ) + uv2 * r;
01958 }
01959 else {
01960 newUV += prevNode1->myUV + dir * step[ iDir ];
01961 }
01962 sumDir += dir;
01963 nbComp++;
01964 }
01965 }
01966 if ( !nbComp ) continue;
01967 newUV /= nbComp;
01968 node->myUV = newUV;
01969
01970
01971
01972 if ( nbPrev > 1 ) {
01973
01974 if ( !checkQuads( node, newUV, reversed, FIX_OLD, step[0] + step[1] )) {
01975
01976
01977 node->myUV = newUV;
01978 }
01979 }
01980 internNodes.push_back( node );
01981 }
01982
01983
01984
01985 static int maxNbIter = 100;
01986 #ifdef DEB_COMPUVBYELASTICISOLINES
01987
01988 bool useNbMoveNode = 0;
01989 static int maxNbNodeMove = 100;
01990 maxNbNodeMove++;
01991 int nbNodeMove = 0;
01992 if ( !useNbMoveNode )
01993 maxNbIter = ( maxNbIter < 0 ) ? 100 : -1;
01994 #endif
01995 double maxMove;
01996 int nbIter = 0;
01997 do {
01998 if ( !needIteration) break;
01999 #ifdef DEB_COMPUVBYELASTICISOLINES
02000 if ( nbIter >= maxNbIter ) break;
02001 #endif
02002 maxMove = 0.0;
02003 list < TIsoNode* >::iterator nIt = internNodes.begin();
02004 for ( ; nIt != internNodes.end(); nIt++ ) {
02005 #ifdef DEB_COMPUVBYELASTICISOLINES
02006 if (useNbMoveNode )
02007 cout << nbNodeMove <<" =================================================="<<endl;
02008 #endif
02009 TIsoNode * node = *nIt;
02010
02011
02012 gp_XY loc[2];
02013 for ( iDir = 0; iDir < 2; iDir++ )
02014 {
02015 gp_XY & uv1 = node->GetNext( iDir, 0 )->myUV;
02016 gp_XY & uv2 = node->GetNext( iDir, 1 )->myUV;
02017 double r = node->myRatio[ iDir ];
02018 loc[ iDir ] = uv1 * ( 1 - r ) + uv2 * r;
02019
02020
02021 }
02022
02023 bool ok = true;
02024
02025 for ( iDir = 0; iDir < 2; iDir++ )
02026 {
02027 const int iCoord = 2 - iDir;
02028 TIsoNode* bndNode1 = node->GetBoundaryNode( iDir, 0 );
02029 TIsoNode* bndNode2 = node->GetBoundaryNode( iDir, 1 );
02030 if ( !bndNode1 || !bndNode2 ) {
02031 ok = false; break;
02032 }
02033 double par1 = bndNode1->myInitUV.Coord( iCoord );
02034 double par2 = node->myInitUV.Coord( iCoord );
02035 double par3 = bndNode2->myInitUV.Coord( iCoord );
02036 double r = ( par2 - par1 ) / ( par3 - par1 );
02037 r = Abs ( r - 0.5 ) * 2.0;
02038
02039 }
02040
02041
02042
02043 if ( ok )
02044 {
02045
02046
02047
02048
02049
02050
02051 gp_XY newUV = 0.5 * ( loc[0] + loc[1] );
02052
02053 checkQuads( node, newUV, reversed );
02054
02055 maxMove = Max( maxMove, ( newUV - node->myUV ).SquareModulus());
02056 node->myUV = newUV;
02057 }
02058 #ifdef DEB_COMPUVBYELASTICISOLINES
02059 if (useNbMoveNode && ++nbNodeMove >= maxNbNodeMove ) break;
02060 #endif
02061 }
02062 #ifdef DEB_COMPUVBYELASTICISOLINES
02063 if (useNbMoveNode && nbNodeMove >= maxNbNodeMove ) break;
02064 #endif
02065 } while ( maxMove > 1e-8 && nbIter++ < maxNbIter );
02066
02067 MESSAGE( "compUVByElasticIsolines(): Nb iterations " << nbIter << " dist: " << sqrt( maxMove ));
02068
02069 if ( nbIter >= maxNbIter && sqrt(maxMove) > minUvSize * 0.05 ) {
02070 MESSAGE( "compUVByElasticIsolines() failed: "<<sqrt(maxMove)<<">"<<minUvSize * 0.05);
02071 #ifndef DEB_COMPUVBYELASTICISOLINES
02072 return false;
02073 #endif
02074 }
02075
02076
02077
02078 for ( pIt = thePntToCompute.begin(); pIt != thePntToCompute.end(); pIt++ ) {
02079 TPoint* point = *pIt;
02080
02081 double minDist = DBL_MAX;
02082 list < TIsoNode >::iterator nIt = nodes.begin();
02083 for ( ; nIt != nodes.end(); nIt++ ) {
02084 double dist = ( (*nIt).myInitUV - point->myInitUV ).SquareModulus();
02085 if ( dist < minDist ) {
02086 minDist = dist;
02087 point->myUV = (*nIt).myUV;
02088 }
02089 }
02090 }
02091
02092 return true;
02093 }
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 double SMESH_Pattern::setFirstEdge (list< TopoDS_Edge > & theWire, int theFirstEdgeID)
02105 {
02106 int iE, nbEdges = theWire.size();
02107 if ( nbEdges == 1 )
02108 return 0;
02109
02110
02111
02112
02113 int maxNbPnt = 0;
02114 int eID = theFirstEdgeID;
02115 for ( iE = 0; iE < nbEdges; iE++ )
02116 maxNbPnt = Max ( maxNbPnt, getShapePoints( eID++ ).size() );
02117
02118
02119 TopoDS_Face face = TopoDS::Face( myShape );
02120 Bnd_Box2d bndBox, eBndBox;
02121 eID = theFirstEdgeID;
02122 list< TopoDS_Edge >::iterator eIt;
02123 list< TPoint* >::iterator pIt;
02124 for ( eIt = theWire.begin(); eIt != theWire.end(); eIt++ )
02125 {
02126
02127 list< TPoint* > & ePoints = getShapePoints( eID++ );
02128 for ( pIt = ePoints.begin(); pIt != ePoints.end(); pIt++ ) {
02129 TPoint* p = (*pIt);
02130 bndBox.Add( gp_Pnt2d( p->myXYZ.X(), p->myXYZ.Y() ));
02131 }
02132
02133 double f, l;
02134 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface( *eIt, face, f, l );
02135 double dU = ( l - f ) / ( maxNbPnt - 1 );
02136 for ( int i = 0; i < maxNbPnt; i++ )
02137 eBndBox.Add( C2d->Value( f + i * dU ));
02138 }
02139
02140
02141 double minPar[2], maxPar[2], eMinPar[2], eMaxPar[2];
02142 bndBox.Get( minPar[0], minPar[1], maxPar[0], maxPar[1] );
02143 eBndBox.Get( eMinPar[0], eMinPar[1], eMaxPar[0], eMaxPar[1] );
02144 #ifdef DBG_SETFIRSTEDGE
02145 MESSAGE ( "EDGES: X: " << eMinPar[0] << " - " << eMaxPar[0] << " Y: "
02146 << eMinPar[1] << " - " << eMaxPar[1] );
02147 #endif
02148 for ( int iC = 1, i = 0; i < 2; iC++, i++ )
02149 {
02150 double dMin = eMinPar[i] - minPar[i];
02151 double dMax = eMaxPar[i] - maxPar[i];
02152 double dPar = maxPar[i] - minPar[i];
02153 eID = theFirstEdgeID;
02154 for ( iE = 0; iE < nbEdges; iE++ )
02155 {
02156 list< TPoint* > & ePoints = getShapePoints( eID++ );
02157 for ( pIt = ++ePoints.begin(); pIt != ePoints.end(); pIt++ )
02158 {
02159 double par = (*pIt)->myXYZ.Coord( iC );
02160 double r = ( par - minPar[i] ) / dPar;
02161 par += ( 1 - r ) * dMin + r * dMax;
02162 (*pIt)->myXYZ.SetCoord( iC, par );
02163 }
02164 }
02165 }
02166
02167 TopoDS_Edge eBest;
02168 double minDist = DBL_MAX;
02169 for ( iE = 0 ; iE < nbEdges; iE++ )
02170 {
02171 #ifdef DBG_SETFIRSTEDGE
02172 MESSAGE ( " VARIANT " << iE );
02173 #endif
02174
02175
02176 double dist = 0;
02177 int eID = theFirstEdgeID;
02178 for ( eIt = theWire.begin(); eIt != theWire.end(); eIt++ )
02179 {
02180 list< TPoint* > & ePoints = getShapePoints( eID++ );
02181 computeUVOnEdge( *eIt, ePoints );
02182 for ( pIt = ++ePoints.begin(); pIt != ePoints.end(); pIt++ ) {
02183 TPoint* p = (*pIt);
02184 dist += ( p->myUV - gp_XY( p->myXYZ.X(), p->myXYZ.Y() )).SquareModulus();
02185 #ifdef DBG_SETFIRSTEDGE
02186 MESSAGE ( " ISO : ( " << p->myXYZ.X() << ", "<< p->myXYZ.Y() << " ) PCURVE : ( " <<
02187 p->myUV.X() << ", " << p->myUV.Y() << ") " );
02188 #endif
02189 }
02190 }
02191 #ifdef DBG_SETFIRSTEDGE
02192 MESSAGE ( "dist -- " << dist );
02193 #endif
02194 if ( dist < minDist ) {
02195 minDist = dist;
02196 eBest = theWire.front();
02197 }
02198
02199 theWire.splice( theWire.begin(), theWire, --theWire.end(), theWire.end() );
02200 }
02201
02202 if ( eBest != theWire.front() ) {
02203 eIt = find ( theWire.begin(), theWire.end(), eBest );
02204 theWire.splice( theWire.begin(), theWire, eIt, theWire.end() );
02205 }
02206
02207 return minDist;
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 bool SMESH_Pattern::sortSameSizeWires (TListOfEdgesList & theWireList,
02220 const TListOfEdgesList::iterator& theFromWire,
02221 const TListOfEdgesList::iterator& theToWire,
02222 const int theFirstEdgeID,
02223 list< list< TPoint* > >& theEdgesPointsList )
02224 {
02225 TopoDS_Face F = TopoDS::Face( myShape );
02226 int iW, nbWires = 0;
02227 TListOfEdgesList::iterator wlIt = theFromWire;
02228 while ( wlIt++ != theToWire )
02229 nbWires++;
02230
02231
02232
02233
02234 bool aBool;
02235 gp_XY orig( gp::Origin2d().XY() );
02236 vector< gp_XY > vGcVec( nbWires, orig ), gcVec( nbWires, orig );
02237 Bnd_Box2d bndBox, vBndBox;
02238 int eID = theFirstEdgeID;
02239 list< TopoDS_Edge >::iterator eIt;
02240 for ( iW = 0, wlIt = theFromWire; wlIt != theToWire; wlIt++, iW++ )
02241 {
02242 list< TopoDS_Edge > & wire = *wlIt;
02243 for ( eIt = wire.begin(); eIt != wire.end(); eIt++ )
02244 {
02245 list< TPoint* > & ePoints = getShapePoints( eID++ );
02246 TPoint* p = ePoints.front();
02247 if ( !compUVByIsoIntersection( theEdgesPointsList, p->myInitUV, p->myUV, aBool )) {
02248 MESSAGE("cant sortSameSizeWires()");
02249 return false;
02250 }
02251 gcVec[iW] += p->myUV;
02252 bndBox.Add( gp_Pnt2d( p->myUV ));
02253 TopoDS_Vertex V = TopExp::FirstVertex( *eIt, true );
02254 gp_Pnt2d vXY = BRep_Tool::Parameters( V, F );
02255 vGcVec[iW] += vXY.XY();
02256 vBndBox.Add( vXY );
02257
02258 p->myXYZ.SetCoord( p->myUV.X(), p->myUV.Y(), 0. );
02259 }
02260 gcVec[iW] /= nbWires;
02261 vGcVec[iW] /= nbWires;
02262
02263
02264 }
02265
02266
02267
02268 double minPar[2], maxPar[2], vMinPar[2], vMaxPar[2];
02269 bndBox.Get( minPar[0], minPar[1], maxPar[0], maxPar[1] );
02270 vBndBox.Get( vMinPar[0], vMinPar[1], vMaxPar[0], vMaxPar[1] );
02271 for ( int iC = 1, i = 0; i < 2; iC++, i++ )
02272 {
02273 double dMin = vMinPar[i] - minPar[i];
02274 double dMax = vMaxPar[i] - maxPar[i];
02275 double dPar = maxPar[i] - minPar[i];
02276 if ( Abs( dPar ) <= DBL_MIN )
02277 continue;
02278 for ( iW = 0; iW < nbWires; iW++ ) {
02279 double par = gcVec[iW].Coord( iC );
02280 double r = ( par - minPar[i] ) / dPar;
02281 par += ( 1 - r ) * dMin + r * dMax;
02282 gcVec[iW].SetCoord( iC, par );
02283 }
02284 }
02285
02286
02287
02288 TListOfEdgesList tmpWList;
02289 tmpWList.splice( tmpWList.end(), theWireList, theFromWire, theToWire );
02290 typedef map< int, TListOfEdgesList::iterator > TIntWirePosMap;
02291 TIntWirePosMap bndIndWirePosMap;
02292 vector< bool > bndFound( nbWires, false );
02293 for ( iW = 0, wlIt = tmpWList.begin(); iW < nbWires; iW++, wlIt++ )
02294 {
02295
02296
02297 double minDist = DBL_MAX;
02298 gp_XY & wGc = vGcVec[ iW ];
02299 int bIndex;
02300 for ( int iB = 0; iB < nbWires; iB++ ) {
02301 if ( bndFound[ iB ] ) continue;
02302 double dist = ( wGc - gcVec[ iB ] ).SquareModulus();
02303 if ( dist < minDist ) {
02304 minDist = dist;
02305 bIndex = iB;
02306 }
02307 }
02308 bndFound[ bIndex ] = true;
02309 bndIndWirePosMap.insert( TIntWirePosMap::value_type( bIndex, wlIt ));
02310 }
02311
02312
02313
02314 TIntWirePosMap::iterator bIndWPosIt = bndIndWirePosMap.begin();
02315 eID = theFirstEdgeID;
02316 for ( ; bIndWPosIt != bndIndWirePosMap.end(); bIndWPosIt++ )
02317 {
02318 TListOfEdgesList::iterator wirePos = (*bIndWPosIt).second;
02319 list < TopoDS_Edge > & wire = ( *wirePos );
02320
02321
02322 setFirstEdge( wire, eID );
02323
02324
02325 theEdgesPointsList.push_back( list< TPoint* >() );
02326 list< TPoint* > & edgesPoints = theEdgesPointsList.back();
02327 for ( eIt = wire.begin(); eIt != wire.end(); eIt++ )
02328 {
02329 list< TPoint* > & ePoints = getShapePoints( eID++ );
02330 computeUVOnEdge( *eIt, ePoints );
02331 edgesPoints.insert( edgesPoints.end(), ePoints.begin(), (--ePoints.end()));
02332 }
02333
02334 wlIt = wirePos++;
02335 theWireList.splice( theToWire, tmpWList, wlIt, wirePos );
02336 }
02337
02338 return true;
02339 }
02340
02341
02342
02343
02344
02345
02346
02347
02348 bool SMESH_Pattern::Apply (const TopoDS_Face& theFace,
02349 const TopoDS_Vertex& theVertexOnKeyPoint1,
02350 const bool theReverse)
02351 {
02352 MESSAGE(" ::Apply(face) " );
02353 TopoDS_Face face = theReverse ? TopoDS::Face( theFace.Reversed() ) : theFace;
02354 if ( !setShapeToMesh( face ))
02355 return false;
02356
02357
02358 if ( !findBoundaryPoints() )
02359 return false;
02360
02361
02362
02363
02364 list< TopoDS_Edge > eList;
02365 list< int > nbVertexInWires;
02366 int nbWires = SMESH_Block::GetOrderedEdges( face, theVertexOnKeyPoint1, eList, nbVertexInWires);
02367 if ( !theVertexOnKeyPoint1.IsSame( TopExp::FirstVertex( eList.front(), true )))
02368 {
02369 MESSAGE( " theVertexOnKeyPoint1 not found in the outer wire ");
02370 return setErrorCode( ERR_APPLF_BAD_VERTEX );
02371 }
02372
02373 list< int > l1 = myNbKeyPntInBoundary, l2 = nbVertexInWires;
02374 l1.sort(); l2.sort();
02375 if ( l1 != l2 )
02376 {
02377 MESSAGE( "Wrong nb vertices in wires" );
02378 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02379 }
02380
02381
02382 list<TopoDS_Edge>::iterator elIt = eList.begin();
02383 for ( ; elIt != eList.end(); elIt++ ) {
02384 myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
02385 bool isClosed1 = BRep_Tool::IsClosed( *elIt, theFace );
02386
02387 if (isClosed1) {
02388 isClosed1 = false;
02389 for (TopExp_Explorer expw (theFace, TopAbs_WIRE); expw.More() && !isClosed1; expw.Next()) {
02390 const TopoDS_Wire& wire = TopoDS::Wire(expw.Current());
02391 int nbe = 0;
02392 for (BRepTools_WireExplorer we (wire, theFace); we.More() && !isClosed1; we.Next()) {
02393 if (we.Current().IsSame(*elIt)) {
02394 nbe++;
02395 if (nbe == 2) isClosed1 = true;
02396 }
02397 }
02398 }
02399 }
02400
02401 if (isClosed1)
02402 myShapeIDMap.Add( TopExp::LastVertex( *elIt, true ));
02403 }
02404 int nbVertices = myShapeIDMap.Extent();
02405
02406 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
02407 myShapeIDMap.Add( *elIt );
02408
02409 myShapeIDMap.Add( face );
02410
02411 if ( myShapeIDToPointsMap.size() != myShapeIDMap.Extent() ) {
02412 MESSAGE( myShapeIDToPointsMap.size() <<" != " << myShapeIDMap.Extent());
02413 return setErrorCode( ERR_APPLF_INTERNAL_EEROR );
02414 }
02415
02416
02417 list< list< TPoint* > > edgesPointsList;
02418 edgesPointsList.push_back( list< TPoint* >() );
02419 list< TPoint* > * edgesPoints = & edgesPointsList.back();
02420 list< TPoint* >::iterator pIt;
02421
02422
02423 int iE, nbEdgesInOuterWire = nbVertexInWires.front();
02424 for (iE = 0, elIt = eList.begin();
02425 iE < nbEdgesInOuterWire && elIt != eList.end();
02426 iE++, elIt++ )
02427 {
02428 list< TPoint* > & ePoints = getShapePoints( *elIt );
02429
02430 computeUVOnEdge( *elIt, ePoints );
02431
02432 edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end());
02433 }
02434
02435
02436
02437
02438
02439 if ( nbWires > 1 )
02440 {
02441
02442
02443 bool aBool;
02444 list< list< TopoDS_Edge > > wireList;
02445 list<TopoDS_Edge>::iterator eIt = elIt;
02446 list<int>::iterator nbEIt = nbVertexInWires.begin();
02447 for ( nbEIt++; nbEIt != nbVertexInWires.end(); nbEIt++ )
02448 {
02449 int nbEdges = *nbEIt;
02450 wireList.push_back( list< TopoDS_Edge >() );
02451 list< TopoDS_Edge > & wire = wireList.back();
02452 for ( iE = 0 ; iE < nbEdges; eIt++, iE++ )
02453 {
02454 list< TPoint* > & ePoints = getShapePoints( *eIt );
02455 pIt = ePoints.begin();
02456 for ( pIt++; pIt != ePoints.end(); pIt++ ) {
02457 TPoint* p = (*pIt);
02458 if ( !compUVByIsoIntersection( edgesPointsList, p->myInitUV, p->myUV, aBool )) {
02459 MESSAGE("cant Apply(face)");
02460 return false;
02461 }
02462
02463 p->myXYZ.SetCoord( p->myUV.X(), p->myUV.Y(), 0. );
02464 }
02465 wire.push_back( *eIt );
02466 }
02467 }
02468
02469 eList.erase( elIt, eList.end() );
02470
02471
02472 sortBySize< TopoDS_Edge > ( wireList );
02473
02474
02475 int id1 = nbVertices + nbEdgesInOuterWire + 1;
02476
02477
02478
02479
02480
02481
02482 list< list< TopoDS_Edge > >::iterator wlIt = wireList.begin();
02483 while ( wlIt != wireList.end() )
02484 {
02485 list< TopoDS_Edge >& wire = (*wlIt);
02486 int nbEdges = wire.size();
02487 wlIt++;
02488 if ( wlIt == wireList.end() || (*wlIt).size() != nbEdges )
02489 {
02490
02491 setFirstEdge( wire, id1 );
02492
02493
02494 edgesPointsList.push_back( list< TPoint* >() );
02495 edgesPoints = & edgesPointsList.back();
02496 int eID = id1;
02497 for ( eIt = wire.begin(); eIt != wire.end(); eIt++ )
02498 {
02499 list< TPoint* > & ePoints = getShapePoints( eID++ );
02500 computeUVOnEdge( *eIt, ePoints );
02501 edgesPoints->insert( edgesPoints->end(), ePoints.begin(), (--ePoints.end()));
02502 }
02503 }
02504 id1 += nbEdges;
02505 }
02506
02507
02508
02509 id1 = nbVertices + nbEdgesInOuterWire + 1;
02510 wlIt = wireList.begin();
02511 while ( wlIt != wireList.end() )
02512 {
02513 int nbSameSize = 0, nbEdges = (*wlIt).size();
02514 list< list< TopoDS_Edge > >::iterator wlIt2 = wlIt;
02515 wlIt2++;
02516 while ( wlIt2 != wireList.end() && (*wlIt2).size() == nbEdges ) {
02517 nbSameSize++;
02518 wlIt2++;
02519 }
02520 if ( nbSameSize > 0 )
02521 if (!sortSameSizeWires(wireList, wlIt, wlIt2, id1, edgesPointsList))
02522 return false;
02523 wlIt = wlIt2;
02524 id1 += nbEdges * ( nbSameSize + 1 );
02525 }
02526
02527
02528
02529 for ( wlIt = wireList.begin(); wlIt != wireList.end(); wlIt++ )
02530 {
02531 list< TopoDS_Edge >& wire = (*wlIt);
02532 eList.splice( eList.end(), wire, wire.begin(), wire.end() );
02533 }
02534
02535
02536
02537 myShapeIDMap.Clear();
02538 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
02539 myShapeIDMap.Add( TopExp::FirstVertex( *elIt, true ));
02540 for ( elIt = eList.begin(); elIt != eList.end(); elIt++ )
02541 myShapeIDMap.Add( *elIt );
02542 myShapeIDMap.Add( face );
02543
02544 }
02545
02546
02547
02548 TopLoc_Location loc;
02549 for ( iE = nbVertices + 1, elIt = eList.begin(); elIt != eList.end(); elIt++ )
02550 {
02551 BRepAdaptor_Curve C3d( *elIt );
02552 list< TPoint* > & ePoints = getShapePoints( iE++ );
02553 pIt = ePoints.begin();
02554 for ( pIt++; pIt != ePoints.end(); pIt++ )
02555 {
02556 TPoint* point = *pIt;
02557 point->myXYZ = C3d.Value( point->myU );
02558 }
02559 }
02560
02561
02562
02563
02564 list< TPoint* > & fPoints = getShapePoints( face );
02565 bool isDeformed = false;
02566 for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ )
02567 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02568 (*pIt)->myUV, isDeformed )) {
02569 MESSAGE("cant Apply(face)");
02570 return false;
02571 }
02572
02573 if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints ))
02574 {
02575 for ( ; pIt != fPoints.end(); pIt++ )
02576 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02577 (*pIt)->myUV, isDeformed )) {
02578 MESSAGE("cant Apply(face)");
02579 return false;
02580 }
02581 }
02582
02583 Handle(Geom_Surface) aSurface = BRep_Tool::Surface( face, loc );
02584 const gp_Trsf & aTrsf = loc.Transformation();
02585 for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ )
02586 {
02587 TPoint * point = *pIt;
02588 point->myXYZ = aSurface->Value( point->myUV.X(), point->myUV.Y() );
02589 if ( !loc.IsIdentity() )
02590 aTrsf.Transforms( point->myXYZ.ChangeCoord() );
02591 }
02592
02593 myIsComputed = true;
02594
02595 return setErrorCode( ERR_OK );
02596 }
02597
02598
02599
02600
02601
02602
02603
02604
02605 bool SMESH_Pattern::Apply (const SMDS_MeshFace* theFace,
02606 const int theNodeIndexOnKeyPoint1,
02607 const bool theReverse)
02608 {
02609
02610
02611 if ( !IsLoaded() ) {
02612 MESSAGE( "Pattern not loaded" );
02613 return setErrorCode( ERR_APPL_NOT_LOADED );
02614 }
02615
02616
02617 const int nbFaceNodes = theFace->NbCornerNodes();
02618 if ( nbFaceNodes != myNbKeyPntInBoundary.front() ) {
02619 MESSAGE( myKeyPointIDs.size() << " != " << nbFaceNodes );
02620 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02621 }
02622
02623
02624 if ( !findBoundaryPoints() )
02625 return false;
02626
02627
02628 if (myNbKeyPntInBoundary.size() > 1 ) {
02629 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02630 }
02631
02632
02633
02634 list< const SMDS_MeshNode* > nodes;
02635 list< const SMDS_MeshNode* >::iterator n = nodes.end();
02636 SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
02637 int iSub = 0;
02638 while ( noIt->more() && iSub < nbFaceNodes ) {
02639 const SMDS_MeshNode* node = smdsNode( noIt->next() );
02640 nodes.push_back( node );
02641 if ( iSub++ == theNodeIndexOnKeyPoint1 )
02642 n = --nodes.end();
02643 }
02644 if ( n != nodes.end() ) {
02645 if ( theReverse ) {
02646 if ( n != --nodes.end() )
02647 nodes.splice( nodes.begin(), nodes, ++n, nodes.end() );
02648 nodes.reverse();
02649 }
02650 else if ( n != nodes.begin() )
02651 nodes.splice( nodes.end(), nodes, nodes.begin(), n );
02652 }
02653 list< gp_XYZ > xyzList;
02654 myOrderedNodes.resize( nbFaceNodes );
02655 for ( iSub = 0, n = nodes.begin(); n != nodes.end(); ++n ) {
02656 xyzList.push_back( gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() ));
02657 myOrderedNodes[ iSub++] = *n;
02658 }
02659
02660
02661
02662 list< gp_XYZ >::iterator xyzIt = xyzList.begin();
02663 gp_Pnt P ( *xyzIt++ );
02664 gp_Vec Vx( P, *xyzIt++ ), N;
02665 do {
02666 N = Vx ^ gp_Vec( P, *xyzIt++ );
02667 } while ( N.SquareMagnitude() <= DBL_MIN && xyzIt != xyzList.end() );
02668 if ( N.SquareMagnitude() <= DBL_MIN )
02669 return setErrorCode( ERR_APPLF_BAD_FACE_GEOM );
02670 gp_Ax2 pos( P, N, Vx );
02671
02672
02673 for ( xyzIt = xyzList.begin(), iSub = 1; xyzIt != xyzList.end(); xyzIt++, iSub++ )
02674 {
02675 gp_Vec vec ( pos.Location(), *xyzIt );
02676 TPoint* p = getShapePoints( iSub ).front();
02677 p->myUV.SetX( vec * pos.XDirection() );
02678 p->myUV.SetY( vec * pos.YDirection() );
02679 p->myXYZ = *xyzIt;
02680 }
02681
02682
02683 list< list< TPoint* > > edgesPointsList;
02684 edgesPointsList.push_back( list< TPoint* >() );
02685 list< TPoint* > * edgesPoints = & edgesPointsList.back();
02686 list< TPoint* >::iterator pIt;
02687
02688
02689
02690 for ( xyzIt = xyzList.begin(); xyzIt != xyzList.end(); iSub++ )
02691 {
02692 gp_XYZ& xyz1 = *xyzIt++;
02693 gp_XYZ& xyz2 = ( xyzIt != xyzList.end() ) ? *xyzIt : xyzList.front();
02694
02695 list< TPoint* > & ePoints = getShapePoints( iSub );
02696 ePoints.back()->myInitU = 1.0;
02697 list< TPoint* >::const_iterator pIt = ++ePoints.begin();
02698 while ( *pIt != ePoints.back() )
02699 {
02700 TPoint* p = *pIt++;
02701 p->myXYZ = xyz1 * ( 1 - p->myInitU ) + xyz2 * p->myInitU;
02702 gp_Vec vec ( pos.Location(), p->myXYZ );
02703 p->myUV.SetX( vec * pos.XDirection() );
02704 p->myUV.SetY( vec * pos.YDirection() );
02705 }
02706
02707 edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end());
02708 }
02709
02710
02711
02712
02713 list< TPoint* > & fPoints = getShapePoints( iSub );
02714 bool isDeformed = false;
02715 for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ )
02716 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02717 (*pIt)->myUV, isDeformed )) {
02718 MESSAGE("cant Apply(face)");
02719 return false;
02720 }
02721
02722 if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints ))
02723 {
02724 for ( ; pIt != fPoints.end(); pIt++ )
02725 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02726 (*pIt)->myUV, isDeformed )) {
02727 MESSAGE("cant Apply(face)");
02728 return false;
02729 }
02730 }
02731
02732 for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ )
02733 {
02734 (*pIt)->myXYZ = ElSLib::PlaneValue( (*pIt)->myUV.X(), (*pIt)->myUV.Y(), pos );
02735 }
02736
02737 myIsComputed = true;
02738
02739 return setErrorCode( ERR_OK );
02740 }
02741
02742
02743
02744
02745
02746
02747
02748
02749 bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
02750 const SMDS_MeshFace* theFace,
02751 const TopoDS_Shape& theSurface,
02752 const int theNodeIndexOnKeyPoint1,
02753 const bool theReverse)
02754 {
02755
02756 if ( theSurface.IsNull() || theSurface.ShapeType() != TopAbs_FACE ) {
02757 return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse);
02758 }
02759 const TopoDS_Face& face = TopoDS::Face( theSurface );
02760 TopLoc_Location loc;
02761 Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc );
02762 const gp_Trsf & aTrsf = loc.Transformation();
02763
02764 if ( !IsLoaded() ) {
02765 MESSAGE( "Pattern not loaded" );
02766 return setErrorCode( ERR_APPL_NOT_LOADED );
02767 }
02768
02769
02770 if (theFace->NbNodes() != myNbKeyPntInBoundary.front() ) {
02771 MESSAGE( myKeyPointIDs.size() << " != " << theFace->NbNodes() );
02772 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02773 }
02774
02775
02776 if ( !findBoundaryPoints() )
02777 return false;
02778
02779
02780 if (myNbKeyPntInBoundary.size() > 1 ) {
02781 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02782 }
02783
02784
02785
02786 list< const SMDS_MeshNode* > nodes;
02787 list< const SMDS_MeshNode* >::iterator n = nodes.end();
02788 SMDS_ElemIteratorPtr noIt = theFace->nodesIterator();
02789 int iSub = 0;
02790 while ( noIt->more() ) {
02791 const SMDS_MeshNode* node = smdsNode( noIt->next() );
02792 nodes.push_back( node );
02793 if ( iSub++ == theNodeIndexOnKeyPoint1 )
02794 n = --nodes.end();
02795 }
02796 if ( n != nodes.end() ) {
02797 if ( theReverse ) {
02798 if ( n != --nodes.end() )
02799 nodes.splice( nodes.begin(), nodes, ++n, nodes.end() );
02800 nodes.reverse();
02801 }
02802 else if ( n != nodes.begin() )
02803 nodes.splice( nodes.end(), nodes, nodes.begin(), n );
02804 }
02805
02806
02807 SMESH_MesherHelper helper( *theMesh );
02808 helper.SetSubShape( theSurface );
02809 const SMDS_MeshNode* inFaceNode = 0;
02810 if ( helper.GetNodeUVneedInFaceNode() )
02811 {
02812 SMESH_MeshEditor editor( theMesh );
02813 for ( n = nodes.begin(); ( !inFaceNode && n != nodes.end()); ++n ) {
02814 int shapeID = editor.FindShape( *n );
02815 if ( !shapeID )
02816 return Apply( theFace, theNodeIndexOnKeyPoint1, theReverse);
02817 if ( !helper.IsSeamShape( shapeID ))
02818 inFaceNode = *n;
02819 }
02820 }
02821
02822
02823 vector< gp_XY > keyUV( theFace->NbNodes() );
02824 myOrderedNodes.resize( theFace->NbNodes() );
02825 for ( iSub = 1, n = nodes.begin(); n != nodes.end(); ++n, ++iSub )
02826 {
02827 TPoint* p = getShapePoints( iSub ).front();
02828 p->myUV = helper.GetNodeUV( face, *n, inFaceNode );
02829 p->myXYZ = gp_XYZ( (*n)->X(), (*n)->Y(), (*n)->Z() );
02830
02831 keyUV[ iSub-1 ] = p->myUV;
02832 myOrderedNodes[ iSub-1 ] = *n;
02833 }
02834
02835
02836 list< list< TPoint* > > edgesPointsList;
02837 edgesPointsList.push_back( list< TPoint* >() );
02838 list< TPoint* > * edgesPoints = & edgesPointsList.back();
02839 list< TPoint* >::iterator pIt;
02840
02841
02842
02843 for ( int i = 0; i < myOrderedNodes.size(); ++i, ++iSub )
02844 {
02845 gp_XY& uv1 = keyUV[ i ];
02846 gp_XY& uv2 = ( i+1 < keyUV.size() ) ? keyUV[ i+1 ] : keyUV[ 0 ];
02847
02848 list< TPoint* > & ePoints = getShapePoints( iSub );
02849 ePoints.back()->myInitU = 1.0;
02850 list< TPoint* >::const_iterator pIt = ++ePoints.begin();
02851 while ( *pIt != ePoints.back() )
02852 {
02853 TPoint* p = *pIt++;
02854 p->myUV = uv1 * ( 1 - p->myInitU ) + uv2 * p->myInitU;
02855 p->myXYZ = surface->Value( p->myUV.X(), p->myUV.Y() );
02856 if ( !loc.IsIdentity() )
02857 aTrsf.Transforms( p->myXYZ.ChangeCoord() );
02858 }
02859
02860 edgesPoints->insert( edgesPoints->end(), ePoints.begin(), --ePoints.end());
02861 }
02862
02863
02864
02865
02866 list< TPoint* > & fPoints = getShapePoints( iSub );
02867 bool isDeformed = false;
02868 for ( pIt = fPoints.begin(); !isDeformed && pIt != fPoints.end(); pIt++ )
02869 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02870 (*pIt)->myUV, isDeformed )) {
02871 MESSAGE("cant Apply(face)");
02872 return false;
02873 }
02874
02875 if ( isDeformed && !compUVByElasticIsolines( edgesPointsList, fPoints ))
02876 {
02877 for ( ; pIt != fPoints.end(); pIt++ )
02878 if ( !compUVByIsoIntersection( edgesPointsList, (*pIt)->myInitUV,
02879 (*pIt)->myUV, isDeformed )) {
02880 MESSAGE("cant Apply(face)");
02881 return false;
02882 }
02883 }
02884
02885 for ( pIt = fPoints.begin(); pIt != fPoints.end(); pIt++ )
02886 {
02887 TPoint * point = *pIt;
02888 point->myXYZ = surface->Value( point->myUV.X(), point->myUV.Y() );
02889 if ( !loc.IsIdentity() )
02890 aTrsf.Transforms( point->myXYZ.ChangeCoord() );
02891 }
02892
02893 myIsComputed = true;
02894
02895 return setErrorCode( ERR_OK );
02896 }
02897
02898
02899
02900
02901
02902
02903 static const gp_XYZ& undefinedXYZ()
02904 {
02905 static gp_XYZ xyz( 1.e100, 0., 0. );
02906 return xyz;
02907 }
02908
02909
02910
02911
02912
02913
02914 inline static bool isDefined(const gp_XYZ& theXYZ)
02915 {
02916 return theXYZ.X() < 1.e100;
02917 }
02918
02919
02920
02921
02922
02923
02924
02925
02926 bool SMESH_Pattern::Apply (SMESH_Mesh* theMesh,
02927 std::set<const SMDS_MeshFace*>& theFaces,
02928 const int theNodeIndexOnKeyPoint1,
02929 const bool theReverse)
02930 {
02931 MESSAGE(" ::Apply(set<MeshFace>) " );
02932
02933 if ( !IsLoaded() ) {
02934 MESSAGE( "Pattern not loaded" );
02935 return setErrorCode( ERR_APPL_NOT_LOADED );
02936 }
02937
02938
02939 if ( !findBoundaryPoints() )
02940 return false;
02941
02942
02943 if (myNbKeyPntInBoundary.size() > 1 ) {
02944 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
02945 }
02946
02947 myShape.Nullify();
02948 myXYZ.clear();
02949 myElemXYZIDs.clear();
02950 myXYZIdToNodeMap.clear();
02951 myElements.clear();
02952 myIdsOnBoundary.clear();
02953 myReverseConnectivity.clear();
02954
02955 myXYZ.resize( myPoints.size() * theFaces.size(), undefinedXYZ() );
02956 myElements.reserve( theFaces.size() );
02957
02958
02959 map< TPoint*, int > pointIndex;
02960 for ( int i = 0; i < myPoints.size(); i++ )
02961 pointIndex.insert( make_pair( & myPoints[ i ], i ));
02962
02963 int ind1 = 0;
02964
02965
02966 TopoDS_Shape shape;
02967
02968
02969
02970
02971 set<const SMDS_MeshFace*>::iterator face = theFaces.begin();
02972 for ( ; face != theFaces.end(); ++face )
02973 {
02974
02975
02976
02977
02978
02979
02980
02981
02982 bool ok;
02983 if ( shape.IsNull() )
02984 ok = Apply( *face, theNodeIndexOnKeyPoint1, theReverse );
02985 else
02986 ok = Apply( theMesh, *face, shape, theNodeIndexOnKeyPoint1, theReverse );
02987 if ( !ok ) {
02988 MESSAGE( "Failed on " << *face );
02989 continue;
02990 }
02991 myElements.push_back( *face );
02992
02993
02994 list< TElemDef >::iterator ll = myElemPointIDs.begin();
02995 for ( ; ll != myElemPointIDs.end(); ++ll )
02996 {
02997 myElemXYZIDs.push_back(TElemDef());
02998 TElemDef& xyzIds = myElemXYZIDs.back();
02999 TElemDef& pIds = *ll;
03000 for ( TElemDef::iterator id = pIds.begin(); id != pIds.end(); id++ ) {
03001 int pIndex = *id + ind1;
03002 xyzIds.push_back( pIndex );
03003 myXYZ[ pIndex ] = myPoints[ *id ].myXYZ.XYZ();
03004 myReverseConnectivity[ pIndex ].push_back( & xyzIds );
03005 }
03006 }
03007
03008
03009 int nbNodes = (*face)->NbCornerNodes(), eID = nbNodes + 1;
03010 for ( int i = 0; i < nbNodes; i++ )
03011 {
03012 list< TPoint* > & linkPoints = getShapePoints( eID++ );
03013 const SMDS_MeshNode* n1 = myOrderedNodes[ i ];
03014 const SMDS_MeshNode* n2 = myOrderedNodes[ i + 1 == nbNodes ? 0 : i + 1 ];
03015
03016 TNodeSet linkSet, node1Set;
03017 linkSet.insert( n1 );
03018 linkSet.insert( n2 );
03019 node1Set.insert( n1 );
03020 list< TPoint* >::iterator p = linkPoints.begin();
03021 {
03022
03023 int nId = pointIndex[ *p ] + ind1;
03024 myXYZIdToNodeMap[ nId ] = n1;
03025 list< list< int > >& groups = myIdsOnBoundary[ node1Set ];
03026 groups.push_back(list< int > ());
03027 groups.back().push_back( nId );
03028 }
03029
03030 list< list< int > >& groups = myIdsOnBoundary[ linkSet ];
03031 groups.push_back(list< int > ());
03032 list< int >& indList = groups.back();
03033
03034 for ( p++; *p != linkPoints.back(); p++ )
03035 indList.push_back( pointIndex[ *p ] + ind1 );
03036 }
03037 ind1 += myPoints.size();
03038 }
03039
03040 return !myElemXYZIDs.empty();
03041 }
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052 bool SMESH_Pattern::Apply (std::set<const SMDS_MeshVolume*> & theVolumes,
03053 const int theNode000Index,
03054 const int theNode001Index)
03055 {
03056 MESSAGE(" ::Apply(set<MeshVolumes>) " );
03057
03058 if ( !IsLoaded() ) {
03059 MESSAGE( "Pattern not loaded" );
03060 return setErrorCode( ERR_APPL_NOT_LOADED );
03061 }
03062
03063
03064 if ( !findBoundaryPoints() )
03065 return false;
03066
03067
03068 if (myNbKeyPntInBoundary.size() > 1 ) {
03069 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
03070 }
03071
03072 myShape.Nullify();
03073 myXYZ.clear();
03074 myElemXYZIDs.clear();
03075 myXYZIdToNodeMap.clear();
03076 myElements.clear();
03077 myIdsOnBoundary.clear();
03078 myReverseConnectivity.clear();
03079
03080 myXYZ.resize( myPoints.size() * theVolumes.size(), undefinedXYZ() );
03081 myElements.reserve( theVolumes.size() );
03082
03083
03084 map< TPoint*, int > pointIndex;
03085 for ( int i = 0; i < myPoints.size(); i++ )
03086 pointIndex.insert( make_pair( & myPoints[ i ], i ));
03087
03088 int ind1 = 0;
03089
03090
03091 set<const SMDS_MeshVolume*>::iterator vol = theVolumes.begin();
03092 for ( ; vol != theVolumes.end(); ++vol )
03093 {
03094 if ( !Apply( *vol, theNode000Index, theNode001Index )) {
03095 MESSAGE( "Failed on " << *vol );
03096 continue;
03097 }
03098 myElements.push_back( *vol );
03099
03100
03101 list< TElemDef >::iterator ll = myElemPointIDs.begin();
03102 for ( ; ll != myElemPointIDs.end(); ++ll )
03103 {
03104 myElemXYZIDs.push_back(TElemDef());
03105 TElemDef& xyzIds = myElemXYZIDs.back();
03106 TElemDef& pIds = *ll;
03107 for ( TElemDef::iterator id = pIds.begin(); id != pIds.end(); id++ ) {
03108 int pIndex = *id + ind1;
03109 xyzIds.push_back( pIndex );
03110 myXYZ[ pIndex ] = myPoints[ *id ].myXYZ.XYZ();
03111 myReverseConnectivity[ pIndex ].push_back( & xyzIds );
03112 }
03113 }
03114
03115
03116 for ( int Id = SMESH_Block::ID_V000; Id <= SMESH_Block::ID_F1yz; Id++ )
03117 {
03118
03119 TNodeSet subNodes;
03120 vector< int > subIDs;
03121 if ( SMESH_Block::IsVertexID( Id )) {
03122 subNodes.insert( myOrderedNodes[ Id - 1 ]);
03123 }
03124 else if ( SMESH_Block::IsEdgeID( Id )) {
03125 SMESH_Block::GetEdgeVertexIDs( Id, subIDs );
03126 subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
03127 subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
03128 }
03129 else {
03130 SMESH_Block::GetFaceEdgesIDs( Id, subIDs );
03131 int e1 = subIDs[ 0 ], e2 = subIDs[ 1 ];
03132 SMESH_Block::GetEdgeVertexIDs( e1, subIDs );
03133 subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
03134 subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
03135 SMESH_Block::GetEdgeVertexIDs( e2, subIDs );
03136 subNodes.insert( myOrderedNodes[ subIDs.front() - 1 ]);
03137 subNodes.insert( myOrderedNodes[ subIDs.back() - 1 ]);
03138 }
03139
03140 list< TPoint* > & points = getShapePoints( Id );
03141 list< TPoint* >::iterator p = points.begin();
03142 list< list< int > >& groups = myIdsOnBoundary[ subNodes ];
03143 groups.push_back(list< int > ());
03144 list< int >& indList = groups.back();
03145 for ( ; p != points.end(); p++ )
03146 indList.push_back( pointIndex[ *p ] + ind1 );
03147 if ( subNodes.size() == 1 )
03148 myXYZIdToNodeMap[ indList.back() ] = myOrderedNodes[ Id - 1 ];
03149 }
03150 ind1 += myPoints.size();
03151 }
03152
03153 return !myElemXYZIDs.empty();
03154 }
03155
03156
03157
03158
03159
03160
03161 bool SMESH_Pattern::Load (SMESH_Mesh* theMesh,
03162 const TopoDS_Shell& theBlock)
03163 {
03164 MESSAGE(" ::Load(volume) " );
03165 Clear();
03166 myIs2D = false;
03167 SMESHDS_SubMesh * aSubMesh;
03168
03169 const bool isQuadMesh = theMesh->NbVolumes( ORDER_QUADRATIC );
03170
03171
03172 SMESH_Block block;
03173 TopoDS_Vertex v1, v2;
03174 if ( !block.LoadBlockShapes( theBlock, v1, v2, myShapeIDMap ))
03175 return setErrorCode( ERR_LOADV_BAD_SHAPE );
03176
03177
03178 int nbNodes = 0, shapeID;
03179 for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
03180 {
03181 const TopoDS_Shape& S = myShapeIDMap( shapeID );
03182 aSubMesh = getSubmeshWithElements( theMesh, S );
03183 if ( aSubMesh )
03184 nbNodes += aSubMesh->NbNodes();
03185 }
03186 myPoints.resize( nbNodes );
03187
03188
03189 TNodePointIDMap nodePointIDMap;
03190 int iPoint = 0;
03191 for ( shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
03192 {
03193 const TopoDS_Shape& S = myShapeIDMap( shapeID );
03194 list< TPoint* > & shapePoints = getShapePoints( shapeID );
03195 aSubMesh = getSubmeshWithElements( theMesh, S );
03196 if ( ! aSubMesh ) continue;
03197 SMDS_NodeIteratorPtr nIt = aSubMesh->GetNodes();
03198 if ( !nIt->more() ) continue;
03199
03200
03201 while ( nIt->more() ) {
03202 const SMDS_MeshNode* node = smdsNode( nIt->next() );
03203 if ( isQuadMesh && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Volume ))
03204 continue;
03205 nodePointIDMap.insert( make_pair( node, iPoint ));
03206 if ( block.IsVertexID( shapeID ))
03207 myKeyPointIDs.push_back( iPoint );
03208 TPoint* p = & myPoints[ iPoint++ ];
03209 shapePoints.push_back( p );
03210 p->myXYZ.SetCoord( node->X(), node->Y(), node->Z() );
03211 p->myInitXYZ.SetCoord( 0,0,0 );
03212 }
03213 list< TPoint* >::iterator pIt = shapePoints.begin();
03214
03215
03216 switch ( S.ShapeType() )
03217 {
03218 case TopAbs_VERTEX:
03219 case TopAbs_EDGE: {
03220
03221 for ( ; pIt != shapePoints.end(); pIt++ ) {
03222 double * coef = block.GetShapeCoef( shapeID );
03223 for ( int iCoord = 1; iCoord <= 3; iCoord++ )
03224 if ( coef[ iCoord - 1] > 0 )
03225 (*pIt)->myInitXYZ.SetCoord( iCoord, 1. );
03226 }
03227 if ( S.ShapeType() == TopAbs_VERTEX )
03228 break;
03229
03230 const TopoDS_Edge& edge = TopoDS::Edge( S );
03231 double f,l;
03232 BRep_Tool::Range( edge, f, l );
03233 int iCoord = SMESH_Block::GetCoordIndOnEdge( shapeID );
03234 bool isForward = SMESH_Block::IsForwardEdge( edge, myShapeIDMap );
03235 pIt = shapePoints.begin();
03236 nIt = aSubMesh->GetNodes();
03237 for ( ; nIt->more(); pIt++ )
03238 {
03239 const SMDS_MeshNode* node = nIt->next();
03240 if ( isQuadMesh && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge ))
03241 continue;
03242 const SMDS_EdgePosition* epos =
03243 static_cast<const SMDS_EdgePosition*>(node->GetPosition());
03244 double u = ( epos->GetUParameter() - f ) / ( l - f );
03245 (*pIt)->myInitXYZ.SetCoord( iCoord, isForward ? u : 1 - u );
03246 }
03247 break;
03248 }
03249 default:
03250 for ( ; pIt != shapePoints.end(); pIt++ )
03251 {
03252 if ( !block.ComputeParameters( (*pIt)->myXYZ, (*pIt)->myInitXYZ, shapeID )) {
03253 MESSAGE( "!block.ComputeParameters()" );
03254 return setErrorCode( ERR_LOADV_COMPUTE_PARAMS );
03255 }
03256 }
03257 }
03258 }
03259
03260
03261
03262 aSubMesh = getSubmeshWithElements( theMesh, theBlock );
03263 if ( aSubMesh )
03264 {
03265 SMDS_ElemIteratorPtr elemIt = aSubMesh->GetElements();
03266 while ( elemIt->more() ) {
03267 const SMDS_MeshElement* elem = elemIt->next();
03268 myElemPointIDs.push_back( TElemDef() );
03269 TElemDef& elemPoints = myElemPointIDs.back();
03270 int nbNodes = elem->NbCornerNodes();
03271 for ( int i = 0;i < nbNodes; ++i )
03272 elemPoints.push_back( nodePointIDMap[ elem->GetNode( i )]);
03273 }
03274 }
03275
03276 myIsBoundaryPointsFound = true;
03277
03278 return setErrorCode( ERR_OK );
03279 }
03280
03281
03282
03283
03284
03285
03286 SMESHDS_SubMesh * SMESH_Pattern::getSubmeshWithElements(SMESH_Mesh* theMesh,
03287 const TopoDS_Shape& theShape)
03288 {
03289 SMESHDS_SubMesh * aSubMesh = theMesh->GetMeshDS()->MeshElements( theShape );
03290 if ( aSubMesh && ( aSubMesh->GetElements()->more() || aSubMesh->GetNodes()->more() ))
03291 return aSubMesh;
03292
03293 if ( theShape.ShapeType() == TopAbs_SHELL )
03294 {
03295
03296 TopTools_ListIteratorOfListOfShape it( theMesh->GetAncestors( theShape ));
03297 for (; it.More(); it.Next()) {
03298 aSubMesh = theMesh->GetMeshDS()->MeshElements( it.Value() );
03299 if ( aSubMesh && ( aSubMesh->GetElements()->more() || aSubMesh->GetNodes()->more() ))
03300 return aSubMesh;
03301 }
03302 }
03303 return 0;
03304 }
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315 bool SMESH_Pattern::Apply (const TopoDS_Shell& theBlock,
03316 const TopoDS_Vertex& theVertex000,
03317 const TopoDS_Vertex& theVertex001)
03318 {
03319 MESSAGE(" ::Apply(volume) " );
03320
03321 if (!findBoundaryPoints() ||
03322 !setShapeToMesh( theBlock ))
03323 return false;
03324
03325 SMESH_Block block;
03326 if (!block.LoadBlockShapes( theBlock, theVertex000, theVertex001, myShapeIDMap ))
03327 return setErrorCode( ERR_APPLV_BAD_SHAPE );
03328
03329
03330
03331 for ( int shapeID = 1; shapeID <= myShapeIDMap.Extent(); shapeID++ )
03332 {
03333 list< TPoint* > & shapePoints = getShapePoints( shapeID );
03334 list< TPoint* >::iterator pIt = shapePoints.begin();
03335 const TopoDS_Shape& S = myShapeIDMap( shapeID );
03336 switch ( S.ShapeType() )
03337 {
03338 case TopAbs_VERTEX: {
03339
03340 for ( ; pIt != shapePoints.end(); pIt++ )
03341 block.VertexPoint( shapeID, (*pIt)->myXYZ.ChangeCoord() );
03342 break;
03343 }
03344 case TopAbs_EDGE: {
03345
03346 for ( ; pIt != shapePoints.end(); pIt++ )
03347 block.EdgePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03348 break;
03349 }
03350 case TopAbs_FACE: {
03351
03352 for ( ; pIt != shapePoints.end(); pIt++ )
03353 block.FacePoint( shapeID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03354 break;
03355 }
03356 default:
03357 for ( ; pIt != shapePoints.end(); pIt++ )
03358 block.ShellPoint( (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03359 }
03360 }
03361
03362 myIsComputed = true;
03363
03364 return setErrorCode( ERR_OK );
03365 }
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376 bool SMESH_Pattern::Apply (const SMDS_MeshVolume* theVolume,
03377 const int theNode000Index,
03378 const int theNode001Index)
03379 {
03380
03381
03382 if (!findBoundaryPoints())
03383 return false;
03384
03385 SMESH_Block block;
03386 if (!block.LoadMeshBlock( theVolume, theNode000Index, theNode001Index, myOrderedNodes ))
03387 return setErrorCode( ERR_APPLV_BAD_SHAPE );
03388
03389
03390 for ( int ID = SMESH_Block::ID_V000; ID <= SMESH_Block::ID_Shell; ID++ )
03391 {
03392 list< TPoint* > & shapePoints = getShapePoints( ID );
03393 list< TPoint* >::iterator pIt = shapePoints.begin();
03394
03395 if ( block.IsVertexID( ID ))
03396 for ( ; pIt != shapePoints.end(); pIt++ ) {
03397 block.VertexPoint( ID, (*pIt)->myXYZ.ChangeCoord() );
03398 }
03399 else if ( block.IsEdgeID( ID ))
03400 for ( ; pIt != shapePoints.end(); pIt++ ) {
03401 block.EdgePoint( ID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03402 }
03403 else if ( block.IsFaceID( ID ))
03404 for ( ; pIt != shapePoints.end(); pIt++ ) {
03405 block.FacePoint( ID, (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03406 }
03407 else
03408 for ( ; pIt != shapePoints.end(); pIt++ )
03409 block.ShellPoint( (*pIt)->myInitXYZ, (*pIt)->myXYZ.ChangeCoord() );
03410 }
03411
03412 myIsComputed = true;
03413
03414 return setErrorCode( ERR_OK );
03415 }
03416
03417
03418
03419
03420
03421
03422 void SMESH_Pattern::mergePoints (const bool uniteGroups)
03423 {
03424 map< TNodeSet, list< list< int > > >::iterator idListIt = myIdsOnBoundary.begin();
03425 for ( ; idListIt != myIdsOnBoundary.end(); idListIt++ )
03426 {
03427 list<list< int > >& groups = idListIt->second;
03428 if ( groups.size() < 2 )
03429 continue;
03430
03431
03432 const TNodeSet& nodes = idListIt->first;
03433 double tol2 = 1.e-10;
03434 if ( nodes.size() > 1 ) {
03435 Bnd_Box box;
03436 TNodeSet::const_iterator n = nodes.begin();
03437 for ( ; n != nodes.end(); ++n )
03438 box.Add( gp_Pnt( (*n)->X(), (*n)->Y(), (*n)->Z() ));
03439 double x, y, z, X, Y, Z;
03440 box.Get( x, y, z, X, Y, Z );
03441 gp_Pnt p( x, y, z ), P( X, Y, Z );
03442 tol2 = 1.e-4 * p.SquareDistance( P );
03443 }
03444
03445
03446 bool unite = ( uniteGroups && nodes.size() == 2 );
03447 map< double, int > distIndMap;
03448 const SMDS_MeshNode* node = *nodes.begin();
03449 gp_Pnt P( node->X(), node->Y(), node->Z() );
03450
03451
03452
03453 list< int >::iterator ind1, ind2;
03454 list< list< int > >::iterator grpIt1, grpIt2;
03455 for ( grpIt1 = groups.begin(); grpIt1 != groups.end(); grpIt1++ )
03456 {
03457 list< int >& indices1 = *grpIt1;
03458 grpIt2 = grpIt1;
03459 for ( grpIt2++; grpIt2 != groups.end(); grpIt2++ )
03460 {
03461 list< int >& indices2 = *grpIt2;
03462 for ( ind1 = indices1.begin(); ind1 != indices1.end(); ind1++ )
03463 {
03464 gp_XYZ& p1 = myXYZ[ *ind1 ];
03465 ind2 = indices2.begin();
03466 while ( ind2 != indices2.end() )
03467 {
03468 gp_XYZ& p2 = myXYZ[ *ind2 ];
03469
03470 if ( ( p1 - p2 ).SquareModulus() <= tol2 )
03471 {
03472 ASSERT( myReverseConnectivity.find( *ind2 ) != myReverseConnectivity.end() );
03473 list< TElemDef* > & elemXYZIDsList = myReverseConnectivity[ *ind2 ];
03474 list< TElemDef* >::iterator elemXYZIDs = elemXYZIDsList.begin();
03475 for ( ; elemXYZIDs != elemXYZIDsList.end(); elemXYZIDs++ )
03476 {
03477
03478 myXYZ[ *ind2 ] = undefinedXYZ();
03479 replace( (*elemXYZIDs)->begin(), (*elemXYZIDs)->end(), *ind2, *ind1 );
03480 }
03481 ind2 = indices2.erase( ind2 );
03482 }
03483 else
03484 ind2++;
03485 }
03486 }
03487 }
03488 if ( unite ) {
03489 for ( ind1 = indices1.begin(); ind1 != indices1.end(); ind1++ )
03490 {
03491 ASSERT( isDefined( myXYZ[ *ind1 ] ));
03492 double dist = P.SquareDistance( myXYZ[ *ind1 ]);
03493 distIndMap.insert( make_pair( dist, *ind1 ));
03494 }
03495 }
03496 }
03497 if ( unite ) {
03498 list< int >& g = groups.front();
03499 g.clear();
03500 map< double, int >::iterator dist_ind = distIndMap.begin();
03501 for ( ; dist_ind != distIndMap.end(); dist_ind++ )
03502 g.push_back( dist_ind->second );
03503 }
03504 }
03505 }
03506
03507
03508
03509
03510
03511
03512 void SMESH_Pattern::
03513 makePolyElements(const vector< const SMDS_MeshNode* >& theNodes,
03514 const bool toCreatePolygons,
03515 const bool toCreatePolyedrs)
03516 {
03517 myPolyElemXYZIDs.clear();
03518 myPolyElems.clear();
03519 myPolyElems.reserve( myIdsOnBoundary.size() );
03520
03521
03522 TIDSortedElemSet avoidSet, elemSet;
03523 std::vector<const SMDS_MeshElement*>::iterator itv = myElements.begin();
03524 for(; itv!=myElements.end(); itv++) {
03525 const SMDS_MeshElement* el = (*itv);
03526 avoidSet.insert( el );
03527 }
03528
03529
03530 map< TNodeSet, list< list< int > > >::iterator indListIt, nn_IdList;
03531
03532 if ( toCreatePolygons )
03533 {
03534 int lastFreeId = myXYZ.size();
03535
03536
03537 indListIt = myIdsOnBoundary.begin();
03538 for ( ; indListIt != myIdsOnBoundary.end(); indListIt++ )
03539 {
03540 const TNodeSet & linkNodes = indListIt->first;
03541 if ( linkNodes.size() != 2 )
03542 continue;
03543 const SMDS_MeshNode* n1 = * linkNodes.begin();
03544 const SMDS_MeshNode* n2 = * linkNodes.rbegin();
03545
03546 list<list< int > >& idGroups = indListIt->second;
03547 if ( idGroups.empty() || idGroups.front().empty() )
03548 continue;
03549
03550
03551
03552 while (true)
03553 {
03554 const SMDS_MeshElement* face =
03555 SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet );
03556 if ( face )
03557 {
03558 avoidSet.insert ( face );
03559 myPolyElems.push_back( face );
03560
03561
03562
03563 myPolyElemXYZIDs.push_back(TElemDef());
03564 TElemDef & faceNodeIds = myPolyElemXYZIDs.back();
03565
03566 SMDS_ElemIteratorPtr nIt = face->nodesIterator();
03567 int i = 0, nbNodes = face->NbNodes();
03568 vector<const SMDS_MeshNode*> nodes( nbNodes + 1 );
03569 while ( nIt->more() )
03570 nodes[ i++ ] = smdsNode( nIt->next() );
03571 nodes[ i ] = nodes[ 0 ];
03572 for ( i = 0; i < nbNodes; ++i )
03573 {
03574
03575 TNodeSet faceLinkNodes;
03576 faceLinkNodes.insert( nodes[ i ] );
03577 faceLinkNodes.insert( nodes[ i + 1 ] );
03578 if ( faceLinkNodes == linkNodes )
03579 nn_IdList = indListIt;
03580 else
03581 nn_IdList = myIdsOnBoundary.find( faceLinkNodes );
03582
03583 faceNodeIds.push_back( ++lastFreeId );
03584 myXYZIdToNodeMap.insert( make_pair( lastFreeId, nodes[ i ]));
03585 if ( nn_IdList != myIdsOnBoundary.end() )
03586 {
03587
03588 list< int >& mappedIds = nn_IdList->second.front();
03589 if ( isReversed( nodes[ i ], mappedIds ))
03590 faceNodeIds.insert (faceNodeIds.end(),mappedIds.rbegin(), mappedIds.rend() );
03591 else
03592 faceNodeIds.insert (faceNodeIds.end(),mappedIds.begin(), mappedIds.end() );
03593 }
03594 }
03595 }
03596 else
03597 break;
03598 }
03599
03600 if ( myIs2D && idGroups.size() > 1 ) {
03601
03602
03603
03604 list< int >& idsOnLink = idGroups.front();
03605
03606 bool rev = isReversed( n1, idsOnLink );
03607 for ( int i = 0; i < 2; ++i )
03608 {
03609 TNodeSet nodeSet;
03610 nodeSet.insert( i ? n2 : n1 );
03611 ASSERT( myIdsOnBoundary.find( nodeSet ) != myIdsOnBoundary.end() );
03612 list<list< int > >& groups = myIdsOnBoundary[ nodeSet ];
03613 int nodeId = groups.front().front();
03614 bool append = i;
03615 if ( rev ) append = !append;
03616 if ( append )
03617 idsOnLink.push_back( nodeId );
03618 else
03619 idsOnLink.push_front( nodeId );
03620 }
03621 list< int >::iterator id = idsOnLink.begin();
03622 for ( ; id != idsOnLink.end(); ++id )
03623 {
03624 list< TElemDef* >& elemDefs = myReverseConnectivity[ *id ];
03625 list< TElemDef* >::iterator pElemDef = elemDefs.begin();
03626 for ( ; pElemDef != elemDefs.end(); pElemDef++ )
03627 {
03628 TElemDef* pIdList = *pElemDef;
03629
03630 TElemDef::iterator idDef = find( pIdList->begin(), pIdList->end(), *id );
03631 ASSERT ( idDef != pIdList->end() );
03632
03633 for ( int prev = 0; prev < 2; ++prev ) {
03634 TElemDef::iterator idDef2 = idDef;
03635 if ( prev )
03636 idDef2 = ( idDef2 == pIdList->begin() ) ? --pIdList->end() : --idDef2;
03637 else
03638 idDef2 = ( ++idDef2 == pIdList->end() ) ? pIdList->begin() : idDef2;
03639
03640 list< int >::iterator id2 = find( id, idsOnLink.end(), *idDef2 );
03641 if ( id2 != idsOnLink.end() && id != --id2 ) {
03642
03643
03644 if ( prev )
03645 for ( ; id2 != id; --id2 )
03646 pIdList->insert( idDef, *id2 );
03647 else {
03648 list< int >::iterator id1 = id;
03649 for ( ++id1, ++id2; id1 != id2; ++id1 )
03650 pIdList->insert( idDef2, *id1 );
03651 }
03652 }
03653 }
03654 }
03655 }
03656
03657 idsOnLink.pop_front();
03658 idsOnLink.pop_back();
03659 }
03660 }
03661 }
03662
03663 if ( toCreatePolyedrs )
03664 {
03665
03666 SMDS_VolumeTool volTool;
03667 vector<const SMDS_MeshElement*>::iterator refinedElem = myElements.begin();
03668 for ( ; refinedElem != myElements.end(); ++refinedElem )
03669 {
03670
03671 SMDS_ElemIteratorPtr nIt = (*refinedElem)->nodesIterator();
03672 while ( nIt->more() ) {
03673 const SMDS_MeshNode* node = smdsNode( nIt->next() );
03674
03675 SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
03676 while ( eIt->more() )
03677 {
03678 const SMDS_MeshElement* elem = eIt->next();
03679 if ( !volTool.Set( elem ) || !avoidSet.insert( elem ).second )
03680 continue;
03681
03682 myPolyhedronQuantities.push_back(vector<int> ());
03683 myPolyElemXYZIDs.push_back(TElemDef());
03684 vector<int>& quantity = myPolyhedronQuantities.back();
03685 TElemDef & elemDef = myPolyElemXYZIDs.back();
03686
03687 bool makePoly = false;
03688 for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
03689 {
03690 if ( getFacesDefinition(volTool.GetFaceNodes( iF ),
03691 volTool.NbFaceNodes( iF ),
03692 theNodes, elemDef, quantity))
03693 makePoly = true;
03694 }
03695 if ( makePoly )
03696 myPolyElems.push_back( elem );
03697 else {
03698 myPolyhedronQuantities.pop_back();
03699 myPolyElemXYZIDs.pop_back();
03700 }
03701 }
03702 }
03703 }
03704 }
03705 }
03706
03707
03708
03709
03710
03711
03712 bool SMESH_Pattern::
03713 getFacesDefinition(const SMDS_MeshNode** theBndNodes,
03714 const int theNbBndNodes,
03715 const vector< const SMDS_MeshNode* >& theNodes,
03716 list< int >& theFaceDefs,
03717 vector<int>& theQuantity)
03718 {
03719 bool makePoly = false;
03720
03721 set< const SMDS_MeshNode* > bndNodeSet( theBndNodes, theBndNodes + theNbBndNodes);
03722
03723 map< TNodeSet, list< list< int > > >::iterator nn_IdList;
03724
03725
03726 set< int > ids;
03727 if ( !myIs2D ) {
03728 nn_IdList = myIdsOnBoundary.find( bndNodeSet );
03729 if ( nn_IdList != myIdsOnBoundary.end() ) {
03730 list< int > & faceIds = nn_IdList->second.front();
03731 if ( !faceIds.empty() ) {
03732 makePoly = true;
03733 ids.insert( faceIds.begin(), faceIds.end() );
03734 }
03735 }
03736 }
03737
03738
03739 int lastFreeId = Max( myXYZIdToNodeMap.rbegin()->first, theNodes.size() );
03740 TElemDef faceDef;
03741 for ( int iN = 0; iN < theNbBndNodes; ++iN )
03742 {
03743
03744 TNodeSet nSet;
03745 nSet.insert( theBndNodes[ iN ] );
03746 nn_IdList = myIdsOnBoundary.find( nSet );
03747 int bndId = ++lastFreeId;
03748 if ( nn_IdList != myIdsOnBoundary.end() ) {
03749 bndId = nn_IdList->second.front().front();
03750 ids.insert( bndId );
03751 }
03752 else {
03753 myXYZIdToNodeMap.insert( make_pair( bndId, theBndNodes[ iN ] ));
03754 }
03755 faceDef.push_back( bndId );
03756
03757 TNodeSet linkNodes;
03758 linkNodes.insert( theBndNodes[ iN ]);
03759 linkNodes.insert( theBndNodes[ (iN + 1) % theNbBndNodes] );
03760 nn_IdList = myIdsOnBoundary.find( linkNodes );
03761 if ( nn_IdList != myIdsOnBoundary.end() ) {
03762 list< int > & linkIds = nn_IdList->second.front();
03763 if ( !linkIds.empty() )
03764 {
03765 makePoly = true;
03766 ids.insert( linkIds.begin(), linkIds.end() );
03767 if ( isReversed( theBndNodes[ iN ], linkIds ))
03768 faceDef.insert( faceDef.end(), linkIds.begin(), linkIds.end() );
03769 else
03770 faceDef.insert( faceDef.end(), linkIds.rbegin(), linkIds.rend() );
03771 }
03772 }
03773 }
03774
03775
03776
03777 bool defsAdded = false;
03778 if ( !myIs2D ) {
03779 SMDS_VolumeTool vol;
03780 set< TElemDef* > checkedVolDefs;
03781 set< int >::iterator id = ids.begin();
03782 for ( ; id != ids.end(); ++id )
03783 {
03784
03785 list< TElemDef* >& defList = myReverseConnectivity[ *id ];
03786 ASSERT( !defList.empty() );
03787
03788 list< TElemDef* >::iterator pIdList = defList.begin();
03789 for ( ; pIdList != defList.end(); ++pIdList)
03790 {
03791 if ( !checkedVolDefs.insert( *pIdList ).second )
03792 continue;
03793 vector< int > idVec( (*pIdList)->begin(), (*pIdList)->end() );
03794
03795 SMDS_VolumeTool::VolumeType volType = vol.GetType( idVec.size() );
03796 if ( volType == SMDS_VolumeTool::UNKNOWN )
03797 continue;
03798 int nbFaces = vol.NbFaces( volType );
03799 for ( int iF = 0; iF < nbFaces; ++iF )
03800 {
03801 const int* nodeInds = vol.GetFaceNodesIndices( volType, iF, true );
03802 int iN, nbN = vol.NbFaceNodes( volType, iF );
03803
03804 bool all = true;
03805 for ( iN = 0; iN < nbN && all; ++iN ) {
03806 int nodeId = idVec[ nodeInds[ iN ]];
03807 all = ( ids.find( nodeId ) != ids.end() );
03808 }
03809 if ( all ) {
03810
03811 for ( iN = 0; iN < nbN; ++iN ) {
03812 theFaceDefs.push_back( idVec[ nodeInds[ iN ]]);
03813 }
03814 theQuantity.push_back( nbN );
03815 defsAdded = true;
03816 }
03817 }
03818 }
03819 }
03820 }
03821 if ( !defsAdded ) {
03822 theQuantity.push_back( faceDef.size() );
03823 theFaceDefs.splice( theFaceDefs.end(), faceDef );
03824 }
03825
03826 return makePoly;
03827 }
03828
03829
03830
03831
03832
03833
03834 static bool clearSubMesh( SMESH_Mesh* theMesh,
03835 const TopoDS_Shape& theShape)
03836 {
03837 bool removed = false;
03838 if ( SMESH_subMesh * aSubMesh = theMesh->GetSubMeshContaining( theShape ))
03839 {
03840 removed = !aSubMesh->IsEmpty();
03841 if ( removed )
03842 aSubMesh->ComputeStateEngine( SMESH_subMesh::CLEAN );
03843 }
03844 else {
03845 SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
03846 if ( SMESHDS_SubMesh* aSubMeshDS = aMeshDS->MeshElements( theShape ))
03847 {
03848 SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
03849 removed = eIt->more();
03850 while ( eIt->more() )
03851 aMeshDS->RemoveElement( eIt->next() );
03852 SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
03853 removed = removed || nIt->more();
03854 while ( nIt->more() )
03855 aMeshDS->RemoveNode( smdsNode( nIt->next() ));
03856 }
03857 }
03858 return removed;
03859 }
03860
03861
03862
03863
03864
03865
03866 void SMESH_Pattern::clearMesh(SMESH_Mesh* theMesh) const
03867 {
03868
03869 if ( !myShape.IsNull() )
03870 {
03871 if ( !clearSubMesh( theMesh, myShape ) && !myIs2D ) {
03872 TopTools_ListIteratorOfListOfShape it( theMesh->GetAncestors( myShape ));
03873 for (; it.More() && it.Value().ShapeType() == TopAbs_SOLID; it.Next())
03874 {
03875 clearSubMesh( theMesh, it.Value() );
03876 }
03877 }
03878 }
03879 }
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890 bool SMESH_Pattern::MakeMesh(SMESH_Mesh* theMesh,
03891 const bool toCreatePolygons,
03892 const bool toCreatePolyedrs)
03893 {
03894 MESSAGE(" ::MakeMesh() " );
03895 if ( !myIsComputed )
03896 return setErrorCode( ERR_MAKEM_NOT_COMPUTED );
03897
03898 mergePoints( toCreatePolygons );
03899
03900 SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
03901
03902
03903 clearMesh(theMesh);
03904
03905 bool onMeshElements = ( !myElements.empty() );
03906
03907
03908
03909 vector< const SMDS_MeshNode* > nodesVector;
03910 if ( onMeshElements )
03911 {
03912 nodesVector.resize( Max( myXYZ.size(), myXYZIdToNodeMap.rbegin()->first ), 0 );
03913 map< int, const SMDS_MeshNode*>::iterator i_node = myXYZIdToNodeMap.begin();
03914 for ( ; i_node != myXYZIdToNodeMap.end(); i_node++ ) {
03915 nodesVector[ i_node->first ] = i_node->second;
03916 }
03917 for ( int i = 0; i < myXYZ.size(); ++i ) {
03918 if ( !nodesVector[ i ] && isDefined( myXYZ[ i ] ) )
03919 nodesVector[ i ] = aMeshDS->AddNode (myXYZ[ i ].X(),
03920 myXYZ[ i ].Y(),
03921 myXYZ[ i ].Z());
03922 }
03923 }
03924 else
03925 {
03926 nodesVector.resize( myPoints.size(), 0 );
03927
03928
03929 map< TPoint*, int > pointIndex;
03930 for ( int i = 0; i < myPoints.size(); i++ )
03931 pointIndex.insert( make_pair( & myPoints[ i ], i ));
03932
03933
03934 map< int, list< TPoint* > >::iterator idPointIt = myShapeIDToPointsMap.begin();
03935 for ( ; idPointIt != myShapeIDToPointsMap.end(); idPointIt++ )
03936 {
03937 TopoDS_Shape S;
03938
03939 if ( !myShapeIDMap.IsEmpty() ) {
03940 S = myShapeIDMap( idPointIt->first );
03941
03942 }
03943 list< TPoint* > & points = idPointIt->second;
03944 list< TPoint* >::iterator pIt = points.begin();
03945 for ( ; pIt != points.end(); pIt++ )
03946 {
03947 TPoint* point = *pIt;
03948 int pIndex = pointIndex[ point ];
03949 if ( nodesVector [ pIndex ] )
03950 continue;
03951 SMDS_MeshNode* node = aMeshDS->AddNode (point->myXYZ.X(),
03952 point->myXYZ.Y(),
03953 point->myXYZ.Z());
03954 nodesVector [ pIndex ] = node;
03955
03956 if ( !S.IsNull() ) {
03957
03958 switch ( S.ShapeType() ) {
03959 case TopAbs_VERTEX: {
03960 aMeshDS->SetNodeOnVertex( node, TopoDS::Vertex( S )); break;
03961 }
03962 case TopAbs_EDGE: {
03963 aMeshDS->SetNodeOnEdge( node, TopoDS::Edge( S ), point->myU ); break;
03964 }
03965 case TopAbs_FACE: {
03966 aMeshDS->SetNodeOnFace( node, TopoDS::Face( S ),
03967 point->myUV.X(), point->myUV.Y() ); break;
03968 }
03969 default:
03970 aMeshDS->SetNodeInVolume( node, TopoDS::Shell( S ));
03971 }
03972 }
03973 }
03974 }
03975 }
03976
03977
03978
03979 if ( onMeshElements )
03980 {
03981
03982 makePolyElements( nodesVector, toCreatePolygons, toCreatePolyedrs );
03983
03984
03985 createElements( theMesh, nodesVector, myElemXYZIDs, myElements );
03986
03987 createElements( theMesh, nodesVector, myPolyElemXYZIDs, myPolyElems );
03988 }
03989 else
03990 {
03991 createElements( theMesh, nodesVector, myElemPointIDs, myElements );
03992 }
03993
03994 aMeshDS->compactMesh();
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008 return setErrorCode( ERR_OK );
04009 }
04010
04011
04012
04013
04014
04015
04016 void SMESH_Pattern::createElements(SMESH_Mesh* theMesh,
04017 const vector<const SMDS_MeshNode* >& theNodesVector,
04018 const list< TElemDef > & theElemNodeIDs,
04019 const vector<const SMDS_MeshElement*>& theElements)
04020 {
04021 SMESHDS_Mesh* aMeshDS = theMesh->GetMeshDS();
04022 SMESH_MeshEditor editor( theMesh );
04023
04024 bool onMeshElements = !theElements.empty();
04025
04026
04027 vector< int > shapeIDs;
04028 vector< list< SMESHDS_Group* > > groups;
04029 set< const SMDS_MeshNode* > shellNodes;
04030 if ( onMeshElements )
04031 {
04032 shapeIDs.resize( theElements.size() );
04033 groups.resize( theElements.size() );
04034 const set<SMESHDS_GroupBase*>& allGroups = aMeshDS->GetGroups();
04035 set<SMESHDS_GroupBase*>::const_iterator grIt;
04036 for ( int i = 0; i < theElements.size(); i++ )
04037 {
04038 shapeIDs[ i ] = editor.FindShape( theElements[ i ] );
04039 for ( grIt = allGroups.begin(); grIt != allGroups.end(); grIt++ ) {
04040 SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
04041 if ( group && group->SMDSGroup().Contains( theElements[ i ] ))
04042 groups[ i ].push_back( group );
04043 }
04044 }
04045
04046
04047 TopoDS_Shape aMainShape = aMeshDS->ShapeToMesh();
04048 if ( !aMainShape.IsNull() ) {
04049 TopExp_Explorer shellExp( aMainShape, TopAbs_SHELL );
04050 for ( ; shellExp.More(); shellExp.Next() )
04051 {
04052 SMESHDS_SubMesh * sm = aMeshDS->MeshElements( shellExp.Current() );
04053 if ( sm ) {
04054 SMDS_NodeIteratorPtr nIt = sm->GetNodes();
04055 while ( nIt->more() )
04056 shellNodes.insert( nIt->next() );
04057 }
04058 }
04059 }
04060 }
04061
04062 int nbNewElemsPerOld = 1;
04063 if ( onMeshElements )
04064 nbNewElemsPerOld = theElemNodeIDs.size() / theElements.size();
04065
04066 bool is2d = myIs2D;
04067
04068 list< TElemDef >::const_iterator enIt = theElemNodeIDs.begin();
04069 list< vector<int> >::iterator quantity = myPolyhedronQuantities.begin();
04070 for ( int iElem = 0; enIt != theElemNodeIDs.end(); enIt++, iElem++ )
04071 {
04072 const TElemDef & elemNodeInd = *enIt;
04073
04074 vector< const SMDS_MeshNode* > nodes( elemNodeInd.size() );
04075 TElemDef::const_iterator id = elemNodeInd.begin();
04076 int nbNodes;
04077 for ( nbNodes = 0; id != elemNodeInd.end(); id++ ) {
04078 if ( *id < theNodesVector.size() )
04079 nodes[ nbNodes++ ] = theNodesVector[ *id ];
04080 else
04081 nodes[ nbNodes++ ] = myXYZIdToNodeMap[ *id ];
04082 }
04083
04084 int elemIndex = iElem / nbNewElemsPerOld;
04085 if ( onMeshElements ) {
04086 is2d = ( theElements[ elemIndex ]->GetType() == SMDSAbs_Face );
04087 }
04088
04089 const SMDS_MeshElement* elem = 0;
04090 if ( is2d ) {
04091 switch ( nbNodes ) {
04092 case 3:
04093 elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2] ); break;
04094 case 4:
04095 elem = aMeshDS->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
04096 case 6:
04097 if ( !onMeshElements ) {
04098 elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3],
04099 nodes[4], nodes[5] ); break;
04100 }
04101 case 8:
04102 if ( !onMeshElements ) {
04103 elem = aMeshDS->AddFace (nodes[0], nodes[1], nodes[2], nodes[3],
04104 nodes[4], nodes[5], nodes[6], nodes[7] ); break;
04105 }
04106 default:
04107 elem = aMeshDS->AddPolygonalFace( nodes );
04108 }
04109 }
04110 else {
04111 switch ( nbNodes ) {
04112 case 4:
04113 elem = aMeshDS->AddVolume (nodes[0], nodes[1], nodes[2], nodes[3] ); break;
04114 case 5:
04115 elem = aMeshDS->AddVolume (nodes[0], nodes[1], nodes[2], nodes[3],
04116 nodes[4] ); break;
04117 case 6:
04118 elem = aMeshDS->AddVolume (nodes[0], nodes[1], nodes[2], nodes[3],
04119 nodes[4], nodes[5] ); break;
04120 case 8:
04121 elem = aMeshDS->AddVolume (nodes[0], nodes[1], nodes[2], nodes[3],
04122 nodes[4], nodes[5], nodes[6], nodes[7] ); break;
04123 default:
04124 elem = aMeshDS->AddPolyhedralVolume( nodes, *quantity++ );
04125 }
04126 }
04127
04128 if ( elem && onMeshElements )
04129 {
04130 int shapeID = shapeIDs[ elemIndex ];
04131 if ( shapeID > 0 ) {
04132 aMeshDS->SetMeshElementOnShape( elem, shapeID );
04133
04134 TopoDS_Shape S = aMeshDS->IndexToShape( shapeID );
04135 if ( S.ShapeType() == TopAbs_SOLID ) {
04136 TopoDS_Iterator shellIt( S );
04137 if ( shellIt.More() )
04138 shapeID = aMeshDS->ShapeToIndex( shellIt.Value() );
04139 }
04140 SMDS_ElemIteratorPtr noIt = elem->nodesIterator();
04141 while ( noIt->more() ) {
04142 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>(smdsNode( noIt->next() ));
04143 if (!node->getshapeId() &&
04144 shellNodes.find( node ) == shellNodes.end() ) {
04145 if ( S.ShapeType() == TopAbs_FACE )
04146 aMeshDS->SetNodeOnFace( node, shapeID,
04147 Precision::Infinite(),
04148 Precision::Infinite());
04149 else {
04150 aMeshDS->SetNodeInVolume( node, shapeID );
04151 shellNodes.insert( node );
04152 }
04153 }
04154 }
04155 }
04156
04157 list< SMESHDS_Group* >::iterator g = groups[ elemIndex ].begin();
04158 for ( ; g != groups[ elemIndex ].end(); ++g )
04159 (*g)->SMDSGroup().Add( elem );
04160 }
04161 if ( elem && !myShape.IsNull() )
04162 aMeshDS->SetMeshElementOnShape( elem, myShape );
04163 }
04164
04165
04166
04167
04168 SMESH_subMesh * subMesh;
04169 if ( !myShape.IsNull() ) {
04170 subMesh = theMesh->GetSubMesh( myShape );
04171 if ( subMesh )
04172 subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
04173 }
04174 if ( onMeshElements ) {
04175 list< int > elemIDs;
04176 for ( int i = 0; i < theElements.size(); i++ )
04177 {
04178 subMesh = theMesh->GetSubMeshContaining( shapeIDs[ i ] );
04179 if ( subMesh )
04180 subMesh->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
04181
04182 elemIDs.push_back( theElements[ i ]->GetID() );
04183 }
04184
04185 editor.Remove( elemIDs, false );
04186 }
04187 }
04188
04189
04190
04191
04192
04193
04194
04195 bool SMESH_Pattern::isReversed(const SMDS_MeshNode* theFirstNode,
04196 const list< int >& theIdsList) const
04197 {
04198 if ( theIdsList.size() < 2 )
04199 return false;
04200
04201 gp_Pnt Pf ( theFirstNode->X(), theFirstNode->Y(), theFirstNode->Z() );
04202 gp_Pnt P[2];
04203 list<int>::const_iterator id = theIdsList.begin();
04204 for ( int i = 0; i < 2; ++i, ++id ) {
04205 if ( *id < myXYZ.size() )
04206 P[ i ] = myXYZ[ *id ];
04207 else {
04208 map< int, const SMDS_MeshNode*>::const_iterator i_n;
04209 i_n = myXYZIdToNodeMap.find( *id );
04210 ASSERT( i_n != myXYZIdToNodeMap.end() );
04211 const SMDS_MeshNode* n = i_n->second;
04212 P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
04213 }
04214 }
04215 return Pf.SquareDistance( P[ 1 ] ) < Pf.SquareDistance( P[ 0 ] );
04216 }
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227 void SMESH_Pattern::arrangeBoundaries (list< list< TPoint* > >& boundaryList)
04228 {
04229 typedef list< list< TPoint* > >::iterator TListOfListIt;
04230 TListOfListIt bndIt;
04231 list< TPoint* >::iterator pIt;
04232
04233 int nbBoundaries = boundaryList.size();
04234 if ( nbBoundaries > 1 )
04235 {
04236
04237 if ( nbBoundaries > 2 )
04238 {
04239
04240 list< list< TPoint* > > tmpList;
04241 tmpList.splice( tmpList.begin(), boundaryList, boundaryList.begin(), boundaryList.end());
04242
04243
04244 typedef map< int, TListOfListIt > TNbKpBndPosMap;
04245 TNbKpBndPosMap nbKpBndPosMap;
04246 bndIt = tmpList.begin();
04247 list< int >::iterator nbKpIt = myNbKeyPntInBoundary.begin();
04248 for ( ; nbKpIt != myNbKeyPntInBoundary.end(); nbKpIt++, bndIt++ ) {
04249 int nb = *nbKpIt * nbBoundaries;
04250 while ( nbKpBndPosMap.find ( nb ) != nbKpBndPosMap.end() )
04251 nb++;
04252 nbKpBndPosMap.insert( TNbKpBndPosMap::value_type( nb, bndIt ));
04253 }
04254
04255 TNbKpBndPosMap::iterator nbKpBndPosIt = nbKpBndPosMap.begin();
04256 for ( ; nbKpBndPosIt != nbKpBndPosMap.end(); nbKpBndPosIt++ ) {
04257 TListOfListIt & bndPos2 = (*nbKpBndPosIt).second;
04258 TListOfListIt bndPos1 = bndPos2++;
04259 boundaryList.splice( boundaryList.end(), tmpList, bndPos1, bndPos2 );
04260 }
04261 }
04262
04263
04264 double leastX = DBL_MAX;
04265 TListOfListIt outerBndPos;
04266 for ( bndIt = boundaryList.begin(); bndIt != boundaryList.end(); bndIt++ )
04267 {
04268 list< TPoint* >& boundary = (*bndIt);
04269 for ( pIt = boundary.begin(); pIt != boundary.end(); pIt++)
04270 {
04271 TPoint* point = *pIt;
04272 if ( point->myInitXYZ.X() < leastX ) {
04273 leastX = point->myInitXYZ.X();
04274 outerBndPos = bndIt;
04275 }
04276 }
04277 }
04278
04279 if ( outerBndPos != boundaryList.begin() )
04280 boundaryList.splice( boundaryList.begin(), boundaryList, outerBndPos, ++outerBndPos );
04281
04282 }
04283
04284
04285
04286 set< TPoint* > keyPointSet;
04287 list< int >::iterator kpIt = myKeyPointIDs.begin();
04288 for ( ; kpIt != myKeyPointIDs.end(); kpIt++ )
04289 keyPointSet.insert( & myPoints[ *kpIt ]);
04290 myKeyPointIDs.clear();
04291
04292
04293 list< int >::iterator nbKpIt = myNbKeyPntInBoundary.begin();
04294
04295 for ( bndIt = boundaryList.begin(); bndIt != boundaryList.end(); bndIt++, nbKpIt++ )
04296 {
04297
04298 double leastX = DBL_MAX;
04299 list< TPoint* >::iterator xpIt;
04300 list< TPoint* >& boundary = (*bndIt);
04301 for ( pIt = boundary.begin(); pIt != boundary.end(); pIt++)
04302 {
04303 TPoint* point = *pIt;
04304 if ( point->myInitXYZ.X() < leastX ) {
04305 leastX = point->myInitXYZ.X();
04306 xpIt = pIt;
04307 }
04308 }
04309
04310 TPoint* p = *xpIt, *pPrev, *pNext;
04311 if ( p == boundary.front() )
04312 pPrev = *(++boundary.rbegin());
04313 else {
04314 xpIt--;
04315 pPrev = *xpIt;
04316 xpIt++;
04317 }
04318 if ( p == boundary.back() )
04319 pNext = *(++boundary.begin());
04320 else {
04321 xpIt++;
04322 pNext = *xpIt;
04323 }
04324
04325 gp_Vec2d v1( pPrev->myInitUV, p->myInitUV ), v2( p->myInitUV, pNext->myInitUV );
04326 double sqMag1 = v1.SquareMagnitude(), sqMag2 = v2.SquareMagnitude();
04327 if ( sqMag1 > DBL_MIN && sqMag2 > DBL_MIN ) {
04328 double yPrev = v1.Y() / sqrt( sqMag1 );
04329 double yNext = v2.Y() / sqrt( sqMag2 );
04330 double sumY = yPrev + yNext;
04331 bool reverse;
04332 if ( bndIt == boundaryList.begin() )
04333 reverse = sumY > 0;
04334 else
04335 reverse = sumY < 0;
04336 if ( reverse )
04337 boundary.reverse();
04338 }
04339
04340
04341 (*nbKpIt) = 0;
04342 pIt = boundary.begin();
04343 for ( ; pIt != boundary.end(); pIt++)
04344 {
04345 TPoint* point = *pIt;
04346 if ( keyPointSet.find( point ) == keyPointSet.end() )
04347 continue;
04348
04349 int index = 0;
04350 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
04351 for ( ; pVecIt != myPoints.end(); pVecIt++, index++ )
04352 if ( &(*pVecIt) == point )
04353 break;
04354 myKeyPointIDs.push_back( index );
04355 (*nbKpIt)++;
04356 }
04357 myKeyPointIDs.pop_back();
04358 (*nbKpIt)--;
04359
04360 }
04361
04362 ASSERT( myKeyPointIDs.size() == keyPointSet.size() );
04363 }
04364
04365
04366
04367
04368
04369
04370
04371 bool SMESH_Pattern::findBoundaryPoints()
04372 {
04373 if ( myIsBoundaryPointsFound ) return true;
04374
04375 MESSAGE(" findBoundaryPoints() ");
04376
04377 myNbKeyPntInBoundary.clear();
04378
04379 if ( myIs2D )
04380 {
04381 set< TPoint* > pointsInElems;
04382
04383
04384
04385
04386 typedef pair< TPoint*, TPoint*> TLink;
04387 set< TLink > linkSet;
04388 list<TElemDef >::iterator epIt = myElemPointIDs.begin();
04389 for ( ; epIt != myElemPointIDs.end(); epIt++ )
04390 {
04391 TElemDef & elemPoints = *epIt;
04392 TElemDef::iterator pIt = elemPoints.begin();
04393 int prevP = elemPoints.back();
04394 for ( ; pIt != elemPoints.end(); pIt++ ) {
04395 TPoint* p1 = & myPoints[ prevP ];
04396 TPoint* p2 = & myPoints[ *pIt ];
04397 TLink link(( p1 < p2 ? p1 : p2 ), ( p1 < p2 ? p2 : p1 ));
04398 ASSERT( link.first != link.second );
04399 pair<set< TLink >::iterator,bool> itUniq = linkSet.insert( link );
04400 if ( !itUniq.second )
04401 linkSet.erase( itUniq.first );
04402 prevP = *pIt;
04403
04404 pointsInElems.insert( p1 );
04405 }
04406 }
04407
04408
04409
04410
04411 set< TPoint* > keyPointSet;
04412 list< int >::iterator kpIt = myKeyPointIDs.begin();
04413 for ( ; kpIt != myKeyPointIDs.end(); kpIt++ )
04414 keyPointSet.insert( & myPoints[ *kpIt ]);
04415
04416
04417 list< list< TPoint* > > boundaryList;
04418 boundaryList.push_back( list< TPoint* >() );
04419 list< TPoint* > * boundary = & boundaryList.back();
04420
04421 TPoint *point1, *point2, *keypoint1;
04422 kpIt = myKeyPointIDs.begin();
04423 point1 = keypoint1 = & myPoints[ *kpIt++ ];
04424
04425 int iKeyPoint = 0;
04426 set< TLink >::iterator lIt = linkSet.begin();
04427 while ( lIt != linkSet.end() )
04428 {
04429 if ( (*lIt).first == point1 )
04430 point2 = (*lIt).second;
04431 else if ( (*lIt).second == point1 )
04432 point2 = (*lIt).first;
04433 else {
04434 lIt++;
04435 continue;
04436 }
04437 linkSet.erase( lIt );
04438 lIt = linkSet.begin();
04439
04440 if ( keyPointSet.find( point2 ) == keyPointSet.end() )
04441 {
04442 boundary->push_back( point2 );
04443 }
04444 else
04445 {
04446 keyPointSet.erase( point2 );
04447 iKeyPoint++;
04448 if ( point2 != keypoint1 )
04449 {
04450 boundary->push_back( point2 );
04451 }
04452 else
04453 {
04454 boundary->push_front( keypoint1 );
04455 boundary->push_back( keypoint1 );
04456 myNbKeyPntInBoundary.push_back( iKeyPoint );
04457 if ( keyPointSet.empty() )
04458 break;
04459
04460
04461 boundaryList.push_back( list< TPoint* >() );
04462 boundary = & boundaryList.back();
04463 point2 = keypoint1 = (*keyPointSet.begin());
04464 }
04465 }
04466 point1 = point2;
04467 }
04468
04469 if ( boundary->empty() ) {
04470 MESSAGE(" a separate key-point");
04471 return setErrorCode( ERR_READ_BAD_KEY_POINT );
04472 }
04473
04474
04475
04476
04477
04478 arrangeBoundaries( boundaryList );
04479
04480
04481
04482
04483 keyPointSet.clear();
04484 for ( kpIt = myKeyPointIDs.begin(); kpIt != myKeyPointIDs.end(); kpIt++ )
04485 keyPointSet.insert( & myPoints[ *kpIt ]);
04486
04487 set< TPoint* > edgePointSet;
04488 int vertexID = 1;
04489 int edgeID = myKeyPointIDs.size() + 1;
04490
04491 list< list< TPoint* > >::iterator bndIt = boundaryList.begin();
04492 for ( ; bndIt != boundaryList.end(); bndIt++ )
04493 {
04494 boundary = & (*bndIt);
04495 double edgeLength = 0;
04496 list< TPoint* >::iterator pIt = boundary->begin();
04497 getShapePoints( edgeID ).push_back( *pIt );
04498 getShapePoints( vertexID++ ).push_back( *pIt );
04499 for ( pIt++; pIt != boundary->end(); pIt++)
04500 {
04501 list< TPoint* > & edgePoints = getShapePoints( edgeID );
04502 TPoint* prevP = edgePoints.empty() ? 0 : edgePoints.back();
04503 TPoint* point = *pIt;
04504 edgePointSet.insert( point );
04505 if ( keyPointSet.find( point ) == keyPointSet.end() )
04506 {
04507 edgePoints.push_back( point );
04508 edgeLength += ( point->myInitUV - prevP->myInitUV ).Modulus();
04509 point->myInitU = edgeLength;
04510 }
04511 else
04512 {
04513
04514 edgePoints.push_back( point );
04515 if ( edgePoints.size() > 2 ) {
04516 edgeLength += ( point->myInitUV - prevP->myInitUV ).Modulus();
04517 list< TPoint* >::iterator epIt = edgePoints.begin();
04518 for ( ; epIt != edgePoints.end(); epIt++ )
04519 (*epIt)->myInitU /= edgeLength;
04520 }
04521
04522 edgeLength = 0;
04523 edgeID++;
04524 if ( point != boundary->front() ) {
04525 getShapePoints( edgeID ).push_back( point );
04526 getShapePoints( vertexID++ ).push_back( point );
04527 }
04528 }
04529 }
04530 }
04531
04532
04533 list< TPoint* > & facePoints = getShapePoints( edgeID );
04534 vector< TPoint >::iterator pVecIt = myPoints.begin();
04535 for ( ; pVecIt != myPoints.end(); pVecIt++ ) {
04536 TPoint* point = &(*pVecIt);
04537 if ( edgePointSet.find( point ) == edgePointSet.end() &&
04538 pointsInElems.find( point ) != pointsInElems.end())
04539 facePoints.push_back( point );
04540 }
04541
04542 }
04543
04544 else
04545 {
04546
04547 vector< TPoint >::iterator pVecIt = myPoints.begin();
04548 for ( int i = 0; pVecIt != myPoints.end(); pVecIt++, i++ ) {
04549 TPoint* point = &(*pVecIt);
04550 int shapeID = SMESH_Block::GetShapeIDByParams( point->myInitXYZ );
04551 getShapePoints( shapeID ).push_back( point );
04552
04553 if ( SMESH_Block::IsVertexID( shapeID ))
04554 myKeyPointIDs.push_back( i );
04555 }
04556 }
04557
04558 myIsBoundaryPointsFound = true;
04559 return myIsBoundaryPointsFound;
04560 }
04561
04562
04563
04564
04565
04566
04567 void SMESH_Pattern::Clear()
04568 {
04569 myIsComputed = myIsBoundaryPointsFound = false;
04570
04571 myPoints.clear();
04572 myKeyPointIDs.clear();
04573 myElemPointIDs.clear();
04574 myShapeIDToPointsMap.clear();
04575 myShapeIDMap.Clear();
04576 myShape.Nullify();
04577 myNbKeyPntInBoundary.clear();
04578
04579 myXYZ.clear();
04580 myElemXYZIDs.clear();
04581 myXYZIdToNodeMap.clear();
04582 myElements.clear();
04583 myOrderedNodes.clear();
04584 myPolyElems.clear();
04585 myPolyElemXYZIDs.clear();
04586 myPolyhedronQuantities.clear();
04587 myIdsOnBoundary.clear();
04588 myReverseConnectivity.clear();
04589 }
04590
04591
04595
04596
04597 bool SMESH_Pattern::setErrorCode( const ErrorCode theErrorCode )
04598 {
04599 myErrorCode = theErrorCode;
04600 return myErrorCode == ERR_OK;
04601 }
04602
04603
04604
04605
04606
04607
04608 bool SMESH_Pattern::setShapeToMesh(const TopoDS_Shape& theShape)
04609 {
04610 if ( !IsLoaded() ) {
04611 MESSAGE( "Pattern not loaded" );
04612 return setErrorCode( ERR_APPL_NOT_LOADED );
04613 }
04614
04615 TopAbs_ShapeEnum aType = theShape.ShapeType();
04616 bool dimOk = ( myIs2D ? aType == TopAbs_FACE : aType == TopAbs_SHELL );
04617 if ( !dimOk ) {
04618 MESSAGE( "Pattern dimention mismatch" );
04619 return setErrorCode( ERR_APPL_BAD_DIMENTION );
04620 }
04621
04622
04623 int nbNodeOnSeamEdge = 0;
04624 if ( myIs2D ) {
04625 TopTools_MapOfShape seamVertices;
04626 TopoDS_Face face = TopoDS::Face( theShape );
04627 TopExp_Explorer eExp( theShape, TopAbs_EDGE );
04628 for ( ; eExp.More() && nbNodeOnSeamEdge == 0; eExp.Next() ) {
04629 const TopoDS_Edge& ee = TopoDS::Edge(eExp.Current());
04630 if ( BRep_Tool::IsClosed(ee, face) ) {
04631
04632 if ( !seamVertices.Add( TopExp::FirstVertex( ee ))) nbNodeOnSeamEdge++;
04633 if ( !seamVertices.Add( TopExp::LastVertex( ee ))) nbNodeOnSeamEdge++;
04634 }
04635 }
04636 }
04637
04638
04639 TopTools_IndexedMapOfShape vMap;
04640 TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap );
04641 if ( vMap.Extent() + nbNodeOnSeamEdge != myKeyPointIDs.size() ) {
04642 MESSAGE( myKeyPointIDs.size() + nbNodeOnSeamEdge << " != " << vMap.Extent() );
04643 return setErrorCode( ERR_APPL_BAD_NB_VERTICES );
04644 }
04645
04646 myElements.clear();
04647 myElemXYZIDs.clear();
04648
04649 myShapeIDMap.Clear();
04650 myShape = theShape;
04651 return true;
04652 }
04653
04654
04655
04656
04657
04658
04659 bool SMESH_Pattern::GetMappedPoints ( list< const gp_XYZ * > & thePoints ) const
04660 {
04661 thePoints.clear();
04662 if ( !myIsComputed )
04663 return false;
04664
04665 if ( myElements.empty() ) {
04666 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
04667 for ( ; pVecIt != myPoints.end(); pVecIt++ )
04668 thePoints.push_back( & (*pVecIt).myXYZ.XYZ() );
04669 }
04670 else {
04671 const gp_XYZ * definedXYZ = & myPoints[ myKeyPointIDs.front() ].myXYZ.XYZ();
04672 vector<gp_XYZ>::const_iterator xyz = myXYZ.begin();
04673 for ( ; xyz != myXYZ.end(); ++xyz )
04674 if ( !isDefined( *xyz ))
04675 thePoints.push_back( definedXYZ );
04676 else
04677 thePoints.push_back( & (*xyz) );
04678 }
04679 return !thePoints.empty();
04680 }
04681
04682
04683
04684
04685
04686
04687
04688 bool SMESH_Pattern::GetPoints ( list< const gp_XYZ * > & thePoints ) const
04689 {
04690 thePoints.clear();
04691
04692 if ( !IsLoaded() )
04693 return false;
04694
04695 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
04696 for ( ; pVecIt != myPoints.end(); pVecIt++ )
04697 thePoints.push_back( & (*pVecIt).myInitXYZ );
04698
04699 return ( thePoints.size() > 0 );
04700 }
04701
04702
04703
04704
04705
04706
04707 list< SMESH_Pattern::TPoint* > &
04708 SMESH_Pattern::getShapePoints(const TopoDS_Shape& theShape)
04709 {
04710 int aShapeID;
04711 if ( !myShapeIDMap.Contains( theShape ))
04712 aShapeID = myShapeIDMap.Add( theShape );
04713 else
04714 aShapeID = myShapeIDMap.FindIndex( theShape );
04715
04716 return myShapeIDToPointsMap[ aShapeID ];
04717 }
04718
04719
04720
04721
04722
04723
04724 list< SMESH_Pattern::TPoint* > & SMESH_Pattern::getShapePoints(const int theShapeID)
04725 {
04726 return myShapeIDToPointsMap[ theShapeID ];
04727 }
04728
04729
04730
04731
04732
04733
04734 void SMESH_Pattern::DumpPoints() const
04735 {
04736 #ifdef _DEBUG_
04737 vector< TPoint >::const_iterator pVecIt = myPoints.begin();
04738 for ( int i = 0; pVecIt != myPoints.end(); pVecIt++, i++ )
04739 MESSAGE_ADD ( std::endl << i << ": " << *pVecIt );
04740 #endif
04741 }
04742
04743
04744
04745
04746
04747
04748 SMESH_Pattern::TPoint::TPoint()
04749 {
04750 #ifdef _DEBUG_
04751 myInitXYZ.SetCoord(0,0,0);
04752 myInitUV.SetCoord(0.,0.);
04753 myInitU = 0;
04754 myXYZ.SetCoord(0,0,0);
04755 myUV.SetCoord(0.,0.);
04756 myU = 0;
04757 #endif
04758 }
04759
04760
04761
04762
04763
04764
04765 ostream & operator <<(ostream & OS, const SMESH_Pattern::TPoint& p)
04766 {
04767 gp_XYZ xyz = p.myInitXYZ;
04768 OS << "\tinit( xyz( " << xyz.X() << " " << xyz.Y() << " " << xyz.Z() << " )";
04769 gp_XY xy = p.myInitUV;
04770 OS << " uv( " << xy.X() << " " << xy.Y() << " )";
04771 double u = p.myInitU;
04772 OS << " u( " << u << " )) " << &p << endl;
04773 xyz = p.myXYZ.XYZ();
04774 OS << "\t ( xyz( " << xyz.X() << " " << xyz.Y() << " " << xyz.Z() << " )";
04775 xy = p.myUV;
04776 OS << " uv( " << xy.X() << " " << xy.Y() << " )";
04777 u = p.myU;
04778 OS << " u( " << u << " ))" << endl;
04779
04780 return OS;
04781 }