00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define CHRONODEF
00029 #include "SMESH_MeshEditor.hxx"
00030
00031 #include "SMDS_FaceOfNodes.hxx"
00032 #include "SMDS_VolumeTool.hxx"
00033 #include "SMDS_EdgePosition.hxx"
00034 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
00035 #include "SMDS_FacePosition.hxx"
00036 #include "SMDS_SpacePosition.hxx"
00037
00038 #include "SMDS_MeshGroup.hxx"
00039 #include "SMDS_LinearEdge.hxx"
00040 #include "SMDS_Downward.hxx"
00041 #include "SMDS_SetIterator.hxx"
00042
00043 #include "SMESHDS_Group.hxx"
00044 #include "SMESHDS_Mesh.hxx"
00045
00046 #include "SMESH_Algo.hxx"
00047 #include "SMESH_ControlsDef.hxx"
00048 #include "SMESH_Group.hxx"
00049 #include "SMESH_MesherHelper.hxx"
00050 #include "SMESH_OctreeNode.hxx"
00051 #include "SMESH_subMesh.hxx"
00052
00053 #include "utilities.h"
00054
00055 #include <BRepAdaptor_Surface.hxx>
00056 #include <BRepClass3d_SolidClassifier.hxx>
00057 #include <BRep_Tool.hxx>
00058 #include <ElCLib.hxx>
00059 #include <Extrema_GenExtPS.hxx>
00060 #include <Extrema_POnCurv.hxx>
00061 #include <Extrema_POnSurf.hxx>
00062 #include <GC_MakeSegment.hxx>
00063 #include <Geom2d_Curve.hxx>
00064 #include <GeomAPI_ExtremaCurveCurve.hxx>
00065 #include <GeomAdaptor_Surface.hxx>
00066 #include <Geom_Curve.hxx>
00067 #include <Geom_Line.hxx>
00068 #include <Geom_Surface.hxx>
00069 #include <IntAna_IntConicQuad.hxx>
00070 #include <IntAna_Quadric.hxx>
00071 #include <Precision.hxx>
00072 #include <TColStd_ListOfInteger.hxx>
00073 #include <TopAbs_State.hxx>
00074 #include <TopExp.hxx>
00075 #include <TopExp_Explorer.hxx>
00076 #include <TopTools_ListIteratorOfListOfShape.hxx>
00077 #include <TopTools_ListOfShape.hxx>
00078 #include <TopTools_SequenceOfShape.hxx>
00079 #include <TopoDS.hxx>
00080 #include <TopoDS_Face.hxx>
00081 #include <gp.hxx>
00082 #include <gp_Ax1.hxx>
00083 #include <gp_Dir.hxx>
00084 #include <gp_Lin.hxx>
00085 #include <gp_Pln.hxx>
00086 #include <gp_Trsf.hxx>
00087 #include <gp_Vec.hxx>
00088 #include <gp_XY.hxx>
00089 #include <gp_XYZ.hxx>
00090
00091 #include <math.h>
00092
00093 #include <map>
00094 #include <set>
00095 #include <numeric>
00096 #include <limits>
00097 #include <algorithm>
00098 #include <sstream>
00099
00100 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
00101
00102 using namespace std;
00103 using namespace SMESH::Controls;
00104
00105 typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> > TElemOfNodeListMap;
00106 typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
00107
00108 typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator> TSetIterator;
00109
00110
00111
00112
00113
00114
00115 SMESH_MeshEditor::SMESH_MeshEditor( SMESH_Mesh* theMesh )
00116 :myMesh( theMesh )
00117 {
00118 }
00119
00120
00124
00125
00126 SMDS_MeshElement*
00127 SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
00128 const SMDSAbs_ElementType type,
00129 const bool isPoly,
00130 const int ID)
00131 {
00132
00133 SMDS_MeshElement* e = 0;
00134 int nbnode = node.size();
00135 SMESHDS_Mesh* mesh = GetMeshDS();
00136 switch ( type ) {
00137 case SMDSAbs_Face:
00138 if ( !isPoly ) {
00139 if (nbnode == 3) {
00140 if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID);
00141 else e = mesh->AddFace (node[0], node[1], node[2] );
00142 }
00143 else if (nbnode == 4) {
00144 if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID);
00145 else e = mesh->AddFace (node[0], node[1], node[2], node[3] );
00146 }
00147 else if (nbnode == 6) {
00148 if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
00149 node[4], node[5], ID);
00150 else e = mesh->AddFace (node[0], node[1], node[2], node[3],
00151 node[4], node[5] );
00152 }
00153 else if (nbnode == 8) {
00154 if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
00155 node[4], node[5], node[6], node[7], ID);
00156 else e = mesh->AddFace (node[0], node[1], node[2], node[3],
00157 node[4], node[5], node[6], node[7] );
00158 }
00159 } else {
00160 if ( ID >= 1 ) e = mesh->AddPolygonalFaceWithID(node, ID);
00161 else e = mesh->AddPolygonalFace (node );
00162 }
00163 break;
00164
00165 case SMDSAbs_Volume:
00166 if ( !isPoly ) {
00167 if (nbnode == 4) {
00168 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID);
00169 else e = mesh->AddVolume (node[0], node[1], node[2], node[3] );
00170 }
00171 else if (nbnode == 5) {
00172 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00173 node[4], ID);
00174 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00175 node[4] );
00176 }
00177 else if (nbnode == 6) {
00178 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00179 node[4], node[5], ID);
00180 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00181 node[4], node[5] );
00182 }
00183 else if (nbnode == 8) {
00184 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00185 node[4], node[5], node[6], node[7], ID);
00186 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00187 node[4], node[5], node[6], node[7] );
00188 }
00189 else if (nbnode == 10) {
00190 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00191 node[4], node[5], node[6], node[7],
00192 node[8], node[9], ID);
00193 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00194 node[4], node[5], node[6], node[7],
00195 node[8], node[9] );
00196 }
00197 else if (nbnode == 13) {
00198 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00199 node[4], node[5], node[6], node[7],
00200 node[8], node[9], node[10],node[11],
00201 node[12],ID);
00202 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00203 node[4], node[5], node[6], node[7],
00204 node[8], node[9], node[10],node[11],
00205 node[12] );
00206 }
00207 else if (nbnode == 15) {
00208 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00209 node[4], node[5], node[6], node[7],
00210 node[8], node[9], node[10],node[11],
00211 node[12],node[13],node[14],ID);
00212 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00213 node[4], node[5], node[6], node[7],
00214 node[8], node[9], node[10],node[11],
00215 node[12],node[13],node[14] );
00216 }
00217 else if (nbnode == 20) {
00218 if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
00219 node[4], node[5], node[6], node[7],
00220 node[8], node[9], node[10],node[11],
00221 node[12],node[13],node[14],node[15],
00222 node[16],node[17],node[18],node[19],ID);
00223 else e = mesh->AddVolume (node[0], node[1], node[2], node[3],
00224 node[4], node[5], node[6], node[7],
00225 node[8], node[9], node[10],node[11],
00226 node[12],node[13],node[14],node[15],
00227 node[16],node[17],node[18],node[19] );
00228 }
00229 }
00230 break;
00231
00232 case SMDSAbs_Edge:
00233 if ( nbnode == 2 ) {
00234 if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], ID);
00235 else e = mesh->AddEdge (node[0], node[1] );
00236 }
00237 else if ( nbnode == 3 ) {
00238 if ( ID >= 1 ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID);
00239 else e = mesh->AddEdge (node[0], node[1], node[2] );
00240 }
00241 break;
00242
00243 case SMDSAbs_0DElement:
00244 if ( nbnode == 1 ) {
00245 if ( ID >= 1 ) e = mesh->Add0DElementWithID(node[0], ID);
00246 else e = mesh->Add0DElement (node[0] );
00247 }
00248 break;
00249
00250 case SMDSAbs_Node:
00251 if ( ID >= 1 ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID);
00252 else e = mesh->AddNode (node[0]->X(), node[0]->Y(), node[0]->Z());
00253 break;
00254
00255 default:;
00256 }
00257 if ( e ) myLastCreatedElems.Append( e );
00258 return e;
00259 }
00260
00261
00265
00266
00267 SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> & nodeIDs,
00268 const SMDSAbs_ElementType type,
00269 const bool isPoly,
00270 const int ID)
00271 {
00272 vector<const SMDS_MeshNode*> nodes;
00273 nodes.reserve( nodeIDs.size() );
00274 vector<int>::const_iterator id = nodeIDs.begin();
00275 while ( id != nodeIDs.end() ) {
00276 if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ ))
00277 nodes.push_back( node );
00278 else
00279 return 0;
00280 }
00281 return AddElement( nodes, type, isPoly, ID );
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 int SMESH_MeshEditor::Remove (const list< int >& theIDs,
00291 const bool isNodes )
00292 {
00293 myLastCreatedElems.Clear();
00294 myLastCreatedNodes.Clear();
00295
00296 SMESHDS_Mesh* aMesh = GetMeshDS();
00297 set< SMESH_subMesh *> smmap;
00298
00299 int removed = 0;
00300 list<int>::const_iterator it = theIDs.begin();
00301 for ( ; it != theIDs.end(); it++ ) {
00302 const SMDS_MeshElement * elem;
00303 if ( isNodes )
00304 elem = aMesh->FindNode( *it );
00305 else
00306 elem = aMesh->FindElement( *it );
00307 if ( !elem )
00308 continue;
00309
00310
00311 if ( isNodes ) {
00312 const SMDS_MeshNode* node = cast2Node( elem );
00313 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
00314 if ( int aShapeID = node->getshapeId() )
00315 if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) )
00316 smmap.insert( sm );
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 if ( isNodes )
00333 aMesh->RemoveNode( static_cast< const SMDS_MeshNode* >( elem ));
00334 else
00335 aMesh->RemoveElement( elem );
00336 removed++;
00337 }
00338
00339
00340 if ( !smmap.empty() ) {
00341 set< SMESH_subMesh *>::iterator smIt;
00342 for ( smIt = smmap.begin(); smIt != smmap.end(); smIt++ )
00343 (*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
00344 }
00345
00346
00347
00348
00349
00350 return removed;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
00360 {
00361 myLastCreatedElems.Clear();
00362 myLastCreatedNodes.Clear();
00363
00364 SMESHDS_Mesh * aMesh = GetMeshDS();
00365 if ( aMesh->ShapeToMesh().IsNull() )
00366 return 0;
00367
00368 int aShapeID = theElem->getshapeId();
00369 if ( aShapeID < 1 )
00370 return 0;
00371
00372 if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ))
00373 if ( sm->Contains( theElem ))
00374 return aShapeID;
00375
00376 if ( theElem->GetType() == SMDSAbs_Node ) {
00377 MESSAGE( ":( Error: invalid myShapeId of node " << theElem->GetID() );
00378 }
00379 else {
00380 MESSAGE( ":( Error: invalid myShapeId of element " << theElem->GetID() );
00381 }
00382
00383 TopoDS_Shape aShape;
00384 if ( theElem->GetType() != SMDSAbs_Node )
00385 {
00386 SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
00387 while ( nodeIt->more() ) {
00388 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
00389 if ((aShapeID = node->getshapeId()) > 0) {
00390 if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ) ) {
00391 if ( sm->Contains( theElem ))
00392 return aShapeID;
00393 if ( aShape.IsNull() )
00394 aShape = aMesh->IndexToShape( aShapeID );
00395 }
00396 }
00397 }
00398 }
00399
00400
00401
00402 if ( !aShape.IsNull() ) {
00403 TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
00404 for ( ; ancIt.More(); ancIt.Next() ) {
00405 SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
00406 if ( sm && sm->Contains( theElem ))
00407 return aMesh->ShapeToIndex( ancIt.Value() );
00408 }
00409 }
00410 else
00411 {
00412 const map<int,SMESHDS_SubMesh*>& id2sm = GetMeshDS()->SubMeshes();
00413 map<int,SMESHDS_SubMesh*>::const_iterator id_sm = id2sm.begin();
00414 for ( ; id_sm != id2sm.end(); ++id_sm )
00415 if ( id_sm->second->Contains( theElem ))
00416 return id_sm->first;
00417 }
00418
00419
00420 return 0;
00421 }
00422
00423
00424
00425
00426
00427
00428 bool SMESH_MeshEditor::IsMedium(const SMDS_MeshNode* node,
00429 const SMDSAbs_ElementType typeToCheck)
00430 {
00431 bool isMedium = false;
00432 SMDS_ElemIteratorPtr it = node->GetInverseElementIterator(typeToCheck);
00433 while (it->more() && !isMedium ) {
00434 const SMDS_MeshElement* elem = it->next();
00435 isMedium = elem->IsMediumNode(node);
00436 }
00437 return isMedium;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 static void ShiftNodesQuadTria(const SMDS_MeshNode* aNodes[])
00447 {
00448 const SMDS_MeshNode* nd1 = aNodes[0];
00449 aNodes[0] = aNodes[1];
00450 aNodes[1] = aNodes[2];
00451 aNodes[2] = nd1;
00452 const SMDS_MeshNode* nd2 = aNodes[3];
00453 aNodes[3] = aNodes[4];
00454 aNodes[4] = aNodes[5];
00455 aNodes[5] = nd2;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1,
00465 const SMDS_MeshElement * theTria2,
00466 const SMDS_MeshNode* N1[],
00467 const SMDS_MeshNode* N2[])
00468 {
00469 SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
00470 int i=0;
00471 while(i<6) {
00472 N1[i] = static_cast<const SMDS_MeshNode*>( it->next() );
00473 i++;
00474 }
00475 if(it->more()) return false;
00476 it = theTria2->nodesIterator();
00477 i=0;
00478 while(i<6) {
00479 N2[i] = static_cast<const SMDS_MeshNode*>( it->next() );
00480 i++;
00481 }
00482 if(it->more()) return false;
00483
00484 int sames[3] = {-1,-1,-1};
00485 int nbsames = 0;
00486 int j;
00487 for(i=0; i<3; i++) {
00488 for(j=0; j<3; j++) {
00489 if(N1[i]==N2[j]) {
00490 sames[i] = j;
00491 nbsames++;
00492 break;
00493 }
00494 }
00495 }
00496 if(nbsames!=2) return false;
00497 if(sames[0]>-1) {
00498 ShiftNodesQuadTria(N1);
00499 if(sames[1]>-1) {
00500 ShiftNodesQuadTria(N1);
00501 }
00502 }
00503 i = sames[0] + sames[1] + sames[2];
00504 for(; i<2; i++) {
00505 ShiftNodesQuadTria(N2);
00506 }
00507
00508
00509
00510 return true;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520 bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
00521 const SMDS_MeshElement * theTria2 )
00522 {
00523 MESSAGE("InverseDiag");
00524 myLastCreatedElems.Clear();
00525 myLastCreatedNodes.Clear();
00526
00527 if (!theTria1 || !theTria2)
00528 return false;
00529
00530 const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( theTria1 );
00531 if (!F1) return false;
00532 const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( theTria2 );
00533 if (!F2) return false;
00534 if ((theTria1->GetEntityType() == SMDSEntity_Triangle) &&
00535 (theTria2->GetEntityType() == SMDSEntity_Triangle)) {
00536
00537
00538
00539
00540
00541
00542
00543 const SMDS_MeshNode* aNodes [6];
00544 int sameInd [] = { 0, 0, 0, 0, 0, 0 };
00545 int i = 0;
00546 SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
00547 while ( it->more() ) {
00548 aNodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
00549
00550 if ( i > 2 )
00551
00552 for ( int j = 0; j < 3; j++ )
00553 if ( aNodes[ i ] == aNodes[ j ]) {
00554 sameInd[ j ] = i;
00555 sameInd[ i ] = j;
00556 break;
00557 }
00558
00559 i++;
00560 if ( i == 3 ) {
00561 if ( it->more() )
00562 return false;
00563 it = theTria2->nodesIterator();
00564 }
00565 if ( i == 6 && it->more() )
00566 return false;
00567 }
00568
00569
00570 int iA = 0, iB = 0, i1 = 0, i2 = 0;
00571 for ( i = 0; i < 6; i++ ) {
00572 if ( sameInd [ i ] == 0 ) {
00573 if ( i < 3 ) i1 = i;
00574 else i2 = i;
00575 }
00576 else if (i < 3) {
00577 if ( iA ) iB = i;
00578 else iA = i;
00579 }
00580 }
00581
00582 if ( aNodes[ i1 ] == aNodes[ i2 ] )
00583 return false;
00584
00585
00586 aNodes[ iA ] = aNodes[ i2 ];
00587
00588 aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
00589
00590 GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
00591 GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
00592
00593 return true;
00594
00595 }
00596
00597
00598 if (theTria1->GetEntityType() != SMDSEntity_Quad_Triangle)
00599 return false;
00600 if (theTria2->GetEntityType() != SMDSEntity_Quad_Triangle)
00601 return false;
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 const SMDS_MeshNode* N1 [6];
00614 const SMDS_MeshNode* N2 [6];
00615 if(!GetNodesFromTwoTria(theTria1,theTria2,N1,N2))
00616 return false;
00617
00618
00619
00620
00621 const SMDS_MeshNode* N1new [6];
00622 const SMDS_MeshNode* N2new [6];
00623 N1new[0] = N1[0];
00624 N1new[1] = N2[0];
00625 N1new[2] = N2[1];
00626 N1new[3] = N1[4];
00627 N1new[4] = N2[3];
00628 N1new[5] = N1[5];
00629 N2new[0] = N1[0];
00630 N2new[1] = N1[1];
00631 N2new[2] = N2[0];
00632 N2new[3] = N1[3];
00633 N2new[4] = N2[5];
00634 N2new[5] = N1[4];
00635
00636 GetMeshDS()->ChangeElementNodes( theTria1, N1new, 6 );
00637 GetMeshDS()->ChangeElementNodes( theTria2, N2new, 6 );
00638
00639 return true;
00640 }
00641
00642
00643
00644
00645
00646
00647 static bool findTriangles(const SMDS_MeshNode * theNode1,
00648 const SMDS_MeshNode * theNode2,
00649 const SMDS_MeshElement*& theTria1,
00650 const SMDS_MeshElement*& theTria2)
00651 {
00652 if ( !theNode1 || !theNode2 ) return false;
00653
00654 theTria1 = theTria2 = 0;
00655
00656 set< const SMDS_MeshElement* > emap;
00657 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator(SMDSAbs_Face);
00658 while (it->more()) {
00659 const SMDS_MeshElement* elem = it->next();
00660 if ( elem->NbNodes() == 3 )
00661 emap.insert( elem );
00662 }
00663 it = theNode2->GetInverseElementIterator(SMDSAbs_Face);
00664 while (it->more()) {
00665 const SMDS_MeshElement* elem = it->next();
00666 if ( emap.find( elem ) != emap.end() ) {
00667 if ( theTria1 ) {
00668
00669 if( theTria1->GetID() < elem->GetID() ) {
00670 theTria2 = elem;
00671 }
00672 else {
00673 theTria2 = theTria1;
00674 theTria1 = elem;
00675 }
00676 break;
00677 }
00678 else {
00679 theTria1 = elem;
00680 }
00681 }
00682 }
00683 return ( theTria1 && theTria2 );
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693 bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
00694 const SMDS_MeshNode * theNode2)
00695 {
00696 myLastCreatedElems.Clear();
00697 myLastCreatedNodes.Clear();
00698
00699 MESSAGE( "::InverseDiag()" );
00700
00701 const SMDS_MeshElement *tr1, *tr2;
00702 if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
00703 return false;
00704
00705 const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
00706 if (!F1) return false;
00707 const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
00708 if (!F2) return false;
00709 if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
00710 (tr2->GetEntityType() == SMDSEntity_Triangle)) {
00711
00712
00713
00714
00715
00716
00717
00718
00719 int i, iA1 = 0, i1 = 0;
00720 const SMDS_MeshNode* aNodes1 [3];
00721 SMDS_ElemIteratorPtr it;
00722 for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
00723 aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
00724 if ( aNodes1[ i ] == theNode1 )
00725 iA1 = i;
00726 else if ( aNodes1[ i ] != theNode2 )
00727 i1 = i;
00728 }
00729 int iB2 = 0, i2 = 0;
00730 const SMDS_MeshNode* aNodes2 [3];
00731 for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
00732 aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
00733 if ( aNodes2[ i ] == theNode2 )
00734 iB2 = i;
00735 else if ( aNodes2[ i ] != theNode1 )
00736 i2 = i;
00737 }
00738
00739
00740 if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
00741 return false;
00742
00743
00744 aNodes1[ iA1 ] = aNodes2[ i2 ];
00745
00746 aNodes2[ iB2 ] = aNodes1[ i1 ];
00747
00748 GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
00749 GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
00750
00751 return true;
00752 }
00753
00754
00755 return InverseDiag(tr1,tr2);
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765 bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [],
00766 const SMDS_MeshNode * theNode1,
00767 const SMDS_MeshNode * theNode2,
00768 const SMDS_MeshElement * tr1,
00769 const SMDS_MeshElement * tr2 )
00770 {
00771 if( tr1->NbNodes() != tr2->NbNodes() )
00772 return false;
00773
00774 const SMDS_MeshNode* n4 = 0;
00775 SMDS_ElemIteratorPtr it = tr2->nodesIterator();
00776 int i=0;
00777 while ( !n4 && i<3 ) {
00778 const SMDS_MeshNode * n = cast2Node( it->next() );
00779 i++;
00780 bool isDiag = ( n == theNode1 || n == theNode2 );
00781 if ( !isDiag )
00782 n4 = n;
00783 }
00784
00785 int iNode = 0, iFirstDiag = -1;
00786 it = tr1->nodesIterator();
00787 i=0;
00788 while ( i<3 ) {
00789 const SMDS_MeshNode * n = cast2Node( it->next() );
00790 i++;
00791 bool isDiag = ( n == theNode1 || n == theNode2 );
00792 if ( isDiag ) {
00793 if ( iFirstDiag < 0 )
00794 iFirstDiag = iNode;
00795 else if ( iNode - iFirstDiag == 1 )
00796 theQuadNodes[ iNode++ ] = n4;
00797 }
00798 else if ( n == n4 ) {
00799 return false;
00800 }
00801 theQuadNodes[ iNode++ ] = n;
00802 }
00803 if ( iNode == 3 )
00804 theQuadNodes[ iNode ] = n4;
00805
00806 return true;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816 bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
00817 const SMDS_MeshNode * theNode2)
00818 {
00819 myLastCreatedElems.Clear();
00820 myLastCreatedNodes.Clear();
00821
00822 MESSAGE( "::DeleteDiag()" );
00823
00824 const SMDS_MeshElement *tr1, *tr2;
00825 if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
00826 return false;
00827
00828 const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
00829 if (!F1) return false;
00830 const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
00831 if (!F2) return false;
00832 SMESHDS_Mesh * aMesh = GetMeshDS();
00833
00834 if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
00835 (tr2->GetEntityType() == SMDSEntity_Triangle)) {
00836
00837 const SMDS_MeshNode* aNodes [ 4 ];
00838 if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
00839 return false;
00840
00841 const SMDS_MeshElement* newElem = 0;
00842 newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3] );
00843 myLastCreatedElems.Append(newElem);
00844 AddToSameGroups( newElem, tr1, aMesh );
00845 int aShapeId = tr1->getshapeId();
00846 if ( aShapeId )
00847 {
00848 aMesh->SetMeshElementOnShape( newElem, aShapeId );
00849 }
00850 aMesh->RemoveElement( tr1 );
00851 aMesh->RemoveElement( tr2 );
00852
00853 return true;
00854 }
00855
00856
00857 if (tr1->GetEntityType() != SMDSEntity_Quad_Triangle)
00858 return false;
00859 if (tr2->GetEntityType() != SMDSEntity_Quad_Triangle)
00860 return false;
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 const SMDS_MeshNode* N1 [6];
00873 const SMDS_MeshNode* N2 [6];
00874 if(!GetNodesFromTwoTria(tr1,tr2,N1,N2))
00875 return false;
00876
00877
00878
00879
00880 const SMDS_MeshNode* aNodes[8];
00881 aNodes[0] = N1[0];
00882 aNodes[1] = N1[1];
00883 aNodes[2] = N2[0];
00884 aNodes[3] = N2[1];
00885 aNodes[4] = N1[3];
00886 aNodes[5] = N2[5];
00887 aNodes[6] = N2[3];
00888 aNodes[7] = N1[5];
00889
00890 const SMDS_MeshElement* newElem = 0;
00891 newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
00892 aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
00893 myLastCreatedElems.Append(newElem);
00894 AddToSameGroups( newElem, tr1, aMesh );
00895 int aShapeId = tr1->getshapeId();
00896 if ( aShapeId )
00897 {
00898 aMesh->SetMeshElementOnShape( newElem, aShapeId );
00899 }
00900 aMesh->RemoveElement( tr1 );
00901 aMesh->RemoveElement( tr2 );
00902
00903
00904 GetMeshDS()->RemoveNode( N1[4] );
00905
00906 return true;
00907 }
00908
00909
00910
00911
00912
00913
00914 bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
00915 {
00916 MESSAGE("Reorient");
00917 myLastCreatedElems.Clear();
00918 myLastCreatedNodes.Clear();
00919
00920 if (!theElem)
00921 return false;
00922 SMDS_ElemIteratorPtr it = theElem->nodesIterator();
00923 if ( !it || !it->more() )
00924 return false;
00925
00926 switch ( theElem->GetType() ) {
00927
00928 case SMDSAbs_Edge:
00929 case SMDSAbs_Face: {
00930 if(!theElem->IsQuadratic()) {
00931 int i = theElem->NbNodes();
00932 vector<const SMDS_MeshNode*> aNodes( i );
00933 while ( it->more() )
00934 aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
00935 return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
00936 }
00937 else {
00938
00939 if(theElem->GetType()==SMDSAbs_Edge) {
00940 vector<const SMDS_MeshNode*> aNodes(3);
00941 aNodes[1]= static_cast<const SMDS_MeshNode*>( it->next() );
00942 aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
00943 aNodes[2]= static_cast<const SMDS_MeshNode*>( it->next() );
00944 return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], 3 );
00945 }
00946 else {
00947 int nbn = theElem->NbNodes();
00948 vector<const SMDS_MeshNode*> aNodes(nbn);
00949 aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
00950 int i=1;
00951 for(; i<nbn/2; i++) {
00952 aNodes[nbn/2-i]= static_cast<const SMDS_MeshNode*>( it->next() );
00953 }
00954 for(i=0; i<nbn/2; i++) {
00955 aNodes[nbn-i-1]= static_cast<const SMDS_MeshNode*>( it->next() );
00956 }
00957 return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], nbn );
00958 }
00959 }
00960 }
00961 case SMDSAbs_Volume: {
00962 if (theElem->IsPoly()) {
00963
00964 MESSAGE("reorient vtk polyhedron ?");
00965 const SMDS_VtkVolume* aPolyedre =
00966 dynamic_cast<const SMDS_VtkVolume*>( theElem );
00967 if (!aPolyedre) {
00968 MESSAGE("Warning: bad volumic element");
00969 return false;
00970 }
00971
00972 int nbFaces = aPolyedre->NbFaces();
00973 vector<const SMDS_MeshNode *> poly_nodes;
00974 vector<int> quantities (nbFaces);
00975
00976
00977 for (int iface = 1; iface <= nbFaces; iface++) {
00978 int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
00979 quantities[iface - 1] = nbFaceNodes;
00980
00981 for (inode = nbFaceNodes; inode >= 1; inode--) {
00982 const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
00983 poly_nodes.push_back(curNode);
00984 }
00985 }
00986
00987 return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );
00988
00989 }
00990 else {
00991 SMDS_VolumeTool vTool;
00992 if ( !vTool.Set( theElem ))
00993 return false;
00994 vTool.Inverse();
00995 MESSAGE("ChangeElementNodes reorient: check vTool.Inverse");
00996 return GetMeshDS()->ChangeElementNodes( theElem, vTool.GetNodes(), vTool.NbNodes() );
00997 }
00998 }
00999 default:;
01000 }
01001
01002 return false;
01003 }
01004
01005
01006
01007
01008
01009
01010 static double getBadRate (const SMDS_MeshElement* theElem,
01011 SMESH::Controls::NumericalFunctorPtr& theCrit)
01012 {
01013 SMESH::Controls::TSequenceOfXYZ P;
01014 if ( !theElem || !theCrit->GetPoints( theElem, P ))
01015 return 1e100;
01016 return theCrit->GetBadRate( theCrit->GetValue( P ), theElem->NbNodes() );
01017
01018 }
01019
01020
01021
01022
01023
01024
01025
01026 bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
01027 SMESH::Controls::NumericalFunctorPtr theCrit)
01028 {
01029 myLastCreatedElems.Clear();
01030 myLastCreatedNodes.Clear();
01031
01032 MESSAGE( "::QuadToTri()" );
01033
01034 if ( !theCrit.get() )
01035 return false;
01036
01037 SMESHDS_Mesh * aMesh = GetMeshDS();
01038
01039 Handle(Geom_Surface) surface;
01040 SMESH_MesherHelper helper( *GetMesh() );
01041
01042 TIDSortedElemSet::iterator itElem;
01043 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
01044 const SMDS_MeshElement* elem = *itElem;
01045 if ( !elem || elem->GetType() != SMDSAbs_Face )
01046 continue;
01047 if ( elem->NbNodes() != ( elem->IsQuadratic() ? 8 : 4 ))
01048 continue;
01049
01050
01051 const SMDS_MeshNode* aNodes [8];
01052 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
01053 int i = 0;
01054 while ( itN->more() )
01055 aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
01056
01057
01058 double aBadRate1, aBadRate2;
01059 SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
01060 SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
01061 aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
01062
01063 SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
01064 SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
01065 aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
01066
01067 int aShapeId = FindShape( elem );
01068 const SMDS_MeshElement* newElem1 = 0;
01069 const SMDS_MeshElement* newElem2 = 0;
01070
01071 if( !elem->IsQuadratic() ) {
01072
01073
01074 if ( aBadRate1 <= aBadRate2 ) {
01075
01076 newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
01077 newElem2 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] );
01078 }
01079 else {
01080
01081 newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
01082 newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
01083 }
01084 }
01085 else {
01086
01087
01088
01089
01090 if ( aShapeId != helper.GetSubShapeID() ) {
01091 surface.Nullify();
01092 TopoDS_Shape shape;
01093 if ( aShapeId > 0 )
01094 shape = aMesh->IndexToShape( aShapeId );
01095 if ( !shape.IsNull() && shape.ShapeType() == TopAbs_FACE ) {
01096 TopoDS_Face face = TopoDS::Face( shape );
01097 surface = BRep_Tool::Surface( face );
01098 if ( !surface.IsNull() )
01099 helper.SetSubShape( shape );
01100 }
01101 }
01102
01103 const SMDS_MeshNode* aNodes [8];
01104 const SMDS_MeshNode* inFaceNode = 0;
01105 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
01106 int i = 0;
01107 while ( itN->more() ) {
01108 aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
01109 if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
01110 aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
01111 {
01112 inFaceNode = aNodes[ i-1 ];
01113 }
01114 }
01115
01116
01117 gp_XYZ p( 0,0,0 );
01118 if ( surface.IsNull() ) {
01119 for(i=0; i<4; i++)
01120 p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
01121 p /= 4;
01122 }
01123 else {
01124 TopoDS_Face face = TopoDS::Face( helper.GetSubShape() );
01125 gp_XY uv( 0,0 );
01126 for(i=0; i<4; i++)
01127 uv += helper.GetNodeUV( face, aNodes[i], inFaceNode );
01128 uv /= 4.;
01129 p = surface->Value( uv.X(), uv.Y() ).XYZ();
01130 }
01131 const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
01132 myLastCreatedNodes.Append(newN);
01133
01134
01135 if ( aBadRate1 <= aBadRate2 ) {
01136 newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
01137 aNodes[6], aNodes[7], newN );
01138 newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
01139 newN, aNodes[4], aNodes[5] );
01140 }
01141 else {
01142 newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
01143 aNodes[7], aNodes[4], newN );
01144 newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
01145 newN, aNodes[5], aNodes[6] );
01146 }
01147 }
01148
01149
01150
01151 myLastCreatedElems.Append(newElem1);
01152 myLastCreatedElems.Append(newElem2);
01153 AddToSameGroups( newElem1, elem, aMesh );
01154 AddToSameGroups( newElem2, elem, aMesh );
01155
01156
01157 if ( aShapeId )
01158 {
01159 aMesh->SetMeshElementOnShape( newElem1, aShapeId );
01160 aMesh->SetMeshElementOnShape( newElem2, aShapeId );
01161 }
01162 aMesh->RemoveElement( elem );
01163 }
01164 return true;
01165 }
01166
01167
01168
01169
01170
01171
01172 int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement* theQuad,
01173 SMESH::Controls::NumericalFunctorPtr theCrit)
01174 {
01175 myLastCreatedElems.Clear();
01176 myLastCreatedNodes.Clear();
01177
01178 if (!theCrit.get())
01179 return -1;
01180
01181 if (!theQuad || theQuad->GetType() != SMDSAbs_Face )
01182 return -1;
01183
01184 if( theQuad->NbNodes()==4 ||
01185 (theQuad->NbNodes()==8 && theQuad->IsQuadratic()) ) {
01186
01187
01188 const SMDS_MeshNode* aNodes [4];
01189 SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
01190 int i = 0;
01191
01192 while (i<4) {
01193 aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
01194 }
01195
01196 double aBadRate1, aBadRate2;
01197 SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
01198 SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
01199 aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
01200
01201 SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
01202 SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
01203 aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
01204
01205 if (aBadRate1 <= aBadRate2)
01206 return 1;
01207
01208 return 2;
01209 }
01210 return -1;
01211 }
01212
01213 namespace
01214 {
01215
01216
01217 const int theHexTo5_1[5*4+1] =
01218 {
01219 0, 1, 2, 5, 0, 4, 5, 7, 0, 2, 3, 7, 2, 5, 6, 7, 0, 5, 2, 7, -1
01220 };
01221 const int theHexTo5_2[5*4+1] =
01222 {
01223 1, 2, 3, 6, 1, 4, 5, 6, 0, 1, 3, 4, 3, 4, 6, 7, 1, 3, 4, 6, -1
01224 };
01225 const int* theHexTo5[2] = { theHexTo5_1, theHexTo5_2 };
01226
01227 const int theHexTo6_1[6*4+1] =
01228 {
01229 1, 5, 6, 0, 0, 1, 2, 6, 0, 4, 5, 6, 0, 4, 6, 7, 0, 2, 3, 6, 0, 3, 7, 6, -1
01230 };
01231 const int theHexTo6_2[6*4+1] =
01232 {
01233 2, 6, 7, 1, 1, 2, 3, 7, 1, 5, 6, 7, 1, 5, 7, 4, 1, 3, 0, 7, 1, 0, 4, 7, -1
01234 };
01235 const int theHexTo6_3[6*4+1] =
01236 {
01237 3, 7, 4, 2, 2, 3, 0, 4, 2, 6, 7, 4, 2, 6, 4, 5, 2, 0, 1, 4, 2, 1, 5, 4, -1
01238 };
01239 const int theHexTo6_4[6*4+1] =
01240 {
01241 0, 4, 5, 3, 3, 0, 1, 5, 3, 7, 4, 5, 3, 7, 5, 6, 3, 1, 2, 5, 3, 2, 6, 5, -1
01242 };
01243 const int* theHexTo6[4] = { theHexTo6_1, theHexTo6_2, theHexTo6_3, theHexTo6_4 };
01244
01245 const int thePyraTo2_1[2*4+1] =
01246 {
01247 0, 1, 2, 4, 0, 2, 3, 4, -1
01248 };
01249 const int thePyraTo2_2[2*4+1] =
01250 {
01251 1, 2, 3, 4, 1, 3, 0, 4, -1
01252 };
01253 const int* thePyraTo2[2] = { thePyraTo2_1, thePyraTo2_2 };
01254
01255 const int thePentaTo3_1[3*4+1] =
01256 {
01257 0, 1, 2, 3, 1, 3, 4, 2, 2, 3, 4, 5, -1
01258 };
01259 const int thePentaTo3_2[3*4+1] =
01260 {
01261 1, 2, 0, 4, 2, 4, 5, 0, 0, 4, 5, 3, -1
01262 };
01263 const int thePentaTo3_3[3*4+1] =
01264 {
01265 2, 0, 1, 5, 0, 5, 3, 1, 1, 5, 3, 4, -1
01266 };
01267 const int thePentaTo3_4[3*4+1] =
01268 {
01269 0, 1, 2, 3, 1, 3, 4, 5, 2, 3, 1, 5, -1
01270 };
01271 const int thePentaTo3_5[3*4+1] =
01272 {
01273 1, 2, 0, 4, 2, 4, 5, 3, 0, 4, 2, 3, -1
01274 };
01275 const int thePentaTo3_6[3*4+1] =
01276 {
01277 2, 0, 1, 5, 0, 5, 3, 4, 1, 5, 0, 4, -1
01278 };
01279 const int* thePentaTo3[6] = { thePentaTo3_1, thePentaTo3_2, thePentaTo3_3,
01280 thePentaTo3_4, thePentaTo3_5, thePentaTo3_6 };
01281
01282 struct TTriangleFacet
01283 {
01284 int _n1, _n2, _n3;
01285 TTriangleFacet(int n1, int n2, int n3): _n1(n1), _n2(n2), _n3(n3) {}
01286 bool contains(int n) const { return ( n == _n1 || n == _n2 || n == _n3 ); }
01287 bool hasAdjacentTetra( const SMDS_MeshElement* elem ) const;
01288 };
01289 struct TSplitMethod
01290 {
01291 int _nbTetra;
01292 const int* _connectivity;
01293 bool _baryNode;
01294 bool _ownConn;
01295 map<int, const SMDS_MeshNode*> _faceBaryNode;
01296
01297 TSplitMethod( int nbTet=0, const int* conn=0, bool addNode=false)
01298 : _nbTetra(nbTet), _connectivity(conn), _baryNode(addNode), _ownConn(false) {}
01299 ~TSplitMethod() { if ( _ownConn ) delete [] _connectivity; _connectivity = 0; }
01300 bool hasFacet( const TTriangleFacet& facet ) const
01301 {
01302 const int* tetConn = _connectivity;
01303 for ( ; tetConn[0] >= 0; tetConn += 4 )
01304 if (( facet.contains( tetConn[0] ) +
01305 facet.contains( tetConn[1] ) +
01306 facet.contains( tetConn[2] ) +
01307 facet.contains( tetConn[3] )) == 3 )
01308 return true;
01309 return false;
01310 }
01311 };
01312
01313
01317
01318
01319 TSplitMethod getSplitMethod( SMDS_VolumeTool& vol, const int theMethodFlags)
01320 {
01321 const int iQ = vol.Element()->IsQuadratic() ? 2 : 1;
01322
01323
01324
01325
01326 const bool is24TetMode = ( theMethodFlags == SMESH_MeshEditor::HEXA_TO_24 );
01327
01328
01329
01330 vector < list< TTriangleFacet > > triaSplitsByFace( vol.NbFaces() );
01331 int hasAdjacentSplits = 0, maxTetConnSize = 0;
01332 for ( int iF = 0; iF < vol.NbFaces(); ++iF )
01333 {
01334 int nbNodes = vol.NbFaceNodes( iF ) / iQ;
01335 maxTetConnSize += 4 * ( nbNodes - (is24TetMode ? 0 : 2));
01336 if ( nbNodes < 4 ) continue;
01337
01338 list< TTriangleFacet >& triaSplits = triaSplitsByFace[ iF ];
01339 const int* nInd = vol.GetFaceNodesIndices( iF );
01340 if ( nbNodes == 4 )
01341 {
01342 TTriangleFacet t012( nInd[0*iQ], nInd[1*iQ], nInd[2*iQ] );
01343 TTriangleFacet t123( nInd[1*iQ], nInd[2*iQ], nInd[3*iQ] );
01344 if ( t012.hasAdjacentTetra( vol.Element() )) triaSplits.push_back( t012 );
01345 else if ( t123.hasAdjacentTetra( vol.Element() )) triaSplits.push_back( t123 );
01346 }
01347 else
01348 {
01349 int iCom = 0;
01350 for ( int iVar = 0; iVar < nbNodes; ++iVar, ++iCom )
01351 {
01352 TTriangleFacet t012( nInd[ iQ * ( iCom )],
01353 nInd[ iQ * ( (iCom+1)%nbNodes )],
01354 nInd[ iQ * ( (iCom+2)%nbNodes )]);
01355 TTriangleFacet t023( nInd[ iQ * ( iCom )],
01356 nInd[ iQ * ( (iCom+2)%nbNodes )],
01357 nInd[ iQ * ( (iCom+3)%nbNodes )]);
01358 if ( t012.hasAdjacentTetra( vol.Element() ) && t023.hasAdjacentTetra( vol.Element() ))
01359 {
01360 triaSplits.push_back( t012 );
01361 triaSplits.push_back( t023 );
01362 break;
01363 }
01364 }
01365 }
01366 if ( !triaSplits.empty() )
01367 hasAdjacentSplits = true;
01368 }
01369
01370
01371
01372 TSplitMethod method;
01373 if ( !vol.Element()->IsPoly() && !is24TetMode )
01374 {
01375 int nbVariants = 2, nbTet = 0;
01376 const int** connVariants = 0;
01377 switch ( vol.Element()->GetEntityType() )
01378 {
01379 case SMDSEntity_Hexa:
01380 case SMDSEntity_Quad_Hexa:
01381 if ( theMethodFlags == SMESH_MeshEditor::HEXA_TO_5 )
01382 connVariants = theHexTo5, nbTet = 5;
01383 else
01384 connVariants = theHexTo6, nbTet = 6, nbVariants = 4;
01385 break;
01386 case SMDSEntity_Pyramid:
01387 case SMDSEntity_Quad_Pyramid:
01388 connVariants = thePyraTo2; nbTet = 2;
01389 break;
01390 case SMDSEntity_Penta:
01391 case SMDSEntity_Quad_Penta:
01392 connVariants = thePentaTo3; nbTet = 3; nbVariants = 6;
01393 break;
01394 default:
01395 nbVariants = 0;
01396 }
01397 for ( int variant = 0; variant < nbVariants && method._nbTetra == 0; ++variant )
01398 {
01399
01400
01401 method = TSplitMethod( nbTet, connVariants[variant] );
01402 if ( hasAdjacentSplits && method._nbTetra > 0 )
01403 {
01404 bool facetCreated = true;
01405 for ( int iF = 0; facetCreated && iF < triaSplitsByFace.size(); ++iF )
01406 {
01407 list< TTriangleFacet >::const_iterator facet = triaSplitsByFace[iF].begin();
01408 for ( ; facetCreated && facet != triaSplitsByFace[iF].end(); ++facet )
01409 facetCreated = method.hasFacet( *facet );
01410 }
01411 if ( !facetCreated )
01412 method = TSplitMethod(0);
01413 }
01414 }
01415 }
01416 if ( method._nbTetra < 1 )
01417 {
01418
01419
01420
01421
01422 int* connectivity = new int[ maxTetConnSize + 1 ];
01423 method._connectivity = connectivity;
01424 method._ownConn = true;
01425 method._baryNode = true;
01426
01427 int connSize = 0;
01428 int baryCenInd = vol.NbNodes();
01429 for ( int iF = 0; iF < vol.NbFaces(); ++iF )
01430 {
01431 const int nbNodes = vol.NbFaceNodes( iF ) / iQ;
01432 const int* nInd = vol.GetFaceNodesIndices( iF );
01433
01434 int iCommon = 0;
01435 const list< TTriangleFacet >& triaSplits = triaSplitsByFace[ iF ];
01436 if ( !triaSplits.empty() )
01437 {
01438
01439 const TTriangleFacet* facet = &triaSplits.front();
01440 for ( ; iCommon < nbNodes-1 ; ++iCommon )
01441 if ( facet->contains( nInd[ iQ * iCommon ]) &&
01442 facet->contains( nInd[ iQ * ((iCommon+2)%nbNodes) ]))
01443 break;
01444 }
01445 else if ( nbNodes > 3 && !is24TetMode )
01446 {
01447
01448 SMESH::Controls::NumericalFunctorPtr aspectRatio( new SMESH::Controls::AspectRatio);
01449 map< double, int > badness2iCommon;
01450 const SMDS_MeshNode** nodes = vol.GetFaceNodes( iF );
01451 int nbVariants = ( nbNodes == 4 ? 2 : nbNodes );
01452 for ( int iVar = 0; iVar < nbVariants; ++iVar, ++iCommon )
01453 for ( int iLast = iCommon+2; iLast < iCommon+nbNodes; ++iLast )
01454 {
01455 SMDS_FaceOfNodes tria ( nodes[ iQ*( iCommon )],
01456 nodes[ iQ*((iLast-1)%nbNodes)],
01457 nodes[ iQ*((iLast )%nbNodes)]);
01458 double badness = getBadRate( &tria, aspectRatio );
01459 badness2iCommon.insert( make_pair( badness, iCommon ));
01460 }
01461
01462 iCommon = badness2iCommon.begin()->second;
01463 }
01464 if ( iCommon >= nbNodes )
01465 iCommon = 0;
01466
01467
01468 int nbTet = nbNodes - 2;
01469 if ( is24TetMode && nbNodes > 3 && triaSplits.empty())
01470 {
01471 method._faceBaryNode.insert( make_pair( iF, (const SMDS_MeshNode*)0 ));
01472 int faceBaryCenInd = baryCenInd + method._faceBaryNode.size();
01473 nbTet = nbNodes;
01474 for ( int i = 0; i < nbTet; ++i )
01475 {
01476 int i1 = i, i2 = (i+1) % nbNodes;
01477 if ( !vol.IsFaceExternal( iF )) swap( i1, i2 );
01478 connectivity[ connSize++ ] = nInd[ iQ * i1 ];
01479 connectivity[ connSize++ ] = nInd[ iQ * i2 ];
01480 connectivity[ connSize++ ] = faceBaryCenInd;
01481 connectivity[ connSize++ ] = baryCenInd;
01482 }
01483 }
01484 else
01485 {
01486 for ( int i = 0; i < nbTet; ++i )
01487 {
01488 int i1 = (iCommon+1+i) % nbNodes, i2 = (iCommon+2+i) % nbNodes;
01489 if ( !vol.IsFaceExternal( iF )) swap( i1, i2 );
01490 connectivity[ connSize++ ] = nInd[ iQ * iCommon ];
01491 connectivity[ connSize++ ] = nInd[ iQ * i1 ];
01492 connectivity[ connSize++ ] = nInd[ iQ * i2 ];
01493 connectivity[ connSize++ ] = baryCenInd;
01494 }
01495 }
01496 method._nbTetra += nbTet;
01497 }
01498 connectivity[ connSize++ ] = -1;
01499 }
01500 return method;
01501 }
01502
01506
01507
01508 bool TTriangleFacet::hasAdjacentTetra( const SMDS_MeshElement* elem ) const
01509 {
01510
01511 const SMDS_MeshNode* n1 = elem->GetNode(_n1);
01512 const SMDS_MeshNode* n2 = elem->GetNode(_n2);
01513 const SMDS_MeshNode* n3 = elem->GetNode(_n3);
01514 SMDS_ElemIteratorPtr volIt1 = n1->GetInverseElementIterator(SMDSAbs_Volume);
01515 while ( volIt1->more() )
01516 {
01517 const SMDS_MeshElement* v = volIt1->next();
01518 if ( v->GetEntityType() != ( v->IsQuadratic() ? SMDSEntity_Quad_Tetra : SMDSEntity_Tetra ))
01519 continue;
01520 SMDS_ElemIteratorPtr volIt2 = n2->GetInverseElementIterator(SMDSAbs_Volume);
01521 while ( volIt2->more() )
01522 if ( v != volIt2->next() )
01523 continue;
01524 SMDS_ElemIteratorPtr volIt3 = n3->GetInverseElementIterator(SMDSAbs_Volume);
01525 while ( volIt3->more() )
01526 if ( v == volIt3->next() )
01527 return true;
01528 }
01529 return false;
01530 }
01531
01532
01536
01537
01538 struct TVolumeFaceKey: pair< int, pair< int, int> >
01539 {
01540 TVolumeFaceKey( SMDS_VolumeTool& vol, int iF )
01541 {
01542 TIDSortedNodeSet sortedNodes;
01543 const int iQ = vol.Element()->IsQuadratic() ? 2 : 1;
01544 int nbNodes = vol.NbFaceNodes( iF );
01545 const SMDS_MeshNode** fNodes = vol.GetFaceNodes( iF );
01546 for ( int i = 0; i < nbNodes; i += iQ )
01547 sortedNodes.insert( fNodes[i] );
01548 TIDSortedNodeSet::iterator n = sortedNodes.begin();
01549 first = (*(n++))->GetID();
01550 second.first = (*(n++))->GetID();
01551 second.second = (*(n++))->GetID();
01552 }
01553 };
01554 }
01555
01556
01557
01558
01559
01560
01561 void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
01562 const int theMethodFlags)
01563 {
01564
01565 typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator;
01566 NXyzIterator xyzEnd;
01567
01568 SMDS_VolumeTool volTool;
01569 SMESH_MesherHelper helper( *GetMesh());
01570
01571 SMESHDS_SubMesh* subMesh = 0;
01572 SMESHDS_SubMesh* fSubMesh = 0;
01573
01574 SMESH_SequenceOfElemPtr newNodes, newElems;
01575
01576
01577 map< TVolumeFaceKey, const SMDS_MeshNode* > volFace2BaryNode;
01578 double bc[3];
01579
01580 TIDSortedElemSet::const_iterator elem = theElems.begin();
01581 for ( ; elem != theElems.end(); ++elem )
01582 {
01583 SMDSAbs_EntityType geomType = (*elem)->GetEntityType();
01584 if ( geomType <= SMDSEntity_Quad_Tetra )
01585 continue;
01586
01587 if ( !volTool.Set( *elem )) continue;
01588
01589 TSplitMethod splitMethod = getSplitMethod( volTool, theMethodFlags );
01590 if ( splitMethod._nbTetra < 1 ) continue;
01591
01592
01593 if ( !subMesh || !subMesh->Contains( *elem ))
01594 {
01595 int shapeID = FindShape( *elem );
01596 helper.SetSubShape( shapeID );
01597 subMesh = GetMeshDS()->MeshElements( shapeID );
01598 }
01599 int iQ;
01600 if ( (*elem)->IsQuadratic() )
01601 {
01602 iQ = 2;
01603
01604 for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
01605 {
01606 const SMDS_MeshNode** fNodes = volTool.GetFaceNodes( iF );
01607 for ( int iN = 0; iN < volTool.NbFaceNodes( iF ); iN += iQ )
01608 helper.AddTLinkNode( fNodes[iF], fNodes[iF+2], fNodes[iF+1] );
01609 }
01610 helper.SetIsQuadratic( true );
01611 }
01612 else
01613 {
01614 iQ = 1;
01615 helper.SetIsQuadratic( false );
01616 }
01617 vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
01618 helper.SetElementsOnShape( true );
01619 if ( splitMethod._baryNode )
01620 {
01621
01622 volTool.GetBaryCenter( bc[0], bc[1], bc[2] );
01623 SMDS_MeshNode* gcNode = helper.AddNode( bc[0], bc[1], bc[2] );
01624 nodes.push_back( gcNode );
01625 newNodes.Append( gcNode );
01626 }
01627 if ( !splitMethod._faceBaryNode.empty() )
01628 {
01629
01630 map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.begin();
01631 for ( ; iF_n != splitMethod._faceBaryNode.end(); ++iF_n )
01632 {
01633 map< TVolumeFaceKey, const SMDS_MeshNode* >::iterator f_n =
01634 volFace2BaryNode.insert
01635 ( make_pair( TVolumeFaceKey( volTool,iF_n->first ), (const SMDS_MeshNode*)0) ).first;
01636 if ( !f_n->second )
01637 {
01638 volTool.GetFaceBaryCenter( iF_n->first, bc[0], bc[1], bc[2] );
01639 newNodes.Append( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
01640 }
01641 nodes.push_back( iF_n->second = f_n->second );
01642 }
01643 }
01644
01645
01646 vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra );
01647 const int* tetConn = splitMethod._connectivity;
01648 for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
01649 newElems.Append( tetras[ i ] = helper.AddVolume( nodes[ tetConn[0] ],
01650 nodes[ tetConn[1] ],
01651 nodes[ tetConn[2] ],
01652 nodes[ tetConn[3] ]));
01653
01654 ReplaceElemInGroups( *elem, tetras, GetMeshDS() );
01655
01656
01657
01658 const SMDS_MeshNode** volNodes = volTool.GetNodes();
01659 for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
01660 {
01661 const int nbNodes = volTool.NbFaceNodes( iF ) / iQ;
01662 if ( nbNodes < 4 ) continue;
01663
01664
01665 vector<const SMDS_MeshNode*> fNodes( volTool.GetFaceNodes( iF ),
01666 volTool.GetFaceNodes( iF ) + nbNodes*iQ );
01667 while ( const SMDS_MeshElement* face = GetMeshDS()->FindFace( fNodes ))
01668 {
01669
01670 helper.SetElementsOnShape( false );
01671 vector< const SMDS_MeshElement* > triangles;
01672
01673
01674 if ( !fSubMesh || !fSubMesh->Contains( face ))
01675 {
01676 int shapeID = FindShape( face );
01677 fSubMesh = GetMeshDS()->MeshElements( shapeID );
01678 }
01679 map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
01680 if ( iF_n != splitMethod._faceBaryNode.end() )
01681 {
01682 for ( int iN = 0; iN < nbNodes*iQ; iN += iQ )
01683 {
01684 const SMDS_MeshNode* n1 = fNodes[iN];
01685 const SMDS_MeshNode *n2 = fNodes[(iN+iQ)%nbNodes*iQ];
01686 const SMDS_MeshNode *n3 = iF_n->second;
01687 if ( !volTool.IsFaceExternal( iF ))
01688 swap( n2, n3 );
01689 triangles.push_back( helper.AddFace( n1,n2,n3 ));
01690
01691 if ( fSubMesh && n3->getshapeId() < 1 )
01692 fSubMesh->AddNode( n3 );
01693 }
01694 }
01695 else
01696 {
01697
01698 const int* nInd = volTool.GetFaceNodesIndices( iF );
01699 int nbVariants = ( nbNodes == 4 ? 2 : nbNodes );
01700 int iCom = 0;
01701 list< TTriangleFacet > facets;
01702 for ( int iVar = 0; iVar < nbVariants; ++iVar, ++iCom )
01703 {
01704 TTriangleFacet t012( nInd[ iQ * ( iCom )],
01705 nInd[ iQ * ( (iCom+1)%nbNodes )],
01706 nInd[ iQ * ( (iCom+2)%nbNodes )]);
01707 TTriangleFacet t023( nInd[ iQ * ( iCom )],
01708 nInd[ iQ * ( (iCom+2)%nbNodes )],
01709 nInd[ iQ * ( (iCom+3)%nbNodes )]);
01710 if ( splitMethod.hasFacet( t012 ) && splitMethod.hasFacet( t023 ))
01711 {
01712 facets.push_back( t012 );
01713 facets.push_back( t023 );
01714 for ( int iLast = iCom+4; iLast < iCom+nbNodes; ++iLast )
01715 facets.push_back( TTriangleFacet( nInd[ iQ * ( iCom )],
01716 nInd[ iQ * ((iLast-1)%nbNodes )],
01717 nInd[ iQ * ((iLast )%nbNodes )]));
01718 break;
01719 }
01720 }
01721 list< TTriangleFacet >::iterator facet = facets.begin();
01722 for ( ; facet != facets.end(); ++facet )
01723 {
01724 if ( !volTool.IsFaceExternal( iF ))
01725 swap( facet->_n2, facet->_n3 );
01726 triangles.push_back( helper.AddFace( volNodes[ facet->_n1 ],
01727 volNodes[ facet->_n2 ],
01728 volNodes[ facet->_n3 ]));
01729 }
01730 }
01731 for ( int i = 0; i < triangles.size(); ++i )
01732 {
01733 if ( !triangles[i] ) continue;
01734 if ( fSubMesh )
01735 fSubMesh->AddElement( triangles[i]);
01736 newElems.Append( triangles[i] );
01737 }
01738 ReplaceElemInGroups( face, triangles, GetMeshDS() );
01739 GetMeshDS()->RemoveFreeElement( face, fSubMesh, false );
01740 }
01741
01742 }
01743
01744 GetMeshDS()->RemoveFreeElement( *elem, subMesh, false );
01745
01746 }
01747
01748 myLastCreatedNodes = newNodes;
01749 myLastCreatedElems = newElems;
01750 }
01751
01752
01753
01754
01755
01756
01757 void SMESH_MeshEditor::AddToSameGroups (const SMDS_MeshElement* elemToAdd,
01758 const SMDS_MeshElement* elemInGroups,
01759 SMESHDS_Mesh * aMesh)
01760 {
01761 const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
01762 if (!groups.empty()) {
01763 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
01764 for ( ; grIt != groups.end(); grIt++ ) {
01765 SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
01766 if ( group && group->Contains( elemInGroups ))
01767 group->SMDSGroup().Add( elemToAdd );
01768 }
01769 }
01770 }
01771
01772
01773
01774
01775
01776
01777 void SMESH_MeshEditor::RemoveElemFromGroups (const SMDS_MeshElement* removeelem,
01778 SMESHDS_Mesh * aMesh)
01779 {
01780 const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
01781 if (!groups.empty())
01782 {
01783 set<SMESHDS_GroupBase*>::const_iterator GrIt = groups.begin();
01784 for (; GrIt != groups.end(); GrIt++)
01785 {
01786 SMESHDS_Group* grp = dynamic_cast<SMESHDS_Group*>(*GrIt);
01787 if (!grp || grp->IsEmpty()) continue;
01788 grp->SMDSGroup().Remove(removeelem);
01789 }
01790 }
01791 }
01792
01793
01797
01798
01799 void SMESH_MeshEditor::ReplaceElemInGroups (const SMDS_MeshElement* elemToRm,
01800 const SMDS_MeshElement* elemToAdd,
01801 SMESHDS_Mesh * aMesh)
01802 {
01803 const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
01804 if (!groups.empty()) {
01805 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
01806 for ( ; grIt != groups.end(); grIt++ ) {
01807 SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
01808 if ( group && group->SMDSGroup().Remove( elemToRm ) && elemToAdd )
01809 group->SMDSGroup().Add( elemToAdd );
01810 }
01811 }
01812 }
01813
01814
01818
01819
01820 void SMESH_MeshEditor::ReplaceElemInGroups (const SMDS_MeshElement* elemToRm,
01821 const vector<const SMDS_MeshElement*>& elemToAdd,
01822 SMESHDS_Mesh * aMesh)
01823 {
01824 const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
01825 if (!groups.empty())
01826 {
01827 set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
01828 for ( ; grIt != groups.end(); grIt++ ) {
01829 SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
01830 if ( group && group->SMDSGroup().Remove( elemToRm ) )
01831 for ( int i = 0; i < elemToAdd.size(); ++i )
01832 group->SMDSGroup().Add( elemToAdd[ i ] );
01833 }
01834 }
01835 }
01836
01837
01838
01839
01840
01841
01842
01843 bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
01844 const bool the13Diag)
01845 {
01846 myLastCreatedElems.Clear();
01847 myLastCreatedNodes.Clear();
01848
01849 MESSAGE( "::QuadToTri()" );
01850
01851 SMESHDS_Mesh * aMesh = GetMeshDS();
01852
01853 Handle(Geom_Surface) surface;
01854 SMESH_MesherHelper helper( *GetMesh() );
01855
01856 TIDSortedElemSet::iterator itElem;
01857 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
01858 const SMDS_MeshElement* elem = *itElem;
01859 if ( !elem || elem->GetType() != SMDSAbs_Face )
01860 continue;
01861 bool isquad = elem->NbNodes()==4 || elem->NbNodes()==8;
01862 if(!isquad) continue;
01863
01864 if(elem->NbNodes()==4) {
01865
01866 const SMDS_MeshNode* aNodes [4];
01867 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
01868 int i = 0;
01869 while ( itN->more() )
01870 aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
01871
01872 int aShapeId = FindShape( elem );
01873 const SMDS_MeshElement* newElem1 = 0;
01874 const SMDS_MeshElement* newElem2 = 0;
01875 if ( the13Diag ) {
01876 newElem1 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] );
01877 newElem2 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
01878 }
01879 else {
01880 newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
01881 newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
01882 }
01883 myLastCreatedElems.Append(newElem1);
01884 myLastCreatedElems.Append(newElem2);
01885
01886 if ( aShapeId )
01887 {
01888 aMesh->SetMeshElementOnShape( newElem1, aShapeId );
01889 aMesh->SetMeshElementOnShape( newElem2, aShapeId );
01890 }
01891 AddToSameGroups( newElem1, elem, aMesh );
01892 AddToSameGroups( newElem2, elem, aMesh );
01893
01894 aMesh->RemoveElement( elem );
01895 }
01896
01897
01898
01899 if( elem->NbNodes()==8 && elem->IsQuadratic() ) {
01900
01901
01902 int aShapeId = FindShape( elem );
01903 if ( aShapeId != helper.GetSubShapeID() ) {
01904 surface.Nullify();
01905 TopoDS_Shape shape;
01906 if ( aShapeId > 0 )
01907 shape = aMesh->IndexToShape( aShapeId );
01908 if ( !shape.IsNull() && shape.ShapeType() == TopAbs_FACE ) {
01909 TopoDS_Face face = TopoDS::Face( shape );
01910 surface = BRep_Tool::Surface( face );
01911 if ( !surface.IsNull() )
01912 helper.SetSubShape( shape );
01913 }
01914 }
01915
01916 const SMDS_MeshNode* aNodes [8];
01917 const SMDS_MeshNode* inFaceNode = 0;
01918 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
01919 int i = 0;
01920 while ( itN->more() ) {
01921 aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
01922 if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
01923 aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
01924 {
01925 inFaceNode = aNodes[ i-1 ];
01926 }
01927 }
01928
01929
01930
01931 gp_XYZ p( 0,0,0 );
01932 if ( surface.IsNull() ) {
01933 for(i=0; i<4; i++)
01934 p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
01935 p /= 4;
01936 }
01937 else {
01938 TopoDS_Face geomFace = TopoDS::Face( helper.GetSubShape() );
01939 gp_XY uv( 0,0 );
01940 for(i=0; i<4; i++)
01941 uv += helper.GetNodeUV( geomFace, aNodes[i], inFaceNode );
01942 uv /= 4.;
01943 p = surface->Value( uv.X(), uv.Y() ).XYZ();
01944 }
01945 const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
01946 myLastCreatedNodes.Append(newN);
01947
01948
01949 const SMDS_MeshElement* newElem1 = 0;
01950 const SMDS_MeshElement* newElem2 = 0;
01951 if ( the13Diag ) {
01952 newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
01953 aNodes[6], aNodes[7], newN );
01954 newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
01955 newN, aNodes[4], aNodes[5] );
01956 }
01957 else {
01958 newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
01959 aNodes[7], aNodes[4], newN );
01960 newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
01961 newN, aNodes[5], aNodes[6] );
01962 }
01963 myLastCreatedElems.Append(newElem1);
01964 myLastCreatedElems.Append(newElem2);
01965
01966 if ( aShapeId )
01967 {
01968 aMesh->SetMeshElementOnShape( newElem1, aShapeId );
01969 aMesh->SetMeshElementOnShape( newElem2, aShapeId );
01970 }
01971 AddToSameGroups( newElem1, elem, aMesh );
01972 AddToSameGroups( newElem2, elem, aMesh );
01973 aMesh->RemoveElement( elem );
01974 }
01975 }
01976
01977 return true;
01978 }
01979
01980
01981
01982
01983
01984
01985 double getAngle(const SMDS_MeshElement * tr1,
01986 const SMDS_MeshElement * tr2,
01987 const SMDS_MeshNode * n1,
01988 const SMDS_MeshNode * n2)
01989 {
01990 double angle = 2*PI;
01991
01992
01993 SMESH::Controls::TSequenceOfXYZ P1, P2;
01994 if ( !SMESH::Controls::NumericalFunctor::GetPoints( tr1, P1 ) ||
01995 !SMESH::Controls::NumericalFunctor::GetPoints( tr2, P2 ))
01996 return angle;
01997 gp_Vec N1,N2;
01998 if(!tr1->IsQuadratic())
01999 N1 = gp_Vec( P1(2) - P1(1) ) ^ gp_Vec( P1(3) - P1(1) );
02000 else
02001 N1 = gp_Vec( P1(3) - P1(1) ) ^ gp_Vec( P1(5) - P1(1) );
02002 if ( N1.SquareMagnitude() <= gp::Resolution() )
02003 return angle;
02004 if(!tr2->IsQuadratic())
02005 N2 = gp_Vec( P2(2) - P2(1) ) ^ gp_Vec( P2(3) - P2(1) );
02006 else
02007 N2 = gp_Vec( P2(3) - P2(1) ) ^ gp_Vec( P2(5) - P2(1) );
02008 if ( N2.SquareMagnitude() <= gp::Resolution() )
02009 return angle;
02010
02011
02012
02013 const SMDS_MeshElement *nFirst[2], *tr[] = { tr1, tr2 };
02014 for ( int t = 0; t < 2; t++ ) {
02015 SMDS_ElemIteratorPtr it = tr[ t ]->nodesIterator();
02016 int i = 0, iDiag = -1;
02017 while ( it->more()) {
02018 const SMDS_MeshElement *n = it->next();
02019 if ( n == n1 || n == n2 ) {
02020 if ( iDiag < 0)
02021 iDiag = i;
02022 else {
02023 if ( i - iDiag == 1 )
02024 nFirst[ t ] = ( n == n1 ? n2 : n1 );
02025 else
02026 nFirst[ t ] = n;
02027 break;
02028 }
02029 }
02030 i++;
02031 }
02032 }
02033 if ( nFirst[ 0 ] == nFirst[ 1 ] )
02034 N2.Reverse();
02035
02036 angle = N1.Angle( N2 );
02037
02038 return angle;
02039 }
02040
02041
02042
02043
02044
02045 class LinkID_Gen {
02046 public:
02047
02048 LinkID_Gen( const SMESHDS_Mesh* theMesh )
02049 :myMesh( theMesh ), myMaxID( theMesh->MaxNodeID() + 1)
02050 {}
02051
02052 long GetLinkID (const SMDS_MeshNode * n1,
02053 const SMDS_MeshNode * n2) const
02054 {
02055 return ( Min(n1->GetID(),n2->GetID()) * myMaxID + Max(n1->GetID(),n2->GetID()));
02056 }
02057
02058 bool GetNodes (const long theLinkID,
02059 const SMDS_MeshNode* & theNode1,
02060 const SMDS_MeshNode* & theNode2) const
02061 {
02062 theNode1 = myMesh->FindNode( theLinkID / myMaxID );
02063 if ( !theNode1 ) return false;
02064 theNode2 = myMesh->FindNode( theLinkID % myMaxID );
02065 if ( !theNode2 ) return false;
02066 return true;
02067 }
02068
02069 private:
02070 LinkID_Gen();
02071 const SMESHDS_Mesh* myMesh;
02072 long myMaxID;
02073 };
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084 bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems,
02085 SMESH::Controls::NumericalFunctorPtr theCrit,
02086 const double theMaxAngle)
02087 {
02088 myLastCreatedElems.Clear();
02089 myLastCreatedNodes.Clear();
02090
02091 MESSAGE( "::TriToQuad()" );
02092
02093 if ( !theCrit.get() )
02094 return false;
02095
02096 SMESHDS_Mesh * aMesh = GetMeshDS();
02097
02098
02099
02100
02101
02102 map< SMESH_TLink, list< const SMDS_MeshElement* > > mapLi_listEl;
02103 map< SMESH_TLink, list< const SMDS_MeshElement* > >::iterator itLE;
02104 map< const SMDS_MeshElement*, set< SMESH_TLink > > mapEl_setLi;
02105 map< const SMDS_MeshElement*, set< SMESH_TLink > >::iterator itEL;
02106
02107 TIDSortedElemSet::iterator itElem;
02108 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
02109 const SMDS_MeshElement* elem = *itElem;
02110 if(!elem || elem->GetType() != SMDSAbs_Face ) continue;
02111 bool IsTria = elem->NbNodes()==3 || (elem->NbNodes()==6 && elem->IsQuadratic());
02112 if(!IsTria) continue;
02113
02114
02115 const SMDS_MeshNode* aNodes [4];
02116 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
02117 int i = 0;
02118 while ( i<3 )
02119 aNodes[ i++ ] = cast2Node( itN->next() );
02120 aNodes[ 3 ] = aNodes[ 0 ];
02121
02122
02123 for ( i = 0; i < 3; i++ ) {
02124 SMESH_TLink link( aNodes[i], aNodes[i+1] );
02125
02126 itLE = mapLi_listEl.find( link );
02127 if ( itLE != mapLi_listEl.end() ) {
02128 if ((*itLE).second.size() > 1 )
02129 continue;
02130 const SMDS_MeshElement* elem2 = (*itLE).second.front();
02131
02132
02133 if ( getAngle( elem, elem2, aNodes[i], aNodes[i+1] ) > theMaxAngle )
02134 continue;
02135 (*itLE).second.push_back( elem );
02136 }
02137 else {
02138 mapLi_listEl[ link ].push_back( elem );
02139 }
02140 mapEl_setLi [ elem ].insert( link );
02141 }
02142 }
02143
02144
02145
02146 for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ ) {
02147 int nbElems = (*itLE).second.size();
02148 if ( nbElems < 2 ) {
02149 const SMDS_MeshElement* elem = (*itLE).second.front();
02150 SMESH_TLink link = (*itLE).first;
02151 mapEl_setLi[ elem ].erase( link );
02152 if ( mapEl_setLi[ elem ].empty() )
02153 mapEl_setLi.erase( elem );
02154 }
02155 }
02156
02157
02158
02159 while ( ! mapEl_setLi.empty() ) {
02160
02161
02162 const SMDS_MeshElement* startElem = 0;
02163 int minNbLinks = 4;
02164 for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) {
02165 int nbLinks = (*itEL).second.size();
02166 if ( nbLinks < minNbLinks ) {
02167 startElem = (*itEL).first;
02168 minNbLinks = nbLinks;
02169 if ( minNbLinks == 1 )
02170 break;
02171 }
02172 }
02173
02174
02175
02176 list< SMESH_TLink > startLinks;
02177 while ( startElem || !startLinks.empty() ) {
02178 while ( !startElem && !startLinks.empty() ) {
02179
02180 SMESH_TLink linkId = startLinks.front();
02181 startLinks.pop_front();
02182 itLE = mapLi_listEl.find( linkId );
02183 if ( itLE != mapLi_listEl.end() ) {
02184 list< const SMDS_MeshElement* > & listElem = (*itLE).second;
02185 list< const SMDS_MeshElement* >::iterator itE = listElem.begin();
02186 for ( ; itE != listElem.end() ; itE++ )
02187 if ( mapEl_setLi.find( (*itE) ) != mapEl_setLi.end() )
02188 startElem = (*itE);
02189 mapLi_listEl.erase( itLE );
02190 }
02191 }
02192
02193 if ( startElem ) {
02194
02195 const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0;
02196 const SMESH_TLink *link12, *link13;
02197 startElem = 0;
02198 ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() );
02199 set< SMESH_TLink >& setLi = mapEl_setLi[ tr1 ];
02200 ASSERT( !setLi.empty() );
02201 set< SMESH_TLink >::iterator itLi;
02202 for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ )
02203 {
02204 const SMESH_TLink & link = (*itLi);
02205 itLE = mapLi_listEl.find( link );
02206 if ( itLE == mapLi_listEl.end() )
02207 continue;
02208
02209 const SMDS_MeshElement* elem = (*itLE).second.front();
02210 if ( elem == tr1 )
02211 elem = (*itLE).second.back();
02212 mapLi_listEl.erase( itLE );
02213 if ( mapEl_setLi.find( elem ) == mapEl_setLi.end())
02214 continue;
02215 if ( tr2 ) {
02216 tr3 = elem;
02217 link13 = &link;
02218 }
02219 else {
02220 tr2 = elem;
02221 link12 = &link;
02222 }
02223
02224
02225 set< SMESH_TLink >& links = mapEl_setLi[ elem ];
02226 set< SMESH_TLink >::iterator it;
02227 for ( it = links.begin(); it != links.end(); it++ ) {
02228 const SMESH_TLink& link2 = (*it);
02229 if ( link2 != link )
02230 startLinks.push_back( link2 );
02231 }
02232 }
02233
02234
02235 const SMDS_MeshNode *n12 [4], *n13 [4];
02236 bool Ok12 = false, Ok13 = false;
02237 const SMDS_MeshNode *linkNode1, *linkNode2;
02238 if(tr2) {
02239 linkNode1 = link12->first;
02240 linkNode2 = link12->second;
02241 if ( tr2 && getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
02242 Ok12 = true;
02243 }
02244 if(tr3) {
02245 linkNode1 = link13->first;
02246 linkNode2 = link13->second;
02247 if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
02248 Ok13 = true;
02249 }
02250
02251
02252 if ( Ok12 && Ok13 ) {
02253 SMDS_FaceOfNodes quad12 ( n12[ 0 ], n12[ 1 ], n12[ 2 ], n12[ 3 ] );
02254 SMDS_FaceOfNodes quad13 ( n13[ 0 ], n13[ 1 ], n13[ 2 ], n13[ 3 ] );
02255 double aBadRate12 = getBadRate( &quad12, theCrit );
02256 double aBadRate13 = getBadRate( &quad13, theCrit );
02257 if ( aBadRate13 < aBadRate12 )
02258 Ok12 = false;
02259 else
02260 Ok13 = false;
02261 }
02262
02263
02264
02265 mapEl_setLi.erase( tr1 );
02266 if ( Ok12 ) {
02267 mapEl_setLi.erase( tr2 );
02268 mapLi_listEl.erase( *link12 );
02269 if(tr1->NbNodes()==3) {
02270 const SMDS_MeshElement* newElem = 0;
02271 newElem = aMesh->AddFace(n12[0], n12[1], n12[2], n12[3] );
02272 myLastCreatedElems.Append(newElem);
02273 AddToSameGroups( newElem, tr1, aMesh );
02274 int aShapeId = tr1->getshapeId();
02275 if ( aShapeId )
02276 {
02277 aMesh->SetMeshElementOnShape( newElem, aShapeId );
02278 }
02279 aMesh->RemoveElement( tr1 );
02280 aMesh->RemoveElement( tr2 );
02281 }
02282 else {
02283 const SMDS_MeshNode* N1 [6];
02284 const SMDS_MeshNode* N2 [6];
02285 GetNodesFromTwoTria(tr1,tr2,N1,N2);
02286
02287
02288
02289 const SMDS_MeshNode* aNodes[8];
02290 aNodes[0] = N1[0];
02291 aNodes[1] = N1[1];
02292 aNodes[2] = N2[0];
02293 aNodes[3] = N2[1];
02294 aNodes[4] = N1[3];
02295 aNodes[5] = N2[5];
02296 aNodes[6] = N2[3];
02297 aNodes[7] = N1[5];
02298 const SMDS_MeshElement* newElem = 0;
02299 newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
02300 aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
02301 myLastCreatedElems.Append(newElem);
02302 AddToSameGroups( newElem, tr1, aMesh );
02303 int aShapeId = tr1->getshapeId();
02304 if ( aShapeId )
02305 {
02306 aMesh->SetMeshElementOnShape( newElem, aShapeId );
02307 }
02308 aMesh->RemoveElement( tr1 );
02309 aMesh->RemoveElement( tr2 );
02310
02311 GetMeshDS()->RemoveNode( N1[4] );
02312 }
02313 }
02314 else if ( Ok13 ) {
02315 mapEl_setLi.erase( tr3 );
02316 mapLi_listEl.erase( *link13 );
02317 if(tr1->NbNodes()==3) {
02318 const SMDS_MeshElement* newElem = 0;
02319 newElem = aMesh->AddFace(n13[0], n13[1], n13[2], n13[3] );
02320 myLastCreatedElems.Append(newElem);
02321 AddToSameGroups( newElem, tr1, aMesh );
02322 int aShapeId = tr1->getshapeId();
02323 if ( aShapeId )
02324 {
02325 aMesh->SetMeshElementOnShape( newElem, aShapeId );
02326 }
02327 aMesh->RemoveElement( tr1 );
02328 aMesh->RemoveElement( tr3 );
02329 }
02330 else {
02331 const SMDS_MeshNode* N1 [6];
02332 const SMDS_MeshNode* N2 [6];
02333 GetNodesFromTwoTria(tr1,tr3,N1,N2);
02334
02335
02336
02337 const SMDS_MeshNode* aNodes[8];
02338 aNodes[0] = N1[0];
02339 aNodes[1] = N1[1];
02340 aNodes[2] = N2[0];
02341 aNodes[3] = N2[1];
02342 aNodes[4] = N1[3];
02343 aNodes[5] = N2[5];
02344 aNodes[6] = N2[3];
02345 aNodes[7] = N1[5];
02346 const SMDS_MeshElement* newElem = 0;
02347 newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
02348 aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
02349 myLastCreatedElems.Append(newElem);
02350 AddToSameGroups( newElem, tr1, aMesh );
02351 int aShapeId = tr1->getshapeId();
02352 if ( aShapeId )
02353 {
02354 aMesh->SetMeshElementOnShape( newElem, aShapeId );
02355 }
02356 aMesh->RemoveElement( tr1 );
02357 aMesh->RemoveElement( tr3 );
02358
02359 GetMeshDS()->RemoveNode( N1[4] );
02360 }
02361 }
02362
02363
02364 if ( tr3 )
02365 startElem = Ok12 ? tr3 : tr2;
02366
02367 }
02368 }
02369 }
02370
02371 return true;
02372 }
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02663
02664
02665 void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode,
02666 TIDSortedElemSet & linkedNodes,
02667 SMDSAbs_ElementType type )
02668 {
02669 SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(type);
02670 while ( elemIt->more() )
02671 {
02672 const SMDS_MeshElement* elem = elemIt->next();
02673 if(elem->GetType() == SMDSAbs_0DElement)
02674 continue;
02675
02676 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
02677 if ( elem->GetType() == SMDSAbs_Volume )
02678 {
02679 SMDS_VolumeTool vol( elem );
02680 while ( nodeIt->more() ) {
02681 const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
02682 if ( theNode != n && vol.IsLinked( theNode, n ))
02683 linkedNodes.insert( n );
02684 }
02685 }
02686 else
02687 {
02688 for ( int i = 0; nodeIt->more(); ++i ) {
02689 const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
02690 if ( n == theNode ) {
02691 int iBefore = i - 1;
02692 int iAfter = i + 1;
02693 if ( elem->IsQuadratic() ) {
02694 int nb = elem->NbNodes() / 2;
02695 iAfter = SMESH_MesherHelper::WrapIndex( iAfter, nb );
02696 iBefore = SMESH_MesherHelper::WrapIndex( iBefore, nb );
02697 }
02698 linkedNodes.insert( elem->GetNodeWrap( iAfter ));
02699 linkedNodes.insert( elem->GetNodeWrap( iBefore ));
02700 }
02701 }
02702 }
02703 }
02704 }
02705
02706
02707
02708
02709
02710
02711
02712 void laplacianSmooth(const SMDS_MeshNode* theNode,
02713 const Handle(Geom_Surface)& theSurface,
02714 map< const SMDS_MeshNode*, gp_XY* >& theUVMap)
02715 {
02716
02717
02718 TIDSortedElemSet nodeSet;
02719 SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face );
02720
02721
02722
02723 double coord[] = { 0., 0., 0. };
02724 TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin();
02725 for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) {
02726 const SMDS_MeshNode* node = cast2Node(*nodeSetIt);
02727 if ( theSurface.IsNull() ) {
02728 coord[0] += node->X();
02729 coord[1] += node->Y();
02730 coord[2] += node->Z();
02731 }
02732 else {
02733 ASSERT( theUVMap.find( node ) != theUVMap.end() );
02734 gp_XY* uv = theUVMap[ node ];
02735 coord[0] += uv->X();
02736 coord[1] += uv->Y();
02737 }
02738 }
02739 int nbNodes = nodeSet.size();
02740 if ( !nbNodes )
02741 return;
02742 coord[0] /= nbNodes;
02743 coord[1] /= nbNodes;
02744
02745 if ( !theSurface.IsNull() ) {
02746 ASSERT( theUVMap.find( theNode ) != theUVMap.end() );
02747 theUVMap[ theNode ]->SetCoord( coord[0], coord[1] );
02748 gp_Pnt p3d = theSurface->Value( coord[0], coord[1] );
02749 coord[0] = p3d.X();
02750 coord[1] = p3d.Y();
02751 coord[2] = p3d.Z();
02752 }
02753 else
02754 coord[2] /= nbNodes;
02755
02756
02757
02758 const_cast< SMDS_MeshNode* >( theNode )->setXYZ(coord[0],coord[1],coord[2]);
02759 }
02760
02761
02762
02763
02764
02765
02766
02767 void centroidalSmooth(const SMDS_MeshNode* theNode,
02768 const Handle(Geom_Surface)& theSurface,
02769 map< const SMDS_MeshNode*, gp_XY* >& theUVMap)
02770 {
02771 gp_XYZ aNewXYZ(0.,0.,0.);
02772 SMESH::Controls::Area anAreaFunc;
02773 double totalArea = 0.;
02774 int nbElems = 0;
02775
02776
02777
02778 SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face);
02779 while ( elemIt->more() )
02780 {
02781 const SMDS_MeshElement* elem = elemIt->next();
02782 nbElems++;
02783
02784 gp_XYZ elemCenter(0.,0.,0.);
02785 SMESH::Controls::TSequenceOfXYZ aNodePoints;
02786 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
02787 int nn = elem->NbNodes();
02788 if(elem->IsQuadratic()) nn = nn/2;
02789 int i=0;
02790
02791 while ( i<nn ) {
02792 const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( itN->next() );
02793 i++;
02794 gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() );
02795 aNodePoints.push_back( aP );
02796 if ( !theSurface.IsNull() ) {
02797 ASSERT( theUVMap.find( aNode ) != theUVMap.end() );
02798 gp_XY* uv = theUVMap[ aNode ];
02799 aP.SetCoord( uv->X(), uv->Y(), 0. );
02800 }
02801 elemCenter += aP;
02802 }
02803 double elemArea = anAreaFunc.GetValue( aNodePoints );
02804 totalArea += elemArea;
02805 elemCenter /= nn;
02806 aNewXYZ += elemCenter * elemArea;
02807 }
02808 aNewXYZ /= totalArea;
02809 if ( !theSurface.IsNull() ) {
02810 theUVMap[ theNode ]->SetCoord( aNewXYZ.X(), aNewXYZ.Y() );
02811 aNewXYZ = theSurface->Value( aNewXYZ.X(), aNewXYZ.Y() ).XYZ();
02812 }
02813
02814
02815
02816 const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z());
02817 }
02818
02819
02820
02821
02822
02823
02824 static bool getClosestUV (Extrema_GenExtPS& projector,
02825 const gp_Pnt& point,
02826 gp_XY & result)
02827 {
02828 projector.Perform( point );
02829 if ( projector.IsDone() ) {
02830 double u, v, minVal = DBL_MAX;
02831 for ( int i = projector.NbExt(); i > 0; i-- )
02832 if ( projector.Value( i ) < minVal ) {
02833 minVal = projector.Value( i );
02834 projector.Point( i ).Parameter( u, v );
02835 }
02836 result.SetCoord( u, v );
02837 return true;
02838 }
02839 return false;
02840 }
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852 void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems,
02853 set<const SMDS_MeshNode*> & theFixedNodes,
02854 const SmoothMethod theSmoothMethod,
02855 const int theNbIterations,
02856 double theTgtAspectRatio,
02857 const bool the2D)
02858 {
02859 myLastCreatedElems.Clear();
02860 myLastCreatedNodes.Clear();
02861
02862 MESSAGE((theSmoothMethod==LAPLACIAN ? "LAPLACIAN" : "CENTROIDAL") << "--::Smooth()");
02863
02864 if ( theTgtAspectRatio < 1.0 )
02865 theTgtAspectRatio = 1.0;
02866
02867 const double disttol = 1.e-16;
02868
02869 SMESH::Controls::AspectRatio aQualityFunc;
02870
02871 SMESHDS_Mesh* aMesh = GetMeshDS();
02872
02873 if ( theElems.empty() ) {
02874
02875 SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
02876 while ( fIt->more() ) {
02877 const SMDS_MeshElement* face = fIt->next();
02878 theElems.insert( face );
02879 }
02880 }
02881
02882 set< int > faceIdSet;
02883 TIDSortedElemSet::iterator itElem;
02884 if ( the2D )
02885 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
02886 int fId = FindShape( *itElem );
02887
02888 if (fId &&
02889 faceIdSet.find( fId ) == faceIdSet.end() &&
02890 aMesh->MeshElements( fId )) {
02891 TopoDS_Shape F = aMesh->IndexToShape( fId );
02892 if ( !F.IsNull() && F.ShapeType() == TopAbs_FACE )
02893 faceIdSet.insert( fId );
02894 }
02895 }
02896 faceIdSet.insert( 0 );
02897
02898
02899
02900
02901
02902 set< int >::reverse_iterator fId = faceIdSet.rbegin();
02903 for ( ; fId != faceIdSet.rend(); ++fId ) {
02904
02905 Handle(Geom_Surface) surface;
02906 SMESHDS_SubMesh* faceSubMesh = 0;
02907 TopoDS_Face face;
02908 double fToler2 = 0, f,l;
02909 double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
02910 bool isUPeriodic = false, isVPeriodic = false;
02911 if ( *fId ) {
02912 face = TopoDS::Face( aMesh->IndexToShape( *fId ));
02913 surface = BRep_Tool::Surface( face );
02914 faceSubMesh = aMesh->MeshElements( *fId );
02915 fToler2 = BRep_Tool::Tolerance( face );
02916 fToler2 *= fToler2 * 10.;
02917 isUPeriodic = surface->IsUPeriodic();
02918 if ( isUPeriodic )
02919 surface->UPeriod();
02920 isVPeriodic = surface->IsVPeriodic();
02921 if ( isVPeriodic )
02922 surface->VPeriod();
02923 surface->Bounds( u1, u2, v1, v2 );
02924 }
02925
02926
02927
02928
02929 bool checkBoundaryNodes = false;
02930 bool isQuadratic = false;
02931 set<const SMDS_MeshNode*> setMovableNodes;
02932 map< const SMDS_MeshNode*, gp_XY* > uvMap, uvMap2;
02933 list< gp_XY > listUV;
02934 list< const SMDS_MeshElement* > elemsOnFace;
02935
02936 Extrema_GenExtPS projector;
02937 GeomAdaptor_Surface surfAdaptor;
02938 if ( !surface.IsNull() ) {
02939 surfAdaptor.Load( surface );
02940 projector.Initialize( surfAdaptor, 20,20, 1e-5,1e-5 );
02941 }
02942 int nbElemOnFace = 0;
02943 itElem = theElems.begin();
02944
02945 while ( itElem != theElems.end() ) {
02946 if ( faceSubMesh && nbElemOnFace == faceSubMesh->NbElements() )
02947 break;
02948
02949 const SMDS_MeshElement* elem = *itElem;
02950 if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() < 3 ||
02951 ( faceSubMesh && !faceSubMesh->Contains( elem ))) {
02952 ++itElem;
02953 continue;
02954 }
02955 elemsOnFace.push_back( elem );
02956 theElems.erase( itElem++ );
02957 nbElemOnFace++;
02958
02959 if ( !isQuadratic )
02960 isQuadratic = elem->IsQuadratic();
02961
02962
02963 const SMDS_MeshNode* node;
02964 SMDS_TypeOfPosition posType;
02965 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
02966 int nn = 0, nbn = elem->NbNodes();
02967 if(elem->IsQuadratic())
02968 nbn = nbn/2;
02969 while ( nn++ < nbn ) {
02970 node = static_cast<const SMDS_MeshNode*>( itN->next() );
02971 const SMDS_PositionPtr& pos = node->GetPosition();
02972 posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
02973 if (posType != SMDS_TOP_EDGE &&
02974 posType != SMDS_TOP_VERTEX &&
02975 theFixedNodes.find( node ) == theFixedNodes.end())
02976 {
02977
02978
02979 SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face);
02980 bool all = true;
02981 if ( faceSubMesh ) {
02982 while ( eIt->more() && all ) {
02983 const SMDS_MeshElement* e = eIt->next();
02984 all = faceSubMesh->Contains( e );
02985 }
02986 }
02987 if ( all )
02988 setMovableNodes.insert( node );
02989 else
02990 checkBoundaryNodes = true;
02991 }
02992 if ( posType == SMDS_TOP_3DSPACE )
02993 checkBoundaryNodes = true;
02994 }
02995
02996 if ( surface.IsNull() )
02997 continue;
02998
02999
03000 list< const SMDS_MeshNode* > uvCheckNodes;
03001 itN = elem->nodesIterator();
03002 nn = 0; nbn = elem->NbNodes();
03003 if(elem->IsQuadratic())
03004 nbn = nbn/2;
03005 while ( nn++ < nbn ) {
03006 node = static_cast<const SMDS_MeshNode*>( itN->next() );
03007 if ( uvMap.find( node ) == uvMap.end() )
03008 uvCheckNodes.push_back( node );
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023 }
03024
03025 list< const SMDS_MeshNode* >::iterator n = uvCheckNodes.begin();
03026 for ( ; n != uvCheckNodes.end(); ++n ) {
03027 node = *n;
03028 gp_XY uv( 0, 0 );
03029 const SMDS_PositionPtr& pos = node->GetPosition();
03030 posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
03031
03032 switch ( posType ) {
03033 case SMDS_TOP_FACE: {
03034 SMDS_FacePosition* fPos = ( SMDS_FacePosition* ) pos;
03035 uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() );
03036 break;
03037 }
03038 case SMDS_TOP_EDGE: {
03039 TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() );
03040 Handle(Geom2d_Curve) pcurve;
03041 if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE )
03042 pcurve = BRep_Tool::CurveOnSurface( TopoDS::Edge( S ), face, f,l );
03043 if ( !pcurve.IsNull() ) {
03044 double u = (( SMDS_EdgePosition* ) pos )->GetUParameter();
03045 uv = pcurve->Value( u ).XY();
03046 }
03047 break;
03048 }
03049 case SMDS_TOP_VERTEX: {
03050 TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() );
03051 if ( !S.IsNull() && S.ShapeType() == TopAbs_VERTEX )
03052 uv = BRep_Tool::Parameters( TopoDS::Vertex( S ), face ).XY();
03053 break;
03054 }
03055 default:;
03056 }
03057
03058 bool project = true;
03059 gp_Pnt pNode ( node->X(), node->Y(), node->Z() );
03060 double dist1 = DBL_MAX, dist2 = 0;
03061 if ( posType != SMDS_TOP_3DSPACE ) {
03062 dist1 = pNode.SquareDistance( surface->Value( uv.X(), uv.Y() ));
03063 project = dist1 > fToler2;
03064 }
03065 if ( project ) {
03066 gp_XY newUV;
03067 if ( !getClosestUV( projector, pNode, newUV )) {
03068 MESSAGE("Node Projection Failed " << node);
03069 }
03070 else {
03071 if ( isUPeriodic )
03072 newUV.SetX( ElCLib::InPeriod( newUV.X(), u1, u2 ));
03073 if ( isVPeriodic )
03074 newUV.SetY( ElCLib::InPeriod( newUV.Y(), v1, v2 ));
03075
03076 if ( posType != SMDS_TOP_3DSPACE )
03077 dist2 = pNode.SquareDistance( surface->Value( newUV.X(), newUV.Y() ));
03078 if ( dist2 < dist1 )
03079 uv = newUV;
03080 }
03081 }
03082
03083 listUV.push_back( uv );
03084 uvMap.insert( make_pair( node, &listUV.back() ));
03085 }
03086 }
03087
03088 if ( !faceSubMesh || nbElemOnFace != faceSubMesh->NbElements() )
03089 checkBoundaryNodes = true;
03090
03091
03092
03093 if ( checkBoundaryNodes ) {
03094 map< SMESH_TLink, int > linkNbMap;
03095 map< SMESH_TLink, int >::iterator link_nb;
03096
03097 list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
03098 for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
03099 const SMDS_MeshElement* elem = (*elemIt);
03100 int nbn = elem->NbCornerNodes();
03101
03102 for ( int iN = 0; iN < nbn; ++iN ) {
03103 const SMDS_MeshNode* n1 = elem->GetNode( iN );
03104 const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
03105 SMESH_TLink link( n1, n2 );
03106 link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
03107 link_nb->second++;
03108 }
03109 }
03110
03111 for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
03112 if ( link_nb->second == 1 ) {
03113 setMovableNodes.erase( link_nb->first.node1() );
03114 setMovableNodes.erase( link_nb->first.node2() );
03115 }
03116 }
03117 }
03118
03119
03120
03121
03122
03123
03124
03125 set<const SMDS_MeshNode*> nodesNearSeam;
03126 if ( !surface.IsNull() ) {
03127 TopExp_Explorer eExp( face, TopAbs_EDGE );
03128 for ( ; eExp.More(); eExp.Next() ) {
03129 TopoDS_Edge edge = TopoDS::Edge( eExp.Current() );
03130 if ( !BRep_Tool::IsClosed( edge, face ))
03131 continue;
03132 SMESHDS_SubMesh* sm = aMesh->MeshElements( edge );
03133 if ( !sm ) continue;
03134
03135 double f,l;
03136 gp_Pnt2d uv1, uv2;
03137 Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f, l );
03138 if ( pcurve.IsNull() ) continue;
03139 uv1 = pcurve->Value( f );
03140 edge.Reverse();
03141 pcurve = BRep_Tool::CurveOnSurface( edge, face, f, l );
03142 if ( pcurve.IsNull() ) continue;
03143 uv2 = pcurve->Value( f );
03144 int iPar = Abs( uv1.X() - uv2.X() ) > Abs( uv1.Y() - uv2.Y() ) ? 1 : 2;
03145
03146 if ( uv1.Coord( iPar ) > uv2.Coord( iPar )) {
03147 gp_Pnt2d tmp = uv1; uv1 = uv2; uv2 = tmp;
03148 }
03149
03150 list< const SMDS_MeshNode* > seamNodes;
03151 SMDS_NodeIteratorPtr nSeamIt = sm->GetNodes();
03152 while ( nSeamIt->more() ) {
03153 const SMDS_MeshNode* node = nSeamIt->next();
03154 if ( !isQuadratic || !IsMedium( node ))
03155 seamNodes.push_back( node );
03156 }
03157 TopExp_Explorer vExp( edge, TopAbs_VERTEX );
03158 for ( ; vExp.More(); vExp.Next() ) {
03159 sm = aMesh->MeshElements( vExp.Current() );
03160 if ( sm ) {
03161 nSeamIt = sm->GetNodes();
03162 while ( nSeamIt->more() )
03163 seamNodes.push_back( nSeamIt->next() );
03164 }
03165 }
03166
03167 list< const SMDS_MeshNode* >::iterator noSeIt = seamNodes.begin();
03168 for ( ; noSeIt != seamNodes.end(); ++noSeIt ) {
03169 const SMDS_MeshNode* nSeam = *noSeIt;
03170 map< const SMDS_MeshNode*, gp_XY* >::iterator n_uv = uvMap.find( nSeam );
03171 if ( n_uv == uvMap.end() )
03172 continue;
03173
03174 n_uv->second->SetCoord( iPar, uv1.Coord( iPar ));
03175
03176 listUV.push_back( *n_uv->second );
03177 listUV.back().SetCoord( iPar, uv2.Coord( iPar ));
03178 if ( uvMap2.empty() )
03179 uvMap2 = uvMap;
03180 uvMap2[ nSeam ] = &listUV.back();
03181
03182
03183 SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(SMDSAbs_Face);
03184 while ( eIt->more() ) {
03185 const SMDS_MeshElement* e = eIt->next();
03186 int nbUseMap1 = 0, nbUseMap2 = 0;
03187 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
03188 int nn = 0, nbn = e->NbNodes();
03189 if(e->IsQuadratic()) nbn = nbn/2;
03190 while ( nn++ < nbn )
03191 {
03192 const SMDS_MeshNode* n =
03193 static_cast<const SMDS_MeshNode*>( nIt->next() );
03194 if (n == nSeam ||
03195 setMovableNodes.find( n ) == setMovableNodes.end() )
03196 continue;
03197
03198 gp_Pnt pMid (0.5 * ( n->X() + nSeam->X() ),
03199 0.5 * ( n->Y() + nSeam->Y() ),
03200 0.5 * ( n->Z() + nSeam->Z() ));
03201 gp_XY uv;
03202 getClosestUV( projector, pMid, uv );
03203 if ( uv.Coord( iPar ) > uvMap[ n ]->Coord( iPar ) ) {
03204 nodesNearSeam.insert( n );
03205 nbUseMap2++;
03206 }
03207 else
03208 nbUseMap1++;
03209 }
03210
03211
03212 if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 ) {
03213 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
03214 nn = 0;
03215 while ( nn++ < nbn ) {
03216 const SMDS_MeshNode* n =
03217 static_cast<const SMDS_MeshNode*>( nIt->next() );
03218 setMovableNodes.erase( n );
03219 }
03220 }
03221 }
03222 }
03223 }
03224 }
03225
03226 if ( setMovableNodes.empty() ) {
03227 MESSAGE( "Face id : " << *fId << " - NO SMOOTHING: no nodes to move!!!");
03228 continue;
03229 }
03230
03231
03232
03233
03234
03235 int it = -1;
03236 double maxRatio = -1., maxDisplacement = -1.;
03237 set<const SMDS_MeshNode*>::iterator nodeToMove;
03238 for ( it = 0; it < theNbIterations; it++ ) {
03239 maxDisplacement = 0.;
03240 nodeToMove = setMovableNodes.begin();
03241 for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
03242 const SMDS_MeshNode* node = (*nodeToMove);
03243 gp_XYZ aPrevPos ( node->X(), node->Y(), node->Z() );
03244
03245
03246 bool map2 = ( nodesNearSeam.find( node ) != nodesNearSeam.end() );
03247 if ( theSmoothMethod == LAPLACIAN )
03248 laplacianSmooth( node, surface, map2 ? uvMap2 : uvMap );
03249 else
03250 centroidalSmooth( node, surface, map2 ? uvMap2 : uvMap );
03251
03252
03253 gp_XYZ aNewPos ( node->X(), node->Y(), node->Z() );
03254 Standard_Real aDispl = (aPrevPos - aNewPos).SquareModulus();
03255 if ( aDispl > maxDisplacement )
03256 maxDisplacement = aDispl;
03257 }
03258
03259
03260 if ( maxDisplacement < disttol ) {
03261 MESSAGE("-- no node movement --");
03262 break;
03263 }
03264
03265
03266 maxRatio = 0;
03267 list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
03268 for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
03269 const SMDS_MeshElement* elem = (*elemIt);
03270 if ( !elem || elem->GetType() != SMDSAbs_Face )
03271 continue;
03272 SMESH::Controls::TSequenceOfXYZ aPoints;
03273 if ( aQualityFunc.GetPoints( elem, aPoints )) {
03274 double aValue = aQualityFunc.GetValue( aPoints );
03275 if ( aValue > maxRatio )
03276 maxRatio = aValue;
03277 }
03278 }
03279 if ( maxRatio <= theTgtAspectRatio ) {
03280 MESSAGE("-- quality achived --");
03281 break;
03282 }
03283 if (it+1 == theNbIterations) {
03284 MESSAGE("-- Iteration limit exceeded --");
03285 }
03286 }
03287
03288 MESSAGE(" Face id: " << *fId <<
03289 " Nb iterstions: " << it <<
03290 " Displacement: " << maxDisplacement <<
03291 " Aspect Ratio " << maxRatio);
03292
03293
03294
03295
03296
03297 nodeToMove = setMovableNodes.begin();
03298 for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
03299 SMDS_MeshNode* node = const_cast< SMDS_MeshNode* > (*nodeToMove);
03300 aMesh->MoveNode( node, node->X(), node->Y(), node->Z() );
03301 map< const SMDS_MeshNode*, gp_XY* >::iterator node_uv = uvMap.find( node );
03302 if ( node_uv != uvMap.end() ) {
03303 gp_XY* uv = node_uv->second;
03304 node->SetPosition
03305 ( SMDS_PositionPtr( new SMDS_FacePosition( uv->X(), uv->Y() )));
03306 }
03307 }
03308
03309
03310 if ( isQuadratic )
03311 {
03312 SMESH_MesherHelper helper( *GetMesh() );
03313 if ( !face.IsNull() )
03314 helper.SetSubShape( face );
03315 list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
03316 for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
03317 const SMDS_VtkFace* QF =
03318 dynamic_cast<const SMDS_VtkFace*> (*elemIt);
03319 if(QF && QF->IsQuadratic()) {
03320 vector<const SMDS_MeshNode*> Ns;
03321 Ns.reserve(QF->NbNodes()+1);
03322 SMDS_ElemIteratorPtr anIter = QF->interlacedNodesElemIterator();
03323 while ( anIter->more() )
03324 Ns.push_back( cast2Node(anIter->next()) );
03325 Ns.push_back( Ns[0] );
03326 double x, y, z;
03327 for(int i=0; i<QF->NbNodes(); i=i+2) {
03328 if ( !surface.IsNull() ) {
03329 gp_XY uv1 = helper.GetNodeUV( face, Ns[i], Ns[i+2] );
03330 gp_XY uv2 = helper.GetNodeUV( face, Ns[i+2], Ns[i] );
03331 gp_XY uv = ( uv1 + uv2 ) / 2.;
03332 gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
03333 x = xyz.X(); y = xyz.Y(); z = xyz.Z();
03334 }
03335 else {
03336 x = (Ns[i]->X() + Ns[i+2]->X())/2;
03337 y = (Ns[i]->Y() + Ns[i+2]->Y())/2;
03338 z = (Ns[i]->Z() + Ns[i+2]->Z())/2;
03339 }
03340 if( fabs( Ns[i+1]->X() - x ) > disttol ||
03341 fabs( Ns[i+1]->Y() - y ) > disttol ||
03342 fabs( Ns[i+1]->Z() - z ) > disttol ) {
03343
03344 aMesh->MoveNode( Ns[i+1], x, y, z );
03345 }
03346 }
03347 }
03348 }
03349 }
03350
03351 }
03352
03353 }
03354
03355
03356
03357
03358
03359
03360
03361
03362 static bool isReverse(vector<const SMDS_MeshNode*> prevNodes,
03363 vector<const SMDS_MeshNode*> nextNodes,
03364 const int nbNodes,
03365 const int iNotSame)
03366 {
03367 int iBeforeNotSame = ( iNotSame == 0 ? nbNodes - 1 : iNotSame - 1 );
03368 int iAfterNotSame = ( iNotSame + 1 == nbNodes ? 0 : iNotSame + 1 );
03369
03370 const SMDS_MeshNode* nB = prevNodes[ iBeforeNotSame ];
03371 const SMDS_MeshNode* nA = prevNodes[ iAfterNotSame ];
03372 const SMDS_MeshNode* nP = prevNodes[ iNotSame ];
03373 const SMDS_MeshNode* nN = nextNodes[ iNotSame ];
03374
03375 gp_Pnt pB ( nB->X(), nB->Y(), nB->Z() );
03376 gp_Pnt pA ( nA->X(), nA->Y(), nA->Z() );
03377 gp_Pnt pP ( nP->X(), nP->Y(), nP->Z() );
03378 gp_Pnt pN ( nN->X(), nN->Y(), nN->Z() );
03379
03380 gp_Vec vB ( pP, pB ), vA ( pP, pA ), vN ( pP, pN );
03381
03382 return (vA ^ vB) * vN < 0.0;
03383 }
03384
03385
03394
03395
03396 void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem,
03397 const vector<TNodeOfNodeListMapItr> & newNodesItVec,
03398 list<const SMDS_MeshElement*>& newElems,
03399 const int nbSteps,
03400 SMESH_SequenceOfElemPtr& srcElements)
03401 {
03402
03403 SMESHDS_Mesh* aMesh = GetMeshDS();
03404
03405
03406
03407 int nbNodes = elem->NbNodes();
03408 vector < list< const SMDS_MeshNode* >::const_iterator > itNN( nbNodes );
03409 vector<const SMDS_MeshNode*> prevNod( nbNodes );
03410 vector<const SMDS_MeshNode*> nextNod( nbNodes );
03411 vector<const SMDS_MeshNode*> midlNod( nbNodes );
03412
03413 int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
03414 vector<int> sames(nbNodes);
03415 vector<bool> issimple(nbNodes);
03416
03417 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
03418 TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ];
03419 const SMDS_MeshNode* node = nnIt->first;
03420 const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second;
03421 if ( listNewNodes.empty() ) {
03422 return;
03423 }
03424
03425 issimple[iNode] = (listNewNodes.size()==nbSteps);
03426
03427 itNN[ iNode ] = listNewNodes.begin();
03428 prevNod[ iNode ] = node;
03429 nextNod[ iNode ] = listNewNodes.front();
03430 if( !elem->IsQuadratic() || !issimple[iNode] ) {
03431 if ( prevNod[ iNode ] != nextNod [ iNode ])
03432 iNotSameNode = iNode;
03433 else {
03434 iSameNode = iNode;
03435
03436 sames[nbSame++] = iNode;
03437 }
03438 }
03439 }
03440
03441
03442 if ( nbSame == nbNodes || nbSame > 2) {
03443 MESSAGE( " Too many same nodes of element " << elem->GetID() );
03444
03445 return;
03446 }
03447
03448
03449
03450
03451
03452
03453 int iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
03454 int nbBaseNodes = ( elem->IsQuadratic() ? nbNodes/2 : nbNodes );
03455 if ( nbSame > 0 ) {
03456 iBeforeSame = ( iSameNode == 0 ? nbBaseNodes - 1 : iSameNode - 1 );
03457 iAfterSame = ( iSameNode + 1 == nbBaseNodes ? 0 : iSameNode + 1 );
03458 iOpposSame = ( iSameNode - 2 < 0 ? iSameNode + 2 : iSameNode - 2 );
03459 }
03460
03461
03462
03463
03464
03465
03466
03467
03468 int i0 = 0, i2 = 2;
03469 if ( nbNodes > 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) {
03470
03471 i0 = 2;
03472 i2 = 0;
03473 if ( nbSame > 0 )
03474 std::swap( iBeforeSame, iAfterSame );
03475 }
03476
03477
03478 const SMDS_MeshElement* lastElem = elem;
03479 for (int iStep = 0; iStep < nbSteps; iStep++ ) {
03480
03481 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
03482 if(issimple[iNode]) {
03483 nextNod[ iNode ] = *itNN[ iNode ];
03484 itNN[ iNode ]++;
03485 }
03486 else {
03487 if( elem->GetType()==SMDSAbs_Node ) {
03488
03489 midlNod[ iNode ] = *itNN[ iNode ];
03490 itNN[ iNode ]++;
03491 nextNod[ iNode ] = *itNN[ iNode ];
03492 itNN[ iNode ]++;
03493 }
03494 else if(!elem->IsQuadratic() || lastElem->IsMediumNode(prevNod[iNode]) ) {
03495
03496
03497 nextNod[ iNode ] = *itNN[ iNode ];
03498 itNN[ iNode ]++;
03499 }
03500 else {
03501
03502 midlNod[ iNode ] = *itNN[ iNode ];
03503 itNN[ iNode ]++;
03504 nextNod[ iNode ] = *itNN[ iNode ];
03505 itNN[ iNode ]++;
03506 }
03507 }
03508 }
03509 SMDS_MeshElement* aNewElem = 0;
03510 if(!elem->IsPoly()) {
03511 switch ( nbNodes ) {
03512 case 0:
03513 return;
03514 case 1: {
03515 if ( nbSame == 0 ) {
03516 if(issimple[0])
03517 aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
03518 else
03519 aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ], midlNod[ 0 ] );
03520 }
03521 break;
03522 }
03523 case 2: {
03524 if ( nbSame == 0 )
03525 aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
03526 nextNod[ 1 ], nextNod[ 0 ] );
03527 else
03528 aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
03529 nextNod[ iNotSameNode ] );
03530 break;
03531 }
03532
03533 case 3: {
03534 if(elem->GetType() == SMDSAbs_Face) {
03535
03536 if ( nbSame == 0 )
03537 aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
03538 nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
03539
03540 else if ( nbSame == 1 )
03541 aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
03542 nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
03543 nextNod[ iSameNode ]);
03544
03545 else
03546 aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
03547 nextNod[ iNotSameNode ]);
03548 }
03549 else {
03550 if(nbSame==0) {
03551 aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], nextNod[1], prevNod[1],
03552 midlNod[0], nextNod[2], midlNod[1], prevNod[2]);
03553 }
03554 else if(nbSame==1) {
03555 if(sames[0]==2) {
03556 return;
03557 }
03558 else if(sames[0]==0) {
03559 aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1],
03560 nextNod[2], midlNod[1], prevNod[2]);
03561 }
03562 else {
03563 aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
03564 midlNod[0], nextNod[2], prevNod[2]);
03565 }
03566 }
03567 else {
03568 return;
03569 }
03570 }
03571 break;
03572 }
03573 case 4: {
03574
03575 if ( nbSame == 0 )
03576 aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
03577 nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);
03578
03579 else if ( nbSame == 1 ) {
03580 aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
03581 nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
03582 nextNod[ iSameNode ]);
03583 newElems.push_back( aNewElem );
03584 aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iOpposSame ],
03585 prevNod[ iBeforeSame ], nextNod[ iAfterSame ],
03586 nextNod[ iOpposSame ], nextNod[ iBeforeSame ] );
03587 }
03588 else if ( nbSame == 2 ) {
03589 if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] )
03590
03591 aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ],
03592 nextNod[ iOpposSame ], prevNod[ iSameNode ],
03593 prevNod[ iAfterSame ], nextNod[ iAfterSame ]);
03594 else
03595
03596 aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
03597 nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
03598 prevNod[ iOpposSame ], nextNod[ iOpposSame ]);
03599 }
03600 break;
03601 }
03602 case 6: {
03603
03604 if(nbSame==0) {
03605 if(i0>0) {
03606 aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1],
03607 nextNod[0], nextNod[2], nextNod[1],
03608 prevNod[5], prevNod[4], prevNod[3],
03609 nextNod[5], nextNod[4], nextNod[3],
03610 midlNod[0], midlNod[2], midlNod[1]);
03611 }
03612 else {
03613 aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
03614 nextNod[0], nextNod[1], nextNod[2],
03615 prevNod[3], prevNod[4], prevNod[5],
03616 nextNod[3], nextNod[4], nextNod[5],
03617 midlNod[0], midlNod[1], midlNod[2]);
03618 }
03619 }
03620 else if(nbSame==1) {
03621
03622
03623
03624
03625 int n5 = iSameNode;
03626 int n1,n4,n41,n15,n45;
03627 if(i0>0) {
03628 n1 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
03629 n4 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
03630 n41 = n1 + 3;
03631 n15 = n5 + 3;
03632 n45 = n4 + 3;
03633 }
03634 else {
03635 n1 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
03636 n4 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
03637 n41 = n4 + 3;
03638 n15 = n1 + 3;
03639 n45 = n5 + 3;
03640 }
03641 aNewElem = aMesh->AddVolume(prevNod[n1], nextNod[n1],
03642 nextNod[n4], prevNod[n4], prevNod[n5],
03643 midlNod[n1], nextNod[n41],
03644 midlNod[n4], prevNod[n41],
03645 prevNod[n15], nextNod[n15],
03646 nextNod[n45], prevNod[n45]);
03647 }
03648 else if(nbSame==2) {
03649
03650
03651
03652
03653 int n1 = iNotSameNode;
03654 int n2,n3,n12,n23,n31;
03655 if(i0>0) {
03656 n2 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
03657 n3 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
03658 n12 = n2 + 3;
03659 n23 = n3 + 3;
03660 n31 = n1 + 3;
03661 }
03662 else {
03663 n2 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
03664 n3 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
03665 n12 = n1 + 3;
03666 n23 = n2 + 3;
03667 n31 = n3 + 3;
03668 }
03669 aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], prevNod[n3], nextNod[n1],
03670 prevNod[n12], prevNod[n23], prevNod[n31],
03671 midlNod[n1], nextNod[n12], nextNod[n31]);
03672 }
03673 break;
03674 }
03675 case 8: {
03676 if(nbSame==0) {
03677
03678 if(i0>0) {
03679 aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1],
03680 nextNod[0], nextNod[3], nextNod[2], nextNod[1],
03681 prevNod[7], prevNod[6], prevNod[5], prevNod[4],
03682 nextNod[7], nextNod[6], nextNod[5], nextNod[4],
03683 midlNod[0], midlNod[3], midlNod[2], midlNod[1]);
03684 }
03685 else {
03686 aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
03687 nextNod[0], nextNod[1], nextNod[2], nextNod[3],
03688 prevNod[4], prevNod[5], prevNod[6], prevNod[7],
03689 nextNod[4], nextNod[5], nextNod[6], nextNod[7],
03690 midlNod[0], midlNod[1], midlNod[2], midlNod[3]);
03691 }
03692 }
03693 else if(nbSame==1) {
03694
03695
03696 INFOS( " Sweep for face " << elem->GetID() << " can not be created" );
03697 return;
03698 }
03699 else if(nbSame==2) {
03700
03701
03702
03703
03704 int n1,n2,n4,n5;
03705 if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] ) {
03706
03707 n1 = iBeforeSame;
03708 n2 = iOpposSame;
03709 n4 = iSameNode;
03710 n5 = iAfterSame;
03711 }
03712 else {
03713
03714 n1 = iSameNode;
03715 n2 = iBeforeSame;
03716 n4 = iAfterSame;
03717 n5 = iOpposSame;
03718 }
03719 int n12,n45,n14,n25;
03720 if(i0>0) {
03721 n12 = n1 + 4;
03722 n45 = n5 + 4;
03723 n14 = n4 + 4;
03724 n25 = n2 + 4;
03725 }
03726 else {
03727 n12 = n2 + 4;
03728 n45 = n4 + 4;
03729 n14 = n1 + 4;
03730 n25 = n5 + 4;
03731 }
03732 aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], nextNod[n2],
03733 prevNod[n4], prevNod[n5], nextNod[n5],
03734 prevNod[n12], midlNod[n2], nextNod[n12],
03735 prevNod[n45], midlNod[n5], nextNod[n45],
03736 prevNod[n14], prevNod[n25], nextNod[n25]);
03737 }
03738 break;
03739 }
03740 default: {
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764 break;
03765 }
03766 }
03767 }
03768
03769 if(!aNewElem) {
03770
03771 vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
03772 vector<int> quantities (nbNodes + 2);
03773
03774 quantities[0] = nbNodes;
03775 for (int inode = 0; inode < nbNodes; inode++) {
03776 polyedre_nodes[inode] = prevNod[inode];
03777 }
03778
03779 quantities[1] = nbNodes;
03780 for (int inode = 0; inode < nbNodes; inode++) {
03781 polyedre_nodes[nbNodes + inode] = nextNod[inode];
03782 }
03783
03784 for (int iface = 0; iface < nbNodes; iface++) {
03785 quantities[iface + 2] = 4;
03786 int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
03787 polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
03788 polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
03789 polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
03790 polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
03791 }
03792 aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
03793 }
03794
03795 if ( aNewElem ) {
03796 newElems.push_back( aNewElem );
03797 myLastCreatedElems.Append(aNewElem);
03798 srcElements.Append( elem );
03799 lastElem = aNewElem;
03800 }
03801
03802
03803 for ( iNode = 0; iNode < nbNodes; iNode++ )
03804 prevNod[ iNode ] = nextNod[ iNode ];
03805
03806 }
03807 }
03808
03809
03819
03820
03821 void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes,
03822 TElemOfElemListMap & newElemsMap,
03823 TElemOfVecOfNnlmiMap & elemNewNodesMap,
03824 TIDSortedElemSet& elemSet,
03825 const int nbSteps,
03826 SMESH_SequenceOfElemPtr& srcElements)
03827 {
03828 MESSAGE("makeWalls");
03829 ASSERT( newElemsMap.size() == elemNewNodesMap.size() );
03830 SMESHDS_Mesh* aMesh = GetMeshDS();
03831
03832
03833
03834 TNodeOfNodeListMapItr nList = mapNewNodes.begin();
03835 for ( ; nList != mapNewNodes.end(); nList++ ) {
03836 const SMDS_MeshNode* node =
03837 static_cast<const SMDS_MeshNode*>( nList->first );
03838 SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
03839 int nbInitElems = 0;
03840 const SMDS_MeshElement* el = 0;
03841 SMDSAbs_ElementType highType = SMDSAbs_Edge;
03842 while ( eIt->more() && nbInitElems < 2 ) {
03843 el = eIt->next();
03844 SMDSAbs_ElementType type = el->GetType();
03845 if ( type == SMDSAbs_Volume || type < highType ) continue;
03846 if ( type > highType ) {
03847 nbInitElems = 0;
03848 highType = type;
03849 }
03850 if ( elemSet.find(el) != elemSet.end() )
03851 nbInitElems++;
03852 }
03853 if ( nbInitElems < 2 ) {
03854 bool NotCreateEdge = el && el->IsQuadratic() && el->IsMediumNode(node);
03855 if(!NotCreateEdge) {
03856 vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
03857 list<const SMDS_MeshElement*> newEdges;
03858 sweepElement( node, newNodesItVec, newEdges, nbSteps, srcElements );
03859 }
03860 }
03861 }
03862
03863
03864
03865
03866 TElemOfElemListMap::iterator itElem = newElemsMap.begin();
03867 TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin();
03868 for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ ) {
03869 const SMDS_MeshElement* elem = itElem->first;
03870 vector<TNodeOfNodeListMapItr>& vecNewNodes = itElemNodes->second;
03871
03872 if(itElem->second.size()==0) continue;
03873
03874 if ( elem->GetType() == SMDSAbs_Edge ) {
03875
03876 if (!elem->IsQuadratic()) {
03877 if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
03878 vecNewNodes[ 1 ]->second.back())) {
03879 myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
03880 vecNewNodes[ 1 ]->second.back()));
03881 srcElements.Append( myLastCreatedElems.Last() );
03882 }
03883 }
03884 else {
03885 if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
03886 vecNewNodes[ 1 ]->second.back(),
03887 vecNewNodes[ 2 ]->second.back())) {
03888 myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
03889 vecNewNodes[ 1 ]->second.back(),
03890 vecNewNodes[ 2 ]->second.back()));
03891 srcElements.Append( myLastCreatedElems.Last() );
03892 }
03893 }
03894 }
03895 if ( elem->GetType() != SMDSAbs_Face )
03896 continue;
03897
03898 bool hasFreeLinks = false;
03899
03900 TIDSortedElemSet avoidSet;
03901 avoidSet.insert( elem );
03902
03903 set<const SMDS_MeshNode*> aFaceLastNodes;
03904 int iNode, nbNodes = vecNewNodes.size();
03905 if(!elem->IsQuadratic()) {
03906
03907 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
03908 aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
03909
03910 int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
03911 const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
03912 const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
03913
03914 if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
03915 hasFreeLinks = true;
03916
03917 if ( !aMesh->FindEdge( n1, n2 )) {
03918 myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 ));
03919 srcElements.Append( myLastCreatedElems.Last() );
03920 }
03921 n1 = vecNewNodes[ iNode ]->second.back();
03922 n2 = vecNewNodes[ iNext ]->second.back();
03923 if ( !aMesh->FindEdge( n1, n2 )) {
03924 myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 ));
03925 srcElements.Append( myLastCreatedElems.Last() );
03926 }
03927 }
03928 }
03929 }
03930 else {
03931 int nbn = nbNodes/2;
03932 for ( iNode = 0; iNode < nbn; iNode++ ) {
03933 aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
03934 int iNext = ( iNode + 1 == nbn ) ? 0 : iNode + 1;
03935 const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
03936 const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
03937
03938 if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
03939 hasFreeLinks = true;
03940
03941
03942 const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first;
03943 if ( !aMesh->FindEdge( n1, n2, n3 )) {
03944 myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 ));
03945 srcElements.Append( myLastCreatedElems.Last() );
03946 }
03947 n1 = vecNewNodes[ iNode ]->second.back();
03948 n2 = vecNewNodes[ iNext ]->second.back();
03949 n3 = vecNewNodes[ iNode+nbn ]->second.back();
03950 if ( !aMesh->FindEdge( n1, n2, n3 )) {
03951 myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 ));
03952 srcElements.Append( myLastCreatedElems.Last() );
03953 }
03954 }
03955 }
03956 for ( iNode = nbn; iNode < 2*nbn; iNode++ ) {
03957 aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
03958 }
03959 }
03960
03961
03962
03963 if ( hasFreeLinks ) {
03964 list<const SMDS_MeshElement*> & newVolumes = itElem->second;
03965 int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps;
03966
03967 set<const SMDS_MeshNode*> initNodeSet, topNodeSet, faceNodeSet;
03968 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
03969 initNodeSet.insert( vecNewNodes[ iNode ]->first );
03970 topNodeSet .insert( vecNewNodes[ iNode ]->second.back() );
03971 }
03972 for ( volNb = 0; volNb < nbVolumesByStep; volNb++ ) {
03973 list<const SMDS_MeshElement*>::iterator v = newVolumes.begin();
03974 iVol = 0;
03975 while ( iVol++ < volNb ) v++;
03976
03977 list< int > freeInd;
03978 list< const SMDS_MeshElement* > srcEdges;
03979 SMDS_VolumeTool vTool( *v );
03980 int iF, nbF = vTool.NbFaces();
03981 for ( iF = 0; iF < nbF; iF ++ ) {
03982 if (vTool.IsFreeFace( iF ) &&
03983 vTool.GetFaceNodes( iF, faceNodeSet ) &&
03984 initNodeSet != faceNodeSet)
03985 {
03986 if ( nbSteps == 1 && faceNodeSet == topNodeSet )
03987 continue;
03988 freeInd.push_back( iF );
03989
03990 vector<const SMDS_MeshNode*> commonNodes;
03991 commonNodes.resize( initNodeSet.size(), NULL );
03992 std::set_intersection( faceNodeSet.begin(), faceNodeSet.end(),
03993 initNodeSet.begin(), initNodeSet.end(),
03994 commonNodes.begin());
03995 if ( (*v)->IsQuadratic() )
03996 srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2]));
03997 else
03998 srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1]));
03999 #ifdef _DEBUG_
04000 if ( !srcEdges.back() )
04001 {
04002 cout << "SMESH_MeshEditor::makeWalls(), no source edge found for a free face #"
04003 << iF << " of volume #" << vTool.ID() << endl;
04004 }
04005 #endif
04006 }
04007 }
04008 if ( freeInd.empty() )
04009 continue;
04010
04011
04012
04013
04014 for ( int iStep = 0; iStep < nbSteps; iStep++ ) {
04015 vTool.Set( *v );
04016 vTool.SetExternalNormal();
04017 const int nextShift = vTool.IsForward() ? +1 : -1;
04018 list< int >::iterator ind = freeInd.begin();
04019 list< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin();
04020 for ( ; ind != freeInd.end(); ++ind, ++srcEdge )
04021 {
04022 const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
04023 int nbn = vTool.NbFaceNodes( *ind );
04024 if ( ! (*v)->IsPoly() )
04025 switch ( nbn ) {
04026 case 3: {
04027 const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
04028 if ( !f ||
04029 nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
04030 {
04031 const SMDS_MeshNode* newOrder[3] = { nodes[ 1 - nextShift ],
04032 nodes[ 1 ],
04033 nodes[ 1 + nextShift ] };
04034 if ( f )
04035 aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
04036 else
04037 myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
04038 newOrder[ 2 ] ));
04039 }
04040 break;
04041 }
04042 case 4: {
04043 const SMDS_MeshFace * f =
04044 aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
04045 if ( !f ||
04046 nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
04047 {
04048 const SMDS_MeshNode* newOrder[4] = { nodes[ 0 ], nodes[ 2-nextShift ],
04049 nodes[ 2 ], nodes[ 2+nextShift ] };
04050 if ( f )
04051 aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
04052 else
04053 myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
04054 newOrder[ 2 ], newOrder[ 3 ]));
04055 }
04056 break;
04057 }
04058 case 6: {
04059 const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
04060 nodes[1], nodes[3], nodes[5] );
04061 if ( !f ||
04062 nodes[2] != f->GetNodeWrap( f->GetNodeIndex( nodes[0] ) + 2*nextShift ))
04063 {
04064 const SMDS_MeshNode* newOrder[6] = { nodes[2 - 2*nextShift],
04065 nodes[2],
04066 nodes[2 + 2*nextShift],
04067 nodes[3 - 2*nextShift],
04068 nodes[3],
04069 nodes[3 + 2*nextShift]};
04070 if ( f )
04071 aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
04072 else
04073 myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ],
04074 newOrder[ 1 ],
04075 newOrder[ 2 ],
04076 newOrder[ 3 ],
04077 newOrder[ 4 ],
04078 newOrder[ 5 ] ));
04079 }
04080 break;
04081 }
04082 default:
04083 const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
04084 nodes[1], nodes[3], nodes[5], nodes[7] );
04085 if ( !f ||
04086 nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift ))
04087 {
04088 const SMDS_MeshNode* newOrder[8] = { nodes[0],
04089 nodes[4 - 2*nextShift],
04090 nodes[4],
04091 nodes[4 + 2*nextShift],
04092 nodes[1],
04093 nodes[5 - 2*nextShift],
04094 nodes[5],
04095 nodes[5 + 2*nextShift] };
04096 if ( f )
04097 aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
04098 else
04099 myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
04100 newOrder[ 2 ], newOrder[ 3 ],
04101 newOrder[ 4 ], newOrder[ 5 ],
04102 newOrder[ 6 ], newOrder[ 7 ]));
04103 }
04104 }
04105
04106 else {
04107
04108 vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
04109 const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
04110 if ( !f ||
04111 nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + nextShift ))
04112 {
04113 if ( !vTool.IsForward() )
04114 std::reverse( polygon_nodes.begin(), polygon_nodes.end());
04115 if ( f )
04116 aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
04117 else
04118 AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
04119 }
04120 }
04121
04122 while ( srcElements.Length() < myLastCreatedElems.Length() )
04123 srcElements.Append( *srcEdge );
04124
04125 }
04126
04127
04128 iVol = 0;
04129 while ( iVol++ < nbVolumesByStep ) v++;
04130
04131 }
04132 }
04133 }
04134
04135
04136
04137 SMDS_VolumeTool lastVol( itElem->second.back() );
04138
04139 int iF = lastVol.GetFaceIndex( aFaceLastNodes );
04140 if ( iF >= 0 ) {
04141 lastVol.SetExternalNormal();
04142 const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
04143 int nbn = lastVol.NbFaceNodes( iF );
04144 switch ( nbn ) {
04145 case 3:
04146 if (!hasFreeLinks ||
04147 !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]))
04148 myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
04149 break;
04150 case 4:
04151 if (!hasFreeLinks ||
04152 !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]))
04153 myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
04154 break;
04155 default:
04156 if(itElem->second.back()->IsQuadratic()) {
04157 if(nbn==6) {
04158 if (!hasFreeLinks ||
04159 !aMesh->FindFace(nodes[0], nodes[2], nodes[4],
04160 nodes[1], nodes[3], nodes[5]) ) {
04161 myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
04162 nodes[1], nodes[3], nodes[5]));
04163 }
04164 }
04165 else {
04166 if (!hasFreeLinks ||
04167 !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
04168 nodes[1], nodes[3], nodes[5], nodes[7]) )
04169 myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
04170 nodes[1], nodes[3], nodes[5], nodes[7]));
04171 }
04172 }
04173 else {
04174 vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
04175 if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
04176 myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
04177 }
04178 }
04179
04180 while ( srcElements.Length() < myLastCreatedElems.Length() )
04181 srcElements.Append( myLastCreatedElems.Last() );
04182 }
04183 }
04184 }
04185
04186
04187
04188
04189
04190
04191 SMESH_MeshEditor::PGroupIDs
04192 SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
04193 const gp_Ax1& theAxis,
04194 const double theAngle,
04195 const int theNbSteps,
04196 const double theTol,
04197 const bool theMakeGroups,
04198 const bool theMakeWalls)
04199 {
04200 myLastCreatedElems.Clear();
04201 myLastCreatedNodes.Clear();
04202
04203
04204 SMESH_SequenceOfElemPtr srcElems, srcNodes;
04205
04206 MESSAGE( "RotationSweep()");
04207 gp_Trsf aTrsf;
04208 aTrsf.SetRotation( theAxis, theAngle );
04209 gp_Trsf aTrsf2;
04210 aTrsf2.SetRotation( theAxis, theAngle/2. );
04211
04212 gp_Lin aLine( theAxis );
04213 double aSqTol = theTol * theTol;
04214
04215 SMESHDS_Mesh* aMesh = GetMeshDS();
04216
04217 TNodeOfNodeListMap mapNewNodes;
04218 TElemOfVecOfNnlmiMap mapElemNewNodes;
04219 TElemOfElemListMap newElemsMap;
04220
04221
04222 TIDSortedElemSet::iterator itElem;
04223 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
04224 const SMDS_MeshElement* elem = *itElem;
04225 if ( !elem || elem->GetType() == SMDSAbs_Volume )
04226 continue;
04227 vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
04228 newNodesItVec.reserve( elem->NbNodes() );
04229
04230
04231 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
04232 while ( itN->more() ) {
04233
04234 const SMDS_MeshNode* node = cast2Node( itN->next() );
04235
04236 gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
04237 double coord[3];
04238 aXYZ.Coord( coord[0], coord[1], coord[2] );
04239 bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol );
04240
04241 TNodeOfNodeListMapItr nIt = mapNewNodes.find( node );
04242 if ( nIt == mapNewNodes.end() ) {
04243 nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
04244 list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
04245
04246
04247
04248
04249
04250
04251 const SMDS_MeshNode * newNode = node;
04252 for ( int i = 0; i < theNbSteps; i++ ) {
04253 if ( !isOnAxis ) {
04254 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
04255
04256 aTrsf2.Transforms( coord[0], coord[1], coord[2] );
04257
04258 newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
04259 myLastCreatedNodes.Append(newNode);
04260 srcNodes.Append( node );
04261 listNewNodes.push_back( newNode );
04262 aTrsf2.Transforms( coord[0], coord[1], coord[2] );
04263
04264 }
04265 else {
04266 aTrsf.Transforms( coord[0], coord[1], coord[2] );
04267 }
04268 newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
04269 myLastCreatedNodes.Append(newNode);
04270 srcNodes.Append( node );
04271 listNewNodes.push_back( newNode );
04272 }
04273 else {
04274 listNewNodes.push_back( newNode );
04275 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
04276 listNewNodes.push_back( newNode );
04277 }
04278 }
04279 }
04280 }
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317 newNodesItVec.push_back( nIt );
04318 }
04319
04320 sweepElement( elem, newNodesItVec, newElemsMap[elem], theNbSteps, srcElems );
04321 }
04322
04323 if ( theMakeWalls )
04324 makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, srcElems );
04325
04326 PGroupIDs newGroupIDs;
04327 if ( theMakeGroups )
04328 newGroupIDs = generateGroups( srcNodes, srcElems, "rotated");
04329
04330 return newGroupIDs;
04331 }
04332
04333
04334
04335
04336
04337
04338 const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
04339 const double y,
04340 const double z,
04341 const double tolnode,
04342 SMESH_SequenceOfNode& aNodes)
04343 {
04344 myLastCreatedElems.Clear();
04345 myLastCreatedNodes.Clear();
04346
04347 gp_Pnt P1(x,y,z);
04348 SMESHDS_Mesh * aMesh = myMesh->GetMeshDS();
04349
04350
04351
04352
04353 if(aNodes.Length()>0) {
04354 int i;
04355 for(i=1; i<=aNodes.Length(); i++) {
04356 gp_Pnt P2(aNodes.Value(i)->X(),aNodes.Value(i)->Y(),aNodes.Value(i)->Z());
04357 if(P1.Distance(P2)<tolnode)
04358 return aNodes.Value(i);
04359 }
04360 }
04361 else {
04362 SMDS_NodeIteratorPtr itn = aMesh->nodesIterator();
04363 while(itn->more()) {
04364 const SMDS_MeshNode* aN = static_cast<const SMDS_MeshNode*> (itn->next());
04365 gp_Pnt P2(aN->X(),aN->Y(),aN->Z());
04366 if(P1.Distance(P2)<tolnode)
04367 return aN;
04368 }
04369 }
04370
04371
04372 const SMDS_MeshNode* NewNode = aMesh->AddNode(x,y,z);
04373 myLastCreatedNodes.Append(NewNode);
04374 return NewNode;
04375 }
04376
04377
04378
04379
04380
04381
04382
04383 SMESH_MeshEditor::PGroupIDs
04384 SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems,
04385 const gp_Vec& theStep,
04386 const int theNbSteps,
04387 TElemOfElemListMap& newElemsMap,
04388 const bool theMakeGroups,
04389 const int theFlags,
04390 const double theTolerance)
04391 {
04392 ExtrusParam aParams;
04393 aParams.myDir = gp_Dir(theStep);
04394 aParams.myNodes.Clear();
04395 aParams.mySteps = new TColStd_HSequenceOfReal;
04396 int i;
04397 for(i=1; i<=theNbSteps; i++)
04398 aParams.mySteps->Append(theStep.Magnitude());
04399
04400 return
04401 ExtrusionSweep(theElems,aParams,newElemsMap,theMakeGroups,theFlags,theTolerance);
04402 }
04403
04404
04405
04406
04407
04408
04409
04410 SMESH_MeshEditor::PGroupIDs
04411 SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems,
04412 ExtrusParam& theParams,
04413 TElemOfElemListMap& newElemsMap,
04414 const bool theMakeGroups,
04415 const int theFlags,
04416 const double theTolerance)
04417 {
04418 MESSAGE("ExtrusionSweep " << theMakeGroups << " " << theFlags << " " << theTolerance);
04419 myLastCreatedElems.Clear();
04420 myLastCreatedNodes.Clear();
04421
04422
04423 SMESH_SequenceOfElemPtr srcElems, srcNodes;
04424
04425 SMESHDS_Mesh* aMesh = GetMeshDS();
04426
04427 int nbsteps = theParams.mySteps->Length();
04428
04429 TNodeOfNodeListMap mapNewNodes;
04430
04431 TElemOfVecOfNnlmiMap mapElemNewNodes;
04432
04433
04434
04435 TIDSortedElemSet::iterator itElem;
04436 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
04437
04438 const SMDS_MeshElement* elem = *itElem;
04439 if ( !elem || elem->GetType() == SMDSAbs_Volume )
04440 continue;
04441
04442 vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
04443
04444 newNodesItVec.reserve( elem->NbNodes() );
04445
04446
04447 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
04448 while ( itN->more() )
04449 {
04450
04451 const SMDS_MeshNode* node = cast2Node( itN->next() );
04452 TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
04453
04454 if ( nIt == mapNewNodes.end() ) {
04455 nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
04456
04457 list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
04458
04459
04460
04461
04462 double coord[] = { node->X(), node->Y(), node->Z() };
04463
04464 for ( int i = 0; i < nbsteps; i++ ) {
04465 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
04466
04467 double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1)/2.;
04468 double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1)/2.;
04469 double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1)/2.;
04470 if( theFlags & EXTRUSION_FLAG_SEW ) {
04471 const SMDS_MeshNode * newNode = CreateNode(x, y, z,
04472 theTolerance, theParams.myNodes);
04473 listNewNodes.push_back( newNode );
04474 }
04475 else {
04476 const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
04477 myLastCreatedNodes.Append(newNode);
04478 srcNodes.Append( node );
04479 listNewNodes.push_back( newNode );
04480 }
04481 }
04482
04483 coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
04484 coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
04485 coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
04486 if( theFlags & EXTRUSION_FLAG_SEW ) {
04487 const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
04488 theTolerance, theParams.myNodes);
04489 listNewNodes.push_back( newNode );
04490
04491 }
04492 else {
04493 const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
04494 myLastCreatedNodes.Append(newNode);
04495 srcNodes.Append( node );
04496 listNewNodes.push_back( newNode );
04497
04498 }
04499 }
04500 }
04501 else {
04502
04503
04504 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
04505 list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
04506 if(listNewNodes.size()==nbsteps) {
04507 listNewNodes.clear();
04508 double coord[] = { node->X(), node->Y(), node->Z() };
04509 for ( int i = 0; i < nbsteps; i++ ) {
04510 double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
04511 double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
04512 double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
04513 if( theFlags & EXTRUSION_FLAG_SEW ) {
04514 const SMDS_MeshNode * newNode = CreateNode(x, y, z,
04515 theTolerance, theParams.myNodes);
04516 listNewNodes.push_back( newNode );
04517 }
04518 else {
04519 const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
04520 myLastCreatedNodes.Append(newNode);
04521 srcNodes.Append( node );
04522 listNewNodes.push_back( newNode );
04523 }
04524 coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
04525 coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
04526 coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
04527 if( theFlags & EXTRUSION_FLAG_SEW ) {
04528 const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
04529 theTolerance, theParams.myNodes);
04530 listNewNodes.push_back( newNode );
04531 }
04532 else {
04533 const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
04534 myLastCreatedNodes.Append(newNode);
04535 srcNodes.Append( node );
04536 listNewNodes.push_back( newNode );
04537 }
04538 }
04539 }
04540 }
04541 }
04542 newNodesItVec.push_back( nIt );
04543 }
04544
04545 sweepElement( elem, newNodesItVec, newElemsMap[elem], nbsteps, srcElems );
04546 }
04547
04548 if( theFlags & EXTRUSION_FLAG_BOUNDARY ) {
04549 makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, srcElems );
04550 }
04551 PGroupIDs newGroupIDs;
04552 if ( theMakeGroups )
04553 newGroupIDs = generateGroups( srcNodes, srcElems, "extruded");
04554
04555 return newGroupIDs;
04556 }
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608 SMESH_MeshEditor::Extrusion_Error
04609 SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements,
04610 SMESH_subMesh* theTrack,
04611 const SMDS_MeshNode* theN1,
04612 const bool theHasAngles,
04613 list<double>& theAngles,
04614 const bool theLinearVariation,
04615 const bool theHasRefPoint,
04616 const gp_Pnt& theRefPoint,
04617 const bool theMakeGroups)
04618 {
04619 MESSAGE("ExtrusionAlongTrack");
04620 myLastCreatedElems.Clear();
04621 myLastCreatedNodes.Clear();
04622
04623 int aNbE;
04624 std::list<double> aPrms;
04625 TIDSortedElemSet::iterator itElem;
04626
04627 gp_XYZ aGC;
04628 TopoDS_Edge aTrackEdge;
04629 TopoDS_Vertex aV1, aV2;
04630
04631 SMDS_ElemIteratorPtr aItE;
04632 SMDS_NodeIteratorPtr aItN;
04633 SMDSAbs_ElementType aTypeE;
04634
04635 TNodeOfNodeListMap mapNewNodes;
04636
04637
04638 aNbE = theElements.size();
04639
04640 if ( !aNbE )
04641 return EXTR_NO_ELEMENTS;
04642
04643
04644 ASSERT( theTrack );
04645
04646 SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS();
04647
04648 aItE = pSubMeshDS->GetElements();
04649 while ( aItE->more() ) {
04650 const SMDS_MeshElement* pE = aItE->next();
04651 aTypeE = pE->GetType();
04652
04653 if ( aTypeE != SMDSAbs_Edge )
04654 return EXTR_PATH_NOT_EDGE;
04655 }
04656
04657 list<SMESH_MeshEditor_PathPoint> fullList;
04658
04659 const TopoDS_Shape& aS = theTrack->GetSubShape();
04660
04661 if( aS.ShapeType() == TopAbs_EDGE ) {
04662 aTrackEdge = TopoDS::Edge( aS );
04663
04664 if ( BRep_Tool::Degenerated( aTrackEdge ) )
04665 return EXTR_BAD_PATH_SHAPE;
04666 TopExp::Vertices( aTrackEdge, aV1, aV2 );
04667 aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
04668 const SMDS_MeshNode* aN1 = aItN->next();
04669 aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
04670 const SMDS_MeshNode* aN2 = aItN->next();
04671
04672 if ( !( aN1 == theN1 || aN2 == theN1 ) )
04673 return EXTR_BAD_STARTING_NODE;
04674 aItN = pSubMeshDS->GetNodes();
04675 while ( aItN->more() ) {
04676 const SMDS_MeshNode* pNode = aItN->next();
04677 const SMDS_EdgePosition* pEPos =
04678 static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
04679 double aT = pEPos->GetUParameter();
04680 aPrms.push_back( aT );
04681 }
04682
04683 MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
04684 }
04685 else if( aS.ShapeType() == TopAbs_WIRE ) {
04686 list< SMESH_subMesh* > LSM;
04687 TopTools_SequenceOfShape Edges;
04688 SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
04689 while(itSM->more()) {
04690 SMESH_subMesh* SM = itSM->next();
04691 LSM.push_back(SM);
04692 const TopoDS_Shape& aS = SM->GetSubShape();
04693 Edges.Append(aS);
04694 }
04695 list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
04696 int startNid = theN1->GetID();
04697 TColStd_MapOfInteger UsedNums;
04698 int NbEdges = Edges.Length();
04699 int i = 1;
04700 for(; i<=NbEdges; i++) {
04701 int k = 0;
04702 list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
04703 for(; itLSM!=LSM.end(); itLSM++) {
04704 k++;
04705 if(UsedNums.Contains(k)) continue;
04706 aTrackEdge = TopoDS::Edge( Edges.Value(k) );
04707 SMESH_subMesh* locTrack = *itLSM;
04708 SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
04709 TopExp::Vertices( aTrackEdge, aV1, aV2 );
04710 aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
04711 const SMDS_MeshNode* aN1 = aItN->next();
04712 aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
04713 const SMDS_MeshNode* aN2 = aItN->next();
04714
04715 if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
04716
04717 aPrms.clear();
04718 aItN = locMeshDS->GetNodes();
04719 while ( aItN->more() ) {
04720 const SMDS_MeshNode* pNode = aItN->next();
04721 const SMDS_EdgePosition* pEPos =
04722 static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
04723 double aT = pEPos->GetUParameter();
04724 aPrms.push_back( aT );
04725 }
04726 list<SMESH_MeshEditor_PathPoint> LPP;
04727
04728 MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
04729 LLPPs.push_back(LPP);
04730 UsedNums.Add(k);
04731
04732 if( aN1->GetID() == startNid ) startNid = aN2->GetID();
04733 else startNid = aN1->GetID();
04734 break;
04735 }
04736 }
04737 list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
04738 list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
04739 list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
04740 for(; itPP!=firstList.end(); itPP++) {
04741 fullList.push_back( *itPP );
04742 }
04743 SMESH_MeshEditor_PathPoint PP1 = fullList.back();
04744 fullList.pop_back();
04745 itLLPP++;
04746 for(; itLLPP!=LLPPs.end(); itLLPP++) {
04747 list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
04748 itPP = currList.begin();
04749 SMESH_MeshEditor_PathPoint PP2 = currList.front();
04750 gp_Dir D1 = PP1.Tangent();
04751 gp_Dir D2 = PP2.Tangent();
04752 gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
04753 (D1.Z()+D2.Z())/2 ) );
04754 PP1.SetTangent(Dnew);
04755 fullList.push_back(PP1);
04756 itPP++;
04757 for(; itPP!=firstList.end(); itPP++) {
04758 fullList.push_back( *itPP );
04759 }
04760 PP1 = fullList.back();
04761 fullList.pop_back();
04762 }
04763
04764 fullList.push_back(PP1);
04765
04766 }
04767 else {
04768 return EXTR_BAD_PATH_SHAPE;
04769 }
04770
04771 return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
04772 theHasRefPoint, theRefPoint, theMakeGroups);
04773 }
04774
04775
04776
04777
04778
04779
04780 SMESH_MeshEditor::Extrusion_Error
04781 SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements,
04782 SMESH_Mesh* theTrack,
04783 const SMDS_MeshNode* theN1,
04784 const bool theHasAngles,
04785 list<double>& theAngles,
04786 const bool theLinearVariation,
04787 const bool theHasRefPoint,
04788 const gp_Pnt& theRefPoint,
04789 const bool theMakeGroups)
04790 {
04791 myLastCreatedElems.Clear();
04792 myLastCreatedNodes.Clear();
04793
04794 int aNbE;
04795 std::list<double> aPrms;
04796 TIDSortedElemSet::iterator itElem;
04797
04798 gp_XYZ aGC;
04799 TopoDS_Edge aTrackEdge;
04800 TopoDS_Vertex aV1, aV2;
04801
04802 SMDS_ElemIteratorPtr aItE;
04803 SMDS_NodeIteratorPtr aItN;
04804 SMDSAbs_ElementType aTypeE;
04805
04806 TNodeOfNodeListMap mapNewNodes;
04807
04808
04809 aNbE = theElements.size();
04810
04811 if ( !aNbE )
04812 return EXTR_NO_ELEMENTS;
04813
04814
04815 ASSERT( theTrack );
04816
04817 SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS();
04818
04819 aItE = pMeshDS->elementsIterator();
04820 while ( aItE->more() ) {
04821 const SMDS_MeshElement* pE = aItE->next();
04822 aTypeE = pE->GetType();
04823
04824 if ( aTypeE != SMDSAbs_Edge )
04825 return EXTR_PATH_NOT_EDGE;
04826 }
04827
04828 list<SMESH_MeshEditor_PathPoint> fullList;
04829
04830 const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
04831
04832 if( aS.ShapeType() == TopAbs_EDGE ) {
04833 aTrackEdge = TopoDS::Edge( aS );
04834
04835 if ( BRep_Tool::Degenerated( aTrackEdge ) )
04836 return EXTR_BAD_PATH_SHAPE;
04837 TopExp::Vertices( aTrackEdge, aV1, aV2 );
04838 aItN = theTrack->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
04839 const SMDS_MeshNode* aN1 = aItN->next();
04840 aItN = theTrack->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
04841 const SMDS_MeshNode* aN2 = aItN->next();
04842
04843 if ( !( aN1 == theN1 || aN2 == theN1 ) )
04844 return EXTR_BAD_STARTING_NODE;
04845 aItN = pMeshDS->nodesIterator();
04846 while ( aItN->more() ) {
04847 const SMDS_MeshNode* pNode = aItN->next();
04848 if( pNode==aN1 || pNode==aN2 ) continue;
04849 const SMDS_EdgePosition* pEPos =
04850 static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
04851 double aT = pEPos->GetUParameter();
04852 aPrms.push_back( aT );
04853 }
04854
04855 MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
04856 }
04857 else if( aS.ShapeType() == TopAbs_WIRE ) {
04858 list< SMESH_subMesh* > LSM;
04859 TopTools_SequenceOfShape Edges;
04860 TopExp_Explorer eExp(aS, TopAbs_EDGE);
04861 for(; eExp.More(); eExp.Next()) {
04862 TopoDS_Edge E = TopoDS::Edge( eExp.Current() );
04863 if( BRep_Tool::Degenerated(E) ) continue;
04864 SMESH_subMesh* SM = theTrack->GetSubMesh(E);
04865 if(SM) {
04866 LSM.push_back(SM);
04867 Edges.Append(E);
04868 }
04869 }
04870 list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
04871 int startNid = theN1->GetID();
04872 TColStd_MapOfInteger UsedNums;
04873 int NbEdges = Edges.Length();
04874 int i = 1;
04875 for(; i<=NbEdges; i++) {
04876 int k = 0;
04877 list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
04878 for(; itLSM!=LSM.end(); itLSM++) {
04879 k++;
04880 if(UsedNums.Contains(k)) continue;
04881 aTrackEdge = TopoDS::Edge( Edges.Value(k) );
04882 SMESH_subMesh* locTrack = *itLSM;
04883 SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
04884 TopExp::Vertices( aTrackEdge, aV1, aV2 );
04885 aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
04886 const SMDS_MeshNode* aN1 = aItN->next();
04887 aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
04888 const SMDS_MeshNode* aN2 = aItN->next();
04889
04890 if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
04891
04892 aPrms.clear();
04893 aItN = locMeshDS->GetNodes();
04894 while ( aItN->more() ) {
04895 const SMDS_MeshNode* pNode = aItN->next();
04896 const SMDS_EdgePosition* pEPos =
04897 static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
04898 double aT = pEPos->GetUParameter();
04899 aPrms.push_back( aT );
04900 }
04901 list<SMESH_MeshEditor_PathPoint> LPP;
04902
04903 MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
04904 LLPPs.push_back(LPP);
04905 UsedNums.Add(k);
04906
04907 if( aN1->GetID() == startNid ) startNid = aN2->GetID();
04908 else startNid = aN1->GetID();
04909 break;
04910 }
04911 }
04912 list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
04913 list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
04914 list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
04915 for(; itPP!=firstList.end(); itPP++) {
04916 fullList.push_back( *itPP );
04917 }
04918 SMESH_MeshEditor_PathPoint PP1 = fullList.back();
04919 fullList.pop_back();
04920 itLLPP++;
04921 for(; itLLPP!=LLPPs.end(); itLLPP++) {
04922 list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
04923 itPP = currList.begin();
04924 SMESH_MeshEditor_PathPoint PP2 = currList.front();
04925 gp_Dir D1 = PP1.Tangent();
04926 gp_Dir D2 = PP2.Tangent();
04927 gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
04928 (D1.Z()+D2.Z())/2 ) );
04929 PP1.SetTangent(Dnew);
04930 fullList.push_back(PP1);
04931 itPP++;
04932 for(; itPP!=currList.end(); itPP++) {
04933 fullList.push_back( *itPP );
04934 }
04935 PP1 = fullList.back();
04936 fullList.pop_back();
04937 }
04938
04939 fullList.push_back(PP1);
04940
04941 }
04942 else {
04943 return EXTR_BAD_PATH_SHAPE;
04944 }
04945
04946 return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
04947 theHasRefPoint, theRefPoint, theMakeGroups);
04948 }
04949
04950
04951
04952
04953
04954
04955 SMESH_MeshEditor::Extrusion_Error
04956 SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>& aPrms,
04957 const TopoDS_Edge& aTrackEdge,
04958 bool FirstIsStart,
04959 list<SMESH_MeshEditor_PathPoint>& LPP)
04960 {
04961 Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
04962 aTolVec=1.e-7;
04963 aTolVec2=aTolVec*aTolVec;
04964 double aT1, aT2;
04965 TopoDS_Vertex aV1, aV2;
04966 TopExp::Vertices( aTrackEdge, aV1, aV2 );
04967 aT1=BRep_Tool::Parameter( aV1, aTrackEdge );
04968 aT2=BRep_Tool::Parameter( aV2, aTrackEdge );
04969
04970 aPrms.push_front( aT1 );
04971 aPrms.push_back( aT2 );
04972
04973 aPrms.sort();
04974 if( FirstIsStart ) {
04975 if ( aT1 > aT2 ) {
04976 aPrms.reverse();
04977 }
04978 }
04979 else {
04980 if ( aT2 > aT1 ) {
04981 aPrms.reverse();
04982 }
04983 }
04984
04985 SMESH_MeshEditor_PathPoint aPP;
04986 Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 );
04987 std::list<double>::iterator aItD = aPrms.begin();
04988 for(; aItD != aPrms.end(); ++aItD) {
04989 double aT = *aItD;
04990 gp_Pnt aP3D;
04991 gp_Vec aVec;
04992 aC3D->D1( aT, aP3D, aVec );
04993 aL2 = aVec.SquareMagnitude();
04994 if ( aL2 < aTolVec2 )
04995 return EXTR_CANT_GET_TANGENT;
04996 gp_Dir aTgt( aVec );
04997 aPP.SetPnt( aP3D );
04998 aPP.SetTangent( aTgt );
04999 aPP.SetParameter( aT );
05000 LPP.push_back(aPP);
05001 }
05002 return EXTR_OK;
05003 }
05004
05005
05006
05007
05008
05009
05010 SMESH_MeshEditor::Extrusion_Error
05011 SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet& theElements,
05012 list<SMESH_MeshEditor_PathPoint>& fullList,
05013 const bool theHasAngles,
05014 list<double>& theAngles,
05015 const bool theLinearVariation,
05016 const bool theHasRefPoint,
05017 const gp_Pnt& theRefPoint,
05018 const bool theMakeGroups)
05019 {
05020 MESSAGE("MakeExtrElements");
05021
05022 int aNbTP = fullList.size();
05023 vector<SMESH_MeshEditor_PathPoint> aPPs(aNbTP);
05024
05025 if( theHasAngles && theAngles.size()>0 && theLinearVariation ) {
05026 LinearAngleVariation(aNbTP-1, theAngles);
05027 }
05028 vector<double> aAngles( aNbTP );
05029 int j = 0;
05030 for(; j<aNbTP; ++j) {
05031 aAngles[j] = 0.;
05032 }
05033 if ( theHasAngles ) {
05034 double anAngle;;
05035 std::list<double>::iterator aItD = theAngles.begin();
05036 for ( j=1; (aItD != theAngles.end()) && (j<aNbTP); ++aItD, ++j ) {
05037 anAngle = *aItD;
05038 aAngles[j] = anAngle;
05039 }
05040 }
05041
05042
05043 j = -1;
05044 list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
05045 for(; itPP!=fullList.end(); itPP++) {
05046 j++;
05047 SMESH_MeshEditor_PathPoint PP = *itPP;
05048 PP.SetAngle(aAngles[j]);
05049 aPPs[j] = PP;
05050 }
05051
05052 TNodeOfNodeListMap mapNewNodes;
05053 TElemOfVecOfNnlmiMap mapElemNewNodes;
05054 TElemOfElemListMap newElemsMap;
05055 TIDSortedElemSet::iterator itElem;
05056 double aX, aY, aZ;
05057 int aNb;
05058 SMDSAbs_ElementType aTypeE;
05059
05060 SMESH_SequenceOfElemPtr srcElems, srcNodes;
05061
05062
05063 gp_Pnt aV0 = theRefPoint;
05064 gp_XYZ aGC;
05065 if ( !theHasRefPoint ) {
05066 aNb = 0;
05067 aGC.SetCoord( 0.,0.,0. );
05068
05069 itElem = theElements.begin();
05070 for ( ; itElem != theElements.end(); itElem++ ) {
05071 const SMDS_MeshElement* elem = *itElem;
05072
05073 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
05074 while ( itN->more() ) {
05075 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( itN->next() );
05076 aX = node->X();
05077 aY = node->Y();
05078 aZ = node->Z();
05079
05080 if ( mapNewNodes.find( node ) == mapNewNodes.end() ) {
05081 list<const SMDS_MeshNode*> aLNx;
05082 mapNewNodes[node] = aLNx;
05083
05084 gp_XYZ aXYZ( aX, aY, aZ );
05085 aGC += aXYZ;
05086 ++aNb;
05087 }
05088 }
05089 }
05090 aGC /= aNb;
05091 aV0.SetXYZ( aGC );
05092 }
05093 mapNewNodes.clear();
05094
05095
05096 SMESHDS_Mesh* aMesh = GetMeshDS();
05097
05098 for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) {
05099
05100 const SMDS_MeshElement* elem = *itElem;
05101 aTypeE = elem->GetType();
05102 if ( !elem || ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) )
05103 continue;
05104
05105 vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
05106 newNodesItVec.reserve( elem->NbNodes() );
05107
05108
05109 int nodeIndex = -1;
05110 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
05111 while ( itN->more() )
05112 {
05113 ++nodeIndex;
05114
05115 const SMDS_MeshNode* node =
05116 static_cast<const SMDS_MeshNode*>( itN->next() );
05117 TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
05118 if ( nIt == mapNewNodes.end() ) {
05119 nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
05120 list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
05121
05122
05123 aX = node->X(); aY = node->Y(); aZ = node->Z();
05124
05125 Standard_Real aAngle1x, aAngleT1T0, aTolAng;
05126 gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
05127 gp_Ax1 anAx1, anAxT1T0;
05128 gp_Dir aDT1x, aDT0x, aDT1T0;
05129
05130 aTolAng=1.e-4;
05131
05132 aV0x = aV0;
05133 aPN0.SetCoord(aX, aY, aZ);
05134
05135 const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
05136 aP0x = aPP0.Pnt();
05137 aDT0x= aPP0.Tangent();
05138
05139
05140 for ( j = 1; j < aNbTP; ++j ) {
05141 const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
05142 aP1x = aPP1.Pnt();
05143 aDT1x = aPP1.Tangent();
05144 aAngle1x = aPP1.Angle();
05145
05146 gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
05147
05148 gp_Vec aV01x( aP0x, aP1x );
05149 aTrsf.SetTranslation( aV01x );
05150
05151
05152 aV1x = aV0x.Transformed( aTrsf );
05153 aPN1 = aPN0.Transformed( aTrsf );
05154
05155
05156 aAngleT1T0=-aDT1x.Angle( aDT0x );
05157 if (fabs(aAngleT1T0) > aTolAng) {
05158 aDT1T0=aDT1x^aDT0x;
05159 anAxT1T0.SetLocation( aV1x );
05160 anAxT1T0.SetDirection( aDT1T0 );
05161 aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 );
05162
05163 aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
05164 }
05165
05166
05167 if ( theHasAngles ) {
05168 anAx1.SetLocation( aV1x );
05169 anAx1.SetDirection( aDT1x );
05170 aTrsfRot.SetRotation( anAx1, aAngle1x );
05171
05172 aPN1 = aPN1.Transformed( aTrsfRot );
05173 }
05174
05175
05176
05177 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
05178
05179 double x = ( aPN1.X() + aPN0.X() )/2.;
05180 double y = ( aPN1.Y() + aPN0.Y() )/2.;
05181 double z = ( aPN1.Z() + aPN0.Z() )/2.;
05182 const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z);
05183 myLastCreatedNodes.Append(newNode);
05184 srcNodes.Append( node );
05185 listNewNodes.push_back( newNode );
05186 }
05187 aX = aPN1.X();
05188 aY = aPN1.Y();
05189 aZ = aPN1.Z();
05190 const SMDS_MeshNode* newNode = aMesh->AddNode( aX, aY, aZ );
05191 myLastCreatedNodes.Append(newNode);
05192 srcNodes.Append( node );
05193 listNewNodes.push_back( newNode );
05194
05195 aPN0 = aPN1;
05196 aP0x = aP1x;
05197 aV0x = aV1x;
05198 aDT0x = aDT1x;
05199 }
05200 }
05201
05202 else {
05203
05204
05205 if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
05206 list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
05207 if(listNewNodes.size()==aNbTP-1) {
05208 vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
05209 gp_XYZ P(node->X(), node->Y(), node->Z());
05210 list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
05211 int i;
05212 for(i=0; i<aNbTP-1; i++) {
05213 const SMDS_MeshNode* N = *it;
05214 double x = ( N->X() + P.X() )/2.;
05215 double y = ( N->Y() + P.Y() )/2.;
05216 double z = ( N->Z() + P.Z() )/2.;
05217 const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
05218 srcNodes.Append( node );
05219 myLastCreatedNodes.Append(newN);
05220 aNodes[2*i] = newN;
05221 aNodes[2*i+1] = N;
05222 P = gp_XYZ(N->X(),N->Y(),N->Z());
05223 }
05224 listNewNodes.clear();
05225 for(i=0; i<2*(aNbTP-1); i++) {
05226 listNewNodes.push_back(aNodes[i]);
05227 }
05228 }
05229 }
05230 }
05231
05232 newNodesItVec.push_back( nIt );
05233 }
05234
05235
05236
05237 sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
05238 }
05239
05240 makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElements, aNbTP-1, srcElems );
05241
05242 if ( theMakeGroups )
05243 generateGroups( srcNodes, srcElems, "extruded");
05244
05245 return EXTR_OK;
05246 }
05247
05248
05249
05250
05251
05252
05253 void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
05254 list<double>& Angles)
05255 {
05256 int nbAngles = Angles.size();
05257 if( nbSteps > nbAngles ) {
05258 vector<double> theAngles(nbAngles);
05259 list<double>::iterator it = Angles.begin();
05260 int i = -1;
05261 for(; it!=Angles.end(); it++) {
05262 i++;
05263 theAngles[i] = (*it);
05264 }
05265 list<double> res;
05266 double rAn2St = double( nbAngles ) / double( nbSteps );
05267 double angPrev = 0, angle;
05268 for ( int iSt = 0; iSt < nbSteps; ++iSt ) {
05269 double angCur = rAn2St * ( iSt+1 );
05270 double angCurFloor = floor( angCur );
05271 double angPrevFloor = floor( angPrev );
05272 if ( angPrevFloor == angCurFloor )
05273 angle = rAn2St * theAngles[ int( angCurFloor ) ];
05274 else {
05275 int iP = int( angPrevFloor );
05276 double angPrevCeil = ceil(angPrev);
05277 angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
05278
05279 int iC = int( angCurFloor );
05280 if ( iC < nbAngles )
05281 angle += ( angCur - angCurFloor ) * theAngles[ iC ];
05282
05283 iP = int( angPrevCeil );
05284 while ( iC-- > iP )
05285 angle += theAngles[ iC ];
05286 }
05287 res.push_back(angle);
05288 angPrev = angCur;
05289 }
05290 Angles.clear();
05291 it = res.begin();
05292 for(; it!=res.end(); it++)
05293 Angles.push_back( *it );
05294 }
05295 }
05296
05297
05298
05308
05309
05310 SMESH_MeshEditor::PGroupIDs
05311 SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
05312 const gp_Trsf& theTrsf,
05313 const bool theCopy,
05314 const bool theMakeGroups,
05315 SMESH_Mesh* theTargetMesh)
05316 {
05317 myLastCreatedElems.Clear();
05318 myLastCreatedNodes.Clear();
05319
05320 bool needReverse = false;
05321 string groupPostfix;
05322 switch ( theTrsf.Form() ) {
05323 case gp_PntMirror:
05324 MESSAGE("gp_PntMirror");
05325 needReverse = true;
05326 groupPostfix = "mirrored";
05327 break;
05328 case gp_Ax1Mirror:
05329 MESSAGE("gp_Ax1Mirror");
05330 groupPostfix = "mirrored";
05331 break;
05332 case gp_Ax2Mirror:
05333 MESSAGE("gp_Ax2Mirror");
05334 needReverse = true;
05335 groupPostfix = "mirrored";
05336 break;
05337 case gp_Rotation:
05338 MESSAGE("gp_Rotation");
05339 groupPostfix = "rotated";
05340 break;
05341 case gp_Translation:
05342 MESSAGE("gp_Translation");
05343 groupPostfix = "translated";
05344 break;
05345 case gp_Scale:
05346 MESSAGE("gp_Scale");
05347 groupPostfix = "scaled";
05348 break;
05349 case gp_CompoundTrsf:
05350 MESSAGE("gp_CompoundTrsf");
05351 groupPostfix = "scaled";
05352 break;
05353 default:
05354 MESSAGE("default");
05355 needReverse = false;
05356 groupPostfix = "transformed";
05357 }
05358
05359 SMESH_MeshEditor targetMeshEditor( theTargetMesh );
05360 SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
05361 SMESHDS_Mesh* aMesh = GetMeshDS();
05362
05363
05364
05365 TNodeNodeMap nodeMap;
05366
05367
05368
05369 TIDSortedElemSet inverseElemSet;
05370
05371
05372 SMESH_SequenceOfElemPtr srcElems, srcNodes;
05373
05374
05375 TIDSortedElemSet orphanNode;
05376
05377 if ( theElems.empty() )
05378 {
05379
05380 SMDS_ElemIteratorPtr eIt = aMesh->elementsIterator();
05381 while ( eIt->more() ) theElems.insert( eIt->next() );
05382
05383 SMDS_NodeIteratorPtr nIt = aMesh->nodesIterator();
05384 while ( nIt->more() )
05385 {
05386 const SMDS_MeshNode* node = nIt->next();
05387 if ( node->NbInverseElements() == 0)
05388 orphanNode.insert( node );
05389 }
05390 }
05391
05392
05393 TIDSortedElemSet::iterator itElem;
05394 TIDSortedElemSet *elements[] = {&orphanNode, &theElems };
05395 for (int i=0; i<2; i++)
05396 for ( itElem = elements[i]->begin(); itElem != elements[i]->end(); itElem++ ) {
05397 const SMDS_MeshElement* elem = *itElem;
05398 if ( !elem )
05399 continue;
05400
05401
05402 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
05403 while ( itN->more() ) {
05404
05405 const SMDS_MeshNode* node = cast2Node( itN->next() );
05406
05407 pair<TNodeNodeMap::iterator,bool> n2n_isnew =
05408 nodeMap.insert( make_pair ( node, node ));
05409 if ( !n2n_isnew.second )
05410 continue;
05411
05412 double coord[3];
05413 coord[0] = node->X();
05414 coord[1] = node->Y();
05415 coord[2] = node->Z();
05416 theTrsf.Transforms( coord[0], coord[1], coord[2] );
05417 if ( theTargetMesh ) {
05418 const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
05419 n2n_isnew.first->second = newNode;
05420 myLastCreatedNodes.Append(newNode);
05421 srcNodes.Append( node );
05422 }
05423 else if ( theCopy ) {
05424 const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
05425 n2n_isnew.first->second = newNode;
05426 myLastCreatedNodes.Append(newNode);
05427 srcNodes.Append( node );
05428 }
05429 else {
05430 aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
05431
05432 const_cast< SMDS_MeshNode* > ( node )->SetPosition
05433 ( SMDS_SpacePosition::originSpacePosition() );
05434 }
05435
05436
05437 if ( !theCopy && !theTargetMesh && needReverse ) {
05438 SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
05439 while ( invElemIt->more() ) {
05440 const SMDS_MeshElement* iel = invElemIt->next();
05441 inverseElemSet.insert( iel );
05442 }
05443 }
05444 }
05445 }
05446
05447
05448 if ( !theCopy && !needReverse && !theTargetMesh )
05449 return PGroupIDs();
05450
05451 TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
05452 for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
05453 theElems.insert( *invElemIt );
05454
05455
05456
05457 enum {
05458 REV_TETRA = 0,
05459 REV_PYRAMID = 1,
05460 REV_PENTA = 2,
05461 REV_FACE = 3,
05462 REV_HEXA = 4,
05463 FORWARD = 5
05464 };
05465 int index[][8] = {
05466 { 2, 1, 0, 3, 4, 0, 0, 0 },
05467 { 2, 1, 0, 3, 4, 0, 0, 0 },
05468 { 2, 1, 0, 5, 4, 3, 0, 0 },
05469 { 2, 1, 0, 3, 0, 0, 0, 0 },
05470 { 2, 1, 0, 3, 6, 5, 4, 7 },
05471 { 0, 1, 2, 3, 4, 5, 6, 7 }
05472 };
05473
05474 for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
05475 {
05476 const SMDS_MeshElement* elem = *itElem;
05477 if ( !elem || elem->GetType() == SMDSAbs_Node )
05478 continue;
05479
05480 int nbNodes = elem->NbNodes();
05481 int elemType = elem->GetType();
05482
05483 if (elem->IsPoly()) {
05484
05485 switch ( elemType ) {
05486 case SMDSAbs_Face:
05487 {
05488 vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
05489 int iNode = 0;
05490 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
05491 while (itN->more()) {
05492 const SMDS_MeshNode* node =
05493 static_cast<const SMDS_MeshNode*>(itN->next());
05494 TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
05495 if (nodeMapIt == nodeMap.end())
05496 break;
05497 if (needReverse) {
05498
05499 poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
05500 } else {
05501 poly_nodes[iNode] = (*nodeMapIt).second;
05502 }
05503 iNode++;
05504 }
05505 if ( iNode != nbNodes )
05506 continue;
05507
05508 if ( theTargetMesh ) {
05509 myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
05510 srcElems.Append( elem );
05511 }
05512 else if ( theCopy ) {
05513 myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
05514 srcElems.Append( elem );
05515 }
05516 else {
05517 aMesh->ChangePolygonNodes(elem, poly_nodes);
05518 }
05519 }
05520 break;
05521 case SMDSAbs_Volume:
05522 {
05523
05524 const SMDS_VtkVolume* aPolyedre =
05525 dynamic_cast<const SMDS_VtkVolume*>( elem );
05526 if (!aPolyedre) {
05527 MESSAGE("Warning: bad volumic element");
05528 continue;
05529 }
05530
05531 vector<const SMDS_MeshNode*> poly_nodes;
05532 vector<int> quantities;
05533
05534 bool allTransformed = true;
05535 int nbFaces = aPolyedre->NbFaces();
05536 for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
05537 int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
05538 for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
05539 const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
05540 TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
05541 if (nodeMapIt == nodeMap.end()) {
05542 allTransformed = false;
05543 } else {
05544 poly_nodes.push_back((*nodeMapIt).second);
05545 }
05546 }
05547 quantities.push_back(nbFaceNodes);
05548 }
05549 if ( !allTransformed )
05550 continue;
05551
05552 if ( theTargetMesh ) {
05553 myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
05554 srcElems.Append( elem );
05555 }
05556 else if ( theCopy ) {
05557 myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
05558 srcElems.Append( elem );
05559 }
05560 else {
05561 aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
05562 }
05563 }
05564 break;
05565 default:;
05566 }
05567 continue;
05568 }
05569
05570
05571 int* i = index[ FORWARD ];
05572 if ( needReverse && nbNodes > 2) {
05573 if ( elemType == SMDSAbs_Face )
05574 i = index[ REV_FACE ];
05575 else
05576 i = index[ nbNodes - 4 ];
05577 }
05578 if(elem->IsQuadratic()) {
05579 static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
05580 i = anIds;
05581 if(needReverse) {
05582 if(nbNodes==3) {
05583 static int anIds[] = {1,0,2};
05584 i = anIds;
05585 }
05586 else if(nbNodes==6) {
05587 static int anIds[] = {0,2,1,5,4,3};
05588 i = anIds;
05589 }
05590 else if(nbNodes==8) {
05591 static int anIds[] = {0,3,2,1,7,6,5,4};
05592 i = anIds;
05593 }
05594 else if(nbNodes==10) {
05595 static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
05596 i = anIds;
05597 }
05598 else if(nbNodes==13) {
05599 static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
05600 i = anIds;
05601 }
05602 else if(nbNodes==15) {
05603 static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
05604 i = anIds;
05605 }
05606 else {
05607 static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
05608 i = anIds;
05609 }
05610 }
05611 }
05612
05613
05614 vector<const SMDS_MeshNode*> nodes(nbNodes);
05615 int iNode = 0;
05616 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
05617 while ( itN->more() ) {
05618 const SMDS_MeshNode* node =
05619 static_cast<const SMDS_MeshNode*>( itN->next() );
05620 TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
05621 if ( nodeMapIt == nodeMap.end() )
05622 break;
05623 nodes[ i [ iNode++ ]] = (*nodeMapIt).second;
05624 }
05625 if ( iNode != nbNodes )
05626 continue;
05627
05628 if ( theTargetMesh ) {
05629 if ( SMDS_MeshElement* copy =
05630 targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
05631 myLastCreatedElems.Append( copy );
05632 srcElems.Append( elem );
05633 }
05634 }
05635 else if ( theCopy ) {
05636 if ( AddElement( nodes, elem->GetType(), elem->IsPoly() ))
05637 srcElems.Append( elem );
05638 }
05639 else {
05640
05641 if ( nbNodes > 2 )
05642 aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
05643 }
05644 }
05645
05646 PGroupIDs newGroupIDs;
05647
05648 if ( ( theMakeGroups && theCopy ) ||
05649 ( theMakeGroups && theTargetMesh ) )
05650 newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
05651
05652 return newGroupIDs;
05653 }
05654
05655
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757
05758
05759
05760
05761
05762
05763
05764
05765
05766
05767
05768
05769
05770
05771
05772
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797
05798
05799
05800
05801
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816
05817
05818
05819
05820
05821
05822
05823
05824
05825
05826
05827
05828
05829
05830
05831
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854
05855
05856
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929
05930
05931
05932
05933
05934
05935
05936
05937
05938
05939
05940
05941
05942
05943
05944
05945
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05988
05989
05990 SMESH_MeshEditor::PGroupIDs
05991 SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
05992 const SMESH_SequenceOfElemPtr& elemGens,
05993 const std::string& postfix,
05994 SMESH_Mesh* targetMesh)
05995 {
05996 PGroupIDs newGroupIDs( new list<int> );
05997 SMESH_Mesh* mesh = targetMesh ? targetMesh : GetMesh();
05998
05999
06000
06001
06002 typedef pair< SMESHDS_GroupBase*, SMDS_MeshGroup* > TOldNewGroup;
06003 vector< list< TOldNewGroup > > groupsByType( SMDSAbs_NbElementTypes );
06004
06005 set< string > groupNames;
06006
06007 SMDS_MeshGroup* nullNewGroup = (SMDS_MeshGroup*) 0;
06008 SMESH_Mesh::GroupIteratorPtr groupIt = GetMesh()->GetGroups();
06009 while ( groupIt->more() ) {
06010 SMESH_Group * group = groupIt->next();
06011 if ( !group ) continue;
06012 SMESHDS_GroupBase* groupDS = group->GetGroupDS();
06013 if ( !groupDS || groupDS->IsEmpty() ) continue;
06014 groupNames.insert( group->GetName() );
06015 groupDS->SetStoreName( group->GetName() );
06016 groupsByType[ groupDS->GetType() ].push_back( make_pair( groupDS, nullNewGroup ));
06017 }
06018
06019
06020
06021
06022 for ( int isNodes = 0; isNodes < 2; ++isNodes )
06023 {
06024 const SMESH_SequenceOfElemPtr& gens = isNodes ? nodeGens : elemGens;
06025 const SMESH_SequenceOfElemPtr& elems = isNodes ? myLastCreatedNodes : myLastCreatedElems;
06026 if ( gens.Length() != elems.Length() )
06027 throw SALOME_Exception(LOCALIZED("invalid args"));
06028
06029
06030 for (int iElem = 1; iElem <= elems.Length(); ++iElem )
06031 {
06032 const SMDS_MeshElement* sourceElem = gens( iElem );
06033 if ( !sourceElem ) {
06034 MESSAGE("generateGroups(): NULL source element");
06035 continue;
06036 }
06037 list< TOldNewGroup > & groupsOldNew = groupsByType[ sourceElem->GetType() ];
06038 if ( groupsOldNew.empty() ) {
06039 while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
06040 ++iElem;
06041 continue;
06042 }
06043
06044 list< const SMDS_MeshElement* > resultElems;
06045 if ( const SMDS_MeshElement* resElem = elems( iElem ))
06046 if ( resElem != sourceElem )
06047 resultElems.push_back( resElem );
06048 while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
06049 if ( const SMDS_MeshElement* resElem = elems( ++iElem ))
06050 if ( resElem != sourceElem )
06051 resultElems.push_back( resElem );
06052
06053 if ( sourceElem->GetType() == SMDSAbs_Node &&
06054 elems( iElem )->GetType() != SMDSAbs_Node )
06055 continue;
06056
06057
06058 list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
06059 for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew )
06060 {
06061 SMESHDS_GroupBase* oldGroup = gOldNew->first;
06062 if ( oldGroup->Contains( sourceElem ))
06063 {
06064 SMDS_MeshGroup* & newGroup = gOldNew->second;
06065 if ( !newGroup )
06066 {
06067
06068 string name = oldGroup->GetStoreName();
06069 if ( !targetMesh ) {
06070 name += "_";
06071 name += postfix;
06072 int nb = 0;
06073 while ( !groupNames.insert( name ).second )
06074 {
06075 if ( nb == 0 ) {
06076 name += "_1";
06077 }
06078 else {
06079 TCollection_AsciiString nbStr(nb+1);
06080 name.resize( name.rfind('_')+1 );
06081 name += nbStr.ToCString();
06082 }
06083 ++nb;
06084 }
06085 }
06086
06087 int id;
06088 SMESH_Group* group = mesh->AddGroup( resultElems.back()->GetType(),
06089 name.c_str(), id );
06090 SMESHDS_Group* groupDS = static_cast<SMESHDS_Group*>(group->GetGroupDS());
06091 newGroup = & groupDS->SMDSGroup();
06092 newGroupIDs->push_back( id );
06093 }
06094
06095
06096 list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt;
06097 for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt )
06098 newGroup->Add( *resElemIt );
06099 }
06100 }
06101 }
06102 }
06103
06104 return newGroupIDs;
06105 }
06106
06107
06113
06114
06115 void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet & theNodes,
06116 const double theTolerance,
06117 TListOfListOfNodes & theGroupsOfNodes)
06118 {
06119 myLastCreatedElems.Clear();
06120 myLastCreatedNodes.Clear();
06121
06122 if ( theNodes.empty() )
06123 {
06124 SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(true);
06125 while ( nIt->more() )
06126 theNodes.insert( theNodes.end(),nIt->next());
06127 }
06128
06129 SMESH_OctreeNode::FindCoincidentNodes ( theNodes, &theGroupsOfNodes, theTolerance);
06130 }
06131
06132
06133
06137
06138
06139 struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
06140 {
06141
06145 SMESH_NodeSearcherImpl( const SMESHDS_Mesh* theMesh )
06146 {
06147 myMesh = ( SMESHDS_Mesh* ) theMesh;
06148
06149 TIDSortedNodeSet nodes;
06150 if ( theMesh ) {
06151 SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(true);
06152 while ( nIt->more() )
06153 nodes.insert( nodes.end(), nIt->next() );
06154 }
06155 myOctreeNode = new SMESH_OctreeNode(nodes) ;
06156
06157
06158 SMESH_OctreeNode* tree = myOctreeNode;
06159 while ( !tree->isLeaf() )
06160 {
06161 SMESH_OctreeNodeIteratorPtr cIt = tree->GetChildrenIterator();
06162 if ( cIt->more() )
06163 tree = cIt->next();
06164 }
06165 myHalfLeafSize = tree->maxSize() / 2.;
06166 }
06167
06168
06172 void MoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt )
06173 {
06174 myOctreeNode->UpdateByMoveNode( node, toPnt );
06175 myMesh->MoveNode( node, toPnt.X(), toPnt.Y(), toPnt.Z() );
06176 }
06177
06178
06182 const SMDS_MeshNode* FindClosestTo( const gp_Pnt& thePnt )
06183 {
06184 map<double, const SMDS_MeshNode*> dist2Nodes;
06185 myOctreeNode->NodesAround( thePnt.Coord(), dist2Nodes, myHalfLeafSize );
06186 if ( !dist2Nodes.empty() )
06187 return dist2Nodes.begin()->second;
06188 list<const SMDS_MeshNode*> nodes;
06189
06190
06191 double minSqDist = DBL_MAX;
06192 if ( nodes.empty() )
06193 {
06194
06195 typedef map< double, SMESH_OctreeNode* > TDistTreeMap;
06196 TDistTreeMap treeMap;
06197 list< SMESH_OctreeNode* > treeList;
06198 list< SMESH_OctreeNode* >::iterator trIt;
06199 treeList.push_back( myOctreeNode );
06200
06201 gp_XYZ pointNode( thePnt.X(), thePnt.Y(), thePnt.Z() );
06202 bool pointInside = myOctreeNode->isInside( pointNode, myHalfLeafSize );
06203 for ( trIt = treeList.begin(); trIt != treeList.end(); ++trIt)
06204 {
06205 SMESH_OctreeNode* tree = *trIt;
06206 if ( !tree->isLeaf() )
06207 {
06208 if ( pointInside && !tree->isInside( pointNode, myHalfLeafSize )) continue;
06209 SMESH_OctreeNodeIteratorPtr cIt = tree->GetChildrenIterator();
06210 while ( cIt->more() )
06211 treeList.push_back( cIt->next() );
06212 }
06213 else if ( tree->NbNodes() )
06214 {
06215 const Bnd_B3d& box = tree->getBox();
06216 double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
06217 pair<TDistTreeMap::iterator,bool> it_in = treeMap.insert( make_pair( sqDist, tree ));
06218 if ( !it_in.second )
06219 treeMap.insert( it_in.first, make_pair( sqDist + 1e-13*treeMap.size(), tree ));
06220 }
06221 }
06222
06223 double sqLimit = DBL_MAX;
06224 TDistTreeMap::iterator sqDist_tree = treeMap.begin();
06225 if ( treeMap.size() > 5 ) {
06226 SMESH_OctreeNode* closestTree = sqDist_tree->second;
06227 const Bnd_B3d& box = closestTree->getBox();
06228 double limit = sqrt( sqDist_tree->first ) + sqrt ( box.SquareExtent() );
06229 sqLimit = limit * limit;
06230 }
06231
06232 for ( ; sqDist_tree != treeMap.end(); ++sqDist_tree) {
06233 if ( sqDist_tree->first > sqLimit )
06234 break;
06235 SMESH_OctreeNode* tree = sqDist_tree->second;
06236 tree->NodesAround( tree->GetNodeIterator()->next(), &nodes );
06237 }
06238 }
06239
06240 minSqDist = DBL_MAX;
06241 const SMDS_MeshNode* closestNode = 0;
06242 list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
06243 for ( ; nIt != nodes.end(); ++nIt ) {
06244 double sqDist = thePnt.SquareDistance( SMESH_TNodeXYZ( *nIt ) );
06245 if ( minSqDist > sqDist ) {
06246 closestNode = *nIt;
06247 minSqDist = sqDist;
06248 }
06249 }
06250 return closestNode;
06251 }
06252
06253
06257 ~SMESH_NodeSearcherImpl() { delete myOctreeNode; }
06258
06259
06263 const SMESH_OctreeNode* getTree() const { return myOctreeNode; }
06264
06265 private:
06266 SMESH_OctreeNode* myOctreeNode;
06267 SMESHDS_Mesh* myMesh;
06268 double myHalfLeafSize;
06269 };
06270
06271
06275
06276
06277 SMESH_NodeSearcher* SMESH_MeshEditor::GetNodeSearcher()
06278 {
06279 return new SMESH_NodeSearcherImpl( GetMeshDS() );
06280 }
06281
06282
06283 namespace
06284 {
06285 const int MaxNbElemsInLeaf = 10;
06286 const int MaxLevel = 7;
06287 const double NodeRadius = 1e-9;
06288
06289
06293
06294
06295 class ElementBndBoxTree : public SMESH_Octree
06296 {
06297 public:
06298
06299 ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(), double tolerance = NodeRadius );
06300 void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems);
06301 void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems);
06302 ~ElementBndBoxTree();
06303
06304 protected:
06305 ElementBndBoxTree() {}
06306 SMESH_Octree* allocateOctreeChild() const { return new ElementBndBoxTree; }
06307 void buildChildrenData();
06308 Bnd_B3d* buildRootBox();
06309 private:
06311 struct ElementBox : public Bnd_B3d
06312 {
06313 const SMDS_MeshElement* _element;
06314 int _refCount;
06315 ElementBox(const SMDS_MeshElement* elem, double tolerance);
06316 };
06317 vector< ElementBox* > _elements;
06318 };
06319
06320
06324
06325
06326 ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance)
06327 :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, 0. ))
06328 {
06329 int nbElems = mesh.GetMeshInfo().NbElements( elemType );
06330 _elements.reserve( nbElems );
06331
06332 SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType );
06333 while ( elemIt->more() )
06334 _elements.push_back( new ElementBox( elemIt->next(),tolerance ));
06335
06336 if ( _elements.size() > MaxNbElemsInLeaf )
06337 compute();
06338 else
06339 myIsLeaf = true;
06340 }
06341
06342
06346
06347
06348 ElementBndBoxTree::~ElementBndBoxTree()
06349 {
06350 for ( int i = 0; i < _elements.size(); ++i )
06351 if ( --_elements[i]->_refCount <= 0 )
06352 delete _elements[i];
06353 }
06354
06355
06359
06360
06361 Bnd_B3d* ElementBndBoxTree::buildRootBox()
06362 {
06363 Bnd_B3d* box = new Bnd_B3d;
06364 for ( int i = 0; i < _elements.size(); ++i )
06365 box->Add( *_elements[i] );
06366 return box;
06367 }
06368
06369
06373
06374
06375 void ElementBndBoxTree::buildChildrenData()
06376 {
06377 for ( int i = 0; i < _elements.size(); ++i )
06378 {
06379 for (int j = 0; j < 8; j++)
06380 {
06381 if ( !_elements[i]->IsOut( myChildren[j]->getBox() ))
06382 {
06383 _elements[i]->_refCount++;
06384 ((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
06385 }
06386 }
06387 _elements[i]->_refCount--;
06388 }
06389 _elements.clear();
06390
06391 for (int j = 0; j < 8; j++)
06392 {
06393 ElementBndBoxTree* child = static_cast<ElementBndBoxTree*>( myChildren[j]);
06394 if ( child->_elements.size() <= MaxNbElemsInLeaf )
06395 child->myIsLeaf = true;
06396
06397 if ( child->_elements.capacity() - child->_elements.size() > 1000 )
06398 child->_elements.resize( child->_elements.size() );
06399 }
06400 }
06401
06402
06406
06407
06408 void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point,
06409 TIDSortedElemSet& foundElems)
06410 {
06411 if ( level() && getBox().IsOut( point.XYZ() ))
06412 return;
06413
06414 if ( isLeaf() )
06415 {
06416 for ( int i = 0; i < _elements.size(); ++i )
06417 if ( !_elements[i]->IsOut( point.XYZ() ))
06418 foundElems.insert( _elements[i]->_element );
06419 }
06420 else
06421 {
06422 for (int i = 0; i < 8; i++)
06423 ((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems );
06424 }
06425 }
06426
06427
06431
06432
06433 void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line,
06434 TIDSortedElemSet& foundElems)
06435 {
06436 if ( level() && getBox().IsOut( line ))
06437 return;
06438
06439 if ( isLeaf() )
06440 {
06441 for ( int i = 0; i < _elements.size(); ++i )
06442 if ( !_elements[i]->IsOut( line ))
06443 foundElems.insert( _elements[i]->_element );
06444 }
06445 else
06446 {
06447 for (int i = 0; i < 8; i++)
06448 ((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems );
06449 }
06450 }
06451
06452
06456
06457
06458 ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance)
06459 {
06460 _element = elem;
06461 _refCount = 1;
06462 SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
06463 while ( nIt->more() )
06464 Add( SMESH_TNodeXYZ( cast2Node( nIt->next() )));
06465 Enlarge( tolerance );
06466 }
06467
06468 }
06469
06470
06475
06476
06477 struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
06478 {
06479 SMESHDS_Mesh* _mesh;
06480 SMDS_ElemIteratorPtr _meshPartIt;
06481 ElementBndBoxTree* _ebbTree;
06482 SMESH_NodeSearcherImpl* _nodeSearcher;
06483 SMDSAbs_ElementType _elementType;
06484 double _tolerance;
06485 bool _outerFacesFound;
06486 set<const SMDS_MeshElement*> _outerFaces;
06487
06488 SMESH_ElementSearcherImpl( SMESHDS_Mesh& mesh, SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
06489 : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_nodeSearcher(0),_tolerance(-1),_outerFacesFound(false) {}
06490 ~SMESH_ElementSearcherImpl()
06491 {
06492 if ( _ebbTree ) delete _ebbTree; _ebbTree = 0;
06493 if ( _nodeSearcher ) delete _nodeSearcher; _nodeSearcher = 0;
06494 }
06495 virtual int FindElementsByPoint(const gp_Pnt& point,
06496 SMDSAbs_ElementType type,
06497 vector< const SMDS_MeshElement* >& foundElements);
06498 virtual TopAbs_State GetPointState(const gp_Pnt& point);
06499
06500 void GetElementsNearLine( const gp_Ax1& line,
06501 SMDSAbs_ElementType type,
06502 vector< const SMDS_MeshElement* >& foundElems);
06503 double getTolerance();
06504 bool getIntersParamOnLine(const gp_Lin& line, const SMDS_MeshElement* face,
06505 const double tolerance, double & param);
06506 void findOuterBoundary(const SMDS_MeshElement* anyOuterFace);
06507 bool isOuterBoundary(const SMDS_MeshElement* face) const
06508 {
06509 return _outerFaces.empty() || _outerFaces.count(face);
06510 }
06511 struct TInters
06512 {
06513 const SMDS_MeshElement* _face;
06514 gp_Vec _faceNorm;
06515 bool _coincides;
06516 TInters(const SMDS_MeshElement* face, const gp_Vec& faceNorm, bool coinc=false)
06517 : _face(face), _faceNorm( faceNorm ), _coincides( coinc ) {}
06518 };
06519 struct TFaceLink
06520 {
06521 SMESH_TLink _link;
06522 TIDSortedElemSet _faces;
06523 TFaceLink( const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, const SMDS_MeshElement* face)
06524 : _link( n1, n2 ), _faces( &face, &face + 1) {}
06525 };
06526 };
06527
06528 ostream& operator<< (ostream& out, const SMESH_ElementSearcherImpl::TInters& i)
06529 {
06530 return out << "TInters(face=" << ( i._face ? i._face->GetID() : 0)
06531 << ", _coincides="<<i._coincides << ")";
06532 }
06533
06534
06538
06539
06540 double SMESH_ElementSearcherImpl::getTolerance()
06541 {
06542 if ( _tolerance < 0 )
06543 {
06544 const SMDS_MeshInfo& meshInfo = _mesh->GetMeshInfo();
06545
06546 _tolerance = 0;
06547 if ( _nodeSearcher && meshInfo.NbNodes() > 1 )
06548 {
06549 double boxSize = _nodeSearcher->getTree()->maxSize();
06550 _tolerance = 1e-8 * boxSize;
06551 }
06552 else if ( _ebbTree && meshInfo.NbElements() > 0 )
06553 {
06554 double boxSize = _ebbTree->maxSize();
06555 _tolerance = 1e-8 * boxSize;
06556 }
06557 if ( _tolerance == 0 )
06558 {
06559
06560 int complexType = SMDSAbs_Volume;
06561 while ( complexType > SMDSAbs_All &&
06562 meshInfo.NbElements( SMDSAbs_ElementType( complexType )) < 1 )
06563 --complexType;
06564 if ( complexType == SMDSAbs_All ) return 0;
06565 double elemSize;
06566 if ( complexType == int( SMDSAbs_Node ))
06567 {
06568 SMDS_NodeIteratorPtr nodeIt = _mesh->nodesIterator();
06569 elemSize = 1;
06570 if ( meshInfo.NbNodes() > 2 )
06571 elemSize = SMESH_TNodeXYZ( nodeIt->next() ).Distance( nodeIt->next() );
06572 }
06573 else
06574 {
06575 SMDS_ElemIteratorPtr elemIt =
06576 _mesh->elementsIterator( SMDSAbs_ElementType( complexType ));
06577 const SMDS_MeshElement* elem = elemIt->next();
06578 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
06579 SMESH_TNodeXYZ n1( cast2Node( nodeIt->next() ));
06580 elemSize = 0;
06581 while ( nodeIt->more() )
06582 {
06583 double dist = n1.Distance( cast2Node( nodeIt->next() ));
06584 elemSize = max( dist, elemSize );
06585 }
06586 }
06587 _tolerance = 1e-4 * elemSize;
06588 }
06589 }
06590 return _tolerance;
06591 }
06592
06593
06597
06598
06599 bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin& line,
06600 const SMDS_MeshElement* face,
06601 const double tol,
06602 double & param)
06603 {
06604 int nbInts = 0;
06605 param = 0;
06606
06607 GeomAPI_ExtremaCurveCurve anExtCC;
06608 Handle(Geom_Curve) lineCurve = new Geom_Line( line );
06609
06610 int nbNodes = face->IsQuadratic() ? face->NbNodes()/2 : face->NbNodes();
06611 for ( int i = 0; i < nbNodes && nbInts < 2; ++i )
06612 {
06613 GC_MakeSegment edge( SMESH_TNodeXYZ( face->GetNode( i )),
06614 SMESH_TNodeXYZ( face->GetNode( (i+1)%nbNodes) ));
06615 anExtCC.Init( lineCurve, edge);
06616 if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol)
06617 {
06618 Quantity_Parameter pl, pe;
06619 anExtCC.LowerDistanceParameters( pl, pe );
06620 param += pl;
06621 if ( ++nbInts == 2 )
06622 break;
06623 }
06624 }
06625 if ( nbInts > 0 ) param /= nbInts;
06626 return nbInts > 0;
06627 }
06628
06632
06633
06634 void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerFace)
06635 {
06636 if ( _outerFacesFound ) return;
06637
06638
06639
06640
06641
06642 set< SMESH_TLink > visitedLinks, seamLinks;
06643
06644
06645 list < TFaceLink > startLinks;
06646
06647
06648 startLinks.push_back( TFaceLink( outerFace->GetNode(0), outerFace->GetNode(1), outerFace));
06649 _outerFaces.insert( outerFace );
06650
06651 TIDSortedElemSet emptySet;
06652 while ( !startLinks.empty() )
06653 {
06654 const SMESH_TLink& link = startLinks.front()._link;
06655 TIDSortedElemSet& faces = startLinks.front()._faces;
06656
06657 outerFace = *faces.begin();
06658
06659 const SMDS_MeshElement* f;
06660 while (( f = SMESH_MeshEditor::FindFaceInSet(link.node1(), link.node2(), emptySet, faces )))
06661 faces.insert( f );
06662
06663
06664 const SMDS_MeshElement* outerFace2 = 0;
06665 if ( faces.size() == 2 )
06666 {
06667 outerFace2 = (outerFace == *faces.begin() ? *faces.rbegin() : *faces.begin());
06668 }
06669 else if ( faces.size() > 2 )
06670 {
06671 seamLinks.insert( link );
06672
06673
06674 gp_Vec n1n2( SMESH_TNodeXYZ( link.node1()),
06675 SMESH_TNodeXYZ( link.node2()));
06676 int i1 = outerFace->GetNodeIndex( link.node1() );
06677 int i2 = outerFace->GetNodeIndex( link.node2() );
06678 bool rev = ( abs(i2-i1) == 1 ? i1 > i2 : i2 > i1 );
06679 if ( rev ) n1n2.Reverse();
06680
06681 gp_XYZ ofNorm, fNorm;
06682 if ( SMESH_Algo::FaceNormal( outerFace, ofNorm, false ))
06683 {
06684
06685 gp_Vec dirInOF = gp_Vec( ofNorm ) ^ n1n2;
06686
06687 map< double, const SMDS_MeshElement* > angle2Face;
06688 set< const SMDS_MeshElement*, TIDCompare >::const_iterator face = faces.begin();
06689 for ( ; face != faces.end(); ++face )
06690 {
06691 if ( !SMESH_Algo::FaceNormal( *face, fNorm, false ))
06692 continue;
06693 gp_Vec dirInF = gp_Vec( fNorm ) ^ n1n2;
06694 double angle = dirInOF.AngleWithRef( dirInF, n1n2 );
06695 if ( angle < 0 ) angle += 2*PI;
06696 angle2Face.insert( make_pair( angle, *face ));
06697 }
06698 if ( !angle2Face.empty() )
06699 outerFace2 = angle2Face.begin()->second;
06700 }
06701 }
06702
06703 if ( outerFace2 )
06704 {
06705 _outerFaces.insert( outerFace );
06706 int nbNodes = outerFace2->NbNodes()/( outerFace2->IsQuadratic() ? 2 : 1 );
06707 for ( int i = 0; i < nbNodes; ++i )
06708 {
06709 SMESH_TLink link2( outerFace2->GetNode(i), outerFace2->GetNode((i+1)%nbNodes));
06710 if ( visitedLinks.insert( link2 ).second )
06711 startLinks.push_back( TFaceLink( link2.node1(), link2.node2(), outerFace2 ));
06712 }
06713 }
06714 startLinks.pop_front();
06715 }
06716 _outerFacesFound = true;
06717
06718 if ( !seamLinks.empty() )
06719 {
06720
06721
06722
06723
06724 }
06725 else
06726 {
06727 _outerFaces.clear();
06728 }
06729 }
06730
06731
06738
06739
06740 int SMESH_ElementSearcherImpl::
06741 FindElementsByPoint(const gp_Pnt& point,
06742 SMDSAbs_ElementType type,
06743 vector< const SMDS_MeshElement* >& foundElements)
06744 {
06745 foundElements.clear();
06746
06747 double tolerance = getTolerance();
06748
06749
06750 if ( type == SMDSAbs_Node || type == SMDSAbs_0DElement )
06751 {
06752 if ( !_nodeSearcher )
06753 _nodeSearcher = new SMESH_NodeSearcherImpl( _mesh );
06754
06755 const SMDS_MeshNode* closeNode = _nodeSearcher->FindClosestTo( point );
06756 if ( !closeNode ) return foundElements.size();
06757
06758 if ( point.Distance( SMESH_TNodeXYZ( closeNode )) > tolerance )
06759 return foundElements.size();
06760
06761 if ( type == SMDSAbs_Node )
06762 {
06763 foundElements.push_back( closeNode );
06764 }
06765 else
06766 {
06767 SMDS_ElemIteratorPtr elemIt = closeNode->GetInverseElementIterator( SMDSAbs_0DElement );
06768 while ( elemIt->more() )
06769 foundElements.push_back( elemIt->next() );
06770 }
06771 }
06772
06773 else
06774 {
06775 if ( !_ebbTree || _elementType != type )
06776 {
06777 if ( _ebbTree ) delete _ebbTree;
06778 _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt, tolerance );
06779 }
06780 TIDSortedElemSet suspectElems;
06781 _ebbTree->getElementsNearPoint( point, suspectElems );
06782 TIDSortedElemSet::iterator elem = suspectElems.begin();
06783 for ( ; elem != suspectElems.end(); ++elem )
06784 if ( !SMESH_MeshEditor::isOut( *elem, point, tolerance ))
06785 foundElements.push_back( *elem );
06786 }
06787 return foundElements.size();
06788 }
06789
06790
06794
06795
06796 TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
06797 {
06798 double tolerance = getTolerance();
06799 if ( !_ebbTree || _elementType != SMDSAbs_Face )
06800 {
06801 if ( _ebbTree ) delete _ebbTree;
06802 _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face, _meshPartIt );
06803 }
06804
06805
06806
06807
06808 const int nbAxes = 3;
06809 gp_Dir axisDir[ nbAxes ] = { gp::DX(), gp::DY(), gp::DZ() };
06810 map< double, TInters > paramOnLine2TInters[ nbAxes ];
06811 list< TInters > tangentInters[ nbAxes ];
06812 multimap< int, int > nbInt2Axis;
06813 for ( int axis = 0; axis < nbAxes; ++axis )
06814 {
06815 gp_Ax1 lineAxis( point, axisDir[axis]);
06816 gp_Lin line ( lineAxis );
06817
06818 TIDSortedElemSet suspectFaces;
06819 _ebbTree->getElementsNearLine( lineAxis, suspectFaces );
06820
06821
06822
06823 map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
06824 TIDSortedElemSet::iterator face = suspectFaces.begin();
06825 for ( ; face != suspectFaces.end(); ++face )
06826 {
06827
06828 gp_XYZ fNorm;
06829 if ( !SMESH_Algo::FaceNormal( *face, fNorm, false)) continue;
06830 gp_Pln facePlane( SMESH_TNodeXYZ( (*face)->GetNode(0)), fNorm );
06831
06832
06833 IntAna_IntConicQuad intersection( line, IntAna_Quadric( facePlane ));
06834 if ( !intersection.IsDone() )
06835 continue;
06836 if ( intersection.IsInQuadric() )
06837 {
06838 tangentInters[ axis ].push_back( TInters( *face, fNorm, true ));
06839 }
06840 else if ( ! intersection.IsParallel() && intersection.NbPoints() > 0 )
06841 {
06842 gp_Pnt intersectionPoint = intersection.Point(1);
06843 if ( !SMESH_MeshEditor::isOut( *face, intersectionPoint, tolerance ))
06844 u2inters.insert(make_pair( intersection.ParamOnConic(1), TInters( *face, fNorm )));
06845 }
06846 }
06847
06848
06849 int nbInter = u2inters.size();
06850 if ( nbInter == 0 )
06851 return TopAbs_OUT;
06852
06853 double f = u2inters.begin()->first, l = u2inters.rbegin()->first;
06854 if ( nbInter == 1 )
06855 return fabs( f ) < tolerance ? TopAbs_ON : TopAbs_UNKNOWN;
06856
06857 if ( fabs( f ) < tolerance || fabs( l ) < tolerance )
06858 return TopAbs_ON;
06859
06860 if ( (f<0) == (l<0) )
06861 return TopAbs_OUT;
06862
06863 int nbIntBeforePoint = std::distance( u2inters.begin(), u2inters.lower_bound(0));
06864 int nbIntAfterPoint = nbInter - nbIntBeforePoint;
06865 if ( nbIntBeforePoint == 1 || nbIntAfterPoint == 1 )
06866 return TopAbs_IN;
06867
06868 nbInt2Axis.insert( make_pair( min( nbIntBeforePoint, nbIntAfterPoint ), axis ));
06869
06870 if ( _outerFacesFound ) break;
06871
06872 }
06873
06874
06875
06876
06877
06878
06879
06880 for ( int hasPositionInfo = _outerFacesFound; hasPositionInfo < 2; ++hasPositionInfo )
06881 {
06882 multimap< int, int >::const_iterator nb_axis = nbInt2Axis.begin();
06883 for ( ; nb_axis != nbInt2Axis.end(); ++nb_axis )
06884 {
06885 int axis = nb_axis->second;
06886 map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
06887
06888 gp_Ax1 lineAxis( point, axisDir[axis]);
06889 gp_Lin line ( lineAxis );
06890
06891
06892 double param;
06893 list< TInters >::const_iterator tgtInt = tangentInters[ axis ].begin();
06894 for ( ; tgtInt != tangentInters[ axis ].end(); ++tgtInt )
06895 if ( getIntersParamOnLine( line, tgtInt->_face, tolerance, param ))
06896 u2inters.insert(make_pair( param, *tgtInt ));
06897 tangentInters[ axis ].clear();
06898
06899
06900
06901
06902 int nbIntBeforePoint = 0, nbIntAfterPoint = 0;
06903 double f = numeric_limits<double>::max(), l = -numeric_limits<double>::max();
06904 map< double, TInters >::iterator u_int1 = u2inters.begin(), u_int2 = u_int1;
06905 bool ok = ! u_int1->second._coincides;
06906 while ( ok && u_int1 != u2inters.end() )
06907 {
06908 double u = u_int1->first;
06909 bool touchingInt = false;
06910 if ( ++u_int2 != u2inters.end() )
06911 {
06912
06913 int nbSamePnt = 0;
06914 while ( u_int2 != u2inters.end() && fabs( u_int2->first - u ) < tolerance )
06915 {
06916 ++nbSamePnt;
06917 ++u_int2;
06918 }
06919
06920
06921 int nbTgt = 0;
06922 const SMDS_MeshElement* prevFace = u_int1->second._face;
06923 while ( ok && u_int2->second._coincides )
06924 {
06925 if ( SMESH_Algo::GetCommonNodes(prevFace , u_int2->second._face).empty() )
06926 ok = false;
06927 else
06928 {
06929 nbTgt++;
06930 u_int2++;
06931 ok = ( u_int2 != u2inters.end() );
06932 }
06933 }
06934 if ( !ok ) break;
06935
06936
06937 if ( nbTgt > 0 )
06938 {
06939 double u2 = u_int2->first;
06940 ++u_int2;
06941 while ( u_int2 != u2inters.end() && fabs( u_int2->first - u2 ) < tolerance )
06942 {
06943 ++nbSamePnt;
06944 ++u_int2;
06945 }
06946 }
06947
06948 if ( nbSamePnt + nbTgt > 0 )
06949 {
06950 double minDot = numeric_limits<double>::max(), maxDot = -numeric_limits<double>::max();
06951 map< double, TInters >::iterator u_int = u_int1;
06952 for ( ; u_int != u_int2; ++u_int )
06953 {
06954 if ( u_int->second._coincides ) continue;
06955 double dot = u_int->second._faceNorm * line.Direction();
06956 if ( dot > maxDot ) maxDot = dot;
06957 if ( dot < minDot ) minDot = dot;
06958 }
06959 touchingInt = ( minDot*maxDot < 0 );
06960 }
06961 }
06962 if ( !touchingInt )
06963 {
06964 if ( !hasPositionInfo || isOuterBoundary( u_int1->second._face ))
06965 {
06966 if ( u < 0 )
06967 ++nbIntBeforePoint;
06968 else
06969 ++nbIntAfterPoint;
06970 }
06971 if ( u < f ) f = u;
06972 if ( u > l ) l = u;
06973 }
06974
06975 u_int1 = u_int2;
06976
06977 }
06978
06979 if ( ok )
06980 {
06981 if ( fabs( f ) < tolerance || fabs( l ) < tolerance )
06982 return TopAbs_ON;
06983
06984 if ( nbIntBeforePoint == 0 || nbIntAfterPoint == 0)
06985 return TopAbs_OUT;
06986
06987 if ( nbIntBeforePoint + nbIntAfterPoint == 1 )
06988 return fabs( f ) < tolerance ? TopAbs_ON : TopAbs_UNKNOWN;
06989
06990 if ( nbIntBeforePoint == 1 || nbIntAfterPoint == 1 )
06991 return TopAbs_IN;
06992
06993 if ( (f<0) == (l<0) )
06994 return TopAbs_OUT;
06995
06996 if ( hasPositionInfo )
06997 return nbIntBeforePoint % 2 ? TopAbs_IN : TopAbs_OUT;
06998 }
06999 }
07000
07001 if ( !hasPositionInfo )
07002 {
07003
07004 map< double, TInters > & u2inters = paramOnLine2TInters[ 0 ];
07005 findOuterBoundary( u2inters.begin()->second._face );
07006 }
07007
07008 }
07009
07010 return TopAbs_UNKNOWN;
07011 }
07012
07013
07017
07018
07019 void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1& line,
07020 SMDSAbs_ElementType type,
07021 vector< const SMDS_MeshElement* >& foundElems)
07022 {
07023 if ( !_ebbTree || _elementType != type )
07024 {
07025 if ( _ebbTree ) delete _ebbTree;
07026 _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt );
07027 }
07028 TIDSortedElemSet suspectFaces;
07029 _ebbTree->getElementsNearLine( line, suspectFaces );
07030 foundElems.assign( suspectFaces.begin(), suspectFaces.end());
07031 }
07032
07033
07037
07038
07039 SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher()
07040 {
07041 return new SMESH_ElementSearcherImpl( *GetMeshDS() );
07042 }
07043
07044
07048
07049
07050 SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher(SMDS_ElemIteratorPtr elemIt)
07051 {
07052 return new SMESH_ElementSearcherImpl( *GetMeshDS(), elemIt );
07053 }
07054
07055
07059
07060
07061 bool SMESH_MeshEditor::isOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol )
07062 {
07063 if ( element->GetType() == SMDSAbs_Volume)
07064 {
07065 return SMDS_VolumeTool( element ).IsOut( point.X(), point.Y(), point.Z(), tol );
07066 }
07067
07068
07069
07070 vector< gp_XYZ > xyz;
07071 vector<const SMDS_MeshNode*> nodeList;
07072
07073 SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
07074 if ( element->IsQuadratic() ) {
07075 if (const SMDS_VtkFace* f=dynamic_cast<const SMDS_VtkFace*>(element))
07076 nodeIt = f->interlacedNodesElemIterator();
07077 else if (const SMDS_VtkEdge* e =dynamic_cast<const SMDS_VtkEdge*>(element))
07078 nodeIt = e->interlacedNodesElemIterator();
07079 }
07080 while ( nodeIt->more() )
07081 {
07082 const SMDS_MeshNode* node = cast2Node( nodeIt->next() );
07083 xyz.push_back( SMESH_TNodeXYZ(node) );
07084 nodeList.push_back(node);
07085 }
07086
07087 int i, nbNodes = element->NbNodes();
07088
07089 if ( element->GetType() == SMDSAbs_Face )
07090 {
07091
07092 gp_Vec faceNorm(0,0,0);
07093 xyz.push_back( xyz.front() );
07094 nodeList.push_back( nodeList.front() );
07095 for ( i = 0; i < nbNodes; ++i )
07096 {
07097 gp_Vec edge1( xyz[i+1], xyz[i]);
07098 gp_Vec edge2( xyz[i+1], xyz[(i+2)%nbNodes] );
07099 faceNorm += edge1 ^ edge2;
07100 }
07101 double normSize = faceNorm.Magnitude();
07102 if ( normSize <= tol )
07103 {
07104
07105 for ( i = 0; i < nbNodes; ++i )
07106 {
07107 SMDS_LinearEdge edge( nodeList[i], nodeList[i+1] );
07108 if ( !isOut( &edge, point, tol ))
07109 return false;
07110 }
07111 return true;
07112 }
07113 faceNorm /= normSize;
07114
07115
07116 gp_Vec n2p( xyz[0], point );
07117 if ( fabs( n2p * faceNorm ) > tol )
07118 return true;
07119
07120
07121
07122
07123
07124
07125 gp_Vec ray = n2p;
07126 gp_Vec plnNorm = ray ^ faceNorm;
07127 normSize = plnNorm.Magnitude();
07128 if ( normSize <= tol ) return false;
07129 plnNorm /= normSize;
07130
07131 vector<double> dist( nbNodes + 1);
07132 for ( i = 0; i < nbNodes; ++i )
07133 {
07134 gp_Vec n2p( xyz[i], point );
07135 dist[i] = n2p * plnNorm;
07136 }
07137 dist.back() = dist.front();
07138
07139 int iClosest = -1;
07140 double rClosest, distClosest = 1e100;;
07141 gp_Pnt pClosest;
07142 for ( i = 0; i < nbNodes; ++i )
07143 {
07144 double r;
07145 if ( fabs( dist[i]) < tol )
07146 r = 0.;
07147 else if ( fabs( dist[i+1]) < tol )
07148 r = 1.;
07149 else if ( dist[i] * dist[i+1] < 0 )
07150 r = dist[i] / ( dist[i] - dist[i+1] );
07151 else
07152 continue;
07153 gp_Pnt pInt = xyz[i] * (1.-r) + xyz[i+1] * r;
07154 gp_Vec p2int ( point, pInt);
07155 if ( p2int * ray > -tol )
07156 {
07157 double intDist = p2int.SquareMagnitude();
07158 if ( intDist < distClosest )
07159 {
07160 iClosest = i;
07161 rClosest = r;
07162 pClosest = pInt;
07163 distClosest = intDist;
07164 }
07165 }
07166 }
07167 if ( iClosest < 0 )
07168 return true;
07169
07170
07171 gp_Vec edge( xyz[iClosest], xyz[iClosest+1] );
07172 gp_Vec edgeNorm = -( edge ^ faceNorm );
07173 gp_Vec p2int ( point, pClosest );
07174 bool out = (edgeNorm * p2int) < -tol;
07175 if ( rClosest > 0. && rClosest < 1. )
07176 return out;
07177
07178
07179 gp_Pnt p1 = xyz[ (rClosest == 0.) ? ((iClosest+nbNodes-1) % nbNodes) : (iClosest+1) ];
07180 gp_Pnt p2 = xyz[ (rClosest == 0.) ? iClosest : ((iClosest+2) % nbNodes) ];
07181 gp_Vec edgeAdjacent( p1, p2 );
07182 gp_Vec edgeNorm2 = -( edgeAdjacent ^ faceNorm );
07183 bool out2 = (edgeNorm2 * p2int) < -tol;
07184
07185 bool covexCorner = ( edgeNorm * edgeAdjacent * (rClosest==1. ? 1. : -1.)) < 0;
07186 return covexCorner ? (out || out2) : (out && out2);
07187 }
07188 if ( element->GetType() == SMDSAbs_Edge )
07189 {
07190
07191
07192 for ( i = 1; i < nbNodes; ++i )
07193 {
07194 gp_Vec edge( xyz[i-1], xyz[i]);
07195 gp_Vec n1p ( xyz[i-1], point);
07196 double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
07197 if ( dist > tol )
07198 continue;
07199 gp_Vec n2p( xyz[i], point );
07200 if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol )
07201 continue;
07202 return false;
07203 }
07204 return true;
07205 }
07206
07207 {
07208 gp_Vec n2p ( xyz[0], point );
07209 return n2p.Magnitude() <= tol;
07210 }
07211 return true;
07212 }
07213
07214
07215
07216
07217
07218 int SMESH_MeshEditor::SimplifyFace (const vector<const SMDS_MeshNode *> faceNodes,
07219 vector<const SMDS_MeshNode *>& poly_nodes,
07220 vector<int>& quantities) const
07221 {
07222 int nbNodes = faceNodes.size();
07223
07224 if (nbNodes < 3)
07225 return 0;
07226
07227 set<const SMDS_MeshNode*> nodeSet;
07228
07229
07230
07231 vector<const SMDS_MeshNode*> simpleNodes( nbNodes );
07232 int iSimple = 0, nbUnique = 0;
07233
07234 simpleNodes[iSimple++] = faceNodes[0];
07235 nbUnique++;
07236 for (int iCur = 1; iCur < nbNodes; iCur++) {
07237 if (faceNodes[iCur] != simpleNodes[iSimple - 1]) {
07238 simpleNodes[iSimple++] = faceNodes[iCur];
07239 if (nodeSet.insert( faceNodes[iCur] ).second)
07240 nbUnique++;
07241 }
07242 }
07243 int nbSimple = iSimple;
07244 if (simpleNodes[nbSimple - 1] == simpleNodes[0]) {
07245 nbSimple--;
07246 iSimple--;
07247 }
07248
07249 if (nbUnique < 3)
07250 return 0;
07251
07252
07253 int nbNew = 0;
07254 bool foundLoop = (nbSimple > nbUnique);
07255 while (foundLoop) {
07256 foundLoop = false;
07257 set<const SMDS_MeshNode*> loopSet;
07258 for (iSimple = 0; iSimple < nbSimple && !foundLoop; iSimple++) {
07259 const SMDS_MeshNode* n = simpleNodes[iSimple];
07260 if (!loopSet.insert( n ).second) {
07261 foundLoop = true;
07262
07263
07264 int iC = 0, curLast = iSimple;
07265 for (; iC < curLast; iC++) {
07266 if (simpleNodes[iC] == n) break;
07267 }
07268 int loopLen = curLast - iC;
07269 if (loopLen > 2) {
07270
07271 nbNew++;
07272 quantities.push_back(loopLen);
07273 for (; iC < curLast; iC++) {
07274 poly_nodes.push_back(simpleNodes[iC]);
07275 }
07276 }
07277
07278 for (iC = curLast + 1; iC < nbSimple; iC++) {
07279 simpleNodes[iC - loopLen] = simpleNodes[iC];
07280 }
07281 nbSimple -= loopLen;
07282 iSimple -= loopLen;
07283 }
07284 }
07285 }
07286
07287 if (iSimple > 2) {
07288 nbNew++;
07289 quantities.push_back(iSimple);
07290 for (int i = 0; i < iSimple; i++)
07291 poly_nodes.push_back(simpleNodes[i]);
07292 }
07293
07294 return nbNew;
07295 }
07296
07297
07298
07299
07300
07301
07302
07303 void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
07304 {
07305 MESSAGE("MergeNodes");
07306 myLastCreatedElems.Clear();
07307 myLastCreatedNodes.Clear();
07308
07309 SMESHDS_Mesh* aMesh = GetMeshDS();
07310
07311 TNodeNodeMap nodeNodeMap;
07312 set<const SMDS_MeshElement*> elems;
07313 list< int > rmElemIds, rmNodeIds;
07314
07315
07316
07317 TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin();
07318 for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) {
07319 list<const SMDS_MeshNode*>& nodes = *grIt;
07320 list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
07321 const SMDS_MeshNode* nToKeep = *nIt;
07322
07323 for ( ++nIt; nIt != nodes.end(); nIt++ ) {
07324 const SMDS_MeshNode* nToRemove = *nIt;
07325 nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
07326 if ( nToRemove != nToKeep ) {
07327
07328 rmNodeIds.push_back( nToRemove->GetID() );
07329 AddToSameGroups( nToKeep, nToRemove, aMesh );
07330 }
07331
07332 SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
07333 while ( invElemIt->more() ) {
07334 const SMDS_MeshElement* elem = invElemIt->next();
07335 elems.insert(elem);
07336 }
07337 }
07338 }
07339
07340
07341 set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
07342 for ( ; eIt != elems.end(); eIt++ ) {
07343 const SMDS_MeshElement* elem = *eIt;
07344
07345 int nbNodes = elem->NbNodes();
07346 int aShapeId = FindShape( elem );
07347
07348 set<const SMDS_MeshNode*> nodeSet;
07349 vector< const SMDS_MeshNode*> curNodes( nbNodes ), uniqueNodes( nbNodes );
07350 int iUnique = 0, iCur = 0, nbRepl = 0;
07351 vector<int> iRepl( nbNodes );
07352
07353
07354 SMDS_ElemIteratorPtr itN = elem->nodesIterator();
07355 while ( itN->more() ) {
07356 const SMDS_MeshNode* n =
07357 static_cast<const SMDS_MeshNode*>( itN->next() );
07358
07359 TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
07360 if ( nnIt != nodeNodeMap.end() ) {
07361 n = (*nnIt).second;
07362
07363 {
07364 bool stopRecur = false;
07365 set<const SMDS_MeshNode*> nodesRecur;
07366 nodesRecur.insert(n);
07367 while (!stopRecur) {
07368 TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( n );
07369 if ( nnIt_i != nodeNodeMap.end() ) {
07370 n = (*nnIt_i).second;
07371 if (!nodesRecur.insert(n).second) {
07372
07373 stopRecur = true;
07374 }
07375 }
07376 else
07377 stopRecur = true;
07378 }
07379 }
07380
07381 iRepl[ nbRepl++ ] = iCur;
07382 }
07383 curNodes[ iCur ] = n;
07384 bool isUnique = nodeSet.insert( n ).second;
07385 if ( isUnique ) {
07386 uniqueNodes[ iUnique++ ] = n;
07387 if ( nbRepl && iRepl[ nbRepl-1 ] == iCur )
07388 --nbRepl;
07389 }
07390 iCur++;
07391 }
07392
07393
07394
07395 bool isOk = true;
07396 int nbUniqueNodes = nodeSet.size();
07397
07398 if ( nbNodes != nbUniqueNodes ) {
07399
07400 if (elem->IsPoly()) {
07401
07402 if (elem->GetType() == SMDSAbs_Face) {
07403
07404 vector<const SMDS_MeshNode *> face_nodes (nbNodes);
07405 int inode = 0;
07406 for (; inode < nbNodes; inode++) {
07407 face_nodes[inode] = curNodes[inode];
07408 }
07409
07410 vector<const SMDS_MeshNode *> polygons_nodes;
07411 vector<int> quantities;
07412 int nbNew = SimplifyFace(face_nodes, polygons_nodes, quantities);
07413 if (nbNew > 0) {
07414 inode = 0;
07415 for (int iface = 0; iface < nbNew; iface++) {
07416 int nbNodes = quantities[iface];
07417 vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
07418 for (int ii = 0; ii < nbNodes; ii++, inode++) {
07419 poly_nodes[ii] = polygons_nodes[inode];
07420 }
07421 SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
07422 myLastCreatedElems.Append(newElem);
07423 if (aShapeId)
07424 aMesh->SetMeshElementOnShape(newElem, aShapeId);
07425 }
07426
07427 MESSAGE("ChangeElementNodes MergeNodes Polygon");
07428
07429 vector<const SMDS_MeshNode *> polynodes(polygons_nodes.begin()+inode,polygons_nodes.end());
07430 int quid =0;
07431 if (nbNew > 0) quid = nbNew - 1;
07432 vector<int> newquant(quantities.begin()+quid, quantities.end());
07433 const SMDS_MeshElement* newElem = 0;
07434 newElem = aMesh->AddPolyhedralVolume(polynodes, newquant);
07435 myLastCreatedElems.Append(newElem);
07436 if ( aShapeId && newElem )
07437 aMesh->SetMeshElementOnShape( newElem, aShapeId );
07438 rmElemIds.push_back(elem->GetID());
07439 }
07440 else {
07441 rmElemIds.push_back(elem->GetID());
07442 }
07443
07444 }
07445 else if (elem->GetType() == SMDSAbs_Volume) {
07446
07447 if (nbUniqueNodes < 4) {
07448 rmElemIds.push_back(elem->GetID());
07449 }
07450 else {
07451
07452 const SMDS_VtkVolume* aPolyedre =
07453 dynamic_cast<const SMDS_VtkVolume*>( elem );
07454 if (aPolyedre) {
07455 int nbFaces = aPolyedre->NbFaces();
07456
07457 vector<const SMDS_MeshNode *> poly_nodes;
07458 vector<int> quantities;
07459
07460 for (int iface = 1; iface <= nbFaces; iface++) {
07461 int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
07462 vector<const SMDS_MeshNode *> faceNodes (nbFaceNodes);
07463
07464 for (int inode = 1; inode <= nbFaceNodes; inode++) {
07465 const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode);
07466 TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode);
07467 if (nnIt != nodeNodeMap.end()) {
07468 faceNode = (*nnIt).second;
07469 }
07470 faceNodes[inode - 1] = faceNode;
07471 }
07472
07473 SimplifyFace(faceNodes, poly_nodes, quantities);
07474 }
07475
07476 if (quantities.size() > 3) {
07477
07478 }
07479
07480 if (quantities.size() > 3)
07481 {
07482 MESSAGE("ChangeElementNodes MergeNodes Polyhedron");
07483
07484 const SMDS_MeshElement* newElem = 0;
07485 newElem = aMesh->AddPolyhedralVolume(poly_nodes, quantities);
07486 myLastCreatedElems.Append(newElem);
07487 if ( aShapeId && newElem )
07488 aMesh->SetMeshElementOnShape( newElem, aShapeId );
07489 rmElemIds.push_back(elem->GetID());
07490 }
07491 }
07492 else {
07493 rmElemIds.push_back(elem->GetID());
07494 }
07495 }
07496 }
07497 else {
07498 }
07499
07500 continue;
07501 }
07502
07503
07504
07505 switch ( nbNodes ) {
07506 case 2:
07507 isOk = false; break;
07508 case 3:
07509 isOk = false; break;
07510 case 4:
07511 if ( elem->GetType() == SMDSAbs_Volume )
07512 isOk = false;
07513 else {
07514 if ( nbUniqueNodes < 3 )
07515 isOk = false;
07516 else if ( nbRepl == 2 && iRepl[ 1 ] - iRepl[ 0 ] == 2 )
07517 isOk = false;
07518
07519 }
07520 break;
07521 case 6:
07522 if ( nbUniqueNodes == 4 ) {
07523
07524 if (nbRepl == 3 &&
07525 iRepl[ 0 ] > 2 && iRepl[ 1 ] > 2 && iRepl[ 2 ] > 2 ) {
07526
07527 uniqueNodes[ 0 ] = curNodes [ 1 ];
07528 uniqueNodes[ 1 ] = curNodes [ 0 ];
07529 }
07530 else if (nbRepl == 3 &&
07531 iRepl[ 0 ] < 3 && iRepl[ 1 ] < 3 && iRepl[ 2 ] < 3 ) {
07532
07533 uniqueNodes[ 3 ] = uniqueNodes [ 0 ];
07534 uniqueNodes[ 0 ] = curNodes [ 3 ];
07535 uniqueNodes[ 1 ] = curNodes [ 4 ];
07536 uniqueNodes[ 2 ] = curNodes [ 5 ];
07537 }
07538 else if (nbRepl == 4 &&
07539 iRepl[ 2 ] - iRepl [ 0 ] == 3 && iRepl[ 3 ] - iRepl [ 1 ] == 3 ) {
07540
07541 uniqueNodes[ 0 ] = curNodes [ 1 ];
07542 uniqueNodes[ 1 ] = curNodes [ 0 ];
07543 }
07544 else
07545 isOk = false;
07546 }
07547 else if ( nbUniqueNodes == 5 ) {
07548
07549 if ( nbRepl == 2 && iRepl[ 1 ] - iRepl [ 0 ] == 3 ) {
07550
07551
07552 SMDS_MeshElement* newElem =
07553 aMesh->AddVolume(curNodes[ 3 ],
07554 curNodes[ 4 ],
07555 curNodes[ 5 ],
07556 curNodes[ iRepl[ 0 ] == 2 ? 1 : 2 ]);
07557 myLastCreatedElems.Append(newElem);
07558 if ( aShapeId )
07559 aMesh->SetMeshElementOnShape( newElem, aShapeId );
07560
07561 uniqueNodes[ 0 ] = curNodes [ 1 ];
07562 uniqueNodes[ 1 ] = curNodes [ 0 ];
07563 nbUniqueNodes = 4;
07564 }
07565 else
07566 isOk = false;
07567 }
07568 else
07569 isOk = false;
07570 break;
07571 case 8: {
07572 if(elem->IsQuadratic()) {
07573
07574
07575
07576
07577
07578
07579
07580
07581
07582 isOk = false;
07583 if(nbRepl==2) {
07584 MESSAGE("nbRepl=2: " << iRepl[0] << " " << iRepl[1]);
07585 }
07586 if(nbRepl==3) {
07587 MESSAGE("nbRepl=3: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2]);
07588 nbUniqueNodes = 6;
07589 if( iRepl[0]==0 && iRepl[1]==1 && iRepl[2]==4 ) {
07590 uniqueNodes[0] = curNodes[0];
07591 uniqueNodes[1] = curNodes[2];
07592 uniqueNodes[2] = curNodes[3];
07593 uniqueNodes[3] = curNodes[5];
07594 uniqueNodes[4] = curNodes[6];
07595 uniqueNodes[5] = curNodes[7];
07596 isOk = true;
07597 }
07598 if( iRepl[0]==0 && iRepl[1]==3 && iRepl[2]==7 ) {
07599 uniqueNodes[0] = curNodes[0];
07600 uniqueNodes[1] = curNodes[1];
07601 uniqueNodes[2] = curNodes[2];
07602 uniqueNodes[3] = curNodes[4];
07603 uniqueNodes[4] = curNodes[5];
07604 uniqueNodes[5] = curNodes[6];
07605 isOk = true;
07606 }
07607 if( iRepl[0]==0 && iRepl[1]==4 && iRepl[2]==7 ) {
07608 uniqueNodes[0] = curNodes[1];
07609 uniqueNodes[1] = curNodes[2];
07610 uniqueNodes[2] = curNodes[3];
07611 uniqueNodes[3] = curNodes[5];
07612 uniqueNodes[4] = curNodes[6];
07613 uniqueNodes[5] = curNodes[0];
07614 isOk = true;
07615 }
07616 if( iRepl[0]==1 && iRepl[1]==2 && iRepl[2]==5 ) {
07617 uniqueNodes[0] = curNodes[0];
07618 uniqueNodes[1] = curNodes[1];
07619 uniqueNodes[2] = curNodes[3];
07620 uniqueNodes[3] = curNodes[4];
07621 uniqueNodes[4] = curNodes[6];
07622 uniqueNodes[5] = curNodes[7];
07623 isOk = true;
07624 }
07625 if( iRepl[0]==1 && iRepl[1]==4 && iRepl[2]==5 ) {
07626 uniqueNodes[0] = curNodes[0];
07627 uniqueNodes[1] = curNodes[2];
07628 uniqueNodes[2] = curNodes[3];
07629 uniqueNodes[3] = curNodes[1];
07630 uniqueNodes[4] = curNodes[6];
07631 uniqueNodes[5] = curNodes[7];
07632 isOk = true;
07633 }
07634 if( iRepl[0]==2 && iRepl[1]==3 && iRepl[2]==6 ) {
07635 uniqueNodes[0] = curNodes[0];
07636 uniqueNodes[1] = curNodes[1];
07637 uniqueNodes[2] = curNodes[2];
07638 uniqueNodes[3] = curNodes[4];
07639 uniqueNodes[4] = curNodes[5];
07640 uniqueNodes[5] = curNodes[7];
07641 isOk = true;
07642 }
07643 if( iRepl[0]==2 && iRepl[1]==5 && iRepl[2]==6 ) {
07644 uniqueNodes[0] = curNodes[0];
07645 uniqueNodes[1] = curNodes[1];
07646 uniqueNodes[2] = curNodes[3];
07647 uniqueNodes[3] = curNodes[4];
07648 uniqueNodes[4] = curNodes[2];
07649 uniqueNodes[5] = curNodes[7];
07650 isOk = true;
07651 }
07652 if( iRepl[0]==3 && iRepl[1]==6 && iRepl[2]==7 ) {
07653 uniqueNodes[0] = curNodes[0];
07654 uniqueNodes[1] = curNodes[1];
07655 uniqueNodes[2] = curNodes[2];
07656 uniqueNodes[3] = curNodes[4];
07657 uniqueNodes[4] = curNodes[5];
07658 uniqueNodes[5] = curNodes[3];
07659 isOk = true;
07660 }
07661 }
07662 if(nbRepl==4) {
07663 MESSAGE("nbRepl=4: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2] << " " << iRepl[3]);
07664 }
07665 if(nbRepl==5) {
07666 MESSAGE("nbRepl=5: " << iRepl[0] << " " << iRepl[1] << " " << iRepl[2] << " " << iRepl[3] << " " << iRepl[4]);
07667 }
07668 break;
07669 }
07671 isOk = false;
07672 SMDS_VolumeTool hexa (elem);
07673 hexa.SetExternalNormal();
07674 if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
07676 for ( int iFace = 0; iFace < 6; iFace++ ) {
07677 const int *ind = hexa.GetFaceNodesIndices( iFace );
07678 if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
07679 curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
07680 curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
07681
07682 int iOppFace = hexa.GetOppFaceIndex( iFace );
07683 ind = hexa.GetFaceNodesIndices( iOppFace );
07684 int nbStick = 0;
07685 for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
07686 if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
07687 nbStick++;
07688 }
07689 if ( nbStick == 1 ) {
07690
07691
07692 ind = hexa.GetFaceNodesIndices( iFace );
07693 uniqueNodes[ 3 ] = curNodes[ind[ 0 ]];
07694 isOk = true;
07695 }
07696 break;
07697 }
07698 }
07699 }
07700 else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
07702 int nbTria = 0, iTria[3];
07703 const int *ind;
07704
07705 for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
07706 ind = hexa.GetFaceNodesIndices( iFace );
07707 TIDSortedNodeSet faceNodes;
07708 for ( iCur = 0; iCur < 4; iCur++ )
07709 faceNodes.insert( curNodes[ind[iCur]] );
07710 if ( faceNodes.size() == 3 )
07711 iTria[ nbTria++ ] = iFace;
07712 }
07713
07714 if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
07715 {
07716 isOk = true;
07717
07718 ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
07719 vector<int> indB;
07720 for ( iCur = 0; iCur < 4; iCur++ )
07721 if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
07722 indB.push_back( ind[iCur] );
07723 if ( !hexa.IsForward() )
07724 std::swap( indB[0], indB[2] );
07725 for ( iCur = 0; iCur < 3; iCur++ )
07726 uniqueNodes[ iCur ] = curNodes[indB[iCur]];
07727
07728 const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
07729 for ( iCur = 0; iCur < 3; ++iCur )
07730 for ( int j = 0; j < 4; ++j )
07731 if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
07732 {
07733 uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
07734 break;
07735 }
07736 }
07737 break;
07738 }
07739 else if (nbUniqueNodes == 5 && nbRepl == 4 ) {
07741 for ( int iFace = 0; iFace < 6; iFace++ ) {
07742 const int *ind = hexa.GetFaceNodesIndices( iFace );
07743 if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
07744 curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
07745 curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
07746
07747 int iOppFace = hexa.GetOppFaceIndex( iFace );
07748 ind = hexa.GetFaceNodesIndices( iOppFace );
07749 int nbStick = 0;
07750 iUnique = 2;
07751 for ( iCur = 0; iCur < 4 && nbStick == 0; iCur++ ) {
07752 if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
07753 nbStick++;
07754 else if ( iUnique >= 0 )
07755 uniqueNodes[ iUnique-- ] = curNodes[ind[ iCur ]];
07756 }
07757 if ( nbStick == 0 ) {
07758
07759
07760 const int* indTop = hexa.GetFaceNodesIndices( iFace );
07761 uniqueNodes[ 3 ] = curNodes[indTop[ 0 ]];
07762 nbUniqueNodes = 4;
07763
07764 SMDS_MeshElement* newElem =
07765 aMesh->AddVolume(curNodes[ind[ 0 ]],
07766 curNodes[ind[ 3 ]],
07767 curNodes[ind[ 2 ]],
07768 curNodes[indTop[ 0 ]]);
07769 myLastCreatedElems.Append(newElem);
07770 if ( aShapeId )
07771 aMesh->SetMeshElementOnShape( newElem, aShapeId );
07772 isOk = true;
07773 }
07774 break;
07775 }
07776 }
07777 }
07778 else if ( nbUniqueNodes == 6 && nbRepl == 4 ) {
07780
07781 int iQuadFace[ 6 ], iTriFace[ 6 ], nbQuad = 0, nbTri = 0, iFace;
07782 for ( iFace = 0; iFace < 6; iFace++ ) {
07783 const int *ind = hexa.GetFaceNodesIndices( iFace );
07784 nodeSet.clear();
07785 for ( iCur = 0; iCur < 4; iCur++ )
07786 nodeSet.insert( curNodes[ind[ iCur ]] );
07787 nbUniqueNodes = nodeSet.size();
07788 if ( nbUniqueNodes == 3 )
07789 iTriFace[ nbTri++ ] = iFace;
07790 else if ( nbUniqueNodes == 4 )
07791 iQuadFace[ nbQuad++ ] = iFace;
07792 }
07793 if (nbQuad == 2 && nbTri == 4 &&
07794 hexa.GetOppFaceIndex( iQuadFace[ 0 ] ) == iQuadFace[ 1 ]) {
07795
07796
07797
07798 const int *ind1 = hexa.GetFaceNodesIndices( iQuadFace[ 0 ]);
07799 const int *ind2 = hexa.GetFaceNodesIndices( iQuadFace[ 1 ]);
07800 int i0, i1d, i2, i3d, i0t, i2t;
07801 if (curNodes[ind1[ 0 ]] == curNodes[ind2[ 0 ]] &&
07802 curNodes[ind1[ 2 ]] == curNodes[ind2[ 2 ]]) {
07803
07804 i0 = ind1[ 3 ];
07805 i1d = ind1[ 0 ];
07806 i2 = ind1[ 1 ];
07807 i3d = ind1[ 2 ];
07808 i0t = ind2[ 1 ];
07809 i2t = ind2[ 3 ];
07810 }
07811 else if (curNodes[ind1[ 1 ]] == curNodes[ind2[ 3 ]] &&
07812 curNodes[ind1[ 3 ]] == curNodes[ind2[ 1 ]]) {
07813
07814 i0 = ind1[ 0 ];
07815 i1d = ind1[ 1 ];
07816 i2 = ind1[ 2 ];
07817 i3d = ind1[ 3 ];
07818 i0t = ind2[ 0 ];
07819 i2t = ind2[ 1 ];
07820 }
07821 else {
07822 ASSERT(0);
07823 }
07824
07825 uniqueNodes[ 0 ] = curNodes [ i0 ];
07826 uniqueNodes[ 1 ] = curNodes [ i1d ];
07827 uniqueNodes[ 2 ] = curNodes [ i3d ];
07828 uniqueNodes[ 3 ] = curNodes [ i0t ];
07829 nbUniqueNodes = 4;
07830
07831 SMDS_MeshElement* newElem = aMesh->AddVolume(curNodes[ i1d ],
07832 curNodes[ i2 ],
07833 curNodes[ i3d ],
07834 curNodes[ i2t ]);
07835 myLastCreatedElems.Append(newElem);
07836 if ( aShapeId )
07837 aMesh->SetMeshElementOnShape( newElem, aShapeId );
07838 isOk = true;
07839 }
07840 else if (( nbTri == 2 && nbQuad == 3 ) ||
07841 ( nbTri == 4 && nbQuad == 2 )) {
07842
07843
07844 nbUniqueNodes = 6;
07845 for ( iFace = 0; iFace + 1 < nbTri; iFace++ ) {
07846 if ( hexa.GetOppFaceIndex( iTriFace[ iFace ] ) == iTriFace[ iFace + 1 ]) {
07847
07848
07849 const int *ind1 = hexa.GetFaceNodesIndices( iTriFace[ iFace ]);
07850 const int *ind2 = hexa.GetFaceNodesIndices( iTriFace[ iFace + 1 ]);
07851 const SMDS_MeshNode** hexanodes = hexa.GetNodes();
07852
07853 iUnique = 0;
07854 isOk = true;
07855 for ( iCur = 0; iCur < 4 && isOk; iCur++ ) {
07856 const SMDS_MeshNode* n = curNodes[ind1[ iCur ]];
07857 const SMDS_MeshNode* nInit = hexanodes[ind1[ iCur ]];
07858 if ( n == nInit ) {
07859
07860 int iCurOpp = ( iCur == 1 || iCur == 3 ) ? 4 - iCur : iCur;
07861
07862 if ( !hexa.IsLinked( ind1[ iCur ], ind2[ iCurOpp ] ))
07863 isOk = false;
07864 else {
07865 uniqueNodes[ iUnique ] = n;
07866 uniqueNodes[ iUnique + 3 ] = curNodes[ind2[ iCurOpp ]];
07867 iUnique++;
07868 }
07869 }
07870 }
07871 break;
07872 }
07873 }
07874 }
07875 }
07876 else
07877 {
07878 MESSAGE("MergeNodes() removes hexahedron "<< elem);
07879 }
07880 break;
07881 }
07882
07883 default:
07884 isOk = false;
07885 }
07886
07887 }
07888
07889 if ( isOk ) {
07890 if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume)
07891 {
07892
07893 const SMDS_VtkVolume* aPolyedre =
07894 dynamic_cast<const SMDS_VtkVolume*>( elem );
07895 if (aPolyedre) {
07896 int nbFaces = aPolyedre->NbFaces();
07897
07898 vector<const SMDS_MeshNode *> poly_nodes;
07899 vector<int> quantities (nbFaces);
07900
07901 for (int iface = 1; iface <= nbFaces; iface++) {
07902 int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
07903 quantities[iface - 1] = nbFaceNodes;
07904
07905 for (inode = 1; inode <= nbFaceNodes; inode++) {
07906 const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
07907
07908 TNodeNodeMap::iterator nnIt = nodeNodeMap.find( curNode );
07909 if (nnIt != nodeNodeMap.end()) {
07910 curNode = (*nnIt).second;
07911 }
07912 poly_nodes.push_back(curNode);
07913 }
07914 }
07915 aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
07916 }
07917 }
07918 else
07919 {
07920 const SMDSAbs_ElementType etyp = elem->GetType();
07921 const int elemId = elem->GetID();
07922 const bool isPoly = (elem->GetEntityType() == SMDSEntity_Polygon);
07923 uniqueNodes.resize(nbUniqueNodes);
07924
07925 SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
07926
07927 aMesh->RemoveFreeElement(elem, sm, false);
07928 SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId);
07929 if ( sm && newElem )
07930 sm->AddElement( newElem );
07931 if ( elem != newElem )
07932 ReplaceElemInGroups( elem, newElem, aMesh );
07933 }
07934 }
07935 else {
07936
07937 rmElemIds.push_back( elem->GetID() );
07938 }
07939
07940 }
07941
07942
07943
07944 Remove( rmElemIds, false );
07945 Remove( rmNodeIds, true );
07946
07947 }
07948
07949
07950
07951
07952
07953
07954 class SortableElement : public set <const SMDS_MeshElement*>
07955 {
07956 public:
07957
07958 SortableElement( const SMDS_MeshElement* theElem )
07959 {
07960 myElem = theElem;
07961 SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
07962 while ( nodeIt->more() )
07963 this->insert( nodeIt->next() );
07964 }
07965
07966 const SMDS_MeshElement* Get() const
07967 { return myElem; }
07968
07969 void Set(const SMDS_MeshElement* e) const
07970 { myElem = e; }
07971
07972
07973 private:
07974 mutable const SMDS_MeshElement* myElem;
07975 };
07976
07977
07978
07979
07980
07981
07982 void SMESH_MeshEditor::FindEqualElements(set<const SMDS_MeshElement*> & theElements,
07983 TListOfListOfElementsID & theGroupsOfElementsID)
07984 {
07985 myLastCreatedElems.Clear();
07986 myLastCreatedNodes.Clear();
07987
07988 typedef set<const SMDS_MeshElement*> TElemsSet;
07989 typedef map< SortableElement, int > TMapOfNodeSet;
07990 typedef list<int> TGroupOfElems;
07991
07992 TElemsSet elems;
07993 if ( theElements.empty() )
07994 {
07995 SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
07996 while ( eIt->more() )
07997 elems.insert( elems.end(), eIt->next());
07998 }
07999 else
08000 elems = theElements;
08001
08002 vector< TGroupOfElems > arrayOfGroups;
08003 TGroupOfElems groupOfElems;
08004 TMapOfNodeSet mapOfNodeSet;
08005
08006 TElemsSet::iterator elemIt = elems.begin();
08007 for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) {
08008 const SMDS_MeshElement* curElem = *elemIt;
08009 SortableElement SE(curElem);
08010 int ind = -1;
08011
08012 pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
08013 if( !(pp.second) ) {
08014 TMapOfNodeSet::iterator& itSE = pp.first;
08015 ind = (*itSE).second;
08016 arrayOfGroups[ind].push_back(curElem->GetID());
08017 }
08018 else {
08019 groupOfElems.clear();
08020 groupOfElems.push_back(curElem->GetID());
08021 arrayOfGroups.push_back(groupOfElems);
08022 i++;
08023 }
08024 }
08025
08026 vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
08027 for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) {
08028 groupOfElems = *groupIt;
08029 if ( groupOfElems.size() > 1 ) {
08030 groupOfElems.sort();
08031 theGroupsOfElementsID.push_back(groupOfElems);
08032 }
08033 }
08034 }
08035
08036
08037
08038
08039
08040
08041 void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElementsID)
08042 {
08043 myLastCreatedElems.Clear();
08044 myLastCreatedNodes.Clear();
08045
08046 typedef list<int> TListOfIDs;
08047 TListOfIDs rmElemIds;
08048
08049 SMESHDS_Mesh* aMesh = GetMeshDS();
08050
08051 TListOfListOfElementsID::iterator groupsIt = theGroupsOfElementsID.begin();
08052 while ( groupsIt != theGroupsOfElementsID.end() ) {
08053 TListOfIDs& aGroupOfElemID = *groupsIt;
08054 aGroupOfElemID.sort();
08055 int elemIDToKeep = aGroupOfElemID.front();
08056 const SMDS_MeshElement* elemToKeep = aMesh->FindElement(elemIDToKeep);
08057 aGroupOfElemID.pop_front();
08058 TListOfIDs::iterator idIt = aGroupOfElemID.begin();
08059 while ( idIt != aGroupOfElemID.end() ) {
08060 int elemIDToRemove = *idIt;
08061 const SMDS_MeshElement* elemToRemove = aMesh->FindElement(elemIDToRemove);
08062
08063 AddToSameGroups( elemToKeep, elemToRemove, aMesh );
08064 rmElemIds.push_back( elemIDToRemove );
08065 ++idIt;
08066 }
08067 ++groupsIt;
08068 }
08069
08070 Remove( rmElemIds, false );
08071 }
08072
08073
08074
08075
08076
08077
08078 void SMESH_MeshEditor::MergeEqualElements()
08079 {
08080 set<const SMDS_MeshElement*> aMeshElements;
08081
08082 TListOfListOfElementsID aGroupsOfElementsID;
08083 FindEqualElements(aMeshElements, aGroupsOfElementsID);
08084 MergeElements(aGroupsOfElementsID);
08085 }
08086
08087
08088
08089
08090
08091
08092
08093
08094
08095 const SMDS_MeshElement*
08096 SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1,
08097 const SMDS_MeshNode* n2,
08098 const TIDSortedElemSet& elemSet,
08099 const TIDSortedElemSet& avoidSet,
08100 int* n1ind,
08101 int* n2ind)
08102
08103 {
08104 int i1, i2;
08105 const SMDS_MeshElement* face = 0;
08106
08107 SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face);
08108
08109 while ( invElemIt->more() && !face )
08110 {
08111
08112 const SMDS_MeshElement* elem = invElemIt->next();
08113 if (avoidSet.count( elem ))
08114 continue;
08115 if ( !elemSet.empty() && !elemSet.count( elem ))
08116 continue;
08117
08118 i1 = elem->GetNodeIndex( n1 );
08119
08120 int nbN = elem->IsQuadratic() ? elem->NbNodes()/2 : elem->NbNodes();
08121 for ( int di = -1; di < 2 && !face; di += 2 )
08122 {
08123 i2 = (i1+di+nbN) % nbN;
08124 if ( elem->GetNode( i2 ) == n2 )
08125 face = elem;
08126 }
08127 if ( !face && elem->IsQuadratic())
08128 {
08129
08130 const SMDS_VtkFace* F =
08131 dynamic_cast<const SMDS_VtkFace*>(elem);
08132 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
08133
08134 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
08135 const SMDS_MeshNode* prevN = cast2Node( anIter->next() );
08136 for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ )
08137 {
08138 const SMDS_MeshNode* n = cast2Node( anIter->next() );
08139 if ( n1 == prevN && n2 == n )
08140 {
08141 face = elem;
08142 }
08143 else if ( n2 == prevN && n1 == n )
08144 {
08145 face = elem; swap( i1, i2 );
08146 }
08147 prevN = n;
08148 }
08149 }
08150 }
08151 if ( n1ind ) *n1ind = i1;
08152 if ( n2ind ) *n2ind = i2;
08153 return face;
08154 }
08155
08156
08157
08158
08159
08160
08161 static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1,
08162 const SMDS_MeshNode* n2,
08163 const SMDS_MeshElement* elem)
08164 {
08165 TIDSortedElemSet elemSet, avoidSet;
08166 if ( elem )
08167 avoidSet.insert ( elem );
08168 return SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet );
08169 }
08170
08171
08172
08173
08174
08175
08176 #define ControlFreeBorder SMESH::Controls::FreeEdges::IsFreeEdge
08177
08178 bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirstNode,
08179 const SMDS_MeshNode* theSecondNode,
08180 const SMDS_MeshNode* theLastNode,
08181 list< const SMDS_MeshNode* > & theNodes,
08182 list< const SMDS_MeshElement* >& theFaces)
08183 {
08184 if ( !theFirstNode || !theSecondNode )
08185 return false;
08186
08187 const SMDS_MeshElement* curElem = findAdjacentFace( theFirstNode, theSecondNode, 0 );
08188 if ( !curElem )
08189 return false;
08190
08191 theFaces.push_back( curElem );
08192 theNodes.push_back( theFirstNode );
08193 theNodes.push_back( theSecondNode );
08194
08195
08196 const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
08197 TIDSortedElemSet foundElems;
08198 bool needTheLast = ( theLastNode != 0 );
08199
08200 while ( nStart != theLastNode ) {
08201 if ( nStart == theFirstNode )
08202 return !needTheLast;
08203
08204
08205
08206 list< const SMDS_MeshElement* > curElemList;
08207 list< const SMDS_MeshNode* > nStartList;
08208 SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
08209 while ( invElemIt->more() ) {
08210 const SMDS_MeshElement* e = invElemIt->next();
08211 if ( e == curElem || foundElems.insert( e ).second ) {
08212
08213 int iNode = 0, nbNodes = e->NbNodes();
08214
08215 vector<const SMDS_MeshNode*> nodes(nbNodes+1);
08216
08217 if(e->IsQuadratic()) {
08218 const SMDS_VtkFace* F =
08219 dynamic_cast<const SMDS_VtkFace*>(e);
08220 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
08221
08222 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
08223 while( anIter->more() ) {
08224 nodes[ iNode++ ] = cast2Node(anIter->next());
08225 }
08226 }
08227 else {
08228 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
08229 while ( nIt->more() )
08230 nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
08231 }
08232 nodes[ iNode ] = nodes[ 0 ];
08233
08234 for ( iNode = 0; iNode < nbNodes; iNode++ )
08235 if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
08236 (nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
08237 ControlFreeBorder( &nodes[ iNode ], e->GetID() ))
08238 {
08239 nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart ? 1 : 0 )]);
08240 curElemList.push_back( e );
08241 }
08242 }
08243 }
08244
08245
08246 int nbNewBorders = curElemList.size();
08247 if ( nbNewBorders == 0 ) {
08248
08249 return !needTheLast;
08250 }
08251 else if ( nbNewBorders == 1 ) {
08252
08253 nIgnore = nStart;
08254 nStart = nStartList.front();
08255 curElem = curElemList.front();
08256 theFaces.push_back( curElem );
08257 theNodes.push_back( nStart );
08258 }
08259 else {
08260
08261 list< const SMDS_MeshElement* >::iterator curElemIt;
08262 list< const SMDS_MeshNode* >::iterator nStartIt;
08263
08264 if ( needTheLast ) {
08265 for (curElemIt = curElemList.begin(), nStartIt = nStartList.begin();
08266 curElemIt!= curElemList.end();
08267 curElemIt++, nStartIt++ )
08268 if ( *nStartIt == theLastNode ) {
08269 theFaces.push_back( *curElemIt );
08270 theNodes.push_back( *nStartIt );
08271 return true;
08272 }
08273 }
08274
08275 list<const SMDS_MeshNode*> contNodes[ 2 ], *cNL;
08276 list<const SMDS_MeshElement*> contFaces[ 2 ], *cFL;
08277 for (curElemIt = curElemList.begin(), nStartIt = nStartList.begin();
08278 curElemIt!= curElemList.end();
08279 curElemIt++, nStartIt++ )
08280 {
08281 cNL = & contNodes[ contNodes[0].empty() ? 0 : 1 ];
08282 cFL = & contFaces[ contFaces[0].empty() ? 0 : 1 ];
08283
08284 if ( ! FindFreeBorder( nStart, *nStartIt, theLastNode, *cNL, *cFL )) {
08285 cNL->clear();
08286 cFL->clear();
08287 }
08288 else if ( !contNodes[0].empty() && !contNodes[1].empty() ) {
08289
08290 int iLongest = ( contNodes[0].size() < contNodes[1].size() ? 1 : 0 );
08291 int iWorse = ( needTheLast ? 1 - iLongest : iLongest );
08292 contNodes[ iWorse ].clear();
08293 contFaces[ iWorse ].clear();
08294 }
08295 }
08296 if ( contNodes[0].empty() && contNodes[1].empty() )
08297 return false;
08298
08299
08300 cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
08301 cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
08302 theNodes.pop_back();
08303 theNodes.pop_back();
08304 theFaces.pop_back();
08305 list< const SMDS_MeshNode* >::iterator nIt = cNL->begin();
08306 list< const SMDS_MeshElement* >::iterator fIt = cFL->begin();
08307 for ( ; nIt != cNL->end(); nIt++ ) theNodes.push_back( *nIt );
08308 for ( ; fIt != cFL->end(); fIt++ ) theFaces.push_back( *fIt );
08309 return true;
08310
08311 }
08312 }
08313
08314 return true;
08315 }
08316
08317
08318
08319
08320
08321
08322 bool SMESH_MeshEditor::CheckFreeBorderNodes(const SMDS_MeshNode* theNode1,
08323 const SMDS_MeshNode* theNode2,
08324 const SMDS_MeshNode* theNode3)
08325 {
08326 list< const SMDS_MeshNode* > nodes;
08327 list< const SMDS_MeshElement* > faces;
08328 return FindFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
08329 }
08330
08331
08332
08333
08334
08335
08336 SMESH_MeshEditor::Sew_Error
08337 SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
08338 const SMDS_MeshNode* theBordSecondNode,
08339 const SMDS_MeshNode* theBordLastNode,
08340 const SMDS_MeshNode* theSideFirstNode,
08341 const SMDS_MeshNode* theSideSecondNode,
08342 const SMDS_MeshNode* theSideThirdNode,
08343 const bool theSideIsFreeBorder,
08344 const bool toCreatePolygons,
08345 const bool toCreatePolyedrs)
08346 {
08347 myLastCreatedElems.Clear();
08348 myLastCreatedNodes.Clear();
08349
08350 MESSAGE("::SewFreeBorder()");
08351 Sew_Error aResult = SEW_OK;
08352
08353
08354
08355
08356
08357 list< const SMDS_MeshNode* > nSide[ 2 ];
08358 list< const SMDS_MeshElement* > eSide[ 2 ];
08359 list< const SMDS_MeshNode* >::iterator nIt[ 2 ];
08360 list< const SMDS_MeshElement* >::iterator eIt[ 2 ];
08361
08362
08363
08364 if (!FindFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
08365 nSide[0], eSide[0])) {
08366 MESSAGE(" Free Border 1 not found " );
08367 aResult = SEW_BORDER1_NOT_FOUND;
08368 }
08369 if (theSideIsFreeBorder) {
08370
08371
08372 if (!FindFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
08373 nSide[1], eSide[1])) {
08374 MESSAGE(" Free Border 2 not found " );
08375 aResult = ( aResult != SEW_OK ? SEW_BOTH_BORDERS_NOT_FOUND : SEW_BORDER2_NOT_FOUND );
08376 }
08377 }
08378 if ( aResult != SEW_OK )
08379 return aResult;
08380
08381 if (!theSideIsFreeBorder) {
08382
08383
08384
08385
08386
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396 typedef map<const SMDS_MeshNode*, gp_XYZ> TNodeXYZMap;
08397 TNodeXYZMap nBordXYZ;
08398 list< const SMDS_MeshNode* >& bordNodes = nSide[ 0 ];
08399 list< const SMDS_MeshNode* >::iterator nBordIt;
08400
08401 gp_XYZ Pb1( theBordFirstNode->X(), theBordFirstNode->Y(), theBordFirstNode->Z() );
08402 gp_XYZ Pb2( theBordLastNode->X(), theBordLastNode->Y(), theBordLastNode->Z() );
08403 gp_XYZ Ps1( theSideFirstNode->X(), theSideFirstNode->Y(), theSideFirstNode->Z() );
08404 gp_XYZ Ps2( theSideSecondNode->X(), theSideSecondNode->Y(), theSideSecondNode->Z() );
08405 double tol2 = 1.e-8;
08406 gp_Vec Vbs1( Pb1 - Ps1 ),Vbs2( Pb2 - Ps2 );
08407 if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 ) {
08408
08409
08410
08411 gp_Vec Zb( Pb1 - Pb2 ), Zs( Ps1 - Ps2 );
08412 gp_Vec X = Zs ^ Zb;
08413 if ( X.SquareMagnitude() <= gp::Resolution() * gp::Resolution() )
08414
08415 X = gp_Ax2( gp::Origin(), Zb ).XDirection();
08416
08417
08418 gp_Ax3 toBordAx( Pb1, Zb, X );
08419 gp_Ax3 fromSideAx( Ps1, Zs, X );
08420 gp_Ax3 toGlobalAx( gp::Origin(), gp::DZ(), gp::DX() );
08421
08422 gp_Trsf toBordSys, fromSide2Sys;
08423 toBordSys.SetTransformation( toBordAx );
08424 fromSide2Sys.SetTransformation( fromSideAx, toGlobalAx );
08425 fromSide2Sys.SetScaleFactor( Zs.Magnitude() / Zb.Magnitude() );
08426
08427
08428 for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
08429 const SMDS_MeshNode* n = *nBordIt;
08430 gp_XYZ xyz( n->X(),n->Y(),n->Z() );
08431 toBordSys.Transforms( xyz );
08432 fromSide2Sys.Transforms( xyz );
08433 nBordXYZ.insert( TNodeXYZMap::value_type( n, xyz ));
08434 }
08435 }
08436 else {
08437
08438 for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
08439 const SMDS_MeshNode* n = *nBordIt;
08440 nBordXYZ.insert( TNodeXYZMap::value_type( n, gp_XYZ( n->X(),n->Y(),n->Z() )));
08441 }
08442 }
08443
08444
08445
08446
08447 list< const SMDS_MeshElement* >& sideElems = eSide[ 1 ];
08448 list< const SMDS_MeshNode* >& sideNodes = nSide[ 1 ];
08449 sideNodes.push_back( theSideFirstNode );
08450
08451 bool hasVolumes = false;
08452 LinkID_Gen aLinkID_Gen( GetMeshDS() );
08453 set<long> foundSideLinkIDs, checkedLinkIDs;
08454 SMDS_VolumeTool volume;
08455
08456
08457 const SMDS_MeshNode* sideNode;
08458 const SMDS_MeshElement* sideElem;
08459 const SMDS_MeshNode* prevSideNode = theSideFirstNode;
08460 const SMDS_MeshNode* prevBordNode = theBordFirstNode;
08461 nBordIt = bordNodes.begin();
08462 nBordIt++;
08463
08464 gp_XYZ bordPos = nBordXYZ[ *nBordIt ];
08465 gp_XYZ bordDir = bordPos - nBordXYZ[ prevBordNode ];
08466
08467
08468 bool searchByDir = ( *nBordIt != theBordLastNode );
08469 do {
08470
08471 sideNode = 0;
08472 double maxDot = -DBL_MAX, minDist = DBL_MAX;
08473 long linkID;
08474 checkedLinkIDs.clear();
08475 gp_XYZ prevXYZ( prevSideNode->X(), prevSideNode->Y(), prevSideNode->Z() );
08476
08477
08478 SMDS_ElemIteratorPtr invElemIt = prevSideNode->GetInverseElementIterator();
08479 while ( invElemIt->more() )
08480 {
08481 const SMDS_MeshElement* elem = invElemIt->next();
08482
08483 int iPrevNode, iNode = 0, nbNodes = elem->NbNodes();
08484 vector< const SMDS_MeshNode* > faceNodes( nbNodes, (const SMDS_MeshNode*)0 );
08485 bool isVolume = volume.Set( elem );
08486 const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0];
08487 if ( isVolume )
08488 hasVolumes = true;
08489 else if ( elem->GetType()==SMDSAbs_Face ) {
08490
08491 if(elem->IsQuadratic()) {
08492 const SMDS_VtkFace* F =
08493 dynamic_cast<const SMDS_VtkFace*>(elem);
08494 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
08495
08496 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
08497 while( anIter->more() ) {
08498 nodes[ iNode ] = cast2Node(anIter->next());
08499 if ( nodes[ iNode++ ] == prevSideNode )
08500 iPrevNode = iNode - 1;
08501 }
08502 }
08503 else {
08504 SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
08505 while ( nIt->more() ) {
08506 nodes[ iNode ] = cast2Node( nIt->next() );
08507 if ( nodes[ iNode++ ] == prevSideNode )
08508 iPrevNode = iNode - 1;
08509 }
08510 }
08511
08512 nbNodes = 2;
08513 }
08514 else
08515 continue;
08516
08517 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
08518 const SMDS_MeshNode* n = nodes[ iNode ];
08519 if ( isVolume ) {
08520 if ( !volume.IsLinked( n, prevSideNode ))
08521 continue;
08522 }
08523 else {
08524 if ( iNode )
08525 n = nodes[ iPrevNode == 0 ? elem->NbNodes() - 1 : iPrevNode - 1 ];
08526 else
08527 n = nodes[ iPrevNode + 1 == elem->NbNodes() ? 0 : iPrevNode + 1 ];
08528 }
08529
08530 long iLink = aLinkID_Gen.GetLinkID( prevSideNode, n );
08531 bool isJustChecked = !checkedLinkIDs.insert( iLink ).second;
08532 if (!isJustChecked &&
08533 foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() )
08534 {
08535
08536 gp_XYZ nextXYZ ( n->X(), n->Y(), n->Z() );
08537 bool linkIsBetter = false;
08538 double dot = 0.0, dist = 0.0;
08539 if ( searchByDir ) {
08540 dot = bordDir * ( nextXYZ - prevXYZ ).Normalized();
08541 linkIsBetter = ( dot > maxDot );
08542 }
08543 else {
08544 dist = ( nextXYZ - bordPos ).SquareModulus();
08545 linkIsBetter = ( dist < minDist );
08546 }
08547 if ( linkIsBetter ) {
08548 maxDot = dot;
08549 minDist = dist;
08550 linkID = iLink;
08551 sideNode = n;
08552 sideElem = elem;
08553 }
08554 }
08555 }
08556 }
08557
08558 if ( !sideNode ) {
08559 MESSAGE(" Cant find path by links of the Side 2 ");
08560 return SEW_BAD_SIDE_NODES;
08561 }
08562 sideNodes.push_back( sideNode );
08563 sideElems.push_back( sideElem );
08564 foundSideLinkIDs.insert ( linkID );
08565 prevSideNode = sideNode;
08566
08567 if ( *nBordIt == theBordLastNode )
08568 searchByDir = false;
08569 else {
08570
08571 gp_XYZ sidePos( sideNode->X(), sideNode->Y(), sideNode->Z() );
08572 searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
08573
08574 while ( *nBordIt != theBordLastNode && !searchByDir ) {
08575 prevBordNode = *nBordIt;
08576 nBordIt++;
08577 bordPos = nBordXYZ[ *nBordIt ];
08578 bordDir = bordPos - nBordXYZ[ prevBordNode ];
08579 searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
08580 }
08581 }
08582 }
08583 while ( sideNode != theSideSecondNode );
08584
08585 if ( hasVolumes && sideNodes.size () != bordNodes.size() && !toCreatePolyedrs) {
08586 MESSAGE("VOLUME SPLITTING IS FORBIDDEN");
08587 return SEW_VOLUMES_TO_SPLIT;
08588 }
08589 }
08590
08591
08592
08593
08594
08595 int nbNodes[] = { nSide[0].size(), nSide[1].size() };
08596 int maxNbNodes = Max( nbNodes[0], nbNodes[1] );
08597
08598 TListOfListOfNodes nodeGroupsToMerge;
08599 if ( nbNodes[0] == nbNodes[1] ||
08600 ( theSideIsFreeBorder && !theSideThirdNode)) {
08601
08602
08603
08604 for (nIt[0] = nSide[0].begin(), nIt[1] = nSide[1].begin();
08605 nIt[0] != nSide[0].end() && nIt[1] != nSide[1].end();
08606 nIt[0]++, nIt[1]++ )
08607 {
08608 nodeGroupsToMerge.push_back( list<const SMDS_MeshNode*>() );
08609 nodeGroupsToMerge.back().push_back( *nIt[1] );
08610 nodeGroupsToMerge.back().push_back( *nIt[0] );
08611 }
08612 }
08613 else {
08614
08615
08616
08617
08618
08619 double* param[ 2 ];
08620 param[0] = new double [ maxNbNodes ];
08621 param[1] = new double [ maxNbNodes ];
08622 int iNode, iBord;
08623 for ( iBord = 0; iBord < 2; iBord++ ) {
08624 list< const SMDS_MeshNode* >& nodes = nSide[ iBord ];
08625 list< const SMDS_MeshNode* >::iterator nIt = nodes.begin();
08626 const SMDS_MeshNode* nPrev = *nIt;
08627 double bordLength = 0;
08628 for ( iNode = 0; nIt != nodes.end(); nIt++, iNode++ ) {
08629 const SMDS_MeshNode* nCur = *nIt;
08630 gp_XYZ segment (nCur->X() - nPrev->X(),
08631 nCur->Y() - nPrev->Y(),
08632 nCur->Z() - nPrev->Z());
08633 double segmentLen = segment.Modulus();
08634 bordLength += segmentLen;
08635 param[ iBord ][ iNode ] = bordLength;
08636 nPrev = nCur;
08637 }
08638
08639 for ( iNode = 0; iNode < nbNodes[ iBord ]; iNode++ ) {
08640 param[ iBord ][ iNode ] /= bordLength;
08641 }
08642 }
08643
08644
08645 const SMDS_MeshNode *nPrev[ 2 ] = { 0, 0 };
08646 int i[ 2 ] = { 0, 0 };
08647 nIt[0] = nSide[0].begin(); eIt[0] = eSide[0].begin();
08648 nIt[1] = nSide[1].begin(); eIt[1] = eSide[1].begin();
08649
08650 TElemOfNodeListMap insertMap;
08651 TElemOfNodeListMap::iterator insertMapIt;
08652
08653
08654
08655 do {
08656 bool next[ 2 ] = { false, false };
08657
08658
08659 double nextParam = 10., prevParam = 0;
08660 for ( iBord = 0; iBord < 2; iBord++ ) {
08661 if ( i[ iBord ] + 1 < nbNodes[ iBord ])
08662 nextParam = Min( nextParam, param[iBord][ i[iBord] + 1 ]);
08663 if ( i[ iBord ] > 0 )
08664 prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]);
08665 }
08666 double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
08667 double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
08668 double minSegLen = Min( nextParam - minParam, maxParam - prevParam );
08669
08670
08671 double du = param[ 1 ][ i[1] ] - param[ 0 ][ i[0] ];
08672 if ( Abs( du ) <= minSegLen * 0.2 ) {
08673
08674
08675 nodeGroupsToMerge.push_back( list<const SMDS_MeshNode*>() );
08676 const SMDS_MeshNode* n0 = *nIt[0];
08677 const SMDS_MeshNode* n1 = *nIt[1];
08678 nodeGroupsToMerge.back().push_back( n1 );
08679 nodeGroupsToMerge.back().push_back( n0 );
08680
08681 param[ 0 ][ i[0] ] += du;
08682
08683
08684 const_cast<SMDS_MeshNode*>( n0 )->setXYZ( n1->X(), n1->Y(), n1->Z() );
08685 next[0] = next[1] = true;
08686 }
08687 else {
08688
08689
08690 int intoBord = ( du < 0 ) ? 0 : 1;
08691 const SMDS_MeshElement* elem = *eIt[ intoBord ];
08692 const SMDS_MeshNode* n1 = nPrev[ intoBord ];
08693 const SMDS_MeshNode* n2 = *nIt[ intoBord ];
08694 const SMDS_MeshNode* nIns = *nIt[ 1 - intoBord ];
08695 if ( intoBord == 1 ) {
08696
08697 gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
08698 gp_XYZ p2 (n2->X(), n2->Y(), n2->Z());
08699 double ratio = du / ( param[ 1 ][ i[1] ] - param[ 1 ][ i[1]-1 ]);
08700 gp_XYZ p = p2 * ( 1 - ratio ) + p1 * ratio;
08701 GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
08702 }
08703 insertMapIt = insertMap.find( elem );
08704 bool notFound = ( insertMapIt == insertMap.end() );
08705 bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
08706 if ( otherLink ) {
08707
08708
08709 list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
08710 const SMDS_MeshNode* n12 = nodeList.front(); nodeList.pop_front();
08711 const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front();
08712 InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons );
08713
08714 while (true) {
08715 const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem );
08716 if ( adjElem )
08717 InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons );
08718 else
08719 break;
08720 }
08721 if (toCreatePolyedrs) {
08722
08723 UpdateVolumes(n12, n22, nodeList);
08724 }
08725
08726 insertMap.erase( elem );
08727 elem = findAdjacentFace( n1, n2, 0 );
08728 }
08729 if ( notFound || otherLink ) {
08730
08731 insertMapIt = insertMap.insert
08732 ( TElemOfNodeListMap::value_type( elem, list<const SMDS_MeshNode*>() )).first;
08733 (*insertMapIt).second.push_back( n1 );
08734 (*insertMapIt).second.push_back( n2 );
08735 }
08736
08737 (*insertMapIt).second.push_back( nIns );
08738 next[ 1 - intoBord ] = true;
08739 }
08740
08741
08742 for ( iBord = 0; iBord < 2; iBord++ ) {
08743 if ( next[ iBord ] ) {
08744 if ( i[ iBord ] != 0 && eIt[ iBord ] != eSide[ iBord ].end())
08745 eIt[ iBord ]++;
08746 nPrev[ iBord ] = *nIt[ iBord ];
08747 nIt[ iBord ]++; i[ iBord ]++;
08748 }
08749 }
08750 }
08751 while ( nIt[0] != nSide[0].end() && nIt[1] != nSide[1].end());
08752
08753
08754
08755 for (insertMapIt = insertMap.begin();
08756 insertMapIt != insertMap.end();
08757 insertMapIt++ )
08758 {
08759 const SMDS_MeshElement* elem = (*insertMapIt).first;
08760 list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
08761 const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front();
08762 const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front();
08763
08764 InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons );
08765
08766 if ( !theSideIsFreeBorder ) {
08767
08768 while (true) {
08769 const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem );
08770 if ( adjElem )
08771 InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
08772 else
08773 break;
08774 }
08775 }
08776 if (toCreatePolyedrs) {
08777
08778 UpdateVolumes(n1, n2, nodeList);
08779 }
08780 }
08781
08782 delete param[0];
08783 delete param[1];
08784 }
08785
08786 MergeNodes ( nodeGroupsToMerge );
08787
08788 return aResult;
08789 }
08790
08791
08792
08793
08794
08795
08796
08797 void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace,
08798 const SMDS_MeshNode* theBetweenNode1,
08799 const SMDS_MeshNode* theBetweenNode2,
08800 list<const SMDS_MeshNode*>& theNodesToInsert,
08801 const bool toCreatePoly)
08802 {
08803 if ( theFace->GetType() != SMDSAbs_Face ) return;
08804
08805
08806 int iNode = 0, il1, il2, i3, i4;
08807 il1 = il2 = i3 = i4 = -1;
08808
08809 vector<const SMDS_MeshNode*> nodes( theFace->NbNodes() );
08810
08811 if(theFace->IsQuadratic()) {
08812 const SMDS_VtkFace* F =
08813 dynamic_cast<const SMDS_VtkFace*>(theFace);
08814 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
08815
08816 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
08817 while( anIter->more() ) {
08818 const SMDS_MeshNode* n = cast2Node(anIter->next());
08819 if ( n == theBetweenNode1 )
08820 il1 = iNode;
08821 else if ( n == theBetweenNode2 )
08822 il2 = iNode;
08823 else if ( i3 < 0 )
08824 i3 = iNode;
08825 else
08826 i4 = iNode;
08827 nodes[ iNode++ ] = n;
08828 }
08829 }
08830 else {
08831 SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
08832 while ( nodeIt->more() ) {
08833 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
08834 if ( n == theBetweenNode1 )
08835 il1 = iNode;
08836 else if ( n == theBetweenNode2 )
08837 il2 = iNode;
08838 else if ( i3 < 0 )
08839 i3 = iNode;
08840 else
08841 i4 = iNode;
08842 nodes[ iNode++ ] = n;
08843 }
08844 }
08845 if ( il1 < 0 || il2 < 0 || i3 < 0 )
08846 return ;
08847
08848
08849 bool reverse = ( Abs( il2 - il1 ) == 1 ? il2 < il1 : il1 < il2 );
08850 list<const SMDS_MeshNode *> aNodesToInsert = theNodesToInsert;
08851 if ( reverse ) {
08852 iNode = il1;
08853 il1 = il2;
08854 il2 = iNode;
08855 aNodesToInsert.reverse();
08856 }
08857
08858 int nbFaceNodes = theFace->NbNodes();
08859 if ( nbFaceNodes == 4 && i4 - i3 != 1 ) {
08860 iNode = i3;
08861 i3 = i4;
08862 i4 = iNode;
08863 }
08864
08865 if (toCreatePoly || theFace->IsPoly()) {
08866
08867 iNode = 0;
08868 vector<const SMDS_MeshNode *> poly_nodes (nbFaceNodes + aNodesToInsert.size());
08869
08870
08871 bool isFLN = false;
08872
08873 if(theFace->IsQuadratic()) {
08874 const SMDS_VtkFace* F =
08875 dynamic_cast<const SMDS_VtkFace*>(theFace);
08876 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
08877
08878 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
08879 while( anIter->more() && !isFLN ) {
08880 const SMDS_MeshNode* n = cast2Node(anIter->next());
08881 poly_nodes[iNode++] = n;
08882 if (n == nodes[il1]) {
08883 isFLN = true;
08884 }
08885 }
08886
08887 list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
08888 for (; nIt != aNodesToInsert.end(); nIt++) {
08889 poly_nodes[iNode++] = *nIt;
08890 }
08891
08892 while ( anIter->more() ) {
08893 poly_nodes[iNode++] = cast2Node(anIter->next());
08894 }
08895 }
08896 else {
08897 SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
08898 while ( nodeIt->more() && !isFLN ) {
08899 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
08900 poly_nodes[iNode++] = n;
08901 if (n == nodes[il1]) {
08902 isFLN = true;
08903 }
08904 }
08905
08906 list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
08907 for (; nIt != aNodesToInsert.end(); nIt++) {
08908 poly_nodes[iNode++] = *nIt;
08909 }
08910
08911 while ( nodeIt->more() ) {
08912 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
08913 poly_nodes[iNode++] = n;
08914 }
08915 }
08916
08917
08918 SMESHDS_Mesh *aMesh = GetMeshDS();
08919
08920 if (theFace->IsPoly()) {
08921 aMesh->ChangePolygonNodes(theFace, poly_nodes);
08922 }
08923 else {
08924 int aShapeId = FindShape( theFace );
08925
08926 SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
08927 myLastCreatedElems.Append(newElem);
08928 if ( aShapeId && newElem )
08929 aMesh->SetMeshElementOnShape( newElem, aShapeId );
08930
08931 aMesh->RemoveElement(theFace);
08932 }
08933 return;
08934 }
08935
08936 SMESHDS_Mesh *aMesh = GetMeshDS();
08937 if( !theFace->IsQuadratic() ) {
08938
08939
08940 int nbLinkNodes = 2 + aNodesToInsert.size();
08941
08942 vector<const SMDS_MeshNode*> linkNodes( nbLinkNodes );
08943 linkNodes[ 0 ] = nodes[ il1 ];
08944 linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
08945 list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
08946 for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
08947 linkNodes[ iNode++ ] = *nIt;
08948 }
08949
08950
08951 int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
08952 if ( nbFaceNodes == 3 ) {
08953 iBestQuad = nbSplits;
08954 i4 = i3;
08955 }
08956 else if ( nbFaceNodes == 4 ) {
08957 SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
08958 double aBestRate = DBL_MAX;
08959 for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
08960 i1 = 0; i2 = 1;
08961 double aBadRate = 0;
08962
08963 for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
08964 if ( iSplit == iQuad ) {
08965 SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
08966 linkNodes[ i2++ ],
08967 nodes[ i3 ],
08968 nodes[ i4 ]);
08969 aBadRate += getBadRate( &quad, aCrit );
08970 }
08971 else {
08972 SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
08973 linkNodes[ i2++ ],
08974 nodes[ iSplit < iQuad ? i4 : i3 ]);
08975 aBadRate += getBadRate( &tria, aCrit );
08976 }
08977 }
08978
08979 if ( aBadRate < aBestRate ) {
08980 iBestQuad = iQuad;
08981 aBestRate = aBadRate;
08982 }
08983 }
08984 }
08985
08986
08987 int aShapeId = FindShape( theFace );
08988
08989 i1 = 0; i2 = 1;
08990 for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
08991 SMDS_MeshElement* newElem = 0;
08992 if ( iSplit == iBestQuad )
08993 newElem = aMesh->AddFace (linkNodes[ i1++ ],
08994 linkNodes[ i2++ ],
08995 nodes[ i3 ],
08996 nodes[ i4 ]);
08997 else
08998 newElem = aMesh->AddFace (linkNodes[ i1++ ],
08999 linkNodes[ i2++ ],
09000 nodes[ iSplit < iBestQuad ? i4 : i3 ]);
09001 myLastCreatedElems.Append(newElem);
09002 if ( aShapeId && newElem )
09003 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09004 }
09005
09006
09007 const SMDS_MeshNode* newNodes[ 4 ];
09008 newNodes[ 0 ] = linkNodes[ i1 ];
09009 newNodes[ 1 ] = linkNodes[ i2 ];
09010 newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
09011 newNodes[ 3 ] = nodes[ i4 ];
09012
09013 const SMDS_MeshElement* newElem = 0;
09014 if (iSplit == iBestQuad)
09015 newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
09016 else
09017 newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
09018 myLastCreatedElems.Append(newElem);
09019 if ( aShapeId && newElem )
09020 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09021 }
09022 else {
09023
09024 int tmp = il1/2;
09025 int nbshift = tmp*2;
09026
09027 int i,j;
09028 for(i=0; i<nbshift; i++) {
09029 const SMDS_MeshNode* n = nodes[0];
09030 for(j=0; j<nbFaceNodes-1; j++) {
09031 nodes[j] = nodes[j+1];
09032 }
09033 nodes[nbFaceNodes-1] = n;
09034 }
09035 il1 = il1 - nbshift;
09036
09037
09038
09039
09040
09041
09042
09043
09044
09045
09046
09047
09048 int aShapeId = FindShape( theFace );
09049
09050 int n1,n2,n3;
09051 if(nbFaceNodes==6) {
09052 SMDS_MeshElement* newElem =
09053 aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
09054 myLastCreatedElems.Append(newElem);
09055 if ( aShapeId && newElem )
09056 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09057 if(theFace->IsMediumNode(nodes[il1])) {
09058
09059 newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]);
09060 myLastCreatedElems.Append(newElem);
09061 if ( aShapeId && newElem )
09062 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09063 n1 = 1;
09064 n2 = 2;
09065 n3 = 3;
09066 }
09067 else {
09068
09069 newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]);
09070 myLastCreatedElems.Append(newElem);
09071 if ( aShapeId && newElem )
09072 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09073 n1 = 0;
09074 n2 = 1;
09075 n3 = 5;
09076 }
09077 }
09078 else {
09079 SMDS_MeshElement* newElem =
09080 aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
09081 myLastCreatedElems.Append(newElem);
09082 if ( aShapeId && newElem )
09083 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09084 newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
09085 myLastCreatedElems.Append(newElem);
09086 if ( aShapeId && newElem )
09087 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09088 newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
09089 myLastCreatedElems.Append(newElem);
09090 if ( aShapeId && newElem )
09091 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09092 if(theFace->IsMediumNode(nodes[il1])) {
09093
09094 newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]);
09095 myLastCreatedElems.Append(newElem);
09096 if ( aShapeId && newElem )
09097 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09098 n1 = 1;
09099 n2 = 2;
09100 n3 = 3;
09101 }
09102 else {
09103
09104 newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]);
09105 myLastCreatedElems.Append(newElem);
09106 if ( aShapeId && newElem )
09107 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09108 n1 = 0;
09109 n2 = 1;
09110 n3 = 7;
09111 }
09112 }
09113
09114 int nbn = 2 + aNodesToInsert.size();
09115
09116 vector<const SMDS_MeshNode*> aNodes(nbn);
09117 aNodes[0] = nodes[n1];
09118 aNodes[nbn-1] = nodes[n2];
09119 list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
09120 for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
09121 aNodes[iNode++] = *nIt;
09122 }
09123 for(i=1; i<nbn; i++) {
09124 SMDS_MeshElement* newElem =
09125 aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
09126 myLastCreatedElems.Append(newElem);
09127 if ( aShapeId && newElem )
09128 aMesh->SetMeshElementOnShape( newElem, aShapeId );
09129 }
09130 }
09131
09132 aMesh->RemoveElement(theFace);
09133 }
09134
09135
09136
09137
09138
09139 void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode1,
09140 const SMDS_MeshNode* theBetweenNode2,
09141 list<const SMDS_MeshNode*>& theNodesToInsert)
09142 {
09143 myLastCreatedElems.Clear();
09144 myLastCreatedNodes.Clear();
09145
09146 SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume);
09147 while (invElemIt->more()) {
09148 const SMDS_MeshElement* elem = invElemIt->next();
09149
09150
09151 SMDS_VolumeTool aVolume (elem);
09152 if (!aVolume.IsLinked(theBetweenNode1, theBetweenNode2))
09153 continue;
09154
09155
09156 int iface, nbFaces = aVolume.NbFaces();
09157 vector<const SMDS_MeshNode *> poly_nodes;
09158 vector<int> quantities (nbFaces);
09159
09160 for (iface = 0; iface < nbFaces; iface++) {
09161 int nbFaceNodes = aVolume.NbFaceNodes(iface), nbInserted = 0;
09162
09163 const SMDS_MeshNode** faceNodes = aVolume.GetFaceNodes(iface);
09164
09165 for (int inode = 0; inode < nbFaceNodes; inode++) {
09166 poly_nodes.push_back(faceNodes[inode]);
09167
09168 if (nbInserted == 0) {
09169 if (faceNodes[inode] == theBetweenNode1) {
09170 if (faceNodes[inode + 1] == theBetweenNode2) {
09171 nbInserted = theNodesToInsert.size();
09172
09173
09174 list<const SMDS_MeshNode*>::iterator nIt = theNodesToInsert.begin();
09175 for (; nIt != theNodesToInsert.end(); nIt++) {
09176 poly_nodes.push_back(*nIt);
09177 }
09178 }
09179 }
09180 else if (faceNodes[inode] == theBetweenNode2) {
09181 if (faceNodes[inode + 1] == theBetweenNode1) {
09182 nbInserted = theNodesToInsert.size();
09183
09184
09185 list<const SMDS_MeshNode*>::iterator nIt = theNodesToInsert.end();
09186 nIt--;
09187 for (; nIt != theNodesToInsert.begin(); nIt--) {
09188 poly_nodes.push_back(*nIt);
09189 }
09190 poly_nodes.push_back(*nIt);
09191 }
09192 }
09193 else {
09194 }
09195 }
09196 }
09197 quantities[iface] = nbFaceNodes + nbInserted;
09198 }
09199
09200
09201 SMESHDS_Mesh *aMesh = GetMeshDS();
09202
09203 if (elem->IsPoly()) {
09204 aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
09205
09206 }
09207 else {
09208 int aShapeId = FindShape( elem );
09209
09210 SMDS_MeshElement* newElem =
09211 aMesh->AddPolyhedralVolume(poly_nodes, quantities);
09212 myLastCreatedElems.Append(newElem);
09213 if (aShapeId && newElem)
09214 aMesh->SetMeshElementOnShape(newElem, aShapeId);
09215
09216 aMesh->RemoveElement(elem);
09217 }
09218 }
09219 }
09220
09221
09226
09227
09228 int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm,
09229 SMESH_MesherHelper& theHelper,
09230 const bool theForce3d)
09231 {
09232 int nbElem = 0;
09233 if( !theSm ) return nbElem;
09234
09235 vector<int> nbNodeInFaces;
09236 SMDS_ElemIteratorPtr ElemItr = theSm->GetElements();
09237 while(ElemItr->more())
09238 {
09239 nbElem++;
09240 const SMDS_MeshElement* elem = ElemItr->next();
09241 if( !elem || elem->IsQuadratic() ) continue;
09242
09243 int id = elem->GetID();
09244 int nbNodes = elem->NbNodes();
09245 SMDSAbs_ElementType aType = elem->GetType();
09246
09247 vector<const SMDS_MeshNode *> nodes (elem->begin_nodes(), elem->end_nodes());
09248 if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
09249 nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
09250
09251 GetMeshDS()->RemoveFreeElement(elem, theSm, false);
09252
09253 const SMDS_MeshElement* NewElem = 0;
09254
09255 switch( aType )
09256 {
09257 case SMDSAbs_Edge :
09258 {
09259 NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
09260 break;
09261 }
09262 case SMDSAbs_Face :
09263 {
09264 switch(nbNodes)
09265 {
09266 case 3:
09267 NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
09268 break;
09269 case 4:
09270 NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
09271 break;
09272 default:
09273 NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
09274 continue;
09275 }
09276 break;
09277 }
09278 case SMDSAbs_Volume :
09279 {
09280 switch(nbNodes)
09281 {
09282 case 4:
09283 NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
09284 break;
09285 case 5:
09286 NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
09287 break;
09288 case 6:
09289 NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
09290 break;
09291 case 8:
09292 NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
09293 nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
09294 break;
09295 default:
09296 NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
09297 }
09298 break;
09299 }
09300 default :
09301 continue;
09302 }
09303 ReplaceElemInGroups( elem, NewElem, GetMeshDS());
09304 if( NewElem )
09305 theSm->AddElement( NewElem );
09306 }
09307
09308
09309 return nbElem;
09310 }
09311
09312
09313
09314
09315
09316 void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
09317 {
09318 SMESHDS_Mesh* meshDS = GetMeshDS();
09319
09320 SMESH_MesherHelper aHelper(*myMesh);
09321 aHelper.SetIsQuadratic( true );
09322
09323 int nbCheckedElems = 0;
09324 if ( myMesh->HasShapeToMesh() )
09325 {
09326 if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
09327 {
09328 SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator(true,false);
09329 while ( smIt->more() ) {
09330 SMESH_subMesh* sm = smIt->next();
09331 if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) {
09332 aHelper.SetSubShape( sm->GetSubShape() );
09333 nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d);
09334 }
09335 }
09336 }
09337 }
09338 int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes();
09339 if ( nbCheckedElems < totalNbElems )
09340 {
09341 SMESHDS_SubMesh *smDS = 0;
09342 SMDS_EdgeIteratorPtr aEdgeItr = meshDS->edgesIterator();
09343 while(aEdgeItr->more())
09344 {
09345 const SMDS_MeshEdge* edge = aEdgeItr->next();
09346 if(edge && !edge->IsQuadratic())
09347 {
09348 int id = edge->GetID();
09349
09350 const SMDS_MeshNode* n1 = edge->GetNode(0);
09351 const SMDS_MeshNode* n2 = edge->GetNode(1);
09352
09353 meshDS->RemoveFreeElement(edge, smDS, false);
09354
09355 const SMDS_MeshEdge* NewEdge = aHelper.AddEdge(n1, n2, id, theForce3d);
09356 ReplaceElemInGroups( edge, NewEdge, GetMeshDS());
09357 }
09358 }
09359 SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator();
09360 while(aFaceItr->more())
09361 {
09362 const SMDS_MeshFace* face = aFaceItr->next();
09363 if(!face || face->IsQuadratic() ) continue;
09364
09365 int id = face->GetID();
09366 int nbNodes = face->NbNodes();
09367 vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());
09368
09369 meshDS->RemoveFreeElement(face, smDS, false);
09370
09371 SMDS_MeshFace * NewFace = 0;
09372 switch(nbNodes)
09373 {
09374 case 3:
09375 NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
09376 break;
09377 case 4:
09378 NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
09379 break;
09380 default:
09381 NewFace = aHelper.AddPolygonalFace(nodes, id, theForce3d);
09382 }
09383 ReplaceElemInGroups( face, NewFace, GetMeshDS());
09384 }
09385 vector<int> nbNodeInFaces;
09386 SMDS_VolumeIteratorPtr aVolumeItr = meshDS->volumesIterator();
09387 while(aVolumeItr->more())
09388 {
09389 const SMDS_MeshVolume* volume = aVolumeItr->next();
09390 if(!volume || volume->IsQuadratic() ) continue;
09391
09392 int id = volume->GetID();
09393 int nbNodes = volume->NbNodes();
09394 vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
09395 if ( volume->GetEntityType() == SMDSEntity_Polyhedra )
09396 nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
09397
09398 meshDS->RemoveFreeElement(volume, smDS, false);
09399
09400 SMDS_MeshVolume * NewVolume = 0;
09401 switch(nbNodes)
09402 {
09403 case 4:
09404 NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
09405 nodes[3], id, theForce3d );
09406 break;
09407 case 5:
09408 NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
09409 nodes[3], nodes[4], id, theForce3d);
09410 break;
09411 case 6:
09412 NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
09413 nodes[3], nodes[4], nodes[5], id, theForce3d);
09414 break;
09415 case 8:
09416 NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
09417 nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
09418 break;
09419 default:
09420 NewVolume = aHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
09421 }
09422 ReplaceElemInGroups(volume, NewVolume, meshDS);
09423 }
09424 }
09425
09426 if ( !theForce3d )
09427 {
09428 aHelper.SetSubShape(0);
09429 aHelper.FixQuadraticElements();
09430 }
09431 }
09432
09433
09439
09440
09441 void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d,
09442 TIDSortedElemSet& theElements)
09443 {
09444 if ( theElements.empty() ) return;
09445
09446
09447 SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
09448
09449
09450 TIDSortedNodeSet allNodes;
09451 TIDSortedElemSet::iterator eIt = theElements.begin();
09452 for ( ; eIt != theElements.end(); ++eIt )
09453 allNodes.insert( (*eIt)->begin_nodes(), (*eIt)->end_nodes() );
09454
09455
09456
09457 TIDSortedElemSet quadAdjacentElems [ SMDSAbs_NbElementTypes ];
09458 TIDSortedElemSet checkedAdjacentElems [ SMDSAbs_NbElementTypes ];
09459 TIDSortedNodeSet::iterator nIt = allNodes.begin();
09460 for ( ; nIt != allNodes.end(); ++nIt )
09461 {
09462 const SMDS_MeshNode* n = *nIt;
09463 SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator();
09464 while ( invIt->more() )
09465 {
09466 const SMDS_MeshElement* e = invIt->next();
09467 if ( e->IsQuadratic() )
09468 {
09469 quadAdjacentElems[ e->GetType() ].insert( e );
09470 continue;
09471 }
09472 if ( e->GetType() >= elemType )
09473 {
09474 continue;
09475 }
09476
09477 if ( !checkedAdjacentElems[ e->GetType() ].insert( e ).second )
09478 continue;
09479
09480
09481 bool allIn = true;
09482 SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
09483 while ( nodeIt->more() && allIn )
09484 allIn = allNodes.count( cast2Node( nodeIt->next() ));
09485 if ( allIn )
09486 theElements.insert(e );
09487 }
09488 }
09489
09490 SMESH_MesherHelper helper(*myMesh);
09491 helper.SetIsQuadratic( true );
09492
09493
09494
09495 if ( !quadAdjacentElems[SMDSAbs_Edge].empty() )
09496 for ( eIt = quadAdjacentElems[SMDSAbs_Edge].begin();
09497 eIt != quadAdjacentElems[SMDSAbs_Edge].end(); ++eIt )
09498 {
09499 helper.AddTLinks( static_cast< const SMDS_MeshEdge*> (*eIt) );
09500 }
09501 if ( !quadAdjacentElems[SMDSAbs_Face].empty() )
09502 for ( eIt = quadAdjacentElems[SMDSAbs_Face].begin();
09503 eIt != quadAdjacentElems[SMDSAbs_Face].end(); ++eIt )
09504 {
09505 helper.AddTLinks( static_cast< const SMDS_MeshFace*> (*eIt) );
09506 }
09507 if ( !quadAdjacentElems[SMDSAbs_Volume].empty() )
09508 for ( eIt = quadAdjacentElems[SMDSAbs_Volume].begin();
09509 eIt != quadAdjacentElems[SMDSAbs_Volume].end(); ++eIt )
09510 {
09511 helper.AddTLinks( static_cast< const SMDS_MeshVolume*> (*eIt) );
09512 }
09513
09514
09515
09516 SMESHDS_Mesh* meshDS = GetMeshDS();
09517 SMESHDS_SubMesh* smDS = 0;
09518 for ( eIt = theElements.begin(); eIt != theElements.end(); ++eIt )
09519 {
09520 const SMDS_MeshElement* elem = *eIt;
09521 if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() )
09522 continue;
09523
09524 int id = elem->GetID();
09525 SMDSAbs_ElementType type = elem->GetType();
09526 vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());
09527
09528 if ( !smDS || !smDS->Contains( elem ))
09529 smDS = meshDS->MeshElements( elem->getshapeId() );
09530 meshDS->RemoveFreeElement(elem, smDS, false);
09531
09532 SMDS_MeshElement * newElem = 0;
09533 switch( nodes.size() )
09534 {
09535 case 4:
09536 if ( type == SMDSAbs_Volume )
09537 newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
09538 else
09539 newElem = helper.AddFace (nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
09540 break;
09541 case 8:
09542 newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
09543 nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
09544 break;
09545 case 3:
09546 newElem = helper.AddFace (nodes[0], nodes[1], nodes[2], id, theForce3d);
09547 break;
09548 case 2:
09549 newElem = helper.AddEdge(nodes[0], nodes[1], id, theForce3d);
09550 break;
09551 case 5:
09552 newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
09553 nodes[4], id, theForce3d);
09554 break;
09555 case 6:
09556 newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
09557 nodes[4], nodes[5], id, theForce3d);
09558 break;
09559 default:;
09560 }
09561 ReplaceElemInGroups( elem, newElem, meshDS);
09562 if( newElem && smDS )
09563 smDS->AddElement( newElem );
09564 }
09565
09566 if ( !theForce3d && !getenv("NO_FixQuadraticElements"))
09567 {
09568 helper.SetSubShape(0);
09569 helper.FixQuadraticElements();
09570 }
09571 }
09572
09573
09578
09579
09580 int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm,
09581 SMDS_ElemIteratorPtr theItr,
09582 const int theShapeID)
09583 {
09584 int nbElem = 0;
09585 SMESHDS_Mesh* meshDS = GetMeshDS();
09586
09587 while( theItr->more() )
09588 {
09589 const SMDS_MeshElement* elem = theItr->next();
09590 nbElem++;
09591 if( elem && elem->IsQuadratic())
09592 {
09593 int id = elem->GetID();
09594 int nbCornerNodes = elem->NbCornerNodes();
09595 SMDSAbs_ElementType aType = elem->GetType();
09596
09597 vector<const SMDS_MeshNode *> nodes( elem->begin_nodes(), elem->end_nodes() );
09598
09599
09600 if ( !theSm || !theSm->Contains( elem ))
09601 theSm = meshDS->MeshElements( elem->getshapeId() );
09602 meshDS->RemoveFreeElement( elem, theSm, false );
09603
09604
09605 for ( unsigned i = nbCornerNodes; i < nodes.size(); ++i )
09606 if ( nodes[i]->NbInverseElements() == 0 )
09607 meshDS->RemoveFreeNode( nodes[i], theSm );
09608
09609
09610 nodes.resize( nbCornerNodes );
09611 SMDS_MeshElement * newElem = AddElement( nodes, aType, false, id );
09612 ReplaceElemInGroups(elem, newElem, meshDS);
09613 if( theSm && newElem )
09614 theSm->AddElement( newElem );
09615 }
09616 }
09617 return nbElem;
09618 }
09619
09620
09621
09622
09623
09624
09625 bool SMESH_MeshEditor::ConvertFromQuadratic()
09626 {
09627 int nbCheckedElems = 0;
09628 if ( myMesh->HasShapeToMesh() )
09629 {
09630 if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
09631 {
09632 SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator(true,false);
09633 while ( smIt->more() ) {
09634 SMESH_subMesh* sm = smIt->next();
09635 if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() )
09636 nbCheckedElems += removeQuadElem( smDS, smDS->GetElements(), sm->GetId() );
09637 }
09638 }
09639 }
09640
09641 int totalNbElems =
09642 GetMeshDS()->NbEdges() + GetMeshDS()->NbFaces() + GetMeshDS()->NbVolumes();
09643 if ( nbCheckedElems < totalNbElems )
09644 {
09645 SMESHDS_SubMesh *aSM = 0;
09646 removeQuadElem( aSM, GetMeshDS()->elementsIterator(), 0 );
09647 }
09648
09649 return true;
09650 }
09651
09652 namespace
09653 {
09654
09658
09659
09660 bool allMediumNodesIn(const SMDS_MeshElement* elem, TIDSortedNodeSet& nodeSet )
09661 {
09662 for ( int i = elem->NbCornerNodes(); i < elem->NbNodes(); ++i )
09663 if ( !nodeSet.count( elem->GetNode(i) ))
09664 return false;
09665 return true;
09666 }
09667 }
09668
09669
09673
09674
09675 void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements)
09676 {
09677 if ( theElements.empty() ) return;
09678
09679
09680 set<int> mediumNodeIDs;
09681 TIDSortedElemSet::iterator eIt = theElements.begin();
09682 for ( ; eIt != theElements.end(); ++eIt )
09683 {
09684 const SMDS_MeshElement* e = *eIt;
09685 for ( int i = e->NbCornerNodes(); i < e->NbNodes(); ++i )
09686 mediumNodeIDs.insert( e->GetNode(i)->GetID() );
09687 }
09688
09689
09690 typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::iterator> TSetIterator;
09691 SMDS_ElemIteratorPtr elemIt( new TSetIterator( theElements.begin(), theElements.end() ));
09692 removeQuadElem( 0, elemIt, 0 );
09693
09694
09695
09696
09697
09698
09699 TIDSortedNodeSet mediumNodes;
09700 set<int>::iterator nIdsIt = mediumNodeIDs.begin();
09701 for ( ; nIdsIt != mediumNodeIDs.end(); ++nIdsIt )
09702 if ( const SMDS_MeshNode* n = GetMeshDS()->FindNode( *nIdsIt ))
09703 mediumNodes.insert( mediumNodes.end(), n );
09704
09705
09706 TIDSortedElemSet moreElemsToConvert;
09707 TIDSortedNodeSet::iterator nIt = mediumNodes.begin();
09708 for ( ; nIt != mediumNodes.end(); ++nIt )
09709 {
09710 SMDS_ElemIteratorPtr invIt = (*nIt)->GetInverseElementIterator();
09711 while ( invIt->more() )
09712 {
09713 const SMDS_MeshElement* e = invIt->next();
09714 if ( e->IsQuadratic() && allMediumNodesIn( e, mediumNodes ))
09715 {
09716
09717
09718 bool complexFound = false;
09719 for ( int type = e->GetType() + 1; type < SMDSAbs_0DElement; ++type )
09720 {
09721 SMDS_ElemIteratorPtr invIt2 =
09722 (*nIt)->GetInverseElementIterator( SMDSAbs_ElementType( type ));
09723 while ( invIt2->more() )
09724 {
09725 const SMDS_MeshElement* eComplex = invIt2->next();
09726 if ( eComplex->IsQuadratic() && !allMediumNodesIn( eComplex, mediumNodes))
09727 {
09728 int nbCommonNodes = SMESH_Algo::GetCommonNodes( e, eComplex ).size();
09729 if ( nbCommonNodes == e->NbNodes())
09730 {
09731 complexFound = true;
09732 type = SMDSAbs_NbElementTypes;
09733 break;
09734 }
09735 }
09736 }
09737 }
09738 if ( !complexFound )
09739 moreElemsToConvert.insert( e );
09740 }
09741 }
09742 }
09743 elemIt = SMDS_ElemIteratorPtr
09744 (new TSetIterator( moreElemsToConvert.begin(), moreElemsToConvert.end() ));
09745 removeQuadElem( 0, elemIt, 0 );
09746 }
09747
09748
09749
09750
09751
09752
09753 SMESH_MeshEditor::Sew_Error
09754 SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1,
09755 TIDSortedElemSet& theSide2,
09756 const SMDS_MeshNode* theFirstNode1,
09757 const SMDS_MeshNode* theFirstNode2,
09758 const SMDS_MeshNode* theSecondNode1,
09759 const SMDS_MeshNode* theSecondNode2)
09760 {
09761 myLastCreatedElems.Clear();
09762 myLastCreatedNodes.Clear();
09763
09764 MESSAGE ("::::SewSideElements()");
09765 if ( theSide1.size() != theSide2.size() )
09766 return SEW_DIFF_NB_OF_ELEMENTS;
09767
09768 Sew_Error aResult = SEW_OK;
09769
09770
09771
09772
09773
09774
09775
09776
09777
09778
09779
09780
09781
09782 SMESHDS_Mesh* aMesh = GetMeshDS();
09783
09784
09785 set<const SMDS_MeshElement*> faceSet1, faceSet2;
09786 set<const SMDS_MeshElement*> volSet1, volSet2;
09787 set<const SMDS_MeshNode*> nodeSet1, nodeSet2;
09788 set<const SMDS_MeshElement*> * faceSetPtr[] = { &faceSet1, &faceSet2 };
09789 set<const SMDS_MeshElement*> * volSetPtr[] = { &volSet1, &volSet2 };
09790 set<const SMDS_MeshNode*> * nodeSetPtr[] = { &nodeSet1, &nodeSet2 };
09791 TIDSortedElemSet * elemSetPtr[] = { &theSide1, &theSide2 };
09792 int iSide, iFace, iNode;
09793
09794 list<const SMDS_MeshElement* > tempFaceList;
09795 for ( iSide = 0; iSide < 2; iSide++ ) {
09796 set<const SMDS_MeshNode*> * nodeSet = nodeSetPtr[ iSide ];
09797 TIDSortedElemSet * elemSet = elemSetPtr[ iSide ];
09798 set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
09799 set<const SMDS_MeshElement*> * volSet = volSetPtr [ iSide ];
09800 set<const SMDS_MeshElement*>::iterator vIt;
09801 TIDSortedElemSet::iterator eIt;
09802 set<const SMDS_MeshNode*>::iterator nIt;
09803
09804
09805 const SMDS_MeshNode* n1 = ( iSide == 0 ) ? theFirstNode1 : theFirstNode2;
09806 const SMDS_MeshNode* n2 = ( iSide == 0 ) ? theSecondNode1 : theSecondNode2;
09807 int firstIndex = -1, secondIndex = -1;
09808 for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
09809 const SMDS_MeshElement* elem = *eIt;
09810 if ( firstIndex < 0 ) firstIndex = elem->GetNodeIndex( n1 );
09811 if ( secondIndex < 0 ) secondIndex = elem->GetNodeIndex( n2 );
09812 if ( firstIndex > -1 && secondIndex > -1 ) break;
09813 }
09814 if ( firstIndex < 0 || secondIndex < 0 ) {
09815
09816 return (iSide == 0 ) ? SEW_BAD_SIDE1_NODES : SEW_BAD_SIDE2_NODES;
09817 }
09818
09819
09820
09821
09822
09823
09824
09825 set< set <const SMDS_MeshNode*> > setOfFaceNodeSet;
09826
09827
09828 for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
09829
09830 const SMDS_MeshElement* elem = *eIt;
09831 if ( elem->GetType() == SMDSAbs_Face ) {
09832 faceSet->insert( elem );
09833 set <const SMDS_MeshNode*> faceNodeSet;
09834 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
09835 while ( nodeIt->more() ) {
09836 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
09837 nodeSet->insert( n );
09838 faceNodeSet.insert( n );
09839 }
09840 setOfFaceNodeSet.insert( faceNodeSet );
09841 }
09842 else if ( elem->GetType() == SMDSAbs_Volume )
09843 volSet->insert( elem );
09844 }
09845
09846
09847
09848
09849 for ( nIt = nodeSet->begin(); nIt != nodeSet->end(); nIt++ ) {
09850 SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face);
09851 while ( fIt->more() ) {
09852 const SMDS_MeshElement* f = fIt->next();
09853 if ( faceSet->find( f ) == faceSet->end() ) {
09854
09855
09856 set <const SMDS_MeshNode*> faceNodeSet;
09857 SMDS_ElemIteratorPtr nodeIt = f->nodesIterator();
09858 bool allInSet = true;
09859 while ( nodeIt->more() && allInSet ) {
09860 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
09861 if ( nodeSet->find( n ) == nodeSet->end() )
09862 allInSet = false;
09863 else
09864 faceNodeSet.insert( n );
09865 }
09866 if ( allInSet ) {
09867 faceSet->insert( f );
09868 setOfFaceNodeSet.insert( faceNodeSet );
09869 }
09870 }
09871 }
09872 }
09873
09874
09875
09876
09877
09878
09879 if ( !volSet->empty() ) {
09880
09881
09882
09883 for ( vIt = volSet->begin(); vIt != volSet->end(); vIt++ ) {
09884 SMDS_VolumeTool vol (*vIt);
09885
09886
09887 list<const SMDS_MeshElement* > freeFaceList;
09888 for ( iFace = 0; iFace < vol.NbFaces(); iFace++ ) {
09889 if ( !vol.IsFreeFace( iFace ))
09890 continue;
09891
09892 const SMDS_MeshElement* aFreeFace = 0;
09893 const SMDS_MeshNode** fNodes = vol.GetFaceNodes( iFace );
09894 int nbNodes = vol.NbFaceNodes( iFace );
09895 set <const SMDS_MeshNode*> faceNodeSet;
09896 vol.GetFaceNodes( iFace, faceNodeSet );
09897 bool isNewFace = setOfFaceNodeSet.insert( faceNodeSet ).second;
09898 if ( isNewFace ) {
09899
09900 if ( nbNodes == 3 ) {
09901 aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2] );
09902 }
09903 else if ( nbNodes == 4 ) {
09904 aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
09905 }
09906 else {
09907 vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
09908 aFreeFace = aMesh->FindFace(poly_nodes);
09909 }
09910 }
09911 if ( !aFreeFace ) {
09912
09913 if ( nbNodes == 3 ) {
09914
09915 aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2] );
09916 }
09917 else if ( nbNodes == 4 ) {
09918
09919 aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
09920 }
09921 else {
09922 vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
09923
09924 aFreeFace = aMesh->AddPolygonalFace(poly_nodes);
09925 }
09926 }
09927 if ( aFreeFace ) {
09928 freeFaceList.push_back( aFreeFace );
09929 tempFaceList.push_back( aFreeFace );
09930 }
09931
09932 }
09933
09934
09935
09936 if ( freeFaceList.size() > 1 ) {
09937
09938 int maxNbNodes = -1;
09939 list<const SMDS_MeshElement* >::iterator fIt = freeFaceList.begin();
09940 while ( fIt != freeFaceList.end() ) {
09941 int nbSharedNodes = 0;
09942 SMDS_ElemIteratorPtr nodeIt = (*fIt)->nodesIterator();
09943 while ( nodeIt->more() ) {
09944 const SMDS_MeshNode* n =
09945 static_cast<const SMDS_MeshNode*>( nodeIt->next() );
09946 SMDS_ElemIteratorPtr invElemIt = n->GetInverseElementIterator();
09947 while ( invElemIt->more() ) {
09948 const SMDS_MeshElement* e = invElemIt->next();
09949 if ( faceSet->find( e ) != faceSet->end() )
09950 nbSharedNodes++;
09951 if ( elemSet->find( e ) != elemSet->end() )
09952 nbSharedNodes++;
09953 }
09954 }
09955 if ( nbSharedNodes >= maxNbNodes ) {
09956 maxNbNodes = nbSharedNodes;
09957 fIt++;
09958 }
09959 else
09960 freeFaceList.erase( fIt++ );
09961 }
09962 if ( freeFaceList.size() > 1 )
09963 {
09964
09965
09966 gp_XYZ aBC( 0., 0., 0. );
09967 set <const SMDS_MeshNode*> addedNodes;
09968 TIDSortedElemSet * elemSet2 = elemSetPtr[ 1 - iSide ];
09969 eIt = elemSet2->begin();
09970 for ( eIt = elemSet2->begin(); eIt != elemSet2->end(); eIt++ ) {
09971 SMDS_ElemIteratorPtr nodeIt = (*eIt)->nodesIterator();
09972 while ( nodeIt->more() ) {
09973 const SMDS_MeshNode* n =
09974 static_cast<const SMDS_MeshNode*>( nodeIt->next() );
09975 if ( addedNodes.insert( n ).second )
09976 aBC += gp_XYZ( n->X(),n->Y(),n->Z() );
09977 }
09978 }
09979 aBC /= addedNodes.size();
09980 double minDist = DBL_MAX;
09981 fIt = freeFaceList.begin();
09982 while ( fIt != freeFaceList.end() ) {
09983 double dist = 0;
09984 SMDS_ElemIteratorPtr nodeIt = (*fIt)->nodesIterator();
09985 while ( nodeIt->more() ) {
09986 const SMDS_MeshNode* n =
09987 static_cast<const SMDS_MeshNode*>( nodeIt->next() );
09988 gp_XYZ p( n->X(),n->Y(),n->Z() );
09989 dist += ( aBC - p ).SquareModulus();
09990 }
09991 if ( dist < minDist ) {
09992 minDist = dist;
09993 freeFaceList.erase( freeFaceList.begin(), fIt++ );
09994 }
09995 else
09996 fIt = freeFaceList.erase( fIt++ );
09997 }
09998 }
09999 }
10000
10001 if ( freeFaceList.size() == 1 ) {
10002 const SMDS_MeshElement* aFreeFace = freeFaceList.front();
10003 faceSet->insert( aFreeFace );
10004
10005
10006
10007 }
10008
10009 }
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039 }
10040 }
10041
10042 if ( faceSet1.size() != faceSet2.size() ) {
10043
10044
10045
10046
10047
10048
10049
10050 MESSAGE("Diff nb of faces");
10051 return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10052 }
10053
10054
10055
10056
10057
10058
10059 TNodeNodeMap nReplaceMap;
10060 if ( theFirstNode1 != theFirstNode2 )
10061 nReplaceMap.insert( TNodeNodeMap::value_type( theFirstNode1, theFirstNode2 ));
10062 if ( theSecondNode1 != theSecondNode2 )
10063 nReplaceMap.insert( TNodeNodeMap::value_type( theSecondNode1, theSecondNode2 ));
10064
10065 LinkID_Gen aLinkID_Gen( GetMeshDS() );
10066 set< long > linkIdSet;
10067 linkIdSet.insert( aLinkID_Gen.GetLinkID( theFirstNode1, theSecondNode1 ));
10068
10069 typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
10070 list< NLink > linkList[2];
10071 linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
10072 linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
10073
10074
10075 list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
10076 for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
10077 NLink link[] = { *linkIt[0], *linkIt[1] };
10078 long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
10079 if ( linkIdSet.find( linkID ) == linkIdSet.end() )
10080 continue;
10081
10082
10083
10084
10085
10086
10087 const SMDS_MeshElement* face[] = { 0, 0 };
10088
10089 vector<const SMDS_MeshNode*> fnodes1(9);
10090 vector<const SMDS_MeshNode*> fnodes2(9);
10091
10092 vector<const SMDS_MeshNode*> notLinkNodes1(6);
10093 vector<const SMDS_MeshNode*> notLinkNodes2(6);
10094 int iLinkNode[2][2];
10095 for ( iSide = 0; iSide < 2; iSide++ ) {
10096 const SMDS_MeshNode* n1 = link[iSide].first;
10097 const SMDS_MeshNode* n2 = link[iSide].second;
10098 set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
10099 set< const SMDS_MeshElement* > fMap;
10100 for ( int i = 0; i < 2; i++ ) {
10101 const SMDS_MeshNode* n = i ? n1 : n2;
10102 SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
10103 while ( fIt->more() ) {
10104 const SMDS_MeshElement* f = fIt->next();
10105 if (faceSet->find( f ) != faceSet->end() &&
10106 ! fMap.insert( f ).second )
10107 {
10108 if ( face[ iSide ] ) {
10109 MESSAGE( "2 faces per link " );
10110 aResult = iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES;
10111 break;
10112 }
10113 face[ iSide ] = f;
10114 faceSet->erase( f );
10115
10116 iNode = 0;
10117 int nbl = -1;
10118 if(f->IsPoly()) {
10119 if(iSide==0) {
10120 fnodes1.resize(f->NbNodes()+1);
10121 notLinkNodes1.resize(f->NbNodes()-2);
10122 }
10123 else {
10124 fnodes2.resize(f->NbNodes()+1);
10125 notLinkNodes2.resize(f->NbNodes()-2);
10126 }
10127 }
10128 if(!f->IsQuadratic()) {
10129 SMDS_ElemIteratorPtr nIt = f->nodesIterator();
10130 while ( nIt->more() ) {
10131 const SMDS_MeshNode* n =
10132 static_cast<const SMDS_MeshNode*>( nIt->next() );
10133 if ( n == n1 ) {
10134 iLinkNode[ iSide ][ 0 ] = iNode;
10135 }
10136 else if ( n == n2 ) {
10137 iLinkNode[ iSide ][ 1 ] = iNode;
10138 }
10139
10140
10141
10142
10143 else {
10144 nbl++;
10145 if(iSide==0)
10146 notLinkNodes1[nbl] = n;
10147
10148 else
10149 notLinkNodes2[nbl] = n;
10150
10151 }
10152
10153 if(iSide==0) {
10154 fnodes1[iNode++] = n;
10155 }
10156 else {
10157 fnodes2[iNode++] = n;
10158 }
10159 }
10160 }
10161 else {
10162 const SMDS_VtkFace* F =
10163 dynamic_cast<const SMDS_VtkFace*>(f);
10164 if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
10165
10166 SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
10167 while ( anIter->more() ) {
10168 const SMDS_MeshNode* n =
10169 static_cast<const SMDS_MeshNode*>( anIter->next() );
10170 if ( n == n1 ) {
10171 iLinkNode[ iSide ][ 0 ] = iNode;
10172 }
10173 else if ( n == n2 ) {
10174 iLinkNode[ iSide ][ 1 ] = iNode;
10175 }
10176 else {
10177 nbl++;
10178 if(iSide==0) {
10179 notLinkNodes1[nbl] = n;
10180 }
10181 else {
10182 notLinkNodes2[nbl] = n;
10183 }
10184 }
10185 if(iSide==0) {
10186 fnodes1[iNode++] = n;
10187 }
10188 else {
10189 fnodes2[iNode++] = n;
10190 }
10191 }
10192 }
10193
10194 if(iSide==0) {
10195 fnodes1[iNode] = fnodes1[0];
10196 }
10197 else {
10198 fnodes2[iNode] = fnodes1[0];
10199 }
10200 }
10201 }
10202 }
10203 }
10204
10205
10206 if (aResult == SEW_OK && (( face[0] && !face[1] ) || ( !face[0] && face[1] ))) {
10207 MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
10208 if ( nReplaceMap.size() == 2 ) {
10209 aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
10210 }
10211 else {
10212 aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10213 }
10214 break;
10215 }
10216
10217
10218
10219
10220 if ( face[0] && face[1] ) {
10221 int nbNodes = face[0]->NbNodes();
10222 if ( nbNodes != face[1]->NbNodes() ) {
10223 MESSAGE("Diff nb of face nodes");
10224 aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10225 break;
10226 }
10227 bool reverse[] = { false, false };
10228 if ( nbNodes == 3 ) {
10229
10230
10231 nReplaceMap.insert( TNodeNodeMap::value_type
10232 ( notLinkNodes1[0], notLinkNodes2[0] ));
10233 }
10234 else {
10235 for ( iSide = 0; iSide < 2; iSide++ ) {
10236
10237 int i1 = iLinkNode[ iSide ][ 0 ];
10238 int i2 = iLinkNode[ iSide ][ 1 ];
10239 reverse[ iSide ] = Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1;
10240
10241
10242 if (( i1 == 1 && i2 == 2 ) ||
10243 ( i1 == 2 && i2 == 1 ))
10244 reverse[ iSide ] = !reverse[ iSide ];
10245 }
10246 if ( reverse[0] == reverse[1] ) {
10247
10248
10249
10250
10251 for(int nn=0; nn<nbNodes-2; nn++) {
10252 nReplaceMap.insert( TNodeNodeMap::value_type
10253 ( notLinkNodes1[nn], notLinkNodes2[nn] ));
10254 }
10255 }
10256 else {
10257
10258
10259
10260
10261 for(int nn=0; nn<nbNodes-2; nn++) {
10262 nReplaceMap.insert( TNodeNodeMap::value_type
10263 ( notLinkNodes1[nn], notLinkNodes2[nbNodes-3-nn] ));
10264 }
10265 }
10266 }
10267
10268
10269
10270
10271
10272 for ( iNode = 0; iNode < nbNodes; iNode++ ) {
10273
10274 linkID = aLinkID_Gen.GetLinkID( fnodes1[iNode], fnodes1[iNode+1] );
10275 pair< set<long>::iterator, bool > iter_isnew = linkIdSet.insert( linkID );
10276 if ( !iter_isnew.second ) {
10277 linkIdSet.erase( iter_isnew.first );
10278 }
10279 else
10280 {
10281
10282
10283 const SMDS_MeshNode* n1 = fnodes1[ iNode ];
10284 const SMDS_MeshNode* n2 = fnodes1[ iNode + 1];
10285 linkList[0].push_back ( NLink( n1, n2 ));
10286 linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
10287 }
10288 }
10289 }
10290 }
10291
10292 if ( aResult == SEW_OK &&
10293 ( linkIt[0] != linkList[0].end() ||
10294 !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
10295 MESSAGE( (linkIt[0] != linkList[0].end()) <<" "<< (faceSetPtr[0]->empty()) <<
10296 " " << (faceSetPtr[1]->empty()));
10297 aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10298 }
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312 if ( aResult != SEW_OK)
10313 return aResult;
10314
10315 list< int > nodeIDsToRemove;
10316
10317 TNodeNodeMap::iterator nReplaceMapIt = nReplaceMap.begin(), nnIt;
10318 for ( ; nReplaceMapIt != nReplaceMap.end(); nReplaceMapIt++ )
10319 if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second ) {
10320 const SMDS_MeshNode* nToRemove = (*nReplaceMapIt).first;
10321 nodeIDsToRemove.push_back( nToRemove->GetID() );
10322
10323 SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
10324 while ( invElemIt->more() ) {
10325 const SMDS_MeshElement* e = invElemIt->next();
10326
10327 int nbReplaced = 0, i = 0, nbNodes = e->NbNodes();
10328 vector< const SMDS_MeshNode*> nodes( nbNodes );
10329 SMDS_ElemIteratorPtr nIt = e->nodesIterator();
10330 while ( nIt->more() ) {
10331 const SMDS_MeshNode* n =
10332 static_cast<const SMDS_MeshNode*>( nIt->next() );
10333 nnIt = nReplaceMap.find( n );
10334 if ( nnIt != nReplaceMap.end() ) {
10335 nbReplaced++;
10336 n = (*nnIt).second;
10337 }
10338 nodes[ i++ ] = n;
10339 }
10340
10341
10342
10343 if ( nbReplaced )
10344 {
10345 SMDSAbs_ElementType etyp = e->GetType();
10346 SMDS_MeshElement* newElem = this->AddElement(nodes, etyp, false);
10347 if (newElem)
10348 {
10349 myLastCreatedElems.Append(newElem);
10350 AddToSameGroups(newElem, e, aMesh);
10351 int aShapeId = e->getshapeId();
10352 if ( aShapeId )
10353 {
10354 aMesh->SetMeshElementOnShape( newElem, aShapeId );
10355 }
10356 }
10357 aMesh->RemoveElement(e);
10358 }
10359 }
10360 }
10361
10362 Remove( nodeIDsToRemove, true );
10363
10364 return aResult;
10365 }
10366
10367
10379
10380
10381 #ifdef _DEBUG_
10382
10383 #endif
10384
10385 SMESH_MeshEditor::Sew_Error
10386 SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
10387 set<const SMDS_MeshElement*>& theSide2,
10388 const SMDS_MeshNode* theFirstNode1,
10389 const SMDS_MeshNode* theFirstNode2,
10390 const SMDS_MeshNode* theSecondNode1,
10391 const SMDS_MeshNode* theSecondNode2,
10392 TNodeNodeMap & nReplaceMap)
10393 {
10394 set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };
10395
10396 nReplaceMap.clear();
10397 if ( theFirstNode1 != theFirstNode2 )
10398 nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
10399 if ( theSecondNode1 != theSecondNode2 )
10400 nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
10401
10402 set< SMESH_TLink > linkSet;
10403 linkSet.insert( SMESH_TLink( theFirstNode1, theSecondNode1 ));
10404
10405 list< NLink > linkList[2];
10406 linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
10407 linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
10408
10409
10410
10411 list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
10412 for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
10413 NLink link[] = { *linkIt[0], *linkIt[1] };
10414 if ( linkSet.find( link[0] ) == linkSet.end() )
10415 continue;
10416
10417
10418
10419
10420
10421
10422 const SMDS_MeshElement* face[] = { 0, 0 };
10423 list<const SMDS_MeshNode*> notLinkNodes[2];
10424
10425 int nbNodes[2];
10426 for ( int iSide = 0; iSide < 2; iSide++ )
10427 {
10428 const SMDS_MeshNode* n1 = link[iSide].first;
10429 const SMDS_MeshNode* n2 = link[iSide].second;
10430 set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
10431 set< const SMDS_MeshElement* > facesOfNode1;
10432 for ( int iNode = 0; iNode < 2; iNode++ )
10433 {
10434
10435
10436 const SMDS_MeshNode* n = iNode ? n1 : n2;
10437 SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
10438 while ( fIt->more() ) {
10439 const SMDS_MeshElement* f = fIt->next();
10440 if (faceSet->find( f ) != faceSet->end() &&
10441 ! facesOfNode1.insert( f ).second )
10442 {
10443 if ( face[ iSide ] ) {
10444 MESSAGE( "2 faces per link " );
10445 return ( iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
10446 }
10447 face[ iSide ] = f;
10448 faceSet->erase( f );
10449
10450
10451 int nbN = f->NbNodes();
10452 if ( f->IsQuadratic() )
10453 nbN /= 2;
10454 nbNodes[ iSide ] = nbN;
10455 list< const SMDS_MeshNode* > & nodes = notLinkNodes[ iSide ];
10456 int i1 = f->GetNodeIndex( n1 );
10457 int i2 = f->GetNodeIndex( n2 );
10458 int iEnd = nbN, iBeg = -1, iDelta = 1;
10459 bool reverse = ( Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1 );
10460 if ( reverse ) {
10461 std::swap( iEnd, iBeg ); iDelta = -1;
10462 }
10463 int i = i2;
10464 while ( true ) {
10465 i += iDelta;
10466 if ( i == iEnd ) i = iBeg + iDelta;
10467 if ( i == i1 ) break;
10468 nodes.push_back ( f->GetNode( i ) );
10469 }
10470 }
10471 }
10472 }
10473 }
10474
10475 if (( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
10476 MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
10477 if ( nReplaceMap.size() == 2 ) {
10478 return ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
10479 }
10480 else {
10481 return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10482 }
10483 }
10484
10485
10486
10487
10488 if ( face[0] && face[1] ) {
10489 if ( nbNodes[0] != nbNodes[1] ) {
10490 MESSAGE("Diff nb of face nodes");
10491 return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
10492 }
10493 #ifdef DEBUG_MATCHING_NODES
10494 MESSAGE ( " Link 1: " << link[0].first->GetID() <<" "<< link[0].second->GetID()
10495 << " F 1: " << face[0] << "| Link 2: " << link[1].first->GetID() <<" "
10496 << link[1].second->GetID() << " F 2: " << face[1] << " | Bind: " ) ;
10497 #endif
10498 int nbN = nbNodes[0];
10499 {
10500 list<const SMDS_MeshNode*>::iterator n1 = notLinkNodes[0].begin();
10501 list<const SMDS_MeshNode*>::iterator n2 = notLinkNodes[1].begin();
10502 for ( int i = 0 ; i < nbN - 2; ++i ) {
10503 #ifdef DEBUG_MATCHING_NODES
10504 MESSAGE ( (*n1)->GetID() << " to " << (*n2)->GetID() );
10505 #endif
10506 nReplaceMap.insert( make_pair( *(n1++), *(n2++) ));
10507 }
10508 }
10509
10510
10511
10512
10513 const SMDS_MeshElement* f0 = face[0];
10514 const SMDS_MeshNode* n1 = f0->GetNode( nbN - 1 );
10515 for ( int i = 0; i < nbN; i++ )
10516 {
10517 const SMDS_MeshNode* n2 = f0->GetNode( i );
10518 pair< set< SMESH_TLink >::iterator, bool > iter_isnew =
10519 linkSet.insert( SMESH_TLink( n1, n2 ));
10520 if ( !iter_isnew.second ) {
10521 linkSet.erase( iter_isnew.first );
10522 }
10523 else
10524 {
10525 #ifdef DEBUG_MATCHING_NODES
10526 MESSAGE ( "Add link 1: " << n1->GetID() << " " << n2->GetID() << " "
10527 << " | link 2: " << nReplaceMap[n1]->GetID() << " " << nReplaceMap[n2]->GetID() << " " );
10528 #endif
10529 linkList[0].push_back ( NLink( n1, n2 ));
10530 linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
10531 }
10532 n1 = n2;
10533 }
10534 }
10535 }
10536
10537 return SEW_OK;
10538 }
10539
10540
10550
10551
10552 bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems,
10553 const TIDSortedElemSet& theNodesNot,
10554 const TIDSortedElemSet& theAffectedElems )
10555 {
10556 myLastCreatedElems.Clear();
10557 myLastCreatedNodes.Clear();
10558
10559 if ( theElems.size() == 0 )
10560 return false;
10561
10562 SMESHDS_Mesh* aMeshDS = GetMeshDS();
10563 if ( !aMeshDS )
10564 return false;
10565
10566 bool res = false;
10567 std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode;
10568
10569 res = doubleNodes( aMeshDS, theElems, theNodesNot, anOldNodeToNewNode, true );
10570
10571 res = doubleNodes( aMeshDS, theAffectedElems, theNodesNot, anOldNodeToNewNode, false );
10572 return res;
10573 }
10574
10575
10585
10586
10587 bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS,
10588 const TIDSortedElemSet& theElems,
10589 const TIDSortedElemSet& theNodesNot,
10590 std::map< const SMDS_MeshNode*,
10591 const SMDS_MeshNode* >& theNodeNodeMap,
10592 const bool theIsDoubleElem )
10593 {
10594 MESSAGE("doubleNodes");
10595
10596 bool res = false;
10597 TIDSortedElemSet::const_iterator elemItr = theElems.begin();
10598 for ( ; elemItr != theElems.end(); ++elemItr )
10599 {
10600 const SMDS_MeshElement* anElem = *elemItr;
10601 if (!anElem)
10602 continue;
10603
10604 bool isDuplicate = false;
10605
10606 std::vector<const SMDS_MeshNode*> newNodes( anElem->NbNodes() );
10607 SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
10608 int ind = 0;
10609 while ( anIter->more() )
10610 {
10611
10612 SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
10613 SMDS_MeshNode* aNewNode = aCurrNode;
10614 if ( theNodeNodeMap.find( aCurrNode ) != theNodeNodeMap.end() )
10615 aNewNode = (SMDS_MeshNode*)theNodeNodeMap[ aCurrNode ];
10616 else if ( theIsDoubleElem && theNodesNot.find( aCurrNode ) == theNodesNot.end() )
10617 {
10618
10619 aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() );
10620 theNodeNodeMap[ aCurrNode ] = aNewNode;
10621 myLastCreatedNodes.Append( aNewNode );
10622 }
10623 isDuplicate |= (aCurrNode != aNewNode);
10624 newNodes[ ind++ ] = aNewNode;
10625 }
10626 if ( !isDuplicate )
10627 continue;
10628
10629 if ( theIsDoubleElem )
10630 AddElement(newNodes, anElem->GetType(), anElem->IsPoly());
10631 else
10632 {
10633 MESSAGE("ChangeElementNodes");
10634 theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() );
10635 }
10636 res = true;
10637 }
10638 return res;
10639 }
10640
10641
10650
10651
10652 bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
10653 const std::list< int >& theListOfModifiedElems )
10654 {
10655 MESSAGE("DoubleNodes");
10656 myLastCreatedElems.Clear();
10657 myLastCreatedNodes.Clear();
10658
10659 if ( theListOfNodes.size() == 0 )
10660 return false;
10661
10662 SMESHDS_Mesh* aMeshDS = GetMeshDS();
10663 if ( !aMeshDS )
10664 return false;
10665
10666
10667
10668 std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode;
10669
10670 std::list< int >::const_iterator aNodeIter;
10671 for ( aNodeIter = theListOfNodes.begin(); aNodeIter != theListOfNodes.end(); ++aNodeIter )
10672 {
10673 int aCurr = *aNodeIter;
10674 SMDS_MeshNode* aNode = (SMDS_MeshNode*)aMeshDS->FindNode( aCurr );
10675 if ( !aNode )
10676 continue;
10677
10678
10679
10680 const SMDS_MeshNode* aNewNode = aMeshDS->AddNode( aNode->X(), aNode->Y(), aNode->Z() );
10681 if ( aNewNode )
10682 {
10683 anOldNodeToNewNode[ aNode ] = aNewNode;
10684 myLastCreatedNodes.Append( aNewNode );
10685 }
10686 }
10687
10688
10689
10690 std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> > anElemToNodes;
10691
10692 std::list< int >::const_iterator anElemIter;
10693 for ( anElemIter = theListOfModifiedElems.begin();
10694 anElemIter != theListOfModifiedElems.end(); ++anElemIter )
10695 {
10696 int aCurr = *anElemIter;
10697 SMDS_MeshElement* anElem = (SMDS_MeshElement*)aMeshDS->FindElement( aCurr );
10698 if ( !anElem )
10699 continue;
10700
10701 vector<const SMDS_MeshNode*> aNodeArr( anElem->NbNodes() );
10702
10703 SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
10704 int ind = 0;
10705 while ( anIter->more() )
10706 {
10707 SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
10708 if ( aCurr && anOldNodeToNewNode.find( aCurrNode ) != anOldNodeToNewNode.end() )
10709 {
10710 const SMDS_MeshNode* aNewNode = anOldNodeToNewNode[ aCurrNode ];
10711 aNodeArr[ ind++ ] = aNewNode;
10712 }
10713 else
10714 aNodeArr[ ind++ ] = aCurrNode;
10715 }
10716 anElemToNodes[ anElem ] = aNodeArr;
10717 }
10718
10719
10720
10721 std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> >::iterator
10722 anElemToNodesIter = anElemToNodes.begin();
10723 for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter )
10724 {
10725 const SMDS_MeshElement* anElem = anElemToNodesIter->first;
10726 vector<const SMDS_MeshNode*> aNodeArr = anElemToNodesIter->second;
10727 if ( anElem )
10728 {
10729 MESSAGE("ChangeElementNodes");
10730 aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() );
10731 }
10732 }
10733
10734 return true;
10735 }
10736
10737 namespace {
10738
10739
10744
10745
10746 template<class Classifier>
10747 bool isInside(const SMDS_MeshElement* theElem,
10748 Classifier& theClassifier,
10749 const double theTol)
10750 {
10751 gp_XYZ centerXYZ (0, 0, 0);
10752 SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
10753 while (aNodeItr->more())
10754 centerXYZ += SMESH_TNodeXYZ(cast2Node( aNodeItr->next()));
10755
10756 gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
10757 theClassifier.Perform(aPnt, theTol);
10758 TopAbs_State aState = theClassifier.State();
10759 return (aState == TopAbs_IN || aState == TopAbs_ON );
10760 }
10761
10762
10767
10768
10769 struct _FaceClassifier
10770 {
10771 Extrema_ExtPS _extremum;
10772 BRepAdaptor_Surface _surface;
10773 TopAbs_State _state;
10774
10775 _FaceClassifier(const TopoDS_Face& face):_extremum(),_surface(face),_state(TopAbs_OUT)
10776 {
10777 _extremum.Initialize( _surface,
10778 _surface.FirstUParameter(), _surface.LastUParameter(),
10779 _surface.FirstVParameter(), _surface.LastVParameter(),
10780 _surface.Tolerance(), _surface.Tolerance() );
10781 }
10782 void Perform(const gp_Pnt& aPnt, double theTol)
10783 {
10784 _state = TopAbs_OUT;
10785 _extremum.Perform(aPnt);
10786 if ( _extremum.IsDone() )
10787 for ( int iSol = 1; iSol <= _extremum.NbExt() && _state == TopAbs_OUT; ++iSol)
10788 _state = ( _extremum.Value(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
10789 }
10790 TopAbs_State State() const
10791 {
10792 return _state;
10793 }
10794 };
10795 }
10796
10797
10807
10808
10809 bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems,
10810 const TIDSortedElemSet& theNodesNot,
10811 const TopoDS_Shape& theShape )
10812 {
10813 if ( theShape.IsNull() )
10814 return false;
10815
10816 const double aTol = Precision::Confusion();
10817 auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
10818 auto_ptr<_FaceClassifier> aFaceClassifier;
10819 if ( theShape.ShapeType() == TopAbs_SOLID )
10820 {
10821 bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
10822 bsc3d->PerformInfinitePoint(aTol);
10823 }
10824 else if (theShape.ShapeType() == TopAbs_FACE )
10825 {
10826 aFaceClassifier.reset( new _FaceClassifier(TopoDS::Face(theShape)));
10827 }
10828
10829
10830 TIDSortedElemSet anAffected;
10831 TIDSortedElemSet::const_iterator elemItr = theElems.begin();
10832 for ( ; elemItr != theElems.end(); ++elemItr )
10833 {
10834 SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
10835 if (!anElem)
10836 continue;
10837
10838 SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
10839 while ( nodeItr->more() )
10840 {
10841 const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
10842 if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() )
10843 continue;
10844 SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator();
10845 while ( backElemItr->more() )
10846 {
10847 const SMDS_MeshElement* curElem = backElemItr->next();
10848 if ( curElem && theElems.find(curElem) == theElems.end() &&
10849 ( bsc3d.get() ?
10850 isInside( curElem, *bsc3d, aTol ) :
10851 isInside( curElem, *aFaceClassifier, aTol )))
10852 anAffected.insert( curElem );
10853 }
10854 }
10855 }
10856 return DoubleNodes( theElems, theNodesNot, anAffected );
10857 }
10858
10867 double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const gp_Pnt& g1, const gp_Pnt& g2)
10868 {
10869
10870
10871
10872
10873 gp_Vec vref(p0, p1);
10874 gp_Vec v1(p0, g1);
10875 gp_Vec v2(p0, g2);
10876 gp_Vec n1 = vref.Crossed(v1);
10877 gp_Vec n2 = vref.Crossed(v2);
10878 return n2.AngleWithRef(n1, vref);
10879 }
10880
10893 bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
10894 bool createJointElems)
10895 {
10896 MESSAGE("----------------------------------------------");
10897 MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
10898 MESSAGE("----------------------------------------------");
10899
10900 SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
10901 meshDS->BuildDownWardConnectivity(true);
10902 CHRONO(50);
10903 SMDS_UnstructuredGrid *grid = meshDS->getGrid();
10904
10905
10906
10907
10908
10909 std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains;
10910 std::map<int,int>celldom;
10911 std::map<DownIdType, std::map<int,int>, DownIdCompare> cellDomains;
10912 std::map<int, std::map<int,int> > nodeDomains;
10913 faceDomains.clear();
10914 celldom.clear();
10915 cellDomains.clear();
10916 nodeDomains.clear();
10917 std::map<int,int> emptyMap;
10918 std::set<int> emptySet;
10919 emptyMap.clear();
10920
10921 for (int idom = 0; idom < theElems.size(); idom++)
10922 {
10923
10924
10925
10926
10927
10928
10929 const TIDSortedElemSet& domain = theElems[idom];
10930 TIDSortedElemSet::const_iterator elemItr = domain.begin();
10931 for (; elemItr != domain.end(); ++elemItr)
10932 {
10933 SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
10934 if (!anElem)
10935 continue;
10936 int vtkId = anElem->getVtkId();
10937 int neighborsVtkIds[NBMAXNEIGHBORS];
10938 int downIds[NBMAXNEIGHBORS];
10939 unsigned char downTypes[NBMAXNEIGHBORS];
10940 int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
10941 for (int n = 0; n < nbNeighbors; n++)
10942 {
10943 int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
10944 const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
10945 if (! domain.count(elem))
10946 {
10947 DownIdType face(downIds[n], downTypes[n]);
10948 if (!faceDomains.count(face))
10949 faceDomains[face] = emptyMap;
10950 if (!faceDomains[face].count(idom))
10951 {
10952 faceDomains[face][idom] = vtkId;
10953 celldom[vtkId] = idom;
10954 }
10955 }
10956 }
10957 }
10958 }
10959
10960
10961 std::map<DownIdType, std::map<int, int>, DownIdCompare>::iterator itface;
10962
10963
10964
10965
10966
10967 for (int idomain = 0; idomain < theElems.size(); idomain++)
10968 {
10969 const TIDSortedElemSet& domain = theElems[idomain];
10970 itface = faceDomains.begin();
10971 for (; itface != faceDomains.end(); ++itface)
10972 {
10973 std::map<int, int> domvol = itface->second;
10974 if (!domvol.count(idomain))
10975 continue;
10976 DownIdType face = itface->first;
10977
10978 std::set<int> oldNodes;
10979 oldNodes.clear();
10980 grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
10981 std::set<int>::iterator itn = oldNodes.begin();
10982 for (; itn != oldNodes.end(); ++itn)
10983 {
10984 int oldId = *itn;
10985
10986 std::set<int> cells;
10987 cells.clear();
10988 vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
10989 for (int i=0; i<l.ncells; i++)
10990 {
10991 int vtkId = l.cells[i];
10992 const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
10993 if (!domain.count(anElem))
10994 continue;
10995 int vtkType = grid->GetCellType(vtkId);
10996 int downId = grid->CellIdToDownId(vtkId);
10997 if (downId < 0)
10998 {
10999 MESSAGE("doubleNodesOnGroupBoundaries: internal algorithm problem");
11000 continue;
11001
11002 }
11003 DownIdType aCell(downId, vtkType);
11004 if (celldom.count(vtkId))
11005 continue;
11006 cellDomains[aCell][idomain] = vtkId;
11007 celldom[vtkId] = idomain;
11008 }
11009 }
11010 }
11011 }
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021 std::map<std::vector<int>, std::vector<int> > edgesMultiDomains;
11022 std::map<int, std::vector<int> > mutipleNodes;
11023
11024 for (int idomain = 0; idomain < theElems.size(); idomain++)
11025 {
11026 itface = faceDomains.begin();
11027 for (; itface != faceDomains.end(); ++itface)
11028 {
11029 std::map<int, int> domvol = itface->second;
11030 if (!domvol.count(idomain))
11031 continue;
11032 DownIdType face = itface->first;
11033
11034 std::set<int> oldNodes;
11035 oldNodes.clear();
11036 grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
11037 bool isMultipleDetected = false;
11038 std::set<int>::iterator itn = oldNodes.begin();
11039 for (; itn != oldNodes.end(); ++itn)
11040 {
11041 int oldId = *itn;
11042
11043 if (!nodeDomains.count(oldId))
11044 nodeDomains[oldId] = emptyMap;
11045 if (nodeDomains[oldId].empty())
11046 nodeDomains[oldId][idomain] = oldId;
11047 std::map<int, int>::iterator itdom = domvol.begin();
11048 for (; itdom != domvol.end(); ++itdom)
11049 {
11050 int idom = itdom->first;
11051
11052 if (!nodeDomains[oldId].count(idom))
11053 {
11054 if (nodeDomains[oldId].size() >= 2)
11055 {
11056 vector<int> orderedDoms;
11057
11058 isMultipleDetected =true;
11059 if (mutipleNodes.count(oldId))
11060 orderedDoms = mutipleNodes[oldId];
11061 else
11062 {
11063 map<int,int>::iterator it = nodeDomains[oldId].begin();
11064 for (; it != nodeDomains[oldId].end(); ++it)
11065 orderedDoms.push_back(it->first);
11066 }
11067 orderedDoms.push_back(idom);
11068
11069
11070
11071
11072 mutipleNodes[oldId] = orderedDoms;
11073 }
11074 double *coords = grid->GetPoint(oldId);
11075 SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
11076 int newId = newNode->getVtkId();
11077 nodeDomains[oldId][idom] = newId;
11078
11079 }
11080 if (nodeDomains[oldId].size() >= 3)
11081 {
11082
11083 isMultipleDetected =true;
11084 }
11085 }
11086 }
11087 if (isMultipleDetected)
11088 {
11089
11090 int downId = itface->first.cellId;
11091 unsigned char cellType = itface->first.cellType;
11092 int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
11093 const int *downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
11094 const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
11095 for (int ie =0; ie < nbEdges; ie++)
11096 {
11097 int nodes[3];
11098 int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
11099 if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
11100 {
11101 vector<int> vn0 = mutipleNodes[nodes[0]];
11102 vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
11103 sort( vn0.begin(), vn0.end() );
11104 sort( vn1.begin(), vn1.end() );
11105 if (vn0 == vn1)
11106 {
11107
11108 double *coords = grid->GetPoint(nodes[0]);
11109 gp_Pnt p0(coords[0], coords[1], coords[2]);
11110 coords = grid->GetPoint(nodes[nbNodes - 1]);
11111 gp_Pnt p1(coords[0], coords[1], coords[2]);
11112 gp_Pnt gref;
11113 int vtkVolIds[1000];
11114 map<int, SMDS_VtkVolume*> domvol;
11115 map<int, double> angleDom;
11116 int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
11117 for (int id=0; id < vn0.size(); id++)
11118 {
11119 int idom = vn0[id];
11120 for (int ivol=0; ivol<nbvol; ivol++)
11121 {
11122 int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
11123 SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
11124 if (theElems[idom].count(elem))
11125 {
11126 SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
11127 domvol[idom] = svol;
11128
11129 double values[3];
11130 vtkIdType npts = 0;
11131 vtkIdType* pts = 0;
11132 grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
11133 SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
11134 if (id ==0)
11135 {
11136 gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
11137 angleDom[idom] = 0;
11138 }
11139 else
11140 {
11141 gp_Pnt g(values[0], values[1], values[2]);
11142 angleDom[idom] = OrientedAngle(p0, p1, gref, g);
11143
11144 }
11145 break;
11146 }
11147 }
11148 }
11149 map<double, int> sortedDom;
11150 for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
11151 sortedDom[ia->second] = ia->first;
11152 vector<int> vnodes;
11153 vector<int> vdom;
11154 for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
11155 {
11156 vdom.push_back(ib->second);
11157
11158 }
11159 for (int ino = 0; ino < nbNodes; ino++)
11160 vnodes.push_back(nodes[ino]);
11161 edgesMultiDomains[vnodes] = vdom;
11162 }
11163 }
11164 }
11165 }
11166 }
11167 }
11168
11169
11170
11171
11172
11173
11174
11175
11176 std::map<int, std::map<long,int> > nodeQuadDomains;
11177 std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
11178
11179 if (createJointElems)
11180 {
11181 itface = faceDomains.begin();
11182 for (; itface != faceDomains.end(); ++itface)
11183 {
11184 DownIdType face = itface->first;
11185 std::set<int> oldNodes;
11186 std::set<int>::iterator itn;
11187 oldNodes.clear();
11188 grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
11189
11190 std::map<int, int> domvol = itface->second;
11191 std::map<int, int>::iterator itdom = domvol.begin();
11192 int dom1 = itdom->first;
11193 int vtkVolId = itdom->second;
11194 itdom++;
11195 int dom2 = itdom->first;
11196 SMDS_MeshVolume *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
11197 nodeQuadDomains);
11198 stringstream grpname;
11199 grpname << "j_";
11200 if (dom1 < dom2)
11201 grpname << dom1 << "_" << dom2;
11202 else
11203 grpname << dom2 << "_" << dom1;
11204 int idg;
11205 string namegrp = grpname.str();
11206 if (!mapOfJunctionGroups.count(namegrp))
11207 mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
11208 SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
11209 if (sgrp)
11210 sgrp->Add(vol->GetID());
11211 }
11212 }
11213
11214
11215
11216
11217 if (createJointElems)
11218 {
11219 std::map<std::vector<int>, std::vector<int> >::iterator ite = edgesMultiDomains.begin();
11220 for (; ite != edgesMultiDomains.end(); ++ite)
11221 {
11222 vector<int> nodes = ite->first;
11223 vector<int> orderDom = ite->second;
11224 vector<vtkIdType> orderedNodes;
11225 if (nodes.size() == 2)
11226 {
11227
11228 for (int ino=0; ino < nodes.size(); ino++)
11229 if (orderDom.size() == 3)
11230 for (int idom = 0; idom <orderDom.size(); idom++)
11231 orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
11232 else
11233 for (int idom = orderDom.size()-1; idom >=0; idom--)
11234 orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
11235 SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
11236
11237 stringstream grpname;
11238 grpname << "mj_";
11239 grpname << 0 << "_" << 0;
11240 int idg;
11241 string namegrp = grpname.str();
11242 if (!mapOfJunctionGroups.count(namegrp))
11243 mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
11244 SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
11245 if (sgrp)
11246 sgrp->Add(vol->GetID());
11247 }
11248 else
11249 {
11250
11251
11252 }
11253 }
11254 }
11255
11256
11257
11258
11259
11260
11261 std::map<DownIdType, std::map<int,int>, DownIdCompare> faceOrEdgeDom;
11262 std::map<int,int> feDom;
11263 faceOrEdgeDom.clear();
11264 feDom.clear();
11265
11266 for (int idomain = 0; idomain < theElems.size(); idomain++)
11267 {
11268 std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
11269 for (; itnod != nodeDomains.end(); ++itnod)
11270 {
11271 int oldId = itnod->first;
11272
11273 vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
11274 for (int i = 0; i < l.ncells; i++)
11275 {
11276 int vtkId = l.cells[i];
11277 int vtkType = grid->GetCellType(vtkId);
11278 int downId = grid->CellIdToDownId(vtkId);
11279 if (downId < 0)
11280 continue;
11281 DownIdType aCell(downId, vtkType);
11282 int volParents[1000];
11283 int nbvol = grid->GetParentVolumes(volParents, vtkId);
11284 for (int j = 0; j < nbvol; j++)
11285 if (celldom.count(volParents[j]) && (celldom[volParents[j]] == idomain))
11286 if (!feDom.count(vtkId))
11287 {
11288 feDom[vtkId] = idomain;
11289 faceOrEdgeDom[aCell] = emptyMap;
11290 faceOrEdgeDom[aCell][idomain] = vtkId;
11291
11292
11293 }
11294 }
11295 }
11296 }
11297
11298
11299
11300
11301
11302 std::map<DownIdType, std::map<int,int>, DownIdCompare>* maps[3] = {&faceDomains, &cellDomains, &faceOrEdgeDom};
11303 for (int m=0; m<3; m++)
11304 {
11305 std::map<DownIdType, std::map<int,int>, DownIdCompare>* amap = maps[m];
11306 itface = (*amap).begin();
11307 for (; itface != (*amap).end(); ++itface)
11308 {
11309 DownIdType face = itface->first;
11310 std::set<int> oldNodes;
11311 std::set<int>::iterator itn;
11312 oldNodes.clear();
11313 grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
11314
11315 std::map<int, int> localClonedNodeIds;
11316
11317 std::map<int, int> domvol = itface->second;
11318 std::map<int, int>::iterator itdom = domvol.begin();
11319 for (; itdom != domvol.end(); ++itdom)
11320 {
11321 int idom = itdom->first;
11322 int vtkVolId = itdom->second;
11323
11324 localClonedNodeIds.clear();
11325 for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
11326 {
11327 int oldId = *itn;
11328 if (nodeDomains[oldId].count(idom))
11329 {
11330 localClonedNodeIds[oldId] = nodeDomains[oldId][idom];
11331
11332 }
11333 }
11334 meshDS->ModifyCellNodes(vtkVolId, localClonedNodeIds);
11335 }
11336 }
11337 }
11338
11339 meshDS->CleanDownWardConnectivity();
11340 grid->BuildLinks();
11341
11342 CHRONOSTOP(50);
11343 counters::stats();
11344 return true;
11345 }
11346
11357 bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSortedElemSet>& theElems)
11358 {
11359 MESSAGE("-------------------------------------------------");
11360 MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
11361 MESSAGE("-------------------------------------------------");
11362
11363 SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
11364
11365
11366
11367
11368
11369 std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
11370 std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
11371 clonedNodes.clear();
11372 intermediateNodes.clear();
11373 std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
11374 mapOfJunctionGroups.clear();
11375
11376 for (int idom = 0; idom < theElems.size(); idom++)
11377 {
11378 const TIDSortedElemSet& domain = theElems[idom];
11379 TIDSortedElemSet::const_iterator elemItr = domain.begin();
11380 for (; elemItr != domain.end(); ++elemItr)
11381 {
11382 SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
11383 SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
11384 if (!aFace)
11385 continue;
11386
11387 bool isQuad = aFace->IsQuadratic();
11388 vector<const SMDS_MeshNode*> ln0, ln1, ln2, ln3, ln4;
11389
11390
11391
11392 SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
11393 while (nodeIt->more())
11394 {
11395 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
11396 bool isMedium = isQuad && (aFace->IsMediumNode(node));
11397 if (isMedium)
11398 ln2.push_back(node);
11399 else
11400 ln0.push_back(node);
11401
11402 const SMDS_MeshNode* clone = 0;
11403 if (!clonedNodes.count(node))
11404 {
11405 clone = meshDS->AddNode(node->X(), node->Y(), node->Z());
11406 clonedNodes[node] = clone;
11407 }
11408 else
11409 clone = clonedNodes[node];
11410
11411 if (isMedium)
11412 ln3.push_back(clone);
11413 else
11414 ln1.push_back(clone);
11415
11416 const SMDS_MeshNode* inter = 0;
11417 if (isQuad && (!isMedium))
11418 {
11419 if (!intermediateNodes.count(node))
11420 {
11421 inter = meshDS->AddNode(node->X(), node->Y(), node->Z());
11422 intermediateNodes[node] = inter;
11423 }
11424 else
11425 inter = intermediateNodes[node];
11426 ln4.push_back(inter);
11427 }
11428 }
11429
11430
11431
11432 vector<const SMDS_MeshNode*> ln;
11433 SMDS_MeshVolume* vol = 0;
11434 vtkIdType aType = aFace->GetVtkType();
11435 switch (aType)
11436 {
11437 case VTK_TRIANGLE:
11438 vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]);
11439
11440 ln.push_back(ln1[0]);
11441 ln.push_back(ln1[1]);
11442 ln.push_back(ln1[2]);
11443 break;
11444 case VTK_QUAD:
11445 vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]);
11446
11447 ln.push_back(ln1[0]);
11448 ln.push_back(ln1[1]);
11449 ln.push_back(ln1[2]);
11450 ln.push_back(ln1[3]);
11451 break;
11452 case VTK_QUADRATIC_TRIANGLE:
11453 vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2],
11454 ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]);
11455
11456 ln.push_back(ln1[0]);
11457 ln.push_back(ln1[1]);
11458 ln.push_back(ln1[2]);
11459 ln.push_back(ln3[0]);
11460 ln.push_back(ln3[1]);
11461 ln.push_back(ln3[2]);
11462 break;
11463 case VTK_QUADRATIC_QUAD:
11464
11465
11466
11467 vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3],
11468 ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3],
11469 ln4[0], ln4[1], ln4[2], ln4[3]);
11470
11471 ln.push_back(ln1[0]);
11472 ln.push_back(ln1[1]);
11473 ln.push_back(ln1[2]);
11474 ln.push_back(ln1[3]);
11475 ln.push_back(ln3[0]);
11476 ln.push_back(ln3[1]);
11477 ln.push_back(ln3[2]);
11478 ln.push_back(ln3[3]);
11479 break;
11480 case VTK_POLYGON:
11481 break;
11482 default:
11483 break;
11484 }
11485
11486 if (vol)
11487 {
11488 stringstream grpname;
11489 grpname << "jf_";
11490 grpname << idom;
11491 int idg;
11492 string namegrp = grpname.str();
11493 if (!mapOfJunctionGroups.count(namegrp))
11494 mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
11495 SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
11496 if (sgrp)
11497 sgrp->Add(vol->GetID());
11498 }
11499
11500
11501
11502 aFace->ChangeNodes(&ln[0], ln.size());
11503 }
11504 }
11505 return true;
11506 }
11507
11508
11514
11515
11516 bool SMESH_MeshEditor::Make2DMeshFrom3D()
11517 {
11518
11519 SMESHDS_Mesh* aMesh = GetMeshDS();
11520 if (!aMesh)
11521 return false;
11522
11523 int nbFree = 0, nbExisted = 0, nbCreated = 0;
11524 SMDS_VolumeIteratorPtr vIt = aMesh->volumesIterator();
11525 while(vIt->more())
11526 {
11527 const SMDS_MeshVolume* volume = vIt->next();
11528 SMDS_VolumeTool vTool( volume );
11529 vTool.SetExternalNormal();
11530 const bool isPoly = volume->IsPoly();
11531 const bool isQuad = volume->IsQuadratic();
11532 for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
11533 {
11534 if (!vTool.IsFreeFace(iface))
11535 continue;
11536 nbFree++;
11537 vector<const SMDS_MeshNode *> nodes;
11538 int nbFaceNodes = vTool.NbFaceNodes(iface);
11539 const SMDS_MeshNode** faceNodes = vTool.GetFaceNodes(iface);
11540 int inode = 0;
11541 for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1)
11542 nodes.push_back(faceNodes[inode]);
11543 if (isQuad)
11544 for ( inode = 1; inode < nbFaceNodes; inode += 2)
11545 nodes.push_back(faceNodes[inode]);
11546
11547
11548 if (aMesh->FindFace( nodes ) ) {
11549 nbExisted++;
11550 continue;
11551 }
11552 AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1);
11553 nbCreated++;
11554 }
11555 }
11556 return ( nbFree==(nbExisted+nbCreated) );
11557 }
11558
11559 namespace
11560 {
11561 inline const SMDS_MeshNode* getNodeWithSameID(SMESHDS_Mesh* mesh, const SMDS_MeshNode* node)
11562 {
11563 if ( const SMDS_MeshNode* n = mesh->FindNode( node->GetID() ))
11564 return n;
11565 return mesh->AddNodeWithID( node->X(),node->Y(),node->Z(), node->GetID() );
11566 }
11567 }
11568
11584
11585
11586 int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
11587 Bnd_Dimension dimension,
11588 SMESH_Group* group,
11589 SMESH_Mesh* targetMesh,
11590 bool toCopyElements,
11591 bool toCopyExistingBoundary,
11592 bool toAddExistingBondary,
11593 bool aroundElements)
11594 {
11595 SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge;
11596 SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
11597
11598 if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
11599 throw SALOME_Exception(LOCALIZED("wrong element type"));
11600
11601 if ( !targetMesh )
11602 toCopyElements = toCopyExistingBoundary = false;
11603
11604 SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
11605 SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
11606 int nbAddedBnd = 0;
11607
11608
11609 SMESH_MeshEditor* presentEditor;
11610 SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() );
11611 presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2;
11612
11613 SMDS_VolumeTool vTool;
11614 TIDSortedElemSet avoidSet;
11615 const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet;
11616 int inode;
11617
11618 typedef vector<const SMDS_MeshNode*> TConnectivity;
11619
11620 SMDS_ElemIteratorPtr eIt;
11621 if (elements.empty())
11622 eIt = aMesh->elementsIterator(elemType);
11623 else
11624 eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
11625
11626 while (eIt->more())
11627 {
11628 const SMDS_MeshElement* elem = eIt->next();
11629 const int iQuad = elem->IsQuadratic();
11630
11631
11632
11633
11634 vector<const SMDS_MeshElement*> presentBndElems;
11635 vector<TConnectivity> missingBndElems;
11636 TConnectivity nodes;
11637 if ( vTool.Set(elem) )
11638 {
11639 vTool.SetExternalNormal();
11640 const SMDS_MeshElement* otherVol = 0;
11641 for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
11642 {
11643 if ( !vTool.IsFreeFace(iface, &otherVol) &&
11644 ( !aroundElements || elements.count( otherVol )))
11645 continue;
11646 const int nbFaceNodes = vTool.NbFaceNodes(iface);
11647 const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
11648 if ( missType == SMDSAbs_Edge )
11649 {
11650 nodes.resize( 2+iQuad );
11651 for ( int i = 0; i < nbFaceNodes; i += 1+iQuad)
11652 {
11653 for ( int j = 0; j < nodes.size(); ++j )
11654 nodes[j] =nn[i+j];
11655 if ( const SMDS_MeshElement* edge =
11656 aMesh->FindElement(nodes,SMDSAbs_Edge,0))
11657 presentBndElems.push_back( edge );
11658 else
11659 missingBndElems.push_back( nodes );
11660 }
11661 }
11662 else
11663 {
11664 nodes.clear();
11665 for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
11666 nodes.push_back( nn[inode] );
11667 if (iQuad)
11668 for ( inode = 1; inode < nbFaceNodes; inode += 2)
11669 nodes.push_back( nn[inode] );
11670
11671 if (const SMDS_MeshFace * f = aMesh->FindFace( nodes ) )
11672 presentBndElems.push_back( f );
11673 else
11674 missingBndElems.push_back( nodes );
11675
11676 if ( targetMesh != myMesh )
11677 {
11678
11679 const SMDS_MeshElement* edge;
11680 for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
11681 {
11682 if ( iQuad )
11683 edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]);
11684 else
11685 edge = aMesh->FindEdge( nn[inode], nn[inode+1]);
11686 if ( edge && avoidSet.insert( edge ).second )
11687 presentBndElems.push_back( edge );
11688 }
11689 }
11690 }
11691 }
11692 }
11693 else
11694 {
11695 avoidSet.clear(), avoidSet.insert( elem );
11696 int nbNodes = elem->NbCornerNodes();
11697 nodes.resize( 2 );
11698 for ( int i = 0; i < nbNodes; i++ )
11699 {
11700 nodes[0] = elem->GetNode(i);
11701 nodes[1] = elem->GetNode((i+1)%nbNodes);
11702 if ( FindFaceInSet( nodes[0], nodes[1], *elemSet, avoidSet))
11703 continue;
11704
11705
11706
11707 if ( const SMDS_MeshElement* edge =
11708 aMesh->FindElement(nodes,SMDSAbs_Edge,true))
11709 presentBndElems.push_back( edge );
11710 else
11711 missingBndElems.push_back( nodes );
11712 }
11713 }
11714
11715
11716
11717
11718 if ( targetMesh != myMesh )
11719
11720
11721 for ( int i = 0; i < missingBndElems.size(); ++i )
11722 {
11723 TConnectivity& srcNodes = missingBndElems[i];
11724 TConnectivity nodes( srcNodes.size() );
11725 for ( inode = 0; inode < nodes.size(); ++inode )
11726 nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
11727 if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
11728 missType,
11729 true))
11730 continue;
11731 tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
11732 ++nbAddedBnd;
11733 }
11734 else
11735 for ( int i = 0; i < missingBndElems.size(); ++i )
11736 {
11737 TConnectivity& nodes = missingBndElems[i];
11738 if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
11739 missType,
11740 true))
11741 continue;
11742 tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
11743 ++nbAddedBnd;
11744 }
11745
11746
11747
11748
11749 if ( toCopyExistingBoundary )
11750 for ( int i = 0 ; i < presentBndElems.size(); ++i )
11751 {
11752 const SMDS_MeshElement* e = presentBndElems[i];
11753 TConnectivity nodes( e->NbNodes() );
11754 for ( inode = 0; inode < nodes.size(); ++inode )
11755 nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
11756 presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
11757 }
11758 else
11759 for ( int i = 0 ; i < presentBndElems.size(); ++i )
11760 {
11761 presentEditor->myLastCreatedElems.Append(presentBndElems[i]);
11762 }
11763
11764 }
11765
11766
11767
11768
11769 if ( group )
11770 {
11771 if ( SMESHDS_Group* g = dynamic_cast<SMESHDS_Group*>( group->GetGroupDS() ))
11772 for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i )
11773 g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 ));
11774 }
11775 tgtEditor.myLastCreatedElems.Clear();
11776 tgtEditor2.myLastCreatedElems.Clear();
11777
11778
11779
11780
11781 if ( toCopyElements && targetMesh != myMesh )
11782 {
11783 if (elements.empty())
11784 eIt = aMesh->elementsIterator(elemType);
11785 else
11786 eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
11787 while (eIt->more())
11788 {
11789 const SMDS_MeshElement* elem = eIt->next();
11790 TConnectivity nodes( elem->NbNodes() );
11791 for ( inode = 0; inode < nodes.size(); ++inode )
11792 nodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
11793 tgtEditor.AddElement(nodes, elemType, elem->IsPoly());
11794
11795 tgtEditor.myLastCreatedElems.Clear();
11796 }
11797 }
11798 return nbAddedBnd;
11799 }