Salome HOME
23627: [IMACS] ASERIS: project point to the mesh and create a slot
[modules/smesh.git] / src / StdMeshers / StdMeshers_Import_1D.cxx
1 // Copyright (C) 2007-2016  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 : implementation 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, SMESH_Gen * gen)
64   :SMESH_1D_Algo(hypId, gen), _sourceHyp(0)
65 {
66   _name = "Import_1D";
67   _shapeType = (1 << TopAbs_EDGE);
68
69   _compatibleHypothesis.push_back("ImportSource1D");
70 }
71
72 //================================================================================
73 namespace // INTERNAL STUFF
74 //================================================================================
75 {
76   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
77
78   enum _ListenerDataType
79     {
80       WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
81       LISTEN_SRC_MESH, // data storing submesh depending on source mesh state
82       SRC_HYP // data storing ImportSource hyp
83     };
84   //================================================================================
85   /*!
86    * \brief _ListenerData holding ImportSource hyp holding in its turn
87    *  imported groups
88    */
89   struct _ListenerData : public SMESH_subMeshEventListenerData
90   {
91     const StdMeshers_ImportSource1D* _srcHyp;
92     _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP):
93       SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
94     {
95       myType = type;
96     }
97   };
98   //================================================================================
99   /*!
100    * \brief Comparator of sub-meshes
101    */
102   struct _SubLess
103   {
104     bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const
105     {
106       if ( sm1 == sm2 ) return false;
107       if ( !sm1 || !sm2 ) return sm1 < sm2;
108       const TopoDS_Shape& s1 = sm1->GetSubShape();
109       const TopoDS_Shape& s2 = sm2->GetSubShape();
110       TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType();
111       TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType();
112       if ( t1 == t2)
113         return (sm1 < sm2);
114       return t1 < t2; // to have: face < edge
115     }
116   };
117   //================================================================================
118   /*!
119    * \brief Container of data dedicated to one source mesh
120    */
121   struct _ImportData
122   {
123     const SMESH_Mesh* _srcMesh;
124     StdMeshers_Import_1D::TNodeNodeMap _n2n;
125     StdMeshers_Import_1D::TElemElemMap _e2e;
126
127     set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh
128     set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying
129     set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting group copying
130     set< SMESH_subMesh*, _SubLess > _computedSubM;
131
132     SMESHDS_SubMesh*     _importMeshSubDS; // submesh storing a copy of _srcMesh
133     int                  _importMeshSubID; // id of _importMeshSubDS
134
135     _ImportData(const SMESH_Mesh* srcMesh=0):
136       _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
137
138     void removeImportedMesh( SMESHDS_Mesh* meshDS )
139     {
140       if ( !_importMeshSubDS ) return;
141       SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
142       while ( eIt->more() )
143         meshDS->RemoveFreeElement( eIt->next(), 0, /*fromGroups=*/false );
144       SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
145       while ( nIt->more() )
146         meshDS->RemoveFreeNode( nIt->next(), 0, /*fromGroups=*/false );
147       _importMeshSubDS->Clear();
148       _n2n.clear();
149       _e2e.clear();
150     }
151     void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
152     {
153       if ( !srcHyp ) return;
154       SMESH_Mesh*           tgtMesh = subM->GetFather();
155       const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
156       const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
157       vector<SMESH_Group*>*  groups =
158         const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
159       if ( groups )
160       {
161         for ( unsigned i = 0; i < groups->size(); ++i )
162           tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
163         groups->clear();
164       }
165     }
166     void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
167     {
168       if ( !srcHyp ) return;
169       bool toCopyMesh, toCopyGroups;
170       srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
171
172       if ( toCopyMesh )_copyMeshSubM.insert( sm );
173       else             _copyMeshSubM.erase( sm );
174
175       if ( toCopyGroups ) _copyGroupSubM.insert( sm );
176       else                _copyGroupSubM.erase( sm );
177     }
178     void addComputed( SMESH_subMesh* sm )
179     {
180       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
181                                                                /*complexShapeFirst=*/true);
182       while ( smIt->more() )
183       {
184         sm = smIt->next();
185         switch ( sm->GetSubShape().ShapeType() )
186         {
187         case TopAbs_EDGE:
188           if ( SMESH_Algo::isDegenerated( TopoDS::Edge( sm->GetSubShape() )))
189             continue;
190         case TopAbs_FACE:
191           _subM.insert( sm );
192           if ( !sm->IsEmpty() )
193             _computedSubM.insert( sm );
194         case TopAbs_VERTEX:
195           break;
196         default:;
197         }
198       }
199     }
200   };
201   //================================================================================
202   /*!
203    * Listener notified on events relating to imported submesh
204    */
205   class _Listener : public SMESH_subMeshEventListener
206   {
207     typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
208     TMesh2ImpData _tgtMesh2ImportData;
209
210     _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false,
211                                            "StdMeshers_Import_1D::_Listener") {}
212
213   public:
214     // return pointer to a static listener
215     static _Listener* get() { static _Listener theListener; return &theListener; }
216
217     static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh);
218
219     static void storeImportSubmesh(SMESH_subMesh*                   importSub,
220                                    const SMESH_Mesh*                srcMesh,
221                                    const StdMeshers_ImportSource1D* srcHyp);
222
223     virtual void ProcessEvent(const int                       event,
224                               const int                       eventType,
225                               SMESH_subMesh*                  subMesh,
226                               SMESH_subMeshEventListenerData* data,
227                               const SMESH_Hypothesis*         hyp);
228     void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data );
229     void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub );
230     void clearN2N     ( SMESH_Mesh* tgtMesh );
231
232     // mark sm as missing src hyp with valid groups
233     static void waitHypModification(SMESH_subMesh* sm)
234     {
235       sm->SetEventListener
236         (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
237     }
238   };
239   //--------------------------------------------------------------------------------
240   /*!
241    * \brief Find or create ImportData for given meshes
242    */
243   _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh,
244                                         SMESH_Mesh*       tgtMesh)
245   {
246     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
247     list< _ImportData >::iterator d = dList.begin();
248     for ( ; d != dList.end(); ++d )
249       if ( d->_srcMesh == srcMesh )
250         return &*d;
251     dList.push_back(_ImportData(srcMesh));
252     return &dList.back();
253   }
254
255   //--------------------------------------------------------------------------------
256   /*!
257    * \brief Remember an imported sub-mesh and set needed even listeners
258    *  \param importSub - submesh computed by Import algo
259    *  \param srcMesh - source mesh
260    *  \param srcHyp - ImportSource hypothesis
261    */
262   void _Listener::storeImportSubmesh(SMESH_subMesh*                   importSub,
263                                      const SMESH_Mesh*                srcMesh,
264                                      const StdMeshers_ImportSource1D* srcHyp)
265   {
266     // set listener to hear events of the submesh computed by "Import" algo
267     importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
268
269     // set listeners to hear events of the source mesh
270     SMESH_subMesh* smToNotify = importSub;
271     vector<SMESH_subMesh*> smToListen = srcHyp->GetSourceSubMeshes( srcMesh );
272     for ( size_t i = 0; i < smToListen.size(); ++i )
273     {
274       SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH);
275       data->mySubMeshes.push_back( smToNotify );
276       importSub->SetEventListener( get(), data, smToListen[i] );
277     }
278     // remember the submesh importSub and its sub-submeshes
279     _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
280     iData->trackHypParams( importSub, srcHyp );
281     iData->addComputed( importSub );
282     if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
283     {
284       SMESH_Mesh* tgtMesh = importSub->GetFather();
285       iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
286       iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
287     }
288   }
289   //--------------------------------------------------------------------------------
290   /*!
291    * \brief Remove imported mesh and/or groups if needed
292    *  \param sm - submesh losing Import algo
293    *  \param data - data holding imported groups
294    */
295   void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
296   {
297     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
298     list< _ImportData >::iterator d = dList.begin();
299     for ( ; d != dList.end(); ++d )
300       if ( (*d)._subM.erase( sm ))
301       {
302         d->_computedSubM.erase( sm );
303         bool rmMesh   = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
304         bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
305         if ( rmMesh )
306           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
307         if ( rmGroups && data && data->myType == SRC_HYP )
308           d->removeGroups( sm, data->_srcHyp );
309       }
310   }
311   //--------------------------------------------------------------------------------
312   /*!
313    * \brief Clear _ImportData::_n2n.
314    *        _n2n is useful within one mesh.Compute() only
315    */
316   void _Listener::clearN2N( SMESH_Mesh* tgtMesh )
317   {
318     list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
319     list< _ImportData >::iterator d = dList.begin();
320     for ( ; d != dList.end(); ++d )
321       d->_n2n.clear();
322   }
323   //--------------------------------------------------------------------------------
324   /*!
325    * \brief Clear submeshes and remove imported mesh and/or groups if necessary
326    *  \param sm - cleared submesh
327    *  \param data - data holding imported groups
328    */
329   void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub)
330   {
331     list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
332     list< _ImportData >::iterator d = dList.begin();
333     for ( ; d != dList.end(); ++d )
334     {
335       if ( !d->_subM.count( sm )) continue;
336       if ( (*d)._computedSubM.erase( sm ) )
337       {
338         bool copyMesh = !d->_copyMeshSubM.empty();
339         if ( copyMesh || clearAllSub )
340         {
341           // remove imported mesh and groups
342           d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
343
344           if ( data && data->myType == SRC_HYP )
345             d->removeGroups( sm, data->_srcHyp );
346
347           // clear the rest submeshes
348           if ( !d->_computedSubM.empty() )
349           {
350             d->_computedSubM.clear();
351             set< SMESH_subMesh*, _SubLess>::iterator sub = d->_subM.begin();
352             for ( ; sub != d->_subM.end(); ++sub )
353             {
354               SMESH_subMesh* subM = *sub;
355               _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
356               if ( hypData && hypData->myType == SRC_HYP )
357                 d->removeGroups( sm, hypData->_srcHyp );
358
359               subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
360               if ( subM->GetSubShape().ShapeType() == TopAbs_FACE )
361                 subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
362             }
363           }
364         }
365         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
366         if ( sm->GetSubShape().ShapeType() == TopAbs_FACE )
367           sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
368       }
369       if ( data && data->myType == SRC_HYP )
370         d->trackHypParams( sm, data->_srcHyp );
371       d->_n2n.clear();
372       d->_e2e.clear();
373     }
374   }
375   //--------------------------------------------------------------------------------
376   /*!
377    * \brief Remove imported mesh and/or groups
378    */
379   void _Listener::ProcessEvent(const int                       event,
380                                const int                       eventType,
381                                SMESH_subMesh*                  subMesh,
382                                SMESH_subMeshEventListenerData* data,
383                                const SMESH_Hypothesis*         /*hyp*/)
384   {
385     if ( data && data->myType == WAIT_HYP_MODIF )
386     {
387       // event of Import submesh
388       if ( SMESH_subMesh::MODIF_HYP  == event &&
389            SMESH_subMesh::ALGO_EVENT == eventType )
390       {
391         // re-call SetEventListener() to take into account valid parameters
392         // of ImportSource hypothesis
393         if ( SMESH_Algo* algo = subMesh->GetAlgo() )
394           algo->SetEventListener( subMesh );
395       }
396     }
397     else if ( data && data->myType == LISTEN_SRC_MESH )
398     {
399       // event of source mesh
400       if ( SMESH_subMesh::COMPUTE_EVENT == eventType )
401       {
402         switch ( event ) {
403         case SMESH_subMesh::CLEAN:
404           // source mesh cleaned -> clean target mesh
405           clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true );
406           break;
407         case SMESH_subMesh::SUBMESH_COMPUTED: {
408           // source mesh computed -> reset FAILED state of Import submeshes to
409           // READY_TO_COMPUTE
410           SMESH_Mesh* srcMesh = subMesh->GetFather();
411           if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 )
412           {
413             SMESH_Mesh* m = data->mySubMeshes.front()->GetFather();
414             if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1))
415             {
416               sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED );
417               sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
418             }
419           }
420           break;
421         }
422         default:;
423         }
424       }
425       if ( !data->mySubMeshes.empty() )
426         clearN2N( data->mySubMeshes.front()->GetFather() );
427     }
428     else // event of Import submesh
429     {
430       // find out what happens: import hyp modified or removed
431       bool removeImport = false, modifHyp = false;
432       if ( SMESH_subMesh::ALGO_EVENT == eventType )
433         modifHyp = true;
434       if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
435       {
436         removeImport = true;
437       }
438       else if (( SMESH_subMesh::REMOVE_ALGO == event ||
439                  SMESH_subMesh::REMOVE_FATHER_ALGO == event ) &&
440                SMESH_subMesh::ALGO_EVENT == eventType )
441       {
442         SMESH_Algo* algo = subMesh->GetAlgo();
443         removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 );
444       }
445
446       if ( removeImport )
447       {
448         // treate removal of Import algo from subMesh
449         removeSubmesh( subMesh, (_ListenerData*) data );
450       }
451       else if ( modifHyp ||
452                 ( SMESH_subMesh::CLEAN         == event &&
453                   SMESH_subMesh::COMPUTE_EVENT == eventType))
454       {
455         // treate modification of ImportSource hypothesis
456         clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false );
457       }
458       else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
459                 SMESH_subMesh::COMPUTE_EVENT       == eventType )
460       {
461         // check compute state of all submeshes impoting from same src mesh;
462         // this is to take into account 1D computed submeshes hidden by 2D import algo;
463         // else source mesh is not copied as _subM.size != _computedSubM.size()
464         list< _ImportData > &  dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
465         list< _ImportData >::iterator d = dList.begin();
466         for ( ; d != dList.end(); ++d )
467           if ( d->_subM.count( subMesh ))
468           {
469             set<SMESH_subMesh*,_SubLess>::iterator smIt = d->_subM.begin();
470             for( ; smIt != d->_subM.end(); ++smIt )
471               if ( (*smIt)->IsMeshComputed() )
472                 d->_computedSubM.insert( *smIt);
473           }
474       }
475       // Clear _ImportData::_n2n if it's no more useful, i.e. when
476       // the event is not within mesh.Compute()
477       if ( SMESH_subMesh::ALGO_EVENT == eventType )
478         clearN2N( subMesh->GetFather() );
479     }
480   }
481
482   //================================================================================
483   /*!
484    * \brief Return an ID of submesh to store nodes and elements of a copied mesh
485    */
486   //================================================================================
487
488   int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
489                                 SMESH_Mesh*         tgtMesh)
490   {
491     // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
492     // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
493     // And this shape must be different from sub-shapes of the main shape.
494     // So we create a compound containing
495     // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
496     //    srcMeshDS->GetPersistentId()
497     // 2) the 1-st vertex of the main shape to assure
498     //    SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
499     TopoDS_Shape shapeForSrcMesh;
500     TopTools_IndexedMapOfShape pseudoSubShapes;
501     TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
502
503     // index of pseudoSubShapes corresponding to srcMeshDS
504     int    subIndex = 1 + srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
505     int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
506
507     // try to find already present shapeForSrcMesh
508     SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
509     for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
510     {
511       const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
512       if ( s.ShapeType() != TopAbs_COMPOUND ) break;
513       TopoDS_Iterator sSubIt( s );
514       for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
515         if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
516           if ( iSub+1 == nbSubShapes )
517           {
518             shapeForSrcMesh = s;
519             break;
520           }
521     }
522     if ( shapeForSrcMesh.IsNull() )
523     {
524       // make a new shapeForSrcMesh
525       BRep_Builder aBuilder;
526       TopoDS_Compound comp;
527       aBuilder.MakeCompound( comp );
528       shapeForSrcMesh = comp;
529       for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
530         if ( subIndex+iSub <= pseudoSubShapes.Extent() )
531           aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
532       TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
533       aBuilder.Add( comp, vExp.Current() );
534     }
535     SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
536     SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
537     if ( !smDS )
538       smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
539
540     // make ordinary submesh from a complex one
541     if ( smDS->IsComplexSubmesh() )
542     {
543       list< const SMESHDS_SubMesh* > subSM;
544       SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
545       while ( smIt->more() ) subSM.push_back( smIt->next() );
546       list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
547       for ( ; sub != subSM.end(); ++sub)
548         smDS->RemoveSubMesh( *sub );
549     }
550     return sm->GetId();
551   }
552
553   //================================================================================
554   /*!
555    * \brief Return a submesh to store nodes and elements of a copied mesh
556    * and set event listeners in order to clear
557    * imported mesh and groups as soon as submesh state requires it
558    */
559   //================================================================================
560
561   SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh*                    srcMesh,
562                                            SMESH_Mesh*                          tgtMesh,
563                                            const TopoDS_Shape&                  tgtShape,
564                                            StdMeshers_Import_1D::TNodeNodeMap*& n2n,
565                                            StdMeshers_Import_1D::TElemElemMap*& e2e,
566                                            bool &                               toCopyGroups)
567   {
568     StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
569
570     _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
571
572     SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
573     iData->addComputed( importedSM );
574     if ( iData->_computedSubM.size() != iData->_subM.size() )
575       return 0; // not all submeshes computed yet
576
577     toCopyGroups = !iData->_copyGroupSubM.empty();
578
579     if ( !iData->_copyMeshSubM.empty())
580     {
581       // make submesh to store a copied mesh
582       int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
583       SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
584
585       iData->_importMeshSubID = smID;
586       iData->_importMeshSubDS = subDS;
587       return subDS;
588     }
589     return 0;
590   }
591
592 } // namespace
593
594 //=============================================================================
595 /*!
596  * Check presence of a hypothesis
597  */
598 //=============================================================================
599
600 bool StdMeshers_Import_1D::CheckHypothesis
601                          (SMESH_Mesh&                          aMesh,
602                           const TopoDS_Shape&                  aShape,
603                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
604 {
605   _sourceHyp = 0;
606
607   const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
608   if ( hyps.size() == 0 )
609   {
610     aStatus = SMESH_Hypothesis::HYP_MISSING;
611     return false;  // can't work with no hypothesis
612   }
613
614   if ( hyps.size() > 1 )
615   {
616     aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
617     return false;
618   }
619
620   const SMESHDS_Hypothesis *theHyp = hyps.front();
621
622   string hypName = theHyp->GetName();
623
624   if (hypName == _compatibleHypothesis.front())
625   {
626     _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
627     aStatus = _sourceHyp->GetGroups().empty() ? HYP_BAD_PARAMETER : HYP_OK;
628     if ( aStatus == HYP_BAD_PARAMETER )
629       _Listener::waitHypModification( aMesh.GetSubMesh( aShape ));
630     return aStatus == HYP_OK;
631   }
632
633   aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
634   return false;
635 }
636
637 //=============================================================================
638 /*!
639  * Import elements from the other mesh
640  */
641 //=============================================================================
642
643 bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
644 {
645   if ( !_sourceHyp ) return false;
646
647   //MESSAGE("---------> StdMeshers_Import_1D::Compute");
648   const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups(/*loaded=*/true);
649   if ( srcGroups.empty() )
650     return error("Invalid source groups");
651
652   SMESH_MesherHelper helper(theMesh);
653   helper.SetSubShape(theShape);
654   SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
655
656   const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
657   const double edgeTol = BRep_Tool::Tolerance( geomEdge );
658   const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
659
660   set<int> subShapeIDs;
661   subShapeIDs.insert( shapeID );
662
663   // get nodes on vertices
664   list < SMESH_TNodeXYZ > vertexNodes;
665   list < SMESH_TNodeXYZ >::iterator vNIt;
666   TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
667   for ( ; vExp.More(); vExp.Next() )
668   {
669     const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
670     if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
671       continue; // closed edge
672     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
673     if ( !n )
674     {
675       _gen->Compute(theMesh,v,/*anUpward=*/true);
676       n = SMESH_Algo::VertexNode( v, tgtMesh );
677       //MESSAGE("_gen->Compute " << n);
678       if ( !n ) return false; // very strange
679     }
680     vertexNodes.push_back( SMESH_TNodeXYZ( n ));
681     //MESSAGE("SMESH_Algo::VertexNode " << n->GetID() << " " << n->X() << " " << n->Y() << " " << n->Z() );
682   }
683
684   // import edges from groups
685   TNodeNodeMap* n2n;
686   TElemElemMap* e2e;
687   for ( size_t iG = 0; iG < srcGroups.size(); ++iG )
688   {
689     const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
690
691     const int meshID = srcGroup->GetMesh()->GetPersistentId();
692     const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
693     if ( !srcMesh ) continue;
694     getMaps( srcMesh, &theMesh, n2n, e2e );
695
696     SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
697     vector<const SMDS_MeshNode*> newNodes;
698     SMDS_MeshNode *tmpNode = helper.AddNode(0,0,0);
699     double u = 0.314159; // "random" value between 0 and 1, avoid 0 and 1, false detection possible on edge restrictions
700     while ( srcElems->more() ) // loop on group contents
701     {
702       const SMDS_MeshElement* edge = srcElems->next();
703       // find or create nodes of a new edge
704       newNodes.resize( edge->NbNodes() );
705       //MESSAGE("edge->NbNodes " << edge->NbNodes());
706       newNodes.back() = 0;
707       SMDS_MeshElement::iterator node = edge->begin_nodes();
708       SMESH_TNodeXYZ a(edge->GetNode(0));
709       // --- define a tolerance relative to the length of an edge
710       double mytol = a.Distance(edge->GetNode(edge->NbNodes()-1))/25;
711       //mytol = max(1.E-5, 10*edgeTol); // too strict and not necessary
712       //MESSAGE("mytol = " << mytol);
713       for ( size_t i = 0; i < newNodes.size(); ++i, ++node )
714       {
715         TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
716         if ( n2nIt->second )
717         {
718           if ( !subShapeIDs.count( n2nIt->second->getshapeId() ))
719             break;
720         }
721         else
722         {
723           // find an existing vertex node
724           double checktol = max(1.E-10, 10*edgeTol*edgeTol);
725           for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
726             if ( vNIt->SquareDistance( *node ) < checktol)
727             {
728               //MESSAGE("SquareDistance " << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<<vNIt->X()<<" "<<vNIt->Y()<<" "<<vNIt->Z());
729               (*n2nIt).second = vNIt->_node;
730               vertexNodes.erase( vNIt );
731               break;
732             }
733             else if ( vNIt->SquareDistance( *node ) < 10*checktol)
734               MESSAGE("SquareDistance missed" << vNIt->SquareDistance( *node ) << " checktol " << checktol <<" "<<vNIt->X()<<" "<<vNIt->Y()<<" "<<vNIt->Z());
735         }
736         if ( !n2nIt->second )
737         {
738           // find out if node lies on theShape
739           //double dxyz[4];
740           tmpNode->setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
741           if ( helper.CheckNodeU( geomEdge, tmpNode, u, mytol, /*force=*/true)) // , dxyz )) // dxyz used for debug purposes
742           {
743             SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
744             n2nIt->second = newNode;
745             tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
746             //MESSAGE("u=" << u << " " << newNode->X()<< " " << newNode->Y()<< " " << newNode->Z());
747             //MESSAGE("d=" << dxyz[0] << " " << dxyz[1] << " " << dxyz[2] << " " << dxyz[3]);
748           }
749         }
750         if ( !(newNodes[i] = n2nIt->second ))
751           break;
752       }
753       if ( !newNodes.back() )
754       {
755         //MESSAGE("not all nodes of edge lie on theShape");
756         continue; // not all nodes of edge lie on theShape
757       }
758
759       // make a new edge
760       SMDS_MeshElement * newEdge;
761       if ( newNodes.size() == 3 )
762         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
763       else
764         newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
765       //MESSAGE("add Edge " << newNodes[0]->GetID() << " " << newNodes[1]->GetID());
766       tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
767       e2e->insert( make_pair( edge, newEdge ));
768     }
769     helper.GetMeshDS()->RemoveNode(tmpNode);
770   }
771   if ( n2n->empty())
772     return error("Empty source groups");
773
774   // check if the whole geom edge is covered by imported segments;
775   // the check consist in passing by segments from one vetrex node to another
776   bool isEdgeMeshed = false;
777   if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
778   {
779     const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
780     const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
781     const SMDS_MeshElement* seg = 0;
782     SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
783     while ( segIt->more() && !seg )
784       if ( !tgtSM->Contains( seg = segIt->next()))
785         seg = 0;
786     int nbPassedSegs = 0;
787     while ( seg )
788     {
789       ++nbPassedSegs;
790       const SMDS_MeshNode* n2 = seg->GetNode(0);
791       n = ( n2 == n ? seg->GetNode(1) : n2 );
792       if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
793         break;
794       const SMDS_MeshElement* seg2 = 0;
795       segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
796       while ( segIt->more() && !seg2 )
797         if ( seg == ( seg2 = segIt->next()))
798           seg2 = 0;
799       seg = seg2;
800     }
801     if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
802       return error( "Source elements overlap one another");
803
804     isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
805                      n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
806   }
807   if ( !isEdgeMeshed )
808     return error( "Source elements don't cover totally the geometrical edge" );
809
810   // copy meshes
811   vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
812   for ( size_t i = 0; i < srcMeshes.size(); ++i )
813     importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
814
815   return true;
816 }
817
818 //================================================================================
819 /*!
820  * \brief Copy mesh and groups
821  */
822 //================================================================================
823
824 void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
825                                       SMESH_Mesh &               tgtMesh,
826                                       StdMeshers_ImportSource1D* srcHyp,
827                                       const TopoDS_Shape&        tgtShape)
828 {
829   // get submesh to store the imported mesh
830   TNodeNodeMap* n2n;
831   TElemElemMap* e2e;
832   bool toCopyGroups;
833   SMESHDS_SubMesh* tgtSubMesh =
834     getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
835   if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
836     return; // not to copy srcMeshDS twice
837
838   SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
839   SMESH_MeshEditor additor( &tgtMesh );
840
841   // 1. Copy mesh
842
843   SMESH_MeshEditor::ElemFeatures elemType;
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, elemType.Init( elem, /*basicOnly=*/false ));
869       tgtSubMesh->AddElement( newElem );
870     }
871     if ( toCopyGroups )
872       (*e2eIt).second = newElem;
873   }
874   // copy free nodes
875   if ( srcMeshDS->NbNodes() > (int) 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() );
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 ( size_t 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