1 // Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SMESH SMESH : implementaion of SMESH idl descriptions
24 // File : StdMeshers_Import_1D.cxx
27 #include "StdMeshers_Import_1D.hxx"
28 #include "StdMeshers_ImportSource.hxx"
30 #include "SMDS_MeshElement.hxx"
31 #include "SMDS_MeshNode.hxx"
32 #include "SMESHDS_Group.hxx"
33 #include "SMESHDS_Mesh.hxx"
34 #include "SMESH_Comment.hxx"
35 #include "SMESH_Gen.hxx"
36 #include "SMESH_Group.hxx"
37 #include "SMESH_HypoFilter.hxx"
38 #include "SMESH_Mesh.hxx"
39 #include "SMESH_MesherHelper.hxx"
40 #include "SMESH_subMesh.hxx"
41 #include "SMESH_subMeshEventListener.hxx"
43 #include "Utils_SALOME_Exception.hxx"
44 #include "utilities.h"
46 #include <BRep_Builder.hxx>
47 #include <BRep_Tool.hxx>
49 #include <TopExp_Explorer.hxx>
51 #include <TopoDS_Compound.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Vertex.hxx>
57 //=============================================================================
59 * Creates StdMeshers_Import_1D
61 //=============================================================================
63 StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen * gen)
64 :SMESH_1D_Algo(hypId, studyId, gen), _sourceHyp(0)
66 MESSAGE("StdMeshers_Import_1D::StdMeshers_Import_1D");
68 _shapeType = (1 << TopAbs_EDGE);
70 _compatibleHypothesis.push_back("ImportSource1D");
73 //=============================================================================
75 * Check presence of a hypothesis
77 //=============================================================================
79 bool StdMeshers_Import_1D::CheckHypothesis
81 const TopoDS_Shape& aShape,
82 SMESH_Hypothesis::Hypothesis_Status& aStatus)
86 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
87 if ( hyps.size() == 0 )
89 aStatus = SMESH_Hypothesis::HYP_MISSING;
90 return false; // can't work with no hypothesis
93 if ( hyps.size() > 1 )
95 aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
99 const SMESHDS_Hypothesis *theHyp = hyps.front();
101 string hypName = theHyp->GetName();
103 if (hypName == _compatibleHypothesis.front())
105 _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
106 aStatus = SMESH_Hypothesis::HYP_OK;
110 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
114 //================================================================================
115 namespace // INTERNAL STUFF
116 //================================================================================
118 int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
120 enum _ListenerDataType
122 WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
123 LISTEN_SRC_MESH, // data storing submesh depending on source mesh state
124 SRC_HYP // data storing ImportSource hyp
126 //================================================================================
128 * \brief _ListenerData holding ImportSource hyp holding in its turn
131 struct _ListenerData : public SMESH_subMeshEventListenerData
133 const StdMeshers_ImportSource1D* _srcHyp;
134 _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP):
135 SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
140 //================================================================================
142 * \brief Comparator of sub-meshes
146 bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const
148 if ( sm1 == sm2 ) return false;
149 if ( !sm1 || !sm2 ) return sm1 < sm2;
150 const TopoDS_Shape& s1 = sm1->GetSubShape();
151 const TopoDS_Shape& s2 = sm2->GetSubShape();
152 TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType();
153 TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType();
156 return t1 < t2; // to have: face < edge
159 //================================================================================
161 * \brief Container of data dedicated to one source mesh
165 const SMESH_Mesh* _srcMesh;
166 StdMeshers_Import_1D::TNodeNodeMap _n2n;
167 StdMeshers_Import_1D::TElemElemMap _e2e;
169 set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh
170 set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying
171 set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting mesh copying
172 set< SMESH_subMesh*, _SubLess > _computedSubM;
174 SMESHDS_SubMesh* _importMeshSubDS; // submesh storing a copy of _srcMesh
175 int _importMeshSubID; // id of _importMeshSubDS
177 _ImportData(const SMESH_Mesh* srcMesh=0):
178 _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
180 void removeImportedMesh( SMESHDS_Mesh* meshDS )
182 if ( !_importMeshSubDS ) return;
183 SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
184 while ( eIt->more() )
185 meshDS->RemoveFreeElement( eIt->next(), _importMeshSubDS, /*fromGroups=*/false );
186 SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
187 while ( nIt->more() )
188 meshDS->RemoveFreeNode( nIt->next(), _importMeshSubDS, /*fromGroups=*/false );
192 void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
194 if ( !srcHyp ) return;
195 SMESH_Mesh* tgtMesh = subM->GetFather();
196 const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
197 const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
198 vector<SMESH_Group*>* groups =
199 const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
202 for ( unsigned i = 0; i < groups->size(); ++i )
203 tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
207 void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
209 if ( !srcHyp ) return;
210 bool toCopyMesh, toCopyGroups;
211 srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
213 if ( toCopyMesh )_copyMeshSubM.insert( sm );
214 else _copyMeshSubM.erase( sm );
216 if ( toCopyGroups ) _copyGroupSubM.insert( sm );
217 else _copyGroupSubM.erase( sm );
219 void addComputed( SMESH_subMesh* sm )
221 SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
222 /*complexShapeFirst=*/true);
223 while ( smIt->more() )
226 switch ( sm->GetSubShape().ShapeType() )
231 if ( !sm->IsEmpty() )
232 _computedSubM.insert( sm );
240 //================================================================================
242 * Listener notified on events relating to imported submesh
244 class _Listener : public SMESH_subMeshEventListener
246 typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
247 TMesh2ImpData _tgtMesh2ImportData;
249 _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false){}
252 // return poiter to a static listener
253 static _Listener* get() { static _Listener theListener; return &theListener; }
255 static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
257 static void storeImportSubmesh(SMESH_subMesh* importSub,
258 const SMESH_Mesh* srcMesh,
259 const StdMeshers_ImportSource1D* srcHyp);
261 virtual void ProcessEvent(const int event,
263 SMESH_subMesh* subMesh,
264 SMESH_subMeshEventListenerData* data,
265 const SMESH_Hypothesis* hyp);
266 void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
267 void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
269 // mark sm as missing src hyp with valid groups
270 static void waitHypModification(SMESH_subMesh* sm)
273 (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
276 //--------------------------------------------------------------------------------
278 * \brief Find or create ImportData for given meshes
280 _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
283 list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
284 list< _ImportData >::iterator d = dList.begin();
285 for ( ; d != dList.end(); ++d )
286 if ( d->_srcMesh == srcMesh )
288 dList.push_back(_ImportData(srcMesh));
289 return &dList.back();
292 //--------------------------------------------------------------------------------
294 * \brief Remember an imported sub-mesh and set needed even listeners
295 * \param importSub - submesh computed by Import algo
296 * \param srcMesh - source mesh
297 * \param srcHyp - ImportSource hypothesis
299 void _Listener::storeImportSubmesh(SMESH_subMesh* importSub,
300 const SMESH_Mesh* srcMesh,
301 const StdMeshers_ImportSource1D* srcHyp)
303 // set listener to hear events of the submesh computed by "Import" algo
304 importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
306 // set a listener to hear events of the source mesh
307 SMESH_subMesh* smToNotify = importSub;
308 SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1);
309 SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
310 data->mySubMeshes.push_back( smToNotify );
311 importSub->SetEventListener( get(), data, smToListen );
313 // remeber the submesh importSub and its sub-submeshes
314 _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
315 iData->trackHypParams( importSub, srcHyp );
316 iData->addComputed( importSub );
317 if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
319 SMESH_Mesh* tgtMesh = importSub->GetFather();
320 iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
321 iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
324 //--------------------------------------------------------------------------------
326 * \brief Remove imported mesh and/or groups if needed
327 * \param sm - submesh loosing Import algo
328 * \param data - data holding imported groups
330 void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
332 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
333 list< _ImportData >::iterator d = dList.begin();
334 for ( ; d != dList.end(); ++d )
335 if ( (*d)._subM.erase( sm ))
337 d->_computedSubM.erase( sm );
338 bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
339 bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
341 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
342 if ( rmGroups && data )
343 d->removeGroups( sm, data->_srcHyp );
346 //--------------------------------------------------------------------------------
348 * \brief Clear submeshes and remove imported mesh and/or groups if necessary
349 * \param sm - cleared submesh
350 * \param data - data holding imported groups
352 void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
354 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
355 list< _ImportData >::iterator d = dList.begin();
356 for ( ; d != dList.end(); ++d )
358 if ( !d->_subM.count( sm )) continue;
359 if ( (*d)._computedSubM.erase( sm ) )
361 bool copyMesh = !d->_copyMeshSubM.empty();
362 if ( copyMesh || clearAllSub )
364 // remove imported mesh and groups
365 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
368 d->removeGroups( sm, data->_srcHyp );
370 // clear the rest submeshes
371 if ( !d->_computedSubM.empty() )
373 set< SMESH_subMesh*, _SubLess> subs;
374 subs.swap( d->_computedSubM ); // avoid recursion via events
375 while ( !subs.empty() )
377 SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() );
378 _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
380 d->removeGroups( sm, hypData->_srcHyp );
382 subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
383 if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
384 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
388 sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
389 if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
390 sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
393 d->trackHypParams( sm, data->_srcHyp );
398 //--------------------------------------------------------------------------------
400 * \brief Remove imported mesh and/or groups
402 void _Listener::ProcessEvent(const int event,
404 SMESH_subMesh* subMesh,
405 SMESH_subMeshEventListenerData* data,
406 const SMESH_Hypothesis* /*hyp*/)
408 if ( data && data->myType == WAIT_HYP_MODIF )
410 // event of Import submesh
411 if ( SMESH_subMesh::MODIF_HYP == event &&
412 SMESH_subMesh::ALGO_EVENT == eventType )
414 // re-call SetEventListener() to take into account valid parameters
415 // of ImportSource hypothesis
416 SMESH_Gen* gen = subMesh->GetFather()->GetGen();
417 if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape()))
418 algo->SetEventListener( subMesh );
421 else if ( data && data->myType == LISTEN_SRC_MESH )
423 // event of source mesh
424 if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
427 case SMESH_subMesh::CLEAN:
428 // source mesh cleaned -> clean target mesh
429 clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
431 case SMESH_subMesh::SUBMESH_COMPUTED: {
432 // source mesh computed -> reset FAILED state of Import submeshes to
434 SMESH_Mesh* srcMesh = subMesh->GetFather();
435 if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
437 SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
438 if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
440 sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
441 sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
450 else // event of Import submesh
452 // find out what happens: import hyp modified or removed
453 bool removeImport = false, modifHyp = false;
454 if ( SMESH_subMesh::ALGO_EVENT == eventType )
456 if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
460 else if ( SMESH_subMesh::REMOVE_ALGO == event ||
461 SMESH_subMesh::REMOVE_FATHER_ALGO == event )
463 SMESH_Gen* gen = subMesh->GetFather()->GetGen();
464 SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(),subMesh->GetSubShape() );
465 removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
470 // treate removal of Import algo from subMesh
471 removeSubmesh( subMesh, (_ListenerData*) data );
475 // treate modification of ImportSource hypothesis
476 clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
478 else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
479 SMESH_subMesh::COMPUTE_EVENT == eventType )
481 // check compute state of all submeshes impoting from same src mesh;
482 // this is to take into account 1D computed submeshes hidden by 2D import algo;
483 // else source mesh is not copied as _subM.size != _computedSubM.size()
484 list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
485 list< _ImportData >::iterator d = dList.begin();
486 for ( ; d != dList.end(); ++d )
487 if ( d->_subM.count( subMesh ))
489 set<SMESH_subMesh*>::iterator smIt = d->_subM.begin();
490 for( ; smIt != d->_subM.end(); ++smIt )
491 if ( (*smIt)->IsMeshComputed() )
492 d->_computedSubM.insert( *smIt);
498 //================================================================================
500 * \brief Return an ID of submesh to store nodes and elements of a copied mesh
502 //================================================================================
504 int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
507 // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
508 // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
509 // And this shape must be different from subshapes of the main shape.
510 // So we create a compound containing
511 // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
512 // srcMeshDS->GetPersistentId()
513 // 2) the 1-st vertex of the main shape to assure
514 // SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
515 TopoDS_Shape shapeForSrcMesh;
516 TopTools_IndexedMapOfShape pseudoSubShapes;
517 TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
519 // index of pseudoSubShapes corresponding to srcMeshDS
520 int subIndex = srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
521 int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
523 // try to find already present shapeForSrcMesh
524 SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
525 for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
527 const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
528 if ( s.ShapeType() != TopAbs_COMPOUND ) break;
529 TopoDS_Iterator sSubIt( s );
530 for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
531 if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
532 if ( iSub+1 == nbSubShapes )
538 if ( shapeForSrcMesh.IsNull() )
540 // make a new shapeForSrcMesh
541 BRep_Builder aBuilder;
542 TopoDS_Compound comp;
543 aBuilder.MakeCompound( comp );
544 shapeForSrcMesh = comp;
545 for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
546 aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
547 TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
548 aBuilder.Add( comp, vExp.Current() );
550 SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
551 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
553 smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
555 // make ordinary submesh from a complex one
556 if ( smDS->IsComplexSubmesh() )
558 list< const SMESHDS_SubMesh* > subSM;
559 SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
560 while ( smIt->more() ) subSM.push_back( smIt->next() );
561 list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
562 for ( ; sub != subSM.end(); ++sub)
563 smDS->RemoveSubMesh( *sub );
568 //================================================================================
570 * \brief Return a submesh to store nodes and elements of a copied mesh
571 * and set event listeners in order to clear
572 * imported mesh and groups as soon as submesh state requires it
574 //================================================================================
576 SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh* srcMesh,
578 const TopoDS_Shape& tgtShape,
579 StdMeshers_Import_1D::TNodeNodeMap*& n2n,
580 StdMeshers_Import_1D::TElemElemMap*& e2e,
583 StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
585 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
587 SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
588 iData->addComputed( importedSM );
589 if ( iData->_computedSubM.size() != iData->_subM.size() )
590 return 0; // not all submeshes computed yet
592 toCopyGroups = !iData->_copyGroupSubM.empty();
594 if ( !iData->_copyMeshSubM.empty())
596 // make submesh to store a copied mesh
597 int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
598 SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
600 iData->_importMeshSubID = smID;
601 iData->_importMeshSubDS = subDS;
610 //=============================================================================
612 * Import elements from the other mesh
614 //=============================================================================
616 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
618 if ( !_sourceHyp ) return false;
620 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
621 if ( srcGroups.empty() )
622 return error("Invalid source groups");
624 SMESH_MesherHelper helper(theMesh);
625 helper.SetSubShape(theShape);
626 SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
628 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
629 const double edgeTol = BRep_Tool::Tolerance( geomEdge );
630 const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
632 set<int> subShapeIDs;
633 subShapeIDs.insert( shapeID );
635 // get nodes on vertices
636 list < SMESH_TNodeXYZ > vertexNodes;
637 list < SMESH_TNodeXYZ >::iterator vNIt;
638 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
639 for ( ; vExp.More(); vExp.Next() )
641 const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
642 if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
643 continue; // closed edge
644 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
647 _gen->Compute(theMesh,v,/*anUpward=*/true);
648 n = SMESH_Algo::VertexNode( v, tgtMesh );
649 if ( !n ) return false; // very strange
651 vertexNodes.push_back( SMESH_TNodeXYZ( n ));
654 // import edges from groups
657 for ( int iG = 0; iG < srcGroups.size(); ++iG )
659 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
661 const int meshID = srcGroup->GetMesh()->GetPersistentId();
662 const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
663 if ( !srcMesh ) continue;
664 getMaps( srcMesh, &theMesh, n2n, e2e );
666 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
667 vector<const SMDS_MeshNode*> newNodes;
668 SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
670 while ( srcElems->more() ) // loop on group contents
672 const SMDS_MeshElement* edge = srcElems->next();
673 // find or create nodes of a new edge
674 newNodes.resize( edge->NbNodes() );
676 SMDS_MeshElement::iterator node = edge->begin_nodes();
677 for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
679 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
682 if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
687 // find an existing vertex node
688 for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
689 if ( vNIt->SquareDistance( *node ) < 10 * edgeTol * edgeTol)
691 (*n2nIt).second = vNIt->_node;
692 vertexNodes.erase( vNIt );
696 if ( !n2nIt->second )
698 // find out if node lies on theShape
699 tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
700 if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
702 SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
703 n2nIt->second = newNode;
704 tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
707 if ( !(newNodes[i] = n2nIt->second ))
710 if ( !newNodes.back() )
711 continue; // not all nodes of edge lie on theShape
714 SMDS_MeshElement * newEdge;
715 if ( newNodes.size() == 3 )
716 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
718 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
719 tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
720 e2e->insert( make_pair( edge, newEdge ));
722 helper.GetMeshDS()->RemoveNode(tmpNode);
725 return error("Empty source groups");
727 // check if the whole geom edge is covered by imported segments;
728 // the check consist in passing by segments from one vetrex node to another
729 bool isEdgeMeshed = false;
730 if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
732 const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
733 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
734 const SMDS_MeshElement* seg = 0;
735 SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
736 while ( segIt->more() && !seg )
737 if ( !tgtSM->Contains( seg = segIt->next()))
739 int nbPassedSegs = 0;
743 const SMDS_MeshNode* n2 = seg->GetNode(0);
744 n = ( n2 == n ? seg->GetNode(1) : n2 );
745 if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
747 const SMDS_MeshElement* seg2 = 0;
748 segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
749 while ( segIt->more() && !seg2 )
750 if ( seg == ( seg2 = segIt->next()))
754 if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
755 return error( "Source elements overlap one another");
757 isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
758 n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
761 return error( "Source elements don't cover totally the geometrical edge" );
764 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
765 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
766 importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
771 //================================================================================
773 * \brief Copy mesh and groups
775 //================================================================================
777 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh* srcMesh,
778 SMESH_Mesh & tgtMesh,
779 StdMeshers_ImportSource1D* srcHyp,
780 const TopoDS_Shape& tgtShape)
782 // get submesh to store the imported mesh
786 SMESHDS_SubMesh* tgtSubMesh =
787 getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
788 if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
789 return; // not to copy srcMeshDS twice
791 SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
792 SMESH_MeshEditor additor( &tgtMesh );
796 vector<const SMDS_MeshNode*> newNodes;
797 const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
798 SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
799 while ( eIt->more() )
801 const SMDS_MeshElement* elem = eIt->next();
802 TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
803 if ( e2eIt->second ) continue; // already copied by Compute()
804 newNodes.resize( elem->NbNodes() );
805 SMDS_MeshElement::iterator node = elem->begin_nodes();
806 for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
808 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
809 if ( !n2nIt->second )
811 (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
812 tgtSubMesh->AddNode( n2nIt->second );
814 newNodes[i] = n2nIt->second;
816 const SMDS_MeshElement* newElem =
817 tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
820 newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
821 tgtSubMesh->AddElement( newElem );
824 (*e2eIt).second = newElem;
827 if ( srcMeshDS->NbNodes() > n2n->size() )
829 SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
832 const SMDS_MeshNode* node = nIt->next();
833 if ( node->NbInverseElements() == 0 )
835 const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
836 n2n->insert( make_pair( node, newNode ));
837 tgtSubMesh->AddNode( newNode );
844 vector<SMESH_Group*> resultGroups;
847 // collect names of existing groups to assure uniqueness of group names within a type
848 map< SMDSAbs_ElementType, set<string> > namesByType;
849 SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
850 while ( groupIt->more() )
852 SMESH_Group* tgtGroup = groupIt->next();
853 namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
857 SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
858 while ( groupIt->more() )
860 SMESH_Group* srcGroup = groupIt->next();
861 SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
862 string name = srcGroup->GetName();
864 while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
865 name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
866 SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
867 SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
868 resultGroups.push_back( newGroup );
870 eIt = srcGroupDS->GetElements();
871 if ( srcGroupDS->GetType() == SMDSAbs_Node )
874 TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
875 if ( n2nIt != n2n->end() && n2nIt->second )
876 newGroupDS->SMDSGroup().Add((*n2nIt).second );
881 TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
882 if ( e2eIt != e2e->end() && e2eIt->second )
883 newGroupDS->SMDSGroup().Add((*e2eIt).second );
891 // Remember created groups in order to remove them as soon as the srcHyp is
892 // modified or something other similar happens. Store them in a hypothesis
893 // as it stores its values anyway
894 srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
897 //=============================================================================
899 * \brief Set needed event listeners and create a submesh for a copied mesh
901 * This method is called only if a submesh has HYP_OK algo_state.
903 //=============================================================================
905 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh* subMesh,
906 StdMeshers_ImportSource1D* sourceHyp)
910 vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
911 if ( srcMeshes.empty() )
912 _Listener::waitHypModification( subMesh );
913 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
914 // set a listener to remove the imported mesh and groups
915 _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
918 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
922 const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
923 SMESH_Mesh* tgtMesh = subMesh->GetFather();
924 Hypothesis_Status aStatus;
925 CheckHypothesis( *tgtMesh, tgtShape, aStatus );
927 setEventListener( subMesh, _sourceHyp );
930 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
932 SetEventListener(subMesh);
935 //=============================================================================
937 * Predict nb of mesh entities created by Compute()
939 //=============================================================================
941 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh & theMesh,
942 const TopoDS_Shape & theShape,
943 MapShapeNbElems& aResMap)
945 if ( !_sourceHyp ) return false;
947 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
948 if ( srcGroups.empty() )
949 return error("Invalid source groups");
951 vector<int> aVec(SMDSEntity_Last,0);
953 bool toCopyMesh, toCopyGroups;
954 _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
955 if ( toCopyMesh ) // the whole mesh is copied
957 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
958 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
960 SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
961 if ( !sm || aResMap.count( sm )) continue; // already counted
962 aVec.assign( SMDSEntity_Last, 0);
963 const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
964 for (int i = 0; i < SMDSEntity_Last; i++)
965 aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
970 SMESH_MesherHelper helper(theMesh);
972 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
973 const double edgeTol = helper.MaxTolerance( geomEdge );
975 // take into account nodes on vertices
976 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
977 for ( ; vExp.More(); vExp.Next() )
978 theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
980 // count edges imported from groups
981 int nbEdges = 0, nbQuadEdges = 0;
982 for ( int iG = 0; iG < srcGroups.size(); ++iG )
984 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
985 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
986 SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
987 while ( srcElems->more() ) // loop on group contents
989 const SMDS_MeshElement* edge = srcElems->next();
990 // find out if edge is located on geomEdge by projecting
991 // a middle of edge to geomEdge
992 SMESH_TNodeXYZ p1( edge->GetNode(0));
993 SMESH_TNodeXYZ p2( edge->GetNode(1));
994 gp_XYZ middle = ( p1 + p2 ) / 2.;
995 tmpNode->setXYZ( middle.X(), middle.Y(), middle.Z());
997 if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
998 ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
1000 helper.GetMeshDS()->RemoveNode(tmpNode);
1003 int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
1005 aVec[SMDSEntity_Node ] = nbNodes;
1006 aVec[SMDSEntity_Edge ] = nbEdges;
1007 aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
1010 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
1011 aResMap.insert(make_pair(sm,aVec));
1016 //================================================================================
1018 * \brief Return node-node and element-element maps for import of geiven source mesh
1020 //================================================================================
1022 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
1023 SMESH_Mesh* tgtMesh,
1027 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
1030 if ( iData->_copyMeshSubM.empty() )
1037 //================================================================================
1039 * \brief Return submesh corresponding to the copied mesh
1041 //================================================================================
1043 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
1044 SMESH_Mesh& srcMesh )
1046 _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
1047 if ( iData->_copyMeshSubM.empty() ) return 0;
1048 SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );