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 SRC_HYP // data storing ImportSource hyp
125 //================================================================================
127 * \brief _ListenerData holding ImportSource hyp holding in its turn
130 struct _ListenerData : public SMESH_subMeshEventListenerData
132 const StdMeshers_ImportSource1D* _srcHyp;
133 _ListenerData(const StdMeshers_ImportSource1D* h):
134 SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
139 //================================================================================
141 * \brief Container of data dedicated to one source mesh
145 const SMESH_Mesh* _srcMesh;
146 StdMeshers_Import_1D::TNodeNodeMap _n2n;
147 StdMeshers_Import_1D::TElemElemMap _e2e;
149 set< SMESH_subMesh*> _subM; // submeshes relating to this srcMesh
150 set< SMESH_subMesh*> _copyMeshSubM; // submeshes requesting mesh copying
151 set< SMESH_subMesh*> _copyGroupSubM; // submeshes requesting mesh copying
152 set< SMESH_subMesh*> _computedSubM;
154 SMESHDS_SubMesh* _importMeshSubDS; // submesh storing a copy of _srcMesh
155 int _importMeshSubID; // id of _importMeshSubDS
157 _ImportData(const SMESH_Mesh* srcMesh=0):
158 _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
160 void removeImportedMesh( SMESHDS_Mesh* meshDS )
162 if ( !_importMeshSubDS ) return;
163 SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
164 while ( eIt->more() )
165 meshDS->RemoveFreeElement( eIt->next(), _importMeshSubDS, /*fromGroups=*/false );
166 SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
167 while ( nIt->more() )
168 meshDS->RemoveFreeNode( nIt->next(), _importMeshSubDS, /*fromGroups=*/false );
172 void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
174 if ( !srcHyp ) return;
175 SMESH_Mesh* tgtMesh = subM->GetFather();
176 const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
177 const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
178 vector<SMESH_Group*>* groups =
179 const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
182 for ( unsigned i = 0; i < groups->size(); ++i )
183 tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
187 void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
189 if ( !srcHyp ) return;
190 bool toCopyMesh, toCopyGroups;
191 srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
193 if ( toCopyMesh )_copyMeshSubM.insert( sm );
194 else _copyMeshSubM.erase( sm );
196 if ( toCopyGroups ) _copyGroupSubM.insert( sm );
197 else _copyGroupSubM.erase( sm );
200 //================================================================================
202 * Listener notified on events of an imported submesh
204 class _Listener : public SMESH_subMeshEventListener
206 typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
207 TMesh2ImpData _tgtMesh2ImportData;
209 _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false){}
212 // return poiter to a static listener
213 static _Listener* get() { static _Listener theListener; return &theListener; }
215 //--------------------------------------------------------------------------------
217 * \brief Find or create ImportData for given meshes
219 static _ImportData* getImportData(const SMESH_Mesh* srcMesh,
222 list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
223 list< _ImportData >::iterator d = dList.begin();
224 for ( ; d != dList.end(); ++d )
225 if ( d->_srcMesh == srcMesh )
227 dList.push_back(_ImportData(srcMesh));
228 return &dList.back();
231 //--------------------------------------------------------------------------------
233 * \brief Remember an imported mesh and groups
234 * \param smDS - submesh DS holding the imported mesh
235 * \param sm - submesh computed by Import algo
236 * \param srcMeshDS - source mesh
237 * \param srcHyp - ImportSource hypothesis
239 static _ImportData* storeImportSubmesh(SMESH_subMesh* importSub,
240 const SMESH_Mesh* srcMesh,
241 const StdMeshers_ImportSource1D* srcHyp)
243 // set listener to hear events of the submesh computed by "Import" algo
244 importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
246 // set a listener to hear events of the source mesh
247 SMESH_subMesh* smToNotify = importSub;
248 SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1);
249 importSub->SetEventListener
250 ( new SMESH_subMeshEventListener(/*isDeletable=*/true),
251 SMESH_subMeshEventListenerData::MakeData( smToNotify ),
254 // remeber the submesh
255 _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
256 iData->_subM.insert( importSub );
257 iData->trackHypParams( importSub, srcHyp );
258 if ( !importSub->IsEmpty() )
259 iData->_computedSubM.insert( importSub );
260 if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
262 SMESH_Mesh* tgtMesh = importSub->GetFather();
263 iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
264 iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
266 if ( !importSub->IsEmpty() )
267 iData->_computedSubM.insert( importSub );
271 //--------------------------------------------------------------------------------
273 * \brief mark sm as missing src hyp with valid groups
275 static void waitHypModification(SMESH_subMesh* sm)
278 (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
281 //--------------------------------------------------------------------------------
283 * \brief Remove imported mesh and/or groups as soon as no more imported submeshes
285 * \param sm - submesh loosing Import algo
286 * \param data - data holding imported groups
288 void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
290 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
291 list< _ImportData >::iterator d = dList.begin();
292 for ( ; d != dList.end(); ++d )
293 if ( (*d)._subM.erase( sm ))
295 d->_computedSubM.erase( sm );
296 bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
297 bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
299 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
300 if ( rmGroups && data )
301 d->removeGroups( sm, data->_srcHyp );
304 //--------------------------------------------------------------------------------
306 * \brief Remove imported mesh and/or groups and
307 * clear all submeshes with common source mesh
308 * \param sm - cleared submesh
309 * \param data - data holding imported groups
311 void clearSubmesh( SMESH_subMesh* sm, _ListenerData* data )
313 list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ];
314 list< _ImportData >::iterator d = dList.begin();
315 for ( ; d != dList.end(); ++d )
317 if ( !d->_subM.count( sm )) continue;
318 if ( (*d)._computedSubM.erase( sm ) )
320 bool copyMesh = !d->_copyMeshSubM.empty();
324 if ( !d->_computedSubM.empty() )
326 set< SMESH_subMesh*> subs;
327 subs.swap( d->_computedSubM ); // avoid recursion via events
328 while ( !subs.empty() )
330 SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() );
331 _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
333 d->removeGroups( sm, hypData->_srcHyp );
335 subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
338 // remove imported mesh and groups
339 d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
342 d->removeGroups( sm, data->_srcHyp );
346 d->trackHypParams( sm, data->_srcHyp );
351 //--------------------------------------------------------------------------------
353 * \brief Remove imported mesh and/or groups
355 virtual void ProcessEvent(const int event,
357 SMESH_subMesh* subMesh,
358 SMESH_subMeshEventListenerData* data,
359 const SMESH_Hypothesis* /*hyp*/)
361 if ( data && data->myType == WAIT_HYP_MODIF )
363 if ( SMESH_subMesh::MODIF_HYP == event &&
364 SMESH_subMesh::ALGO_EVENT == eventType )
366 SMESH_Gen* gen = subMesh->GetFather()->GetGen();
367 if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape()))
368 algo->SetEventListener( subMesh );
373 SMESH_Gen* gen = subMesh->GetFather()->GetGen();
374 SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(),subMesh->GetSubShape() );
376 if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK ||
377 strncmp( "Import", algo->GetName(), 6 ) != 0 )
379 // treate removal of Import algo from subMesh
380 removeSubmesh( subMesh, (_ListenerData*) data );
382 else if ( subMesh->IsEmpty() )
384 // treate modification of ImportSource hypothesis
385 clearSubmesh( subMesh, (_ListenerData*) data );
387 else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
388 SMESH_subMesh::COMPUTE_EVENT == eventType )
390 // check compute state of all submeshes impoting from same src mesh;
391 // this is to take into account 1D computed submeshes hidden by 2D import algo;
392 // else source mesh is not copied as _subM.size != _computedSubM.size()
393 list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
394 list< _ImportData >::iterator d = dList.begin();
395 for ( ; d != dList.end(); ++d )
396 if ( d->_subM.count( subMesh ))
398 set<SMESH_subMesh*>::iterator smIt = d->_subM.begin();
399 for( ; smIt != d->_subM.end(); ++smIt )
400 if ( (*smIt)->IsMeshComputed() )
401 d->_computedSubM.insert( *smIt);
406 }; // class _Listener
408 //================================================================================
410 * \brief Return an ID of submesh to store nodes and elements of a copied mesh
412 //================================================================================
414 int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
417 // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
418 // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
419 // And this shape must be different from subshapes of the main shape.
420 // So we create a compound containing
421 // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
422 // srcMeshDS->GetPersistentId()
423 // 2) the 1-st vertex of the main shape to assure
424 // SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
425 TopoDS_Shape shapeForSrcMesh;
426 TopTools_IndexedMapOfShape pseudoSubShapes;
427 TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
429 // index of pseudoSubShapes corresponding to srcMeshDS
430 int subIndex = srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
431 int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
433 // try to find already present shapeForSrcMesh
434 SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
435 for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
437 const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
438 if ( s.ShapeType() != TopAbs_COMPOUND ) break;
439 TopoDS_Iterator sSubIt( s );
440 for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
441 if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
442 if ( iSub+1 == nbSubShapes )
448 if ( shapeForSrcMesh.IsNull() )
450 // make a new shapeForSrcMesh
451 BRep_Builder aBuilder;
452 TopoDS_Compound comp;
453 aBuilder.MakeCompound( comp );
454 shapeForSrcMesh = comp;
455 for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
456 aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
457 TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
458 aBuilder.Add( comp, vExp.Current() );
460 SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
461 SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
463 smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
465 // make ordinary submesh from a complex one
466 if ( smDS->IsComplexSubmesh() )
468 list< const SMESHDS_SubMesh* > subSM;
469 SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
470 while ( smIt->more() ) subSM.push_back( smIt->next() );
471 list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
472 for ( ; sub != subSM.end(); ++sub)
473 smDS->RemoveSubMesh( *sub );
478 //================================================================================
480 * \brief Return a submesh to store nodes and elements of a copied mesh
481 * and set event listeners in order to clear
482 * imported mesh and groups as soon as submesh state requires it
484 //================================================================================
486 SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh* srcMesh,
488 const TopoDS_Shape& tgtShape,
489 StdMeshers_Import_1D::TNodeNodeMap*& n2n,
490 StdMeshers_Import_1D::TElemElemMap*& e2e,
493 StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
495 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
497 SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
498 iData->_computedSubM.insert( importedSM );
499 if ( iData->_computedSubM.size() != iData->_subM.size() )
500 return 0; // not all submeshes computed yet
502 toCopyGroups = !iData->_copyGroupSubM.empty();
504 if ( !iData->_copyMeshSubM.empty())
506 // make submesh to store a copied mesh
507 int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
508 SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
510 iData->_importMeshSubID = smID;
511 iData->_importMeshSubDS = subDS;
520 //=============================================================================
522 * Import elements from the other mesh
524 //=============================================================================
526 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
528 if ( !_sourceHyp ) return false;
530 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
531 if ( srcGroups.empty() )
532 return error("Invalid source groups");
534 SMESH_MesherHelper helper(theMesh);
535 helper.SetSubShape(theShape);
536 SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
538 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
539 const double edgeTol = BRep_Tool::Tolerance( geomEdge );
540 const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
542 set<int> subShapeIDs;
543 subShapeIDs.insert( shapeID );
545 // get nodes on vertices
546 list < SMESH_MeshEditor::TNodeXYZ > vertexNodes;
547 list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt;
548 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
549 for ( ; vExp.More(); vExp.Next() )
551 const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
552 if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
553 continue; // closed edge
554 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
557 _gen->Compute(theMesh,v,/*anUpward=*/true);
558 n = SMESH_Algo::VertexNode( v, tgtMesh );
559 if ( !n ) return false; // very strange
561 vertexNodes.push_back( SMESH_MeshEditor::TNodeXYZ( n ));
564 // import edges from groups
567 for ( int iG = 0; iG < srcGroups.size(); ++iG )
569 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
571 const int meshID = srcGroup->GetMesh()->GetPersistentId();
572 const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
573 if ( !srcMesh ) continue;
574 getMaps( srcMesh, &theMesh, n2n, e2e );
576 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
577 vector<const SMDS_MeshNode*> newNodes;
578 SMDS_MeshNode tmpNode(0,0,0);
580 while ( srcElems->more() ) // loop on group contents
582 const SMDS_MeshElement* edge = srcElems->next();
583 // find or create nodes of a new edge
584 newNodes.resize( edge->NbNodes() );
586 SMDS_MeshElement::iterator node = edge->begin_nodes();
587 for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
589 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
592 if ( !subShapeIDs.count( n2nIt->second->GetPosition()->GetShapeId() ))
597 // find an existing vertex node
598 for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
599 if ( vNIt->SquareDistance( *node ) < 10 * edgeTol * edgeTol)
601 (*n2nIt).second = vNIt->_node;
602 vertexNodes.erase( vNIt );
606 if ( !n2nIt->second )
608 // find out if node lies on theShape
609 tmpNode.setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
610 if ( helper.CheckNodeU( geomEdge, &tmpNode, u, 10 * edgeTol, /*force=*/true ))
612 SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
613 n2nIt->second = newNode;
614 tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
617 if ( !(newNodes[i] = n2nIt->second ))
620 if ( !newNodes.back() )
621 continue; // not all nodes of edge lie on theShape
624 SMDS_MeshElement * newEdge;
625 if ( newNodes.size() == 3 )
626 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
628 newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
629 tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
630 e2e->insert( make_pair( edge, newEdge ));
634 return error("Empty source groups");
636 // check if the whole geom edge is covered by imported segments;
637 // the check consist in passing by segments from one vetrex node to another
638 bool isEdgeMeshed = false;
639 if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
641 const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
642 const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
643 const SMDS_MeshElement* seg = 0;
644 SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
645 while ( segIt->more() && !seg )
646 if ( !tgtSM->Contains( seg = segIt->next()))
648 int nbPassedSegs = 0;
652 const SMDS_MeshNode* n2 = seg->GetNode(0);
653 n = ( n2 == n ? seg->GetNode(1) : n2 );
654 if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
656 const SMDS_MeshElement* seg2 = 0;
657 segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
658 while ( segIt->more() && !seg2 )
659 if ( seg == ( seg2 = segIt->next()))
663 if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
664 return error( "Source elements overlap one another");
666 isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
667 n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
670 return error( "Source elements don't cover totally the geometrical edge" );
673 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
674 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
675 importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
680 //================================================================================
682 * \brief Copy mesh and groups
684 //================================================================================
686 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh* srcMesh,
687 SMESH_Mesh & tgtMesh,
688 StdMeshers_ImportSource1D* srcHyp,
689 const TopoDS_Shape& tgtShape)
691 // get submesh to store the imported mesh
695 SMESHDS_SubMesh* tgtSubMesh =
696 getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
697 if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
698 return; // not to copy srcMeshDS twice
700 SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
701 SMESH_MeshEditor additor( &tgtMesh );
705 vector<const SMDS_MeshNode*> newNodes;
706 const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
707 SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
708 while ( eIt->more() )
710 const SMDS_MeshElement* elem = eIt->next();
711 TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
712 if ( e2eIt->second ) continue; // already copied by Compute()
713 newNodes.resize( elem->NbNodes() );
714 SMDS_MeshElement::iterator node = elem->begin_nodes();
715 for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
717 TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
718 if ( !n2nIt->second )
720 (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
721 tgtSubMesh->AddNode( n2nIt->second );
723 newNodes[i] = n2nIt->second;
725 const SMDS_MeshElement* newElem =
726 tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
729 newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
730 tgtSubMesh->AddElement( newElem );
733 (*e2eIt).second = newElem;
736 if ( srcMeshDS->NbNodes() > n2n->size() )
738 SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
741 const SMDS_MeshNode* node = nIt->next();
742 if ( node->NbInverseElements() == 0 )
744 const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
745 n2n->insert( make_pair( node, newNode ));
746 tgtSubMesh->AddNode( newNode );
753 vector<SMESH_Group*> resultGroups;
756 // collect names of existing groups to assure uniqueness of group names within a type
757 map< SMDSAbs_ElementType, set<string> > namesByType;
758 SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
759 while ( groupIt->more() )
761 SMESH_Group* tgtGroup = groupIt->next();
762 namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
766 SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
767 while ( groupIt->more() )
769 SMESH_Group* srcGroup = groupIt->next();
770 SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
771 string name = srcGroup->GetName();
773 while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
774 name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
775 SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
776 SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
777 resultGroups.push_back( newGroup );
779 eIt = srcGroupDS->GetElements();
780 if ( srcGroupDS->GetType() == SMDSAbs_Node )
783 TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
784 if ( n2nIt != n2n->end() && n2nIt->second )
785 newGroupDS->SMDSGroup().Add((*n2nIt).second );
790 TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
791 if ( e2eIt != e2e->end() && e2eIt->second )
792 newGroupDS->SMDSGroup().Add((*e2eIt).second );
800 // Remember created groups in order to remove them as soon as the srcHyp is
801 // modified or something other similar happens. Store them in a hypothesis
802 // as it stores its values anyway
803 srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
806 //=============================================================================
808 * \brief Set needed event listeners and create a submesh for a copied mesh
810 * This method is called only if a submesh has HYP_OK algo_state.
812 //=============================================================================
814 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh* subMesh,
815 StdMeshers_ImportSource1D* sourceHyp)
819 vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
820 if ( srcMeshes.empty() )
821 _Listener::waitHypModification( subMesh );
822 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
823 // set a listener to remove the imported mesh and groups
824 _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
827 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
831 const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
832 SMESH_Mesh* tgtMesh = subMesh->GetFather();
833 Hypothesis_Status aStatus;
834 CheckHypothesis( *tgtMesh, tgtShape, aStatus );
836 setEventListener( subMesh, _sourceHyp );
839 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
841 SetEventListener(subMesh);
844 //=============================================================================
846 * Predict nb of mesh entities created by Compute()
848 //=============================================================================
850 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh & theMesh,
851 const TopoDS_Shape & theShape,
852 MapShapeNbElems& aResMap)
854 if ( !_sourceHyp ) return false;
856 const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
857 if ( srcGroups.empty() )
858 return error("Invalid source groups");
860 vector<int> aVec(SMDSEntity_Last,0);
862 bool toCopyMesh, toCopyGroups;
863 _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
864 if ( toCopyMesh ) // the whole mesh is copied
866 vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
867 for ( unsigned i = 0; i < srcMeshes.size(); ++i )
869 SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
870 if ( !sm || aResMap.count( sm )) continue; // already counted
871 aVec.assign( SMDSEntity_Last, 0);
872 const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
873 for (int i = 0; i < SMDSEntity_Last; i++)
874 aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
879 SMESH_MesherHelper helper(theMesh);
881 const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
882 const double edgeTol = helper.MaxTolerance( geomEdge );
884 // take into account nodes on vertices
885 TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
886 for ( ; vExp.More(); vExp.Next() )
887 theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
889 // count edges imported from groups
890 int nbEdges = 0, nbQuadEdges = 0;
891 for ( int iG = 0; iG < srcGroups.size(); ++iG )
893 const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
894 SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
895 SMDS_MeshNode tmpNode(0,0,0);
896 while ( srcElems->more() ) // loop on group contents
898 const SMDS_MeshElement* edge = srcElems->next();
899 // find out if edge is located on geomEdge by projecting
900 // a middle of edge to geomEdge
901 SMESH_MeshEditor::TNodeXYZ p1( edge->GetNode(0));
902 SMESH_MeshEditor::TNodeXYZ p2( edge->GetNode(1));
903 gp_XYZ middle = ( p1 + p2 ) / 2.;
904 tmpNode.setXYZ( middle.X(), middle.Y(), middle.Z());
906 if ( helper.CheckNodeU( geomEdge, &tmpNode, u, 10 * edgeTol, /*force=*/true ))
907 ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
911 int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
913 aVec[SMDSEntity_Node ] = nbNodes;
914 aVec[SMDSEntity_Edge ] = nbEdges;
915 aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
918 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
919 aResMap.insert(make_pair(sm,aVec));
924 //================================================================================
926 * \brief Return node-node and element-element maps for import of geiven source mesh
928 //================================================================================
930 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
935 _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
938 if ( iData->_copyMeshSubM.empty() )
945 //================================================================================
947 * \brief Return submesh corresponding to the copied mesh
949 //================================================================================
951 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
952 SMESH_Mesh& srcMesh )
954 _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
955 if ( iData->_copyMeshSubM.empty() ) return 0;
956 SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );