Salome HOME
22806: EDF SMESH: Regression: Prism_3D error
[modules/smesh.git] / src / StdMeshers / StdMeshers_Import_1D.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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, or (at your option) any later version.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESH : implementaion of SMESH idl descriptions
24 //  File   : StdMeshers_Import_1D.cxx
25 //  Module : SMESH
26 //
27 #include "StdMeshers_Import_1D.hxx"
28 #include "StdMeshers_ImportSource.hxx"
29
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"
42
43 #include "Utils_SALOME_Exception.hxx"
44 #include "utilities.h"
45
46 #include <BRep_Builder.hxx>
47 #include <BRep_Tool.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Compound.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Vertex.hxx>
54
55 using namespace std;
56
57 //=============================================================================
58 /*!
59  * Creates StdMeshers_Import_1D
60  */
61 //=============================================================================
62
63 StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen * gen)
64   :SMESH_1D_Algo(hypId, studyId, gen), _sourceHyp(0)
65 {
66   MESSAGE("StdMeshers_Import_1D::StdMeshers_Import_1D");
67   _name = "Import_1D";
68   _shapeType = (1 << TopAbs_EDGE);
69
70   _compatibleHypothesis.push_back("ImportSource1D");
71 }
72
73 //================================================================================
74 namespace // INTERNAL STUFF
75 //================================================================================
76 {
77   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
78
79   enum _ListenerDataType
80     {
81       WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
82       LISTEN_SRC_MESH, // data storing submesh depending on source mesh state
83       SRC_HYP // data storing ImportSource hyp
84     };
85   //================================================================================
86   /*!
87    * \brief _ListenerData holding ImportSource hyp holding in its turn
88    *  imported groups
89    */
90   struct _ListenerData : public SMESH_subMeshEventListenerData
91   {
92     const StdMeshers_ImportSource1D* _srcHyp;
93     _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP):
94       SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
95     {
96       myType = type;
97     }
98   };
99   //================================================================================
100   /*!
101    * \brief Comparator of sub-meshes
102    */
103   struct _SubLess
104   {
105     bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const
106     {
107       if ( sm1 == sm2 ) return false;
108       if ( !sm1 || !sm2 ) return sm1 < sm2;
109       const TopoDS_Shape& s1 = sm1->GetSubShape();
110       const TopoDS_Shape& s2 = sm2->GetSubShape();
111       TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType();
112       TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType();
113       if ( t1 == t2)
114         return (sm1 < sm2);
115       return t1 < t2; // to have: face < edge
116     }
117   };
118   //================================================================================
119   /*!
120    * \brief Container of data dedicated to one source mesh
121    */
122   struct _ImportData
123   {
124     const SMESH_Mesh* _srcMesh;
125     StdMeshers_Import_1D::TNodeNodeMap _n2n;
126     StdMeshers_Import_1D::TElemElemMap _e2e;
127
128     set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh
129     set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying
130     set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting group copying
131     set< SMESH_subMesh*, _SubLess > _computedSubM;
132
133     SMESHDS_SubMesh*     _importMeshSubDS; // submesh storing a copy of _srcMesh
134     int                  _importMeshSubID; // id of _importMeshSubDS
135
136     _ImportData(const SMESH_Mesh* srcMesh=0):
137       _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
138
139     void removeImportedMesh( SMESHDS_Mesh* meshDS )
140     {
141       if ( !_importMeshSubDS ) return;
142       SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
143       while ( eIt->more() )
144         meshDS->RemoveFreeElement( eIt->next(), 0, /*fromGroups=*/false );
145       SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
146       while ( nIt->more() )
147         meshDS->RemoveFreeNode( nIt->next(), 0, /*fromGroups=*/false );
148       _importMeshSubDS->Clear();
149       _n2n.clear();
150       _e2e.clear();
151     }
152     void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
153     {
154       if ( !srcHyp ) return;
155       SMESH_Mesh*           tgtMesh = subM->GetFather();
156       const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
157       const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
158       vector<SMESH_Group*>*  groups =
159         const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
160       if ( groups )
161       {
162         for ( unsigned i = 0; i < groups->size(); ++i )
163           tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
164         groups->clear();
165       }
166     }
167     void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
168     {
169       if ( !srcHyp ) return;
170       bool toCopyMesh, toCopyGroups;
171       srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
172
173       if ( toCopyMesh )_copyMeshSubM.insert( sm );
174       else             _copyMeshSubM.erase( sm );
175
176       if ( toCopyGroups ) _copyGroupSubM.insert( sm );
177       else                _copyGroupSubM.erase( sm );
178     }
179     void addComputed( SMESH_subMesh* sm )
180     {
181       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
182                                                                /*complexShapeFirst=*/true);
183       while ( smIt->more() )
184       {
185         sm = smIt->next();
186         switch ( sm->GetSubShape().ShapeType() )
187         {
188         case TopAbs_EDGE:
189           if ( SMESH_Algo::isDegenerated( TopoDS::Edge( sm->GetSubShape() )))
190             continue;
191         case TopAbs_FACE:
192           _subM.insert( sm );
193           if ( !sm->IsEmpty() )
194             _computedSubM.insert( sm );
195         case TopAbs_VERTEX:
196           break;
197         default:;
198         }
199       }
200     }
201   };
202   //================================================================================
203   /*!
204    * Listener notified on events relating to imported submesh
205    */
206   class _Listener : public SMESH_subMeshEventListener
207   {
208     typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
209     TMesh2ImpData _tgtMesh2ImportData;
210
211     _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false,
212                                            "StdMeshers_Import_1D::_Listener") {}
213
214   public:
215     // return poiter to a static listener
216     static _Listener* get() { static _Listener theListener; return &theListener; }
217
218     static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
219
220     static void storeImportSubmesh(SMESH_subMesh*                   importSub,
221                                    const SMESH_Mesh*                srcMesh,
222                                    const StdMeshers_ImportSource1D* srcHyp);
223
224     virtual void ProcessEvent(const int                       event,
225                               const int                       eventType,
226                               SMESH_subMesh*                  subMesh,
227                               SMESH_subMeshEventListenerData* data,
228                               const SMESH_Hypothesis*         hyp);
229     void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
230     void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
231     void clearN2N     ( SMESH_Mesh* tgtMesh );
232
233     // mark sm as missing src hyp with valid groups
234     static void waitHypModification(SMESH_subMesh* sm)
235     {
236       sm->SetEventListener
237         (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
238     }
239   };
240   //--------------------------------------------------------------------------------
241   /*!
242    * \brief Find or create ImportData for given meshes
243    */
244   _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
245                                         SMESH_Mesh*       tgtMesh)
246   {
247     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
248     list< _ImportData >::iterator d = dList.begin();
249     for ( ; d != dList.end(); ++d )
250       if ( d->_srcMesh == srcMesh )
251         return &*d;
252     dList.push_back(_ImportData(srcMesh));
253     return &dList.back();
254   }
255
256   //--------------------------------------------------------------------------------
257   /*!
258    * \brief Remember an imported sub-mesh and set needed even listeners
259    *  \param importSub - submesh computed by Import algo
260    *  \param srcMesh - source mesh
261    *  \param srcHyp - ImportSource hypothesis
262    */
263   void _Listener::storeImportSubmesh(SMESH_subMesh*                   importSub,
264                                      const SMESH_Mesh*                srcMesh,
265                                      const StdMeshers_ImportSource1D* srcHyp)
266   {
267     // set listener to hear events of the submesh computed by "Import" algo
268     importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
269
270     // set listeners to hear events of the source mesh
271     SMESH_subMesh* smToNotify = importSub;
272     vector<SMESH_subMesh*> smToListen = srcHyp->GetSourceSubMeshes( srcMesh );
273     for ( size_t i = 0; i < smToListen.size(); ++i )
274     {
275       SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
276       data->mySubMeshes.push_back( smToNotify );
277       importSub->SetEventListener( get(), data, smToListen[i] );
278     }
279     // remember the submesh importSub and its sub-submeshes
280     _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
281     iData->trackHypParams( importSub, srcHyp );
282     iData->addComputed( importSub );
283     if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
284     {
285       SMESH_Mesh* tgtMesh = importSub->GetFather();
286       iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
287       iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
288     }
289   }
290   //--------------------------------------------------------------------------------
291   /*!
292    * \brief Remove imported mesh and/or groups if needed
293    *  \param sm - submesh loosing Import algo
294    *  \param data - data holding imported groups
295    */
296   void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
297   {
298     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
299     list< _ImportData >::iterator d = dList.begin();
300     for ( ; d != dList.end(); ++d )
301       if ( (*d)._subM.erase( sm ))
302       {
303         d->_computedSubM.erase( sm );
304         bool rmMesh   = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
305         bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
306         if ( rmMesh )
307           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
308         if ( rmGroups && data && data->myType == SRC_HYP )
309           d->removeGroups( sm, data->_srcHyp );
310       }
311   }
312   //--------------------------------------------------------------------------------
313   /*!
314    * \brief Clear _ImportData::_n2n.
315    *        _n2n is usefull within one mesh.Compute() only
316    */
317   void _Listener::clearN2N( SMESH_Mesh* tgtMesh )
318   {
319     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
320     list< _ImportData >::iterator d = dList.begin();
321     for ( ; d != dList.end(); ++d )
322       d->_n2n.clear();
323   }
324   //--------------------------------------------------------------------------------
325   /*!
326    * \brief Clear submeshes and remove imported mesh and/or groups if necessary
327    *  \param sm - cleared submesh
328    *  \param data - data holding imported groups
329    */
330   void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
331   {
332     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
333     list< _ImportData >::iterator d = dList.begin();
334     for ( ; d != dList.end(); ++d )
335     {
336       if ( !d->_subM.count( sm )) continue;
337       if ( (*d)._computedSubM.erase( sm ) )
338       {
339         bool copyMesh = !d->_copyMeshSubM.empty();
340         if ( copyMesh || clearAllSub )
341         {
342           // remove imported mesh and groups
343           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
344
345           if ( data && data->myType == SRC_HYP )
346             d->removeGroups( sm, data->_srcHyp );
347
348           // clear the rest submeshes
349           if ( !d->_computedSubM.empty() )
350           {
351             d->_computedSubM.clear();
352             set< SMESH_subMesh*, _SubLess>::iterator sub = d->_subM.begin();
353             for ( ; sub != d->_subM.end(); ++sub )
354             {
355               SMESH_subMesh* subM = *sub;
356               _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
357               if ( hypData && hypData->myType == SRC_HYP )
358                 d->removeGroups( sm, hypData->_srcHyp );
359
360               subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
361               if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
362                 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
363             }
364           }
365         }
366         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
367         if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
368           sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
369       }
370       if ( data && data->myType == SRC_HYP )
371         d->trackHypParams( sm, data->_srcHyp );
372       d->_n2n.clear();
373       d->_e2e.clear();
374     }
375   }
376   //--------------------------------------------------------------------------------
377   /*!
378    * \brief Remove imported mesh and/or groups
379    */
380   void _Listener::ProcessEvent(const int                       event,
381                                const int                       eventType,
382                                SMESH_subMesh*                  subMesh,
383                                SMESH_subMeshEventListenerData* data,
384                                const SMESH_Hypothesis*         /*hyp*/)
385   {
386     if ( data && data->myType == WAIT_HYP_MODIF )
387     {
388       // event of Import submesh
389       if ( SMESH_subMesh::MODIF_HYP  == event &&
390            SMESH_subMesh::ALGO_EVENT == eventType )
391       {
392         // re-call SetEventListener() to take into account valid parameters
393         // of ImportSource hypothesis
394         if ( SMESH_Algo* algo = subMesh->GetAlgo() )
395           algo->SetEventListener( subMesh );
396       }
397     }
398     else if ( data && data->myType == LISTEN_SRC_MESH )
399     {
400       // event of source mesh
401       if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
402       {
403         switch ( event ) {
404         case SMESH_subMesh::CLEAN:
405           // source mesh cleaned -> clean target mesh
406           clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
407           break;
408         case SMESH_subMesh::SUBMESH_COMPUTED: {
409           // source mesh computed -> reset FAILED state of Import submeshes to
410           // READY_TO_COMPUTE
411           SMESH_Mesh* srcMesh = subMesh->GetFather();
412           if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
413           {
414             SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
415             if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
416             {
417               sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
418               sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
419             }
420           }
421           break;
422         }
423         default:;
424         }
425       }
426       if ( !data->mySubMeshes.empty() )
427         clearN2N( data->mySubMeshes.front()->GetFather() );
428     }
429     else // event of Import submesh
430     {
431       // find out what happens: import hyp modified or removed
432       bool removeImport = false, modifHyp = false;
433       if ( SMESH_subMesh::ALGO_EVENT == eventType )
434         modifHyp = true;
435       if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
436       {
437         removeImport = true;
438       }
439       else if (( SMESH_subMesh::REMOVE_ALGO == event ||
440                  SMESH_subMesh::REMOVE_FATHER_ALGO == event ) &&
441                SMESH_subMesh::ALGO_EVENT == eventType )
442       {
443         SMESH_Algo* algo = subMesh->GetAlgo();
444         removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
445       }
446
447       if ( removeImport )
448       {
449         // treate removal of Import algo from subMesh
450         removeSubmesh( subMesh, (_ListenerData*) data );
451       }
452       else if ( modifHyp ||
453                 ( SMESH_subMesh::CLEAN         == event &&
454                   SMESH_subMesh::COMPUTE_EVENT == eventType))
455       {
456         // treate modification of ImportSource hypothesis
457         clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
458       }
459       else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
460                 SMESH_subMesh::COMPUTE_EVENT       == eventType )
461       {
462         // check compute state of all submeshes impoting from same src mesh;
463         // this is to take into account 1D computed submeshes hidden by 2D import algo;
464         // else source mesh is not copied as _subM.size != _computedSubM.size()
465         list< _ImportData > &  dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
466         list< _ImportData >::iterator d = dList.begin();
467         for ( ; d != dList.end(); ++d )
468           if ( d->_subM.count( subMesh ))
469           {
470             set<SMESH_subMesh*,_SubLess>::iterator smIt = d->_subM.begin();
471             for( ; smIt != d->_subM.end(); ++smIt )
472               if ( (*smIt)->IsMeshComputed() )
473                 d->_computedSubM.insert( *smIt);
474           }
475       }
476       // Clear _ImportData::_n2n if it's no more useful, i.e. when
477       // the event is not within mesh.Compute()
478       if ( SMESH_subMesh::ALGO_EVENT == eventType )
479         clearN2N( subMesh->GetFather() );
480     }
481   }
482
483   //================================================================================
484   /*!
485    * \brief Return an ID of submesh to store nodes and elements of a copied mesh
486    */
487   //================================================================================
488
489   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
490                                 SMESH_Mesh*         tgtMesh)
491   {
492     // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
493     // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
494     // And this shape must be different from sub-shapes of the main shape.
495     // So we create a compound containing
496     // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
497     //    srcMeshDS->GetPersistentId()
498     // 2) the 1-st vertex of the main shape to assure
499     //    SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
500     TopoDS_Shape shapeForSrcMesh;
501     TopTools_IndexedMapOfShape pseudoSubShapes;
502     TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
503
504     // index of pseudoSubShapes corresponding to srcMeshDS
505     int    subIndex = 1 + srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
506     int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
507
508     // try to find already present shapeForSrcMesh
509     SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
510     for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
511     {
512       const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
513       if ( s.ShapeType() != TopAbs_COMPOUND ) break;
514       TopoDS_Iterator sSubIt( s );
515       for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
516         if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
517           if ( iSub+1 == nbSubShapes )
518           {
519             shapeForSrcMesh = s;
520             break;
521           }
522     }
523     if ( shapeForSrcMesh.IsNull() )
524     {
525       // make a new shapeForSrcMesh
526       BRep_Builder aBuilder;
527       TopoDS_Compound comp;
528       aBuilder.MakeCompound( comp );
529       shapeForSrcMesh = comp;
530       for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
531         if ( subIndex+iSub <= pseudoSubShapes.Extent() )
532           aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
533       TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
534       aBuilder.Add( comp, vExp.Current() );
535     }
536     SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
537     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
538     if ( !smDS )
539       smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
540
541     // make ordinary submesh from a complex one
542     if ( smDS->IsComplexSubmesh() )
543     {
544       list< const SMESHDS_SubMesh* > subSM;
545       SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
546       while ( smIt->more() ) subSM.push_back( smIt->next() );
547       list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
548       for ( ; sub != subSM.end(); ++sub)
549         smDS->RemoveSubMesh( *sub );
550     }
551     return sm->GetId();
552   }
553
554   //================================================================================
555   /*!
556    * \brief Return a submesh to store nodes and elements of a copied mesh
557    * and set event listeners in order to clear
558    * imported mesh and groups as soon as submesh state requires it
559    */
560   //================================================================================
561
562   SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh*                    srcMesh,
563                                            SMESH_Mesh*                          tgtMesh,
564                                            const TopoDS_Shape&                  tgtShape,
565                                            StdMeshers_Import_1D::TNodeNodeMap*& n2n,
566                                            StdMeshers_Import_1D::TElemElemMap*& e2e,
567                                            bool &                               toCopyGroups)
568   {
569     StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
570
571     _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
572
573     SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
574     iData->addComputed( importedSM );
575     if ( iData->_computedSubM.size() != iData->_subM.size() )
576       return 0; // not all submeshes computed yet
577
578     toCopyGroups = !iData->_copyGroupSubM.empty();
579
580     if ( !iData->_copyMeshSubM.empty())
581     {
582       // make submesh to store a copied mesh
583       int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
584       SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
585
586       iData->_importMeshSubID = smID;
587       iData->_importMeshSubDS = subDS;
588       return subDS;
589     }
590     return 0;
591   }
592
593 } // namespace
594
595 //=============================================================================
596 /*!
597  * Check presence of a hypothesis
598  */
599 //=============================================================================
600
601 bool StdMeshers_Import_1D::CheckHypothesis
602                          (SMESH_Mesh&                          aMesh,
603                           const TopoDS_Shape&                  aShape,
604                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
605 {
606   _sourceHyp = 0;
607
608   const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
609   if ( hyps.size() == 0 )
610   {
611     aStatus = SMESH_Hypothesis::HYP_MISSING;
612     return false;  // can't work with no hypothesis
613   }
614
615   if ( hyps.size() > 1 )
616   {
617     aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
618     return false;
619   }
620
621   const SMESHDS_Hypothesis *theHyp = hyps.front();
622
623   string hypName = theHyp->GetName();
624
625   if (hypName == _compatibleHypothesis.front())
626   {
627     _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
628     aStatus = _sourceHyp->GetGroups().empty() ? HYP_BAD_PARAMETER : HYP_OK;
629     if ( aStatus == HYP_BAD_PARAMETER )
630       _Listener::waitHypModification( aMesh.GetSubMesh( aShape ));
631     return aStatus == HYP_OK;
632   }
633
634   aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
635   return false;
636 }
637
638 //=============================================================================
639 /*!
640  * Import elements from the other mesh
641  */
642 //=============================================================================
643
644 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
645 {
646   if ( !_sourceHyp ) return false;
647
648   //MESSAGE("---------> StdMeshers_Import_1D::Compute");
649   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups(/*loaded=*/true);
650   if ( srcGroups.empty() )
651     return error("Invalid source groups");
652
653   SMESH_MesherHelper helper(theMesh);
654   helper.SetSubShape(theShape);
655   SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
656
657   const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
658   const double edgeTol = BRep_Tool::Tolerance( geomEdge );
659   const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
660
661   set<int> subShapeIDs;
662   subShapeIDs.insert( shapeID );
663
664   // get nodes on vertices
665   list < SMESH_TNodeXYZ > vertexNodes;
666   list < SMESH_TNodeXYZ >::iterator vNIt;
667   TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
668   for ( ; vExp.More(); vExp.Next() )
669   {
670     const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
671     if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
672       continue; // closed edge
673     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
674     if ( !n )
675     {
676       _gen->Compute(theMesh,v,/*anUpward=*/true);
677       n = SMESH_Algo::VertexNode( v, tgtMesh );
678       //MESSAGE("_gen->Compute " << n);
679       if ( !n ) return false; // very strange
680     }
681     vertexNodes.push_back( SMESH_TNodeXYZ( n ));
682     //MESSAGE("SMESH_Algo::VertexNode " << n->GetID() << " " << n->X() << " " << n->Y() << " " << n->Z() );
683   }
684
685   // import edges from groups
686   TNodeNodeMap* n2n;
687   TElemElemMap* e2e;
688   for ( int iG = 0; iG < srcGroups.size(); ++iG )
689   {
690     const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
691
692     const int meshID = srcGroup->GetMesh()->GetPersistentId();
693     const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
694     if ( !srcMesh ) continue;
695     getMaps( srcMesh, &theMesh, n2n, e2e );
696
697     SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
698     vector<const SMDS_MeshNode*> newNodes;
699     SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
700     double u = 0.314159; // "random" value between 0 and 1, avoid 0 and 1, false detection possible on edge restrictions
701     while ( srcElems->more() ) // loop on group contents
702     {
703       const SMDS_MeshElement* edge = srcElems->next();
704       // find or create nodes of a new edge
705       newNodes.resize( edge->NbNodes() );
706       //MESSAGE("edge->NbNodes " << edge->NbNodes());
707       newNodes.back() = 0;
708       SMDS_MeshElement::iterator node = edge->begin_nodes();
709       SMESH_TNodeXYZ a(edge->GetNode(0));
710       // --- define a tolerance relative to the length of an edge
711       double mytol = a.Distance(edge->GetNode(edge->NbNodes()-1))/25;
712       //mytol = max(1.E-5, 10*edgeTol); // too strict and not necessary
713       //MESSAGE("mytol = " << mytol);
714       for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
715       {
716         TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
717         if ( n2nIt->second )
718         {
719           if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
720             break;
721         }
722         else
723         {
724           // find an existing vertex node
725           double checktol = max(1.E-10, 10*edgeTol*edgeTol);
726           for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
727             if ( vNIt->SquareDistance( *node ) < checktol)
728             {
729               //MESSAGE("SquareDistance " << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<<vNIt->X()<<" "<<vNIt->Y()<<" "<<vNIt->Z());
730               (*n2nIt).second = vNIt->_node;
731               vertexNodes.erase( vNIt );
732               break;
733             }
734             else if ( vNIt->SquareDistance( *node ) < 10*checktol)
735               MESSAGE("SquareDistance missed" << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<<vNIt->X()<<" "<<vNIt->Y()<<" "<<vNIt->Z());
736         }
737         if ( !n2nIt->second )
738         {
739           // find out if node lies on theShape
740           //double dxyz[4];
741           tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
742           if ( helper.CheckNodeU( geomEdge, tmpNode, u, mytol, /*force=*/true)) // , dxyz )) // dxyz used for debug purposes
743           {
744             SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
745             n2nIt->second = newNode;
746             tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
747             //MESSAGE("u=" << u << " " << newNode->X()<< " " << newNode->Y()<< " " << newNode->Z());
748             //MESSAGE("d=" << dxyz[0] << " " << dxyz[1] << " " << dxyz[2] << " " << dxyz[3]);
749           }
750         }
751         if ( !(newNodes[i] = n2nIt->second ))
752           break;
753       }
754       if ( !newNodes.back() )
755       {
756         //MESSAGE("not all nodes of edge lie on theShape");
757         continue; // not all nodes of edge lie on theShape
758       }
759
760       // make a new edge
761       SMDS_MeshElement * newEdge;
762       if ( newNodes.size() == 3 )
763         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
764       else
765         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
766       //MESSAGE("add Edge " << newNodes[0]->GetID() << " " << newNodes[1]->GetID());
767       tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
768       e2e->insert( make_pair( edge, newEdge ));
769     }
770     helper.GetMeshDS()->RemoveNode(tmpNode);
771   }
772   if ( n2n->empty())
773     return error("Empty source groups");
774
775   // check if the whole geom edge is covered by imported segments;
776   // the check consist in passing by segments from one vetrex node to another
777   bool isEdgeMeshed = false;
778   if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
779   {
780     const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
781     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
782     const SMDS_MeshElement* seg = 0;
783     SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
784     while ( segIt->more() && !seg )
785       if ( !tgtSM->Contains( seg = segIt->next()))
786         seg = 0;
787     int nbPassedSegs = 0;
788     while ( seg )
789     {
790       ++nbPassedSegs;
791       const SMDS_MeshNode* n2 = seg->GetNode(0);
792       n = ( n2 == n ? seg->GetNode(1) : n2 );
793       if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
794         break;
795       const SMDS_MeshElement* seg2 = 0;
796       segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
797       while ( segIt->more() && !seg2 )
798         if ( seg == ( seg2 = segIt->next()))
799           seg2 = 0;
800       seg = seg2;
801     }
802     if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
803       return error( "Source elements overlap one another");
804
805     isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
806                      n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
807   }
808   if ( !isEdgeMeshed )
809     return error( "Source elements don't cover totally the geometrical edge" );
810
811   // copy meshes
812   vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
813   for ( unsigned i = 0; i < srcMeshes.size(); ++i )
814     importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
815
816   return true;
817 }
818
819 //================================================================================
820 /*!
821  * \brief Copy mesh and groups
822  */
823 //================================================================================
824
825 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
826                                       SMESH_Mesh &               tgtMesh,
827                                       StdMeshers_ImportSource1D* srcHyp,
828                                       const TopoDS_Shape&        tgtShape)
829 {
830   // get submesh to store the imported mesh
831   TNodeNodeMap* n2n;
832   TElemElemMap* e2e;
833   bool toCopyGroups;
834   SMESHDS_SubMesh* tgtSubMesh =
835     getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
836   if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
837     return; // not to copy srcMeshDS twice
838
839   SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
840   SMESH_MeshEditor additor( &tgtMesh );
841
842   // 1. Copy mesh
843
844   vector<const SMDS_MeshNode*> newNodes;
845   const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
846   SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
847   while ( eIt->more() )
848   {
849     const SMDS_MeshElement* elem = eIt->next();
850     TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
851     if ( e2eIt->second ) continue; // already copied by Compute()
852     newNodes.resize( elem->NbNodes() );
853     SMDS_MeshElement::iterator node = elem->begin_nodes();
854     for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
855     {
856       TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
857       if ( !n2nIt->second )
858       {
859         (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
860         tgtSubMesh->AddNode( n2nIt->second );
861       }
862       newNodes[i] = n2nIt->second;
863     }
864     const SMDS_MeshElement* newElem =
865       tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
866     if ( !newElem )
867     {
868       newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
869       tgtSubMesh->AddElement( newElem );
870     }
871     if ( toCopyGroups )
872       (*e2eIt).second = newElem;
873   }
874   // copy free nodes
875   if ( srcMeshDS->NbNodes() > n2n->size() )
876   {
877     SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
878     while( nIt->more() )
879     {
880       const SMDS_MeshNode* node = nIt->next();
881       if ( node->NbInverseElements() == 0 )
882       {
883         const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
884         n2n->insert( make_pair( node, newNode ));
885         tgtSubMesh->AddNode( newNode );
886       }
887     }
888   }
889
890   // 2. Copy groups
891
892   vector<SMESH_Group*> resultGroups;
893   if ( toCopyGroups )
894   {
895     // collect names of existing groups to assure uniqueness of group names within a type
896     map< SMDSAbs_ElementType, set<string> > namesByType;
897     SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
898     while ( groupIt->more() )
899     {
900       SMESH_Group* tgtGroup = groupIt->next();
901       namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
902     }
903     if (srcMesh)
904     {
905       SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
906       while ( groupIt->more() )
907       {
908         SMESH_Group* srcGroup = groupIt->next();
909         SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
910         string name = srcGroup->GetName();
911         int nb = 1;
912         while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
913           name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
914         SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
915         SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
916         resultGroups.push_back( newGroup );
917
918         eIt = srcGroupDS->GetElements();
919         if ( srcGroupDS->GetType() == SMDSAbs_Node )
920           while (eIt->more())
921           {
922             TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
923             if ( n2nIt != n2n->end() && n2nIt->second )
924               newGroupDS->SMDSGroup().Add((*n2nIt).second );
925           }
926         else
927           while (eIt->more())
928           {
929             TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
930             if ( e2eIt != e2e->end() && e2eIt->second )
931               newGroupDS->SMDSGroup().Add((*e2eIt).second );
932           }
933       }
934     }
935   }
936   n2n->clear();
937   e2e->clear();
938
939   // Remember created groups in order to remove them as soon as the srcHyp is
940   // modified or something other similar happens. This imformation must be persistent,
941   // for that store them in a hypothesis as it stores its values in the file anyway
942   srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
943 }
944
945 //=============================================================================
946 /*!
947  * \brief Set needed event listeners and create a submesh for a copied mesh
948  *
949  * This method is called only if a submesh has HYP_OK algo_state.
950  */
951 //=============================================================================
952
953 void StdMeshers_Import_1D::setEventListener(SMESH_subMesh*             subMesh,
954                                             StdMeshers_ImportSource1D* sourceHyp)
955 {
956   if ( sourceHyp )
957   {
958     vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
959     if ( srcMeshes.empty() )
960       _Listener::waitHypModification( subMesh );
961     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
962       // set a listener to remove the imported mesh and groups
963       _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
964   }
965 }
966 void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
967 {
968   if ( !_sourceHyp )
969   {
970     const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
971     SMESH_Mesh*         tgtMesh  = subMesh->GetFather();
972     Hypothesis_Status aStatus;
973     CheckHypothesis( *tgtMesh, tgtShape, aStatus );
974   }
975   setEventListener( subMesh, _sourceHyp );
976 }
977
978 void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
979 {
980   SetEventListener(subMesh);
981 }
982
983 //=============================================================================
984 /*!
985  * Predict nb of mesh entities created by Compute()
986  */
987 //=============================================================================
988
989 bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh &         theMesh,
990                                     const TopoDS_Shape & theShape,
991                                     MapShapeNbElems&     aResMap)
992 {
993   if ( !_sourceHyp ) return false;
994
995   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
996   if ( srcGroups.empty() )
997     return error("Invalid source groups");
998
999   vector<int> aVec(SMDSEntity_Last,0);
1000
1001   bool toCopyMesh, toCopyGroups;
1002   _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
1003   if ( toCopyMesh ) // the whole mesh is copied
1004   {
1005     vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
1006     for ( unsigned i = 0; i < srcMeshes.size(); ++i )
1007     {
1008       SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
1009       if ( !sm || aResMap.count( sm )) continue; // already counted
1010       aVec.assign( SMDSEntity_Last, 0);
1011       const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
1012       for (int i = 0; i < SMDSEntity_Last; i++)
1013         aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
1014     }
1015   }
1016   else
1017   {
1018     SMESH_MesherHelper helper(theMesh);
1019
1020     const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
1021     const double edgeTol = helper.MaxTolerance( geomEdge );
1022
1023     // take into account nodes on vertices
1024     TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
1025     for ( ; vExp.More(); vExp.Next() )
1026       theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
1027
1028     // count edges imported from groups
1029     int nbEdges = 0, nbQuadEdges = 0;
1030     for ( int iG = 0; iG < srcGroups.size(); ++iG )
1031     {
1032       const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
1033       SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
1034       SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
1035       while ( srcElems->more() ) // loop on group contents
1036       {
1037         const SMDS_MeshElement* edge = srcElems->next();
1038         // find out if edge is located on geomEdge by projecting
1039         // a middle of edge to geomEdge
1040         SMESH_TNodeXYZ p1( edge->GetNode(0));
1041         SMESH_TNodeXYZ p2( edge->GetNode(1));
1042         gp_XYZ middle = ( p1 + p2 ) / 2.;
1043         tmpNode->setXYZ( middle.X(), middle.Y(), middle.Z());
1044         double u = 0;
1045         if ( helper.CheckNodeU( geomEdge, tmpNode, u, 10 * edgeTol, /*force=*/true ))
1046           ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
1047       }
1048       helper.GetMeshDS()->RemoveNode(tmpNode);
1049     }
1050
1051     int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
1052
1053     aVec[SMDSEntity_Node     ] = nbNodes;
1054     aVec[SMDSEntity_Edge     ] = nbEdges;
1055     aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
1056   }
1057
1058   SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
1059   aResMap.insert(make_pair(sm,aVec));
1060
1061   return true;
1062 }
1063
1064 //================================================================================
1065 /*!
1066  * \brief Return node-node and element-element maps for import of geiven source mesh
1067  */
1068 //================================================================================
1069
1070 void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
1071                                    SMESH_Mesh*       tgtMesh,
1072                                    TNodeNodeMap*&    n2n,
1073                                    TElemElemMap*&    e2e)
1074 {
1075   _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
1076   n2n = &iData->_n2n;
1077   e2e = &iData->_e2e;
1078   if ( iData->_copyMeshSubM.empty() )
1079   {
1080     // n2n->clear(); -- for sharing nodes on EDGEs
1081     e2e->clear();
1082   }
1083 }
1084
1085 //================================================================================
1086 /*!
1087  * \brief Return submesh corresponding to the copied mesh
1088  */
1089 //================================================================================
1090
1091 SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
1092                                                              SMESH_Mesh& srcMesh )
1093 {
1094   _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
1095   if ( iData->_copyMeshSubM.empty() ) return 0;
1096   SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );
1097   return sm;
1098 }
1099