Salome HOME
0020918: EDF 1447 SMESH: Mesh common borders
authoreap <eap@opencascade.com>
Fri, 12 Nov 2010 14:55:58 +0000 (14:55 +0000)
committereap <eap@opencascade.com>
Fri, 12 Nov 2010 14:55:58 +0000 (14:55 +0000)
src/StdMeshers/Makefile.am
src/StdMeshers/StdMeshers_ImportSource.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ImportSource.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Import_1D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Import_1D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Import_1D2D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Import_1D2D.hxx [new file with mode: 0644]

index 0312e1f78cd0dbb8971dbefdd2c3fc8ad7b9115d..08c312ead58d3e1f86cb6626e3b6cddc4a4d44a0 100644 (file)
@@ -72,7 +72,10 @@ salomeinclude_HEADERS = \
        StdMeshers_MaxLength.hxx \
        StdMeshers_QuadrangleParams.hxx \
        StdMeshers_RadialQuadrangle_1D2D.hxx \
-       StdMeshers_HexaFromSkin_3D.hxx
+       StdMeshers_HexaFromSkin_3D.hxx \
+       StdMeshers_ImportSource.hxx \
+       StdMeshers_Import_1D.hxx \
+       StdMeshers_Import_1D2D.hxx
 
 # Libraries targets
 
@@ -123,7 +126,10 @@ dist_libStdMeshers_la_SOURCES = \
        StdMeshers_MaxLength.cxx \
        StdMeshers_QuadrangleParams.cxx \
        StdMeshers_RadialQuadrangle_1D2D.cxx \
-       StdMeshers_HexaFromSkin_3D.cxx
+       StdMeshers_HexaFromSkin_3D.cxx \
+       StdMeshers_ImportSource.cxx \
+       StdMeshers_Import_1D.cxx \
+       StdMeshers_Import_1D2D.cxx
 
 
 # additionnal information to compil and link file
diff --git a/src/StdMeshers/StdMeshers_ImportSource.cxx b/src/StdMeshers/StdMeshers_ImportSource.cxx
new file mode 100644 (file)
index 0000000..1ba39ea
--- /dev/null
@@ -0,0 +1,443 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH StdMeshers_ImportSource1D : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_ImportSource1D.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_ImportSource.hxx"
+
+#include "SMESHDS_GroupBase.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Algo.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Group.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+
+#include "utilities.h"
+
+#include <Standard_ErrorHandler.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+using namespace std;
+
+//=============================================================================
+/*!
+ * Creates StdMeshers_ImportSource1D
+ */
+//=============================================================================
+
+StdMeshers_ImportSource1D::StdMeshers_ImportSource1D(int         hypId,
+                                                     int         studyId,
+                                                     SMESH_Gen * gen)
+  :SMESH_Hypothesis(hypId, studyId, gen),
+   _toCopyMesh(false),
+   _toCopyGroups(false)
+{
+  _name = "ImportSource1D";
+  _param_algo_dim = 1; // is used by StdMeshers_Import_1D;
+}
+
+//=============================================================================
+/*!
+ * Creates StdMeshers_ImportSource2D
+ */
+//=============================================================================
+
+StdMeshers_ImportSource2D::StdMeshers_ImportSource2D(int         hypId,
+                                                     int         studyId,
+                                                     SMESH_Gen * gen)
+  :StdMeshers_ImportSource1D(hypId, studyId, gen)
+{
+  _name = "ImportSource2D";
+  _param_algo_dim = 2; // is used by StdMeshers_Import_2D;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+StdMeshers_ImportSource1D::~StdMeshers_ImportSource1D()
+{
+}
+//=============================================================================
+/*!
+ *  Sets groups to import elements from
+ */
+//=============================================================================
+
+void StdMeshers_ImportSource1D::SetGroups(const std::vector<SMESH_Group*>& groups)
+{
+  if (_groups != groups)
+  {
+    _groups = groups;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+void StdMeshers_ImportSource1D::SetCopySourceMesh(bool toCopyMesh, bool toCopyGroups)
+{
+  if ( !toCopyMesh ) toCopyGroups = false;
+  if ( _toCopyMesh != toCopyMesh || _toCopyGroups != toCopyGroups )
+  {
+    _toCopyMesh = toCopyMesh; _toCopyGroups = toCopyGroups;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+void StdMeshers_ImportSource1D::GetCopySourceMesh(bool& toCopyMesh, bool& toCopyGroups) const
+{
+  toCopyMesh = _toCopyMesh; toCopyGroups = _toCopyGroups;
+}
+  
+namespace
+{
+  //================================================================================
+  /*!
+   * \brief Return only alive groups
+   */
+  //================================================================================
+
+  vector<SMESH_Group*> getValidGroups(const vector<SMESH_Group*>& groups,
+                                      StudyContextStruct*         studyContext)
+  {
+    vector<SMESH_Group*> okGroups;
+    for ( int i = 0; i < groups.size(); ++i )
+    {
+      try
+      {
+        // we expect SIGSEGV on a dead group
+        OCC_CATCH_SIGNALS;
+        SMESH_Group* okGroup = 0;
+        map<int, SMESH_Mesh*>::iterator itm = itm = studyContext->mapMesh.begin();
+        for ( ; !okGroup && itm != studyContext->mapMesh.end(); itm++)
+        {
+          SMESH_Mesh::GroupIteratorPtr gIt = itm->second->GetGroups();
+          while ( gIt->more() && !okGroup )
+            if ( gIt->next() == groups[i] )
+              okGroup = groups[i];
+        }
+        if ( okGroup )
+          okGroups.push_back( okGroup );
+      }
+      catch(...)
+      {
+      }
+    }
+    return okGroups;
+  }
+  //================================================================================
+  /*!
+   * \brief Pack meshes into a pair of ints
+   */
+  //================================================================================
+
+  pair<int, int> getResMapKey(const SMESHDS_Mesh& srcMesh, const SMESHDS_Mesh& tgtMesh)
+  {
+    return make_pair( srcMesh.GetPersistentId() , tgtMesh.GetPersistentId() );
+  }
+  //================================================================================
+  /*!
+   * \brief Return a target mesh by a pair of ints
+   */
+  //================================================================================
+
+  SMESH_Mesh* getTgtMeshByKey( const pair<int, int> & resMapKey,
+                               StudyContextStruct*    studyContext)
+  {
+    int tgtID = resMapKey.second;
+    SMESH_Mesh* tgtMesh = 0;
+    map<int, SMESH_Mesh*>::iterator itm = itm = studyContext->mapMesh.begin();
+    for ( ; !tgtMesh && itm != studyContext->mapMesh.end(); itm++)
+    {
+      tgtMesh = (*itm).second;
+      if ( tgtMesh->GetMeshDS()->GetPersistentId() != tgtID )
+        tgtMesh = 0;
+    }
+    return tgtMesh;
+  }
+  //================================================================================
+  /*!
+   * \brief Return a target mesh by a pair of ints
+   */
+  //================================================================================
+
+  int getSrcMeshID( const pair<int, int> & resMapKey )
+  {
+    return resMapKey.first;
+  }
+}
+
+//=============================================================================
+/*!
+ *  Returns groups to import elements from
+ */
+//=============================================================================
+
+const std::vector<SMESH_Group*>&  StdMeshers_ImportSource1D::GetGroups() const
+{
+  // filter off deleted groups
+  vector<SMESH_Group*> okGroups = getValidGroups( _groups,
+                                                  _gen->GetStudyContext(_studyId) );
+  if ( okGroups.size() != _groups.size() )
+    ((StdMeshers_ImportSource1D*)this)->_groups = okGroups;
+
+  return _groups;
+}
+
+//================================================================================
+/*!
+ * \brief Return source meshes
+ */
+//================================================================================
+
+std::vector<SMESH_Mesh*> StdMeshers_ImportSource1D::GetSourceMeshes() const
+{
+  // GetPersistentId()'s of meshes
+  set<int> meshIDs;
+  const vector<SMESH_Group*>& groups = GetGroups();
+  if ( !groups.empty() )
+  {
+    for ( unsigned i = 0; i < groups.size(); ++i )
+    {
+      const SMESHDS_GroupBase* gDS = groups[i]->GetGroupDS();
+      int id = gDS->GetMesh()->GetPersistentId();
+      meshIDs.insert( id );
+    }
+  }
+  else
+  {
+    if ( _resultGroups.empty() )
+      ((StdMeshers_ImportSource1D*)this)->RestoreGroups(_groups);
+    TResGroupMap::const_iterator key_groups = _resultGroups.begin();
+    for ( ; key_groups != _resultGroups.end(); ++key_groups )
+      meshIDs.insert( getSrcMeshID( key_groups->first ));
+  }
+
+  // Find corresponding meshes
+  vector<SMESH_Mesh*> meshes;
+  if ( !meshIDs.empty() )
+  {
+    StudyContextStruct* studyContext = _gen->GetStudyContext(_studyId);
+    for ( set<int>::iterator id = meshIDs.begin(); id != meshIDs.end(); ++id )
+    {
+      map<int, SMESH_Mesh*>::iterator itm = itm = studyContext->mapMesh.begin();
+      for ( ; itm != studyContext->mapMesh.end(); itm++)
+      {
+        SMESH_Mesh* mesh = (*itm).second;
+        if ( mesh->GetMeshDS()->GetPersistentId() == *id )
+        {
+          meshes.push_back( mesh );
+          break;
+        }
+      }
+    }
+  }
+  return meshes;
+}
+
+//=============================================================================
+/*!
+ * Save _toCopyMesh and _toCopyGroups to a stream
+ */
+//=============================================================================
+
+ostream & StdMeshers_ImportSource1D::SaveTo(ostream & save)
+{
+  resultGroupsToIntVec();
+
+  save << " " << _toCopyMesh << " " << _toCopyGroups;
+  save << " " << _resultGroupsStorage.size();
+  for ( unsigned i = 0; i < _resultGroupsStorage.size(); ++i )
+    save << " " << _resultGroupsStorage[i];
+
+  return save;
+}
+
+//=============================================================================
+/*!
+ * Load _toCopyMesh and _toCopyGroups from a stream
+ */
+//=============================================================================
+
+istream & StdMeshers_ImportSource1D::LoadFrom(istream & load)
+{
+  load >> _toCopyMesh >> _toCopyGroups;
+
+  _resultGroupsStorage.clear();
+  int val;
+  if ( load >> val )
+  {
+    _resultGroupsStorage.reserve(val);
+    while ( _resultGroupsStorage.size() < _resultGroupsStorage.capacity() && load >> val )
+      _resultGroupsStorage.push_back( val );
+  }
+  return load;
+}
+
+//================================================================================
+/*!
+ * \brief Convert result groups into _resultGroupsStorage
+ */
+//================================================================================
+
+void StdMeshers_ImportSource1D::resultGroupsToIntVec()
+{
+  _resultGroupsStorage.clear();
+  
+  // store result groups
+  TResGroupMap::iterator key2groups = _resultGroups.begin();
+  for ( ; key2groups != _resultGroups.end(); ++key2groups )
+  {
+    const pair<int, int>&          key = key2groups->first;
+    const vector<SMESH_Group*>& groups = key2groups->second;
+    // mesh ids, nb groups
+    _resultGroupsStorage.push_back( key.first );
+    _resultGroupsStorage.push_back( key.second );
+    _resultGroupsStorage.push_back( groups.size() );
+    for ( unsigned i = 0; i < groups.size(); ++i )
+    {
+      // store group names as sequence of ints each standing for a char
+      // of a name; that is to avoid pb with names containing white spaces
+      string name = groups[i]->GetGroupDS()->GetStoreName();
+      _resultGroupsStorage.push_back( name.size() );
+      for ( unsigned j = 0; j < name.size(); ++j )
+        _resultGroupsStorage.push_back( name[j] );
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Restore source groups and result groups by _resultGroupsStorage
+ */
+//================================================================================
+
+void StdMeshers_ImportSource1D::RestoreGroups(const std::vector<SMESH_Group*>& groups)
+{
+  _groups = groups;
+
+  _resultGroups.clear();
+  int i = 0;
+  while ( i < _resultGroupsStorage.size() )
+  {
+    int key1 = _resultGroupsStorage[i++];
+    int key2 = _resultGroupsStorage[i++];
+    pair<int, int> resMapKey( key1, key2 );
+    SMESH_Mesh* mesh = getTgtMeshByKey( resMapKey, _gen->GetStudyContext(_studyId));
+    // restore mesh ids at least
+    _resultGroups.insert( make_pair (resMapKey,vector<SMESH_Group*>() )); 
+
+    int nbGroups = _resultGroupsStorage[i++];
+    for ( int j = 0; j < nbGroups; ++j )
+    {
+      string::size_type nameSize = _resultGroupsStorage[i++];
+      string groupName(nameSize, '\0');
+      for ( unsigned k = 0; k < nameSize; ++k )
+        groupName[k] = (char) _resultGroupsStorage[i++];
+
+      // find a group by name
+      if ( mesh )
+      {
+        SMESH_Group* group = 0;
+        SMESH_Mesh::GroupIteratorPtr gIt = mesh->GetGroups();
+        while ( !group && gIt->more() )
+        {
+          group = gIt->next();
+          if ( !group->GetGroupDS() || groupName != group->GetGroupDS()->GetStoreName() )
+            group = 0;
+        }
+        if ( group )
+          _resultGroups[ resMapKey ].push_back( group );
+      }
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Remember groups imported from other mesh
+ *  \param groups - result groups
+ *  \param srcMesh - source mesh
+ *  \param tgtMesh - destination mesh
+ */
+//================================================================================
+
+void StdMeshers_ImportSource1D::StoreResultGroups(const std::vector<SMESH_Group*>& groups,
+                                                  const SMESHDS_Mesh&              srcMesh,
+                                                  const SMESHDS_Mesh&              tgtMesh)
+{
+  _resultGroups[ getResMapKey(srcMesh,tgtMesh) ] = groups;
+}
+
+//================================================================================
+/*!
+ * \brief Return groups imported from other mesh
+ *  \param srcMesh - source mesh
+ *  \param tgtMesh - destination mesh
+ *  \retval const std::vector<SMESH_Group*>& - groups
+ */
+//================================================================================
+
+std::vector<SMESH_Group*>*
+StdMeshers_ImportSource1D::GetResultGroups(const SMESHDS_Mesh& srcMesh,
+                                           const SMESHDS_Mesh& tgtMesh) 
+{
+  TResGroupMap::iterator key2groups = _resultGroups.find( getResMapKey(srcMesh,tgtMesh ));
+  if ( key2groups == _resultGroups.end() )
+    return 0;
+  vector<SMESH_Group*> vec = getValidGroups((*key2groups).second,
+                                            _gen->GetStudyContext(_studyId) );
+  if ( vec.size() != key2groups->second.size())
+    key2groups->second = vec;
+
+  return & key2groups->second;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize ImportSource value by the mesh built on the geometry
+ * \param theMesh - the built mesh
+ * \param theShape - the geometry of interest
+ * \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_ImportSource1D::SetParametersByMesh(const SMESH_Mesh*, const TopoDS_Shape&)
+{
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Initialize my parameter values by default parameters.
+ *  \retval bool - true if parameter values have been successfully defined
+ */
+//================================================================================
+
+bool StdMeshers_ImportSource1D::SetParametersByDefaults(const TDefaults&, const SMESH_Mesh* )
+{
+  return false;
+}
diff --git a/src/StdMeshers/StdMeshers_ImportSource.hxx b/src/StdMeshers/StdMeshers_ImportSource.hxx
new file mode 100644 (file)
index 0000000..13287cb
--- /dev/null
@@ -0,0 +1,97 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH StdMeshers : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_ImportSource1D.hxx
+//  Module : SMESH
+//
+#ifndef _StdMeshers_ImportSource_HXX_
+#define _StdMeshers_ImportSource_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <vector>
+#include <map>
+
+class SMESH_Group;
+class SMESHDS_Mesh;
+
+//==============================================================================
+/*!
+ * \brief Stores groups to import elements from
+ */
+//==============================================================================
+
+class STDMESHERS_EXPORT StdMeshers_ImportSource1D : public SMESH_Hypothesis
+{
+ public:
+  StdMeshers_ImportSource1D(int hypId, int studyId, SMESH_Gen * gen);
+  virtual ~ StdMeshers_ImportSource1D();
+
+  void SetGroups(const std::vector<SMESH_Group*>& groups);
+  const std::vector<SMESH_Group*>& GetGroups() const;
+
+  void SetCopySourceMesh(bool toCopyMesh, bool toCopyGroups);
+  void GetCopySourceMesh(bool& toCopyMesh, bool& toCopyGroups) const;
+  
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+  virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
+  void RestoreGroups(const std::vector<SMESH_Group*>& groups);
+
+  void StoreResultGroups(const std::vector<SMESH_Group*>& groups,
+                         const SMESHDS_Mesh&              srcMesh,
+                         const SMESHDS_Mesh&              tgtMesh);
+  std::vector<SMESH_Group*>* GetResultGroups(const SMESHDS_Mesh& srcMesh,
+                                             const SMESHDS_Mesh& tgtMesh);
+
+  std::vector<SMESH_Mesh*> GetSourceMeshes() const;
+
+private:
+
+  std::vector<SMESH_Group*> _groups;
+  bool _toCopyMesh, _toCopyGroups;
+
+  // groups imported using this hypothesis
+  typedef std::map< std::pair<int, int>, std::vector<SMESH_Group*> > TResGroupMap;
+  TResGroupMap      _resultGroups;
+  std::vector<int>  _resultGroupsStorage; // persistent representation of _resultGroups
+
+  void resultGroupsToIntVec();
+};
+
+//==============================================================================
+/*!
+ * \brief Redefines name and dimension of inherited StdMeshers_ImportSource1D
+ */
+//==============================================================================
+
+class STDMESHERS_EXPORT StdMeshers_ImportSource2D : public StdMeshers_ImportSource1D
+{
+ public:
+  StdMeshers_ImportSource2D(int hypId, int studyId, SMESH_Gen * gen);
+};
+#endif
diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx
new file mode 100644 (file)
index 0000000..3711644
--- /dev/null
@@ -0,0 +1,951 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Import_1D.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_Import_1D.hxx"
+#include "StdMeshers_ImportSource.hxx"
+
+#include "SMDS_MeshElement.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMESHDS_Group.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Comment.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Group.hxx"
+#include "SMESH_HypoFilter.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+
+#include "Utils_SALOME_Exception.hxx"
+#include "utilities.h"
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+using namespace std;
+
+//=============================================================================
+/*!
+ * Creates StdMeshers_Import_1D
+ */
+//=============================================================================
+
+StdMeshers_Import_1D::StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen * gen)
+  :SMESH_1D_Algo(hypId, studyId, gen), _sourceHyp(0)
+{
+  MESSAGE("StdMeshers_Import_1D::StdMeshers_Import_1D");
+  _name = "Import_1D";
+  _shapeType = (1 << TopAbs_EDGE);
+
+  _compatibleHypothesis.push_back("ImportSource1D");
+}
+
+//=============================================================================
+/*!
+ * Check presence of a hypothesis
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D::CheckHypothesis
+                         (SMESH_Mesh&                          aMesh,
+                          const TopoDS_Shape&                  aShape,
+                          SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  _sourceHyp = 0;
+
+  const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
+  if ( hyps.size() == 0 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_MISSING;
+    return false;  // can't work with no hypothesis
+  }
+
+  if ( hyps.size() > 1 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
+    return false;
+  }
+
+  const SMESHDS_Hypothesis *theHyp = hyps.front();
+
+  string hypName = theHyp->GetName();
+
+  if (hypName == _compatibleHypothesis.front())
+  {
+    _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
+    aStatus = SMESH_Hypothesis::HYP_OK;
+    return true;
+  }
+
+  aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  return true;
+}
+
+//================================================================================
+namespace // INTERNAL STUFF
+//================================================================================
+{
+  int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS, SMESH_Mesh* tgtMesh);
+
+  enum _ListenerDataType
+    {
+      WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp
+      SRC_HYP // data storing ImportSource hyp
+    };
+  //================================================================================
+  /*!
+   * \brief _ListenerData holding ImportSource hyp holding in its turn
+   *  imported groups
+   */
+  struct _ListenerData : public SMESH_subMeshEventListenerData
+  {
+    const StdMeshers_ImportSource1D* _srcHyp;
+    _ListenerData(const StdMeshers_ImportSource1D* h):
+      SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h)
+    {
+      myType = SRC_HYP; 
+    }
+  };
+  //================================================================================
+  /*!
+   * \brief Container of data dedicated to one source mesh
+   */
+  struct _ImportData
+  {
+    const SMESH_Mesh* _srcMesh;
+    StdMeshers_Import_1D::TNodeNodeMap _n2n;
+    StdMeshers_Import_1D::TElemElemMap _e2e;
+
+    set< SMESH_subMesh*> _subM; // submeshes relating to this srcMesh
+    set< SMESH_subMesh*> _copyMeshSubM; // submeshes requesting mesh copying
+    set< SMESH_subMesh*> _copyGroupSubM; // submeshes requesting mesh copying
+    set< SMESH_subMesh*> _computedSubM;
+
+    SMESHDS_SubMesh*     _importMeshSubDS; // submesh storing a copy of _srcMesh
+    int                  _importMeshSubID; // id of _importMeshSubDS
+
+    _ImportData(const SMESH_Mesh* srcMesh=0):
+      _srcMesh(srcMesh), _importMeshSubDS(0),_importMeshSubID(-1) {}
+
+    void removeImportedMesh( SMESHDS_Mesh* meshDS )
+    {
+      if ( !_importMeshSubDS ) return;
+      SMDS_ElemIteratorPtr eIt = _importMeshSubDS->GetElements();
+      while ( eIt->more() )
+        meshDS->RemoveFreeElement( eIt->next(), _importMeshSubDS, /*fromGroups=*/false );
+      SMDS_NodeIteratorPtr nIt = _importMeshSubDS->GetNodes();
+      while ( nIt->more() )
+        meshDS->RemoveFreeNode( nIt->next(), _importMeshSubDS, /*fromGroups=*/false );
+      _n2n.clear();
+      _e2e.clear();
+    }
+    void removeGroups( SMESH_subMesh* subM, const StdMeshers_ImportSource1D* srcHyp )
+    {
+      if ( !srcHyp ) return;
+      SMESH_Mesh*           tgtMesh = subM->GetFather();
+      const SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+      const SMESHDS_Mesh* srcMeshDS = _srcMesh->GetMeshDS();
+      vector<SMESH_Group*>*  groups =
+        const_cast<StdMeshers_ImportSource1D*>(srcHyp)->GetResultGroups(*srcMeshDS,*tgtMeshDS);
+      if ( groups )
+      {
+        for ( unsigned i = 0; i < groups->size(); ++i )
+          tgtMesh->RemoveGroup( groups->at(i)->GetGroupDS()->GetID() );
+        groups->clear();
+      }
+    }
+    void trackHypParams( SMESH_subMesh* sm, const StdMeshers_ImportSource1D* srcHyp )
+    {
+      if ( !srcHyp ) return;
+      bool toCopyMesh, toCopyGroups;
+      srcHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
+
+      if ( toCopyMesh )_copyMeshSubM.insert( sm );
+      else             _copyMeshSubM.erase( sm );
+
+      if ( toCopyGroups ) _copyGroupSubM.insert( sm );
+      else                _copyGroupSubM.erase( sm );
+    }
+  };
+  //================================================================================
+  /*!
+   * Listener notified on events of an imported submesh
+   */
+  class _Listener : public SMESH_subMeshEventListener
+  {
+    typedef map< SMESH_Mesh*, list< _ImportData > > TMesh2ImpData;
+    TMesh2ImpData _tgtMesh2ImportData;
+
+    _Listener():SMESH_subMeshEventListener(/*isDeletable=*/false){}
+
+  public:
+    // return poiter to a static listener
+    static _Listener* get() { static _Listener theListener; return &theListener; }
+
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief Find or create ImportData for given meshes
+     */
+    static _ImportData* getImportData(const SMESH_Mesh* srcMesh,
+                                       SMESH_Mesh*       tgtMesh)
+    {
+      list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh];
+      list< _ImportData >::iterator d = dList.begin();
+      for ( ; d != dList.end(); ++d )
+        if ( d->_srcMesh == srcMesh )
+          return &*d;
+      dList.push_back(_ImportData(srcMesh));
+      return &dList.back();
+    }
+
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief Remember an imported mesh and groups 
+     *  \param smDS - submesh DS holding the imported mesh
+     *  \param sm - submesh computed by Import algo
+     *  \param srcMeshDS - source mesh
+     *  \param srcHyp - ImportSource hypothesis
+     */
+    static _ImportData* storeImportSubmesh(SMESH_subMesh*                   importSub,
+                                           const SMESH_Mesh*                srcMesh,
+                                           const StdMeshers_ImportSource1D* srcHyp)
+    {
+      // set listener to hear events of the submesh computed by "Import" algo
+      importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub );
+
+      // set a listener to hear events of the source mesh
+      SMESH_subMesh* smToNotify = importSub;
+      SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1);
+      importSub->SetEventListener
+        ( new SMESH_subMeshEventListener(/*isDeletable=*/true),
+          SMESH_subMeshEventListenerData::MakeData( smToNotify ),
+          smToListen );
+
+      // remeber the submesh
+      _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather());
+      iData->_subM.insert( importSub );
+      iData->trackHypParams( importSub, srcHyp );
+      if ( !importSub->IsEmpty() )
+        iData->_computedSubM.insert( importSub );
+      if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 )
+      {
+        SMESH_Mesh* tgtMesh = importSub->GetFather();
+        iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh);
+        iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID );
+      }
+      if ( !importSub->IsEmpty() )
+        iData->_computedSubM.insert( importSub );
+
+      return iData;
+    }
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief mark sm as missing src hyp with valid groups
+     */
+    static void waitHypModification(SMESH_subMesh* sm)
+    {
+      sm->SetEventListener
+        (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm);
+    }
+
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief Remove imported mesh and/or groups as soon as no more imported submeshes
+     *               remain computed
+     *  \param sm - submesh loosing Import algo
+     *  \param data - data holding imported groups
+     */
+    void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data )
+    {
+      list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
+      list< _ImportData >::iterator d = dList.begin();
+      for ( ; d != dList.end(); ++d )
+        if ( (*d)._subM.erase( sm ))
+        {
+          d->_computedSubM.erase( sm );
+          bool rmMesh   = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty();
+          bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh;
+          if ( rmMesh )
+            d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
+          if ( rmGroups && data )
+            d->removeGroups( sm, data->_srcHyp );
+        }
+    }
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief Remove imported mesh and/or groups and
+     * clear all submeshes with common source mesh
+     *  \param sm - cleared submesh
+     *  \param data - data holding imported groups
+     */
+    void clearSubmesh( SMESH_subMesh* sm, _ListenerData* data )
+    {
+      list< _ImportData > &  dList = _tgtMesh2ImportData[ sm->GetFather() ];
+      list< _ImportData >::iterator d = dList.begin();
+      for ( ; d != dList.end(); ++d )
+      {
+        if ( !d->_subM.count( sm )) continue;
+        if ( (*d)._computedSubM.erase( sm ) )
+        {
+          bool copyMesh = !d->_copyMeshSubM.empty();
+          if ( copyMesh )
+          {
+            // clear submeshes
+            if ( !d->_computedSubM.empty() )
+            {
+              set< SMESH_subMesh*> subs;
+              subs.swap( d->_computedSubM ); // avoid recursion via events
+              while ( !subs.empty() )
+              {
+                SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() );
+                _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() );
+                if ( hypData )
+                  d->removeGroups( sm, hypData->_srcHyp );
+                
+                subM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+              }
+            }
+            // remove imported mesh and groups
+            d->removeImportedMesh( sm->GetFather()->GetMeshDS() );
+
+            if ( data )
+              d->removeGroups( sm, data->_srcHyp );
+          }
+        }
+        if ( data )
+          d->trackHypParams( sm, data->_srcHyp );
+        d->_n2n.clear();
+        d->_e2e.clear();
+      }
+    }
+    //--------------------------------------------------------------------------------
+    /*!
+     * \brief Remove imported mesh and/or groups
+     */
+    virtual void ProcessEvent(const int                       event,
+                              const int                       eventType,
+                              SMESH_subMesh*                  subMesh,
+                              SMESH_subMeshEventListenerData* data,
+                              const SMESH_Hypothesis*         /*hyp*/)
+    {
+      if ( data && data->myType == WAIT_HYP_MODIF )
+      {
+        if ( SMESH_subMesh::MODIF_HYP  == event &&
+             SMESH_subMesh::ALGO_EVENT == eventType )
+        {
+          SMESH_Gen* gen = subMesh->GetFather()->GetGen();
+          if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape()))
+            algo->SetEventListener( subMesh );
+        }
+      }
+      else
+      {
+        if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK )
+          // treate removal of Import algo from subMesh
+          removeSubmesh( subMesh, (_ListenerData*) data );
+
+        else if ( subMesh->IsEmpty() )
+          // treate modification of ImportSource hypothesis
+          clearSubmesh( subMesh, (_ListenerData*) data );
+
+        else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event &&
+                  SMESH_subMesh::COMPUTE_EVENT       == eventType )
+        {
+          // check compute state of all submeshes impoting from same src mesh;
+          // this is to take into account 1D computed submeshes hidden by 2D import algo
+          list< _ImportData > &  dList = _tgtMesh2ImportData[ subMesh->GetFather() ];
+          list< _ImportData >::iterator d = dList.begin();
+          for ( ; d != dList.end(); ++d )
+            if ( d->_subM.count( subMesh ))
+            {
+              set<SMESH_subMesh*>::iterator smIt = d->_subM.begin();
+              for( ; smIt != d->_subM.end(); ++smIt )
+                if ( (*smIt)->IsMeshComputed() )
+                  d->_computedSubM.insert( *smIt);
+            }
+        }
+      }
+    }
+  }; // class _Listener
+
+  //================================================================================
+  /*!
+   * \brief Return an ID of submesh to store nodes and elements of a copied mesh
+   */
+  //================================================================================
+
+  int getSubmeshIDForCopiedMesh(const SMESHDS_Mesh* srcMeshDS,
+                                SMESH_Mesh*         tgtMesh)
+  {
+    // To get SMESH_subMesh corresponding to srcMeshDS we need to have a shape
+    // for which SMESHDS_Mesh::IsGroupOfSubShapes() returns true.
+    // And this shape must be different from subshapes of the main shape.
+    // So we create a compound containing
+    // 1) some sub-shapes of SMESH_Mesh::PseudoShape() corresponding to
+    //    srcMeshDS->GetPersistentId()
+    // 2) the 1-st vertex of the main shape to assure
+    //    SMESHDS_Mesh::IsGroupOfSubShapes(shape)==true
+    TopoDS_Shape shapeForSrcMesh;
+    TopTools_IndexedMapOfShape pseudoSubShapes;
+    TopExp::MapShapes( SMESH_Mesh::PseudoShape(), pseudoSubShapes );
+
+    // index of pseudoSubShapes corresponding to srcMeshDS
+    int subIndex = srcMeshDS->GetPersistentId() % pseudoSubShapes.Extent();
+    int nbSubShapes = 1 + srcMeshDS->GetPersistentId() / pseudoSubShapes.Extent();
+
+    // try to find already present shapeForSrcMesh
+    SMESHDS_Mesh* tgtMeshDS = tgtMesh->GetMeshDS();
+    for ( int i = tgtMeshDS->MaxShapeIndex(); i > 0 && shapeForSrcMesh.IsNull(); --i )
+    {
+      const TopoDS_Shape& s = tgtMeshDS->IndexToShape(i);
+      if ( s.ShapeType() != TopAbs_COMPOUND ) break;
+      TopoDS_Iterator sSubIt( s );
+      for ( int iSub = 0; iSub < nbSubShapes && sSubIt.More(); ++iSub, sSubIt.Next() )
+        if ( pseudoSubShapes( subIndex+iSub ).IsSame( sSubIt.Value()))
+          if ( iSub+1 == nbSubShapes )
+          {
+            shapeForSrcMesh = s;
+            break;
+          }
+    }
+    if ( shapeForSrcMesh.IsNull() )
+    {
+      // make a new shapeForSrcMesh
+      BRep_Builder aBuilder;
+      TopoDS_Compound comp;
+      aBuilder.MakeCompound( comp );
+      shapeForSrcMesh = comp;
+      for ( int iSub = 0; iSub < nbSubShapes; ++iSub )
+        aBuilder.Add( comp, pseudoSubShapes( subIndex+iSub ));
+      TopExp_Explorer vExp( tgtMeshDS->ShapeToMesh(), TopAbs_VERTEX );
+      aBuilder.Add( comp, vExp.Current() );
+    }
+    SMESH_subMesh* sm = tgtMesh->GetSubMesh( shapeForSrcMesh );
+    SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+    if ( !smDS )
+      smDS = tgtMeshDS->NewSubMesh( sm->GetId() );
+
+    // make ordinary submesh from a complex one
+    if ( smDS->IsComplexSubmesh() )
+    {
+      list< const SMESHDS_SubMesh* > subSM;
+      SMESHDS_SubMeshIteratorPtr smIt = smDS->GetSubMeshIterator();
+      while ( smIt->more() ) subSM.push_back( smIt->next() );
+      list< const SMESHDS_SubMesh* >::iterator sub = subSM.begin();
+      for ( ; sub != subSM.end(); ++sub)
+        smDS->RemoveSubMesh( *sub );
+    }
+    return sm->GetId();
+  }
+
+  //================================================================================
+  /*!
+   * \brief Return a submesh to store nodes and elements of a copied mesh
+   * and set event listeners in order to clear
+   * imported mesh and groups as soon as submesh state requires it
+   */
+  //================================================================================
+
+  SMESHDS_SubMesh* getSubmeshForCopiedMesh(const SMESH_Mesh*                    srcMesh,
+                                           SMESH_Mesh*                          tgtMesh,
+                                           const TopoDS_Shape&                  tgtShape,
+                                           StdMeshers_Import_1D::TNodeNodeMap*& n2n,
+                                           StdMeshers_Import_1D::TElemElemMap*& e2e,
+                                           bool &                               toCopyGroups)
+  {
+    StdMeshers_Import_1D::getMaps( srcMesh, tgtMesh, n2n,e2e );
+
+    _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
+
+    SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape );
+    iData->_computedSubM.insert( importedSM );
+    if ( iData->_computedSubM.size() != iData->_subM.size() )
+      return 0; // not all submeshes computed yet
+
+    toCopyGroups = !iData->_copyGroupSubM.empty();
+
+    if ( !iData->_copyMeshSubM.empty())
+    {
+      // make submesh to store a copied mesh
+      int smID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(), tgtMesh );
+      SMESHDS_SubMesh* subDS = tgtMesh->GetMeshDS()->NewSubMesh( smID );
+
+      iData->_importMeshSubID = smID;
+      iData->_importMeshSubDS = subDS;
+      return subDS;
+    }
+    return 0;
+  }
+
+} // namespace
+
+
+//=============================================================================
+/*!
+ * Import elements from the other mesh 
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
+{
+  if ( !_sourceHyp ) return false;
+
+  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+  if ( srcGroups.empty() )
+    return error("Invalid source groups");
+
+  SMESH_MesherHelper helper(theMesh);
+  helper.SetSubShape(theShape);
+  SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
+
+  const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
+  const double edgeTol = BRep_Tool::Tolerance( geomEdge );
+  const int shapeID = tgtMesh->ShapeToIndex( geomEdge );
+
+  set<int> subShapeIDs;
+  subShapeIDs.insert( shapeID );
+
+  // get nodes on vertices
+  list < SMESH_MeshEditor::TNodeXYZ > vertexNodes;
+  list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt;
+  TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
+  for ( ; vExp.More(); vExp.Next() )
+  {
+    const TopoDS_Vertex& v = TopoDS::Vertex( vExp.Current() );
+    if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
+      continue; // closed edge
+    const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
+    if ( !n )
+    {
+      _gen->Compute(theMesh,v,/*anUpward=*/true);
+      n = SMESH_Algo::VertexNode( v, tgtMesh );
+      if ( !n ) return false; // very strange
+    }
+    vertexNodes.push_back( SMESH_MeshEditor::TNodeXYZ( n ));
+  }
+
+  // import edges from groups
+  TNodeNodeMap* n2n;
+  TElemElemMap* e2e;
+  for ( int iG = 0; iG < srcGroups.size(); ++iG )
+  {
+    const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
+
+    const int meshID = srcGroup->GetMesh()->GetPersistentId();
+    const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
+    if ( !srcMesh ) continue;
+    getMaps( srcMesh, &theMesh, n2n, e2e );
+
+    SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
+    vector<const SMDS_MeshNode*> newNodes;
+    SMDS_MeshNode tmpNode(0,0,0);
+    double u;
+    while ( srcElems->more() ) // loop on group contents
+    {
+      const SMDS_MeshElement* edge = srcElems->next();
+      // find or create nodes of a new edge
+      newNodes.resize( edge->NbNodes() );
+      newNodes.back() = 0;
+      SMDS_MeshElement::iterator node = edge->begin_nodes();
+      for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
+      {
+        TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
+        if ( n2nIt->second )
+        {
+          if ( !subShapeIDs.count( n2nIt->second->GetPosition()->GetShapeId() ))
+            break;
+        }
+        else
+        {
+          // find an existing vertex node
+          for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
+            if ( vNIt->SquareDistance( *node ) < 10 * edgeTol * edgeTol)
+            {
+              (*n2nIt).second = vNIt->_node;
+              vertexNodes.erase( vNIt );
+              break;
+            }
+        }
+        if ( !n2nIt->second )
+        {
+          // find out if node lies on theShape
+          tmpNode.setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
+          if ( helper.CheckNodeU( geomEdge, &tmpNode, u, 10 * edgeTol, /*force=*/true ))
+          {
+            SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
+            n2nIt->second = newNode;
+            tgtMesh->SetNodeOnEdge( newNode, shapeID, u );
+          }
+        }
+        if ( !(newNodes[i] = n2nIt->second ))
+          break;
+      }
+      if ( !newNodes.back() )
+        continue; // not all nodes of edge lie on theShape
+
+      // make a new edge
+      SMDS_MeshElement * newEdge;
+      if ( newNodes.size() == 3 )
+        newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
+      else
+        newEdge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
+      tgtMesh->SetMeshElementOnShape( newEdge, shapeID );
+      e2e->insert( make_pair( edge, newEdge ));
+    }
+  }
+  if ( n2n->empty())
+    return error("Empty source groups");
+
+  // check if the whole geom edge is covered by imported segments;
+  // the check consist in passing by segments from one vetrex node to another
+  bool isEdgeMeshed = false;
+  if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
+  {
+    const TopoDS_Vertex& v = ( vExp.ReInit(), TopoDS::Vertex( vExp.Current() ));
+    const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
+    const SMDS_MeshElement* seg = 0;
+    SMDS_ElemIteratorPtr segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
+    while ( segIt->more() && !seg )
+      if ( !tgtSM->Contains( seg = segIt->next()))
+        seg = 0;
+    int nbPassedSegs = 0;
+    while ( seg )
+    {
+      ++nbPassedSegs;
+      const SMDS_MeshNode* n2 = seg->GetNode(0);
+      n = ( n2 == n ? seg->GetNode(1) : n2 );
+      if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX )
+        break;
+      const SMDS_MeshElement* seg2 = 0;
+      segIt = n->GetInverseElementIterator(SMDSAbs_Edge);
+      while ( segIt->more() && !seg2 )
+        if ( seg == ( seg2 = segIt->next()))
+          seg2 = 0;
+      seg = seg2;
+    }
+    if (nbPassedSegs > 0 && tgtSM->NbElements() > nbPassedSegs )
+      return error( "Source elements overlap one another");
+
+    isEdgeMeshed = ( tgtSM->NbElements() == nbPassedSegs &&
+                     n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX );
+  }
+  if ( !isEdgeMeshed )
+    return error( "Source elements don't cover totally the geometrical edge" );
+
+  // copy meshes
+  vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
+  for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+    importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Copy mesh and groups
+ */
+//================================================================================
+
+void StdMeshers_Import_1D::importMesh(const SMESH_Mesh*          srcMesh,
+                                      SMESH_Mesh &               tgtMesh,
+                                      StdMeshers_ImportSource1D* srcHyp,
+                                      const TopoDS_Shape&        tgtShape)
+{
+  // get submesh to store the imported mesh
+  TNodeNodeMap* n2n;
+  TElemElemMap* e2e;
+  bool toCopyGroups;
+  SMESHDS_SubMesh* tgtSubMesh =
+    getSubmeshForCopiedMesh( srcMesh, &tgtMesh, tgtShape, n2n, e2e, toCopyGroups );
+  if ( !tgtSubMesh || tgtSubMesh->NbNodes() + tgtSubMesh->NbElements() > 0 )
+    return; // not to copy srcMeshDS twice
+
+  SMESHDS_Mesh* tgtMeshDS = tgtMesh.GetMeshDS();
+  SMESH_MeshEditor additor( &tgtMesh );
+
+  // 1. Copy mesh
+
+  vector<const SMDS_MeshNode*> newNodes;
+  const SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
+  SMDS_ElemIteratorPtr eIt = srcMeshDS->elementsIterator();
+  while ( eIt->more() )
+  {
+    const SMDS_MeshElement* elem = eIt->next();
+    TElemElemMap::iterator e2eIt = e2e->insert( make_pair( elem, (SMDS_MeshElement*)0 )).first;
+    if ( e2eIt->second ) continue; // already copied by Compute()
+    newNodes.resize( elem->NbNodes() );
+    SMDS_MeshElement::iterator node = elem->begin_nodes();
+    for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
+    {
+      TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
+      if ( !n2nIt->second )
+      {
+        (*n2nIt).second = tgtMeshDS->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
+        tgtSubMesh->AddNode( n2nIt->second );
+      }
+      newNodes[i] = n2nIt->second;
+    }
+    const SMDS_MeshElement* newElem =
+      tgtMeshDS->FindElement( newNodes, elem->GetType(), /*noMedium=*/false );
+    if ( !newElem )
+    {
+      newElem = additor.AddElement( newNodes, elem->GetType(), elem->IsPoly());
+      tgtSubMesh->AddElement( newElem );
+    }
+    if ( toCopyGroups )
+      (*e2eIt).second = newElem;
+  }
+  // copy free nodes
+  if ( tgtSubMesh->NbNodes() < srcMeshDS->NbNodes() )
+  {
+    SMDS_NodeIteratorPtr nIt = srcMeshDS->nodesIterator();
+    while( nIt->more() )
+    {
+      const SMDS_MeshNode* node = nIt->next();
+      if ( node->NbInverseElements() == 0 )
+      {
+        const SMDS_MeshNode* newNode = tgtMeshDS->AddNode( node->X(), node->Y(), node->Z());
+        n2n->insert( make_pair( node, newNode ));
+      }
+    }
+  }
+
+  // 2. Copy groups
+
+  vector<SMESH_Group*> resultGroups;
+  if ( toCopyGroups )
+  {
+    // collect names of existing groups to assure uniqueness of group names within a type
+    map< SMDSAbs_ElementType, set<string> > namesByType;
+    SMESH_Mesh::GroupIteratorPtr groupIt = tgtMesh.GetGroups();
+    while ( groupIt->more() )
+    {
+      SMESH_Group* tgtGroup = groupIt->next();
+      namesByType[ tgtGroup->GetGroupDS()->GetType() ].insert( tgtGroup->GetName() );
+    }
+    if (srcMesh)
+    {
+      SMESH_Mesh::GroupIteratorPtr groupIt = srcMesh->GetGroups();
+      while ( groupIt->more() )
+      {
+        SMESH_Group* srcGroup = groupIt->next();
+        SMESHDS_GroupBase* srcGroupDS = srcGroup->GetGroupDS();
+        string name = srcGroup->GetName();
+        int nb = 1;
+        while ( !namesByType[ srcGroupDS->GetType() ].insert( name ).second )
+          name = SMESH_Comment(srcGroup->GetName()) << "_imported_" << nb++;
+        SMESH_Group* newGroup = tgtMesh.AddGroup( srcGroupDS->GetType(), name.c_str(), nb );
+        SMESHDS_Group* newGroupDS = (SMESHDS_Group*)newGroup->GetGroupDS();
+        resultGroups.push_back( newGroup );
+
+        eIt = srcGroupDS->GetElements();
+        if ( srcGroupDS->GetType() == SMDSAbs_Node )
+          while (eIt->more())
+          {
+            TNodeNodeMap::iterator n2nIt = n2n->find((const SMDS_MeshNode*) eIt->next() );
+            if ( n2nIt != n2n->end() && n2nIt->second )
+              newGroupDS->SMDSGroup().Add((*n2nIt).second );
+          }
+        else
+          while (eIt->more())
+          {
+            TElemElemMap::iterator e2eIt = e2e->find( eIt->next() );
+            if ( e2eIt != e2e->end() && e2eIt->second )
+              newGroupDS->SMDSGroup().Add((*e2eIt).second );
+          }
+      }
+    }
+  }
+  n2n->clear();
+  e2e->clear();
+
+  // Remember created groups in order to remove them as soon as the srcHyp is
+  // modified or something other similar happens. Store them in a hypothesis
+  // as it stores its values anyway
+  srcHyp->StoreResultGroups( resultGroups, *srcMeshDS, *tgtMeshDS );
+}
+
+//=============================================================================
+/*!
+ * \brief Set needed event listeners and create a submesh for a copied mesh
+ *
+ * This method is called only if a submesh has HYP_OK algo_state.
+ */
+//=============================================================================
+
+void StdMeshers_Import_1D::setEventListener(SMESH_subMesh*             subMesh, 
+                                            StdMeshers_ImportSource1D* sourceHyp)
+{
+  if ( sourceHyp )
+  {
+    vector<SMESH_Mesh*> srcMeshes = sourceHyp->GetSourceMeshes();
+    if ( srcMeshes.empty() )
+      _Listener::waitHypModification( subMesh );
+    for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+      // set a listener to remove the imported mesh and groups
+      _Listener::storeImportSubmesh( subMesh, srcMeshes[i], sourceHyp );
+  }
+}
+void StdMeshers_Import_1D::SetEventListener(SMESH_subMesh* subMesh)
+{
+  if ( !_sourceHyp )
+  {
+    const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
+    SMESH_Mesh*         tgtMesh  = subMesh->GetFather();
+    Hypothesis_Status aStatus;
+    CheckHypothesis( *tgtMesh, tgtShape, aStatus );
+  }
+  setEventListener( subMesh, _sourceHyp );
+}
+
+void StdMeshers_Import_1D::SubmeshRestored(SMESH_subMesh* subMesh)
+{
+  SetEventListener(subMesh);
+}
+
+//=============================================================================
+/*!
+ * Predict nb of mesh entities created by Compute()
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D::Evaluate(SMESH_Mesh &         theMesh,
+                                    const TopoDS_Shape & theShape,
+                                    MapShapeNbElems&     aResMap)
+{
+  if ( !_sourceHyp ) return false;
+
+  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+  if ( srcGroups.empty() )
+    return error("Invalid source groups");
+
+  vector<int> aVec(SMDSEntity_Last,0);
+
+  bool toCopyMesh, toCopyGroups;
+  _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
+  if ( toCopyMesh ) // the whole mesh is copied
+  {
+    vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
+    for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+    {
+      SMESH_subMesh* sm = getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
+      if ( !sm || aResMap.count( sm )) continue; // already counted
+      aVec.assign( SMDSEntity_Last, 0);
+      const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
+      for (int i = 0; i < SMDSEntity_Last; i++)
+        aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
+    }
+  }
+  else
+  {
+    SMESH_MesherHelper helper(theMesh);
+
+    const TopoDS_Edge& geomEdge = TopoDS::Edge( theShape );
+    const double edgeTol = helper.MaxTolerance( geomEdge );
+
+    // take into account nodes on vertices
+    TopExp_Explorer vExp( theShape, TopAbs_VERTEX );
+    for ( ; vExp.More(); vExp.Next() )
+      theMesh.GetSubMesh( vExp.Current())->Evaluate( aResMap );
+
+    // count edges imported from groups
+    int nbEdges = 0, nbQuadEdges = 0;
+    for ( int iG = 0; iG < srcGroups.size(); ++iG )
+    {
+      const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
+      SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
+      SMDS_MeshNode tmpNode(0,0,0);
+      while ( srcElems->more() ) // loop on group contents
+      {
+        const SMDS_MeshElement* edge = srcElems->next();
+        // find out if edge is located on geomEdge by projecting
+        // a middle of edge to geomEdge
+        SMESH_MeshEditor::TNodeXYZ p1( edge->GetNode(0));
+        SMESH_MeshEditor::TNodeXYZ p2( edge->GetNode(1));
+        gp_XYZ middle = ( p1 + p2 ) / 2.;
+        tmpNode.setXYZ( middle.X(), middle.Y(), middle.Z());
+        double u = 0;
+        if ( helper.CheckNodeU( geomEdge, &tmpNode, u, 10 * edgeTol, /*force=*/true ))
+          ++( edge->IsQuadratic() ? nbQuadEdges : nbEdges);
+      }
+    }
+
+    int nbNodes = nbEdges + 2 * nbQuadEdges - 1;
+
+    aVec[SMDSEntity_Node     ] = nbNodes;
+    aVec[SMDSEntity_Edge     ] = nbEdges;
+    aVec[SMDSEntity_Quad_Edge] = nbQuadEdges;
+  }
+
+  SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
+  aResMap.insert(make_pair(sm,aVec));
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return node-node and element-element maps for import of geiven source mesh
+ */
+//================================================================================
+
+void StdMeshers_Import_1D::getMaps(const SMESH_Mesh* srcMesh,
+                                   SMESH_Mesh*       tgtMesh,
+                                   TNodeNodeMap*&    n2n,
+                                   TElemElemMap*&    e2e)
+{
+  _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh);
+  n2n = &iData->_n2n;
+  e2e = &iData->_e2e;
+  if ( iData->_copyMeshSubM.empty() )
+  {
+    n2n->clear();
+    e2e->clear();
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Return submesh corresponding to the copied mesh
+ */
+//================================================================================
+
+SMESH_subMesh* StdMeshers_Import_1D::getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
+                                                             SMESH_Mesh& srcMesh )
+{
+  _ImportData* iData = _Listener::getImportData(&srcMesh,&tgtMesh);
+  if ( iData->_copyMeshSubM.empty() ) return 0;
+  SMESH_subMesh* sm = tgtMesh.GetSubMeshContaining( iData->_importMeshSubID );
+  return sm;
+}
+
diff --git a/src/StdMeshers/StdMeshers_Import_1D.hxx b/src/StdMeshers/StdMeshers_Import_1D.hxx
new file mode 100644 (file)
index 0000000..a3ab382
--- /dev/null
@@ -0,0 +1,81 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Module : SMESH
+//
+#ifndef _SMESH_Import_1D_HXX_
+#define _SMESH_Import_1D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "SMESH_1D_Algo.hxx"
+#include "SMDS_MeshElement.hxx"
+
+class StdMeshers_ImportSource1D;
+
+/*!
+ * \brief Copy elements from other the mesh
+ */
+class STDMESHERS_EXPORT StdMeshers_Import_1D: public SMESH_1D_Algo
+{
+public:
+  StdMeshers_Import_1D(int hypId, int studyId, SMESH_Gen* gen);
+
+  virtual bool CheckHypothesis(SMESH_Mesh& aMesh,
+                               const TopoDS_Shape& aShape,
+                               SMESH_Hypothesis::Hypothesis_Status& aStatus);
+
+  virtual bool Compute (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape);
+  virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape,
+                        MapShapeNbElems& aResMap);
+
+  virtual void SetEventListener(SMESH_subMesh* subMesh);
+  virtual void SubmeshRestored(SMESH_subMesh* subMesh);
+
+  // internal utilities
+
+  typedef std::map<const SMDS_MeshNode*,   const SMDS_MeshNode*,   TIDCompare> TNodeNodeMap;
+  typedef std::map<const SMDS_MeshElement*,const SMDS_MeshElement*,TIDCompare> TElemElemMap;
+
+  static void getMaps(const SMESH_Mesh* srcMesh,
+                      SMESH_Mesh*       tgtMesh,
+                      TNodeNodeMap*&    n2n,
+                      TElemElemMap*&    e2e);
+
+  static void importMesh(const SMESH_Mesh*          srcMesh,
+                         SMESH_Mesh &               tgtMesh,
+                         StdMeshers_ImportSource1D* srcHyp,
+                         const TopoDS_Shape&        tgtShape);
+
+  static void setEventListener( SMESH_subMesh*             subMesh,
+                                StdMeshers_ImportSource1D* sourceHyp );
+
+  static SMESH_subMesh* getSubMeshOfCopiedMesh( SMESH_Mesh& tgtMesh,
+                                                SMESH_Mesh& srcMesh );
+
+ private:
+  
+  StdMeshers_ImportSource1D* _sourceHyp;
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx
new file mode 100644 (file)
index 0000000..0062de3
--- /dev/null
@@ -0,0 +1,642 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  File   : StdMeshers_Import_1D2D.cxx
+//  Module : SMESH
+//
+#include "StdMeshers_Import_1D2D.hxx"
+
+#include "StdMeshers_Import_1D.hxx"
+#include "StdMeshers_ImportSource.hxx"
+
+#include "SMDS_MeshElement.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMESHDS_Group.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Comment.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Group.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMesh.hxx"
+
+#include "Utils_SALOME_Exception.hxx"
+#include "utilities.h"
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#include <numeric>
+
+using namespace std;
+
+//=============================================================================
+/*!
+ * Creates StdMeshers_Import_1D2D
+ */
+//=============================================================================
+
+StdMeshers_Import_1D2D::StdMeshers_Import_1D2D(int hypId, int studyId, SMESH_Gen * gen)
+  :SMESH_2D_Algo(hypId, studyId, gen), _sourceHyp(0)
+{
+  MESSAGE("StdMeshers_Import_1D2D::StdMeshers_Import_1D2D");
+  _name = "Import_1D2D";
+  _shapeType = (1 << TopAbs_FACE);
+
+  _compatibleHypothesis.push_back("ImportSource2D");
+  _requireDescretBoundary = false;
+}
+
+//=============================================================================
+/*!
+ * Check presence of a hypothesis
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D2D::CheckHypothesis
+                         (SMESH_Mesh&                          aMesh,
+                          const TopoDS_Shape&                  aShape,
+                          SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  _sourceHyp = 0;
+
+  const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
+  if ( hyps.size() == 0 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_MISSING;
+    return false;  // can't work with no hypothesis
+  }
+
+  if ( hyps.size() > 1 )
+  {
+    aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
+    return false;
+  }
+
+  const SMESHDS_Hypothesis *theHyp = hyps.front();
+
+  string hypName = theHyp->GetName();
+
+  if (hypName == _compatibleHypothesis.front())
+  {
+    _sourceHyp = (StdMeshers_ImportSource1D *)theHyp;
+    aStatus = SMESH_Hypothesis::HYP_OK;
+    return true;
+  }
+
+  aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  return true;
+}
+
+namespace
+{
+  /*!
+   * \brief OrientedLink additionally storing a medium node
+   */
+  struct TLink : public SMESH_OrientedLink
+  {
+    const SMDS_MeshNode* _medium;
+    TLink( const SMDS_MeshNode* n1,
+           const SMDS_MeshNode* n2,
+           const SMDS_MeshNode* medium=0)
+      : SMESH_OrientedLink( n1,n2 ), _medium( medium ) {}
+  };
+}
+
+//=============================================================================
+/*!
+ * Import elements from the other mesh 
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
+{
+  if ( !_sourceHyp ) return false;
+
+  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+  if ( srcGroups.empty() )
+    return error("Invalid source groups");
+
+  SMESH_MesherHelper helper(theMesh);
+  helper.SetSubShape(theShape);
+  SMESHDS_Mesh* tgtMesh = theMesh.GetMeshDS();
+
+  const TopoDS_Face& geomFace = TopoDS::Face( theShape );
+  const double faceTol = helper.MaxTolerance( geomFace );
+  const int shapeID = tgtMesh->ShapeToIndex( geomFace );
+  const bool toCheckOri = (helper.NbAncestors( geomFace, theMesh, TopAbs_SOLID ) == 1 );
+
+  Handle(Geom_Surface) surface = BRep_Tool::Surface( geomFace );
+  if ( helper.GetSubShapeOri( tgtMesh->ShapeToMesh(), geomFace) == TopAbs_REVERSED )
+    surface->UReverse();
+  gp_Pnt p; gp_Vec du, dv;
+
+  set<int> subShapeIDs;
+  subShapeIDs.insert( shapeID );
+
+  // get nodes on vertices
+  list < SMESH_MeshEditor::TNodeXYZ > vertexNodes;
+  list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt;
+  TopExp_Explorer exp( theShape, TopAbs_VERTEX );
+  for ( ; exp.More(); exp.Next() )
+  {
+    const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() );
+    if ( !subShapeIDs.insert( tgtMesh->ShapeToIndex( v )).second )
+      continue;
+    const SMDS_MeshNode* n = SMESH_Algo::VertexNode( v, tgtMesh );
+    if ( !n )
+    {
+      _gen->Compute(theMesh,v,/*anUpward=*/true);
+      n = SMESH_Algo::VertexNode( v, tgtMesh );
+      if ( !n ) return false; // very strange
+    }
+    vertexNodes.push_back( SMESH_MeshEditor::TNodeXYZ( n ));
+  }
+
+  // to count now many times a link between nodes encounters
+  map<TLink, int> linkCount;
+  map<TLink, int>::iterator link2Nb;
+
+  // =========================
+  // Import faces from groups
+  // =========================
+
+  StdMeshers_Import_1D::TNodeNodeMap* n2n;
+  StdMeshers_Import_1D::TElemElemMap* e2e;
+  vector<const SMDS_MeshNode*> newNodes;
+  for ( int iG = 0; iG < srcGroups.size(); ++iG )
+  {
+    const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
+
+    const int meshID = srcGroup->GetMesh()->GetPersistentId();
+    const SMESH_Mesh* srcMesh = GetMeshByPersistentID( meshID );
+    if ( !srcMesh ) continue;
+    StdMeshers_Import_1D::getMaps( srcMesh, &theMesh, n2n, e2e );
+
+    SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
+    SMDS_MeshNode tmpNode(0,0,0);
+    gp_XY uv;
+    while ( srcElems->more() ) // loop on group contents
+    {
+      const SMDS_MeshElement* face = srcElems->next();
+      // find or create nodes of a new face
+      newNodes.resize( face->NbNodes() );
+      newNodes.back() = 0;
+      int nbCreatedNodes = 0;
+      SMDS_MeshElement::iterator node = face->begin_nodes();
+      for ( unsigned i = 0; i < newNodes.size(); ++i, ++node )
+      {
+        TNodeNodeMap::iterator n2nIt = n2n->insert( make_pair( *node, (SMDS_MeshNode*)0 )).first;
+        if ( n2nIt->second )
+        {
+          if ( !subShapeIDs.count( n2nIt->second->GetPosition()->GetShapeId() ))
+            break;
+        }
+        else
+        {
+          // find an existing vertex node
+          for ( vNIt = vertexNodes.begin(); vNIt != vertexNodes.end(); ++vNIt)
+            if ( vNIt->SquareDistance( *node ) < 10 * faceTol * faceTol)
+            {
+              (*n2nIt).second = vNIt->_node;
+              vertexNodes.erase( vNIt );
+              break;
+            }
+        }
+        if ( !n2nIt->second )
+        {
+          // find out if node lies on theShape
+          tmpNode.setXYZ( (*node)->X(), (*node)->Y(), (*node)->Z());
+          if ( helper.CheckNodeUV( geomFace, &tmpNode, uv, 10 * faceTol, /*force=*/true ))
+          {
+            SMDS_MeshNode* newNode = tgtMesh->AddNode( (*node)->X(), (*node)->Y(), (*node)->Z());
+            n2nIt->second = newNode;
+            tgtMesh->SetNodeOnFace( newNode, shapeID, uv.X(), uv.Y() );
+            nbCreatedNodes++;
+          }
+        }
+        if ( !(newNodes[i] = n2nIt->second ))
+          break;
+      }
+      if ( !newNodes.back() )
+        continue; // not all nodes of the face lie on theShape
+
+      // try to find already created face
+      SMDS_MeshElement * newFace = 0;
+      if ( nbCreatedNodes == 0 &&
+           tgtMesh->FindElement(newNodes, SMDSAbs_Face, /*noMedium=*/false))
+        continue; // repeated face in source groups already created 
+
+      // check future face orientation
+      if ( toCheckOri )
+      {
+        int iNode = -1;
+        gp_Vec geomNorm;
+        do
+        {
+          uv = helper.GetNodeUV( geomFace, newNodes[++iNode] );
+          surface->D1( uv.X(),uv.Y(), p, du,dv );
+          geomNorm = du ^ dv;
+        }
+        while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < face->NbCornerNodes());
+
+        int iNext = helper.WrapIndex( iNode+1, face->NbCornerNodes() );
+        int iPrev = helper.WrapIndex( iNode-1, face->NbCornerNodes() );
+
+        gp_Vec n1n0( SMESH_MeshEditor::TNodeXYZ( newNodes[iPrev] ) -
+                     SMESH_MeshEditor::TNodeXYZ( newNodes[iNode] ));
+        gp_Vec n1n2( SMESH_MeshEditor::TNodeXYZ( newNodes[iNext] ) -
+                     SMESH_MeshEditor::TNodeXYZ( newNodes[iNode] ));
+        gp_Vec meshNorm = n1n2 ^ n1n0;
+
+        if ( geomNorm * meshNorm < 0 )
+          std::reverse( newNodes.begin(), newNodes.end() );
+      }
+
+      // make a new face
+      switch ( newNodes.size() )
+      {
+      case 3:
+        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
+        break;
+      case 4:
+        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
+        break;
+      case 6:
+        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2],
+                                    newNodes[3], newNodes[4], newNodes[5]);
+        break;
+      case 8:
+        newFace = tgtMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3],
+                                    newNodes[4], newNodes[5], newNodes[6], newNodes[7]);
+        break;
+      default: continue;
+      }
+      tgtMesh->SetMeshElementOnShape( newFace, shapeID );
+      e2e->insert( make_pair( face, newFace ));
+
+      // collect links
+      int nbNodes = face->NbCornerNodes();
+      const SMDS_MeshNode* medium = 0;
+      for ( int i = 0; i < nbNodes; ++i )
+      {
+        const SMDS_MeshNode* n1 = newNodes[i];
+        const SMDS_MeshNode* n2 = newNodes[ (i+1)%nbNodes ];
+        if ( newFace->IsQuadratic() )
+          medium = newNodes[i+nbNodes];
+        link2Nb = linkCount.insert( make_pair( TLink( n1, n2, medium ), 0)).first;
+        ++link2Nb->second;
+      }
+    }
+  }
+
+  // ==========================================================
+  // Put nodes on geom edges and create edges on them;
+  // check if the whole geom face is covered by imported faces
+  // ==========================================================
+
+  vector< TopoDS_Edge > edges;
+  for ( exp.Init( theShape, TopAbs_EDGE ); exp.More(); exp.Next() )
+    if ( subShapeIDs.insert( tgtMesh->ShapeToIndex( exp.Current() )).second )
+      edges.push_back( TopoDS::Edge( exp.Current() ));
+
+  bool isFaceMeshed = false;
+  if ( SMESHDS_SubMesh* tgtSM = tgtMesh->MeshElements( theShape ))
+  {
+    // the imported mesh is valid if all external links (encountered once)
+    // lie on geom edges
+    subShapeIDs.erase( shapeID ); // to contain edges and vertices only
+    double u, f, l;
+    for ( link2Nb = linkCount.begin(); link2Nb != linkCount.end(); ++link2Nb)
+    {
+      const TLink& link = (*link2Nb).first;
+      int nbFaces = link2Nb->second;
+      if ( nbFaces == 1 )
+      {
+        // check if the link lie on face boundary
+        bool nodesOnBoundary = true;
+        list< TopoDS_Shape > bndShapes;
+        for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN )
+        {
+          const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2();
+          if ( !subShapeIDs.count( n->GetPosition()->GetShapeId() ))
+          {
+            for ( unsigned iE = 0; iE < edges.size(); ++iE )
+              if ( helper.CheckNodeU( edges[iE], n, u, 10 * faceTol, /*force=*/true ))
+              {
+                BRep_Tool::Range(edges[iE],f,l);
+                if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol )
+                  // duplicated node on vertex
+                  return error("Source elements overlap one another");
+                tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u );
+                break;
+              }
+            nodesOnBoundary = subShapeIDs.count( n->GetPosition()->GetShapeId());
+          }
+          if ( nodesOnBoundary )
+          {
+            TopoDS_Shape s = helper.GetSubShapeByNode( n, tgtMesh );
+            if ( s.ShapeType() == TopAbs_VERTEX )
+              bndShapes.push_front( s ); // vertex first
+            else
+              bndShapes.push_back( s ); // edges last
+          }
+        }
+        if ( !nodesOnBoundary )
+          break; // free internal link
+        if ( bndShapes.front().ShapeType() == TopAbs_EDGE &&
+             bndShapes.front() != bndShapes.back() )
+          break; // link nodes on different geom edges
+
+        // find geom edge the link is on
+        if ( bndShapes.back().ShapeType() != TopAbs_EDGE )
+        {
+          // find geom edge by two vertices
+          TopoDS_Shape geomEdge;
+          PShapeIteratorPtr edgeIt = helper.GetAncestors( bndShapes.back(), theMesh, TopAbs_EDGE );
+          while ( edgeIt->more() )
+          {
+            geomEdge = *(edgeIt->next());
+            if ( !helper.IsSubShape( bndShapes.front(), geomEdge ))
+              geomEdge.Nullify();
+          }
+          if ( geomEdge.IsNull() )
+            break; // vertices belong to different edges -> free internal link
+          bndShapes.push_back( geomEdge );
+        }
+
+        // create an edge if not yet exists
+        newNodes.resize(2);
+        newNodes[0] = link.node1(), newNodes[1] = link.node2();
+        const SMDS_MeshElement* edge = tgtMesh->FindElement( newNodes, SMDSAbs_Edge );
+        if ( edge ) continue;
+
+        if ( link._reversed ) std::swap( newNodes[0], newNodes[1] );
+        if ( link._medium )
+        {
+          newNodes.push_back( link._medium );
+          edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], newNodes[2] );
+
+          TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back());
+          helper.CheckNodeU( geomEdge, link._medium, u, 10*faceTol, /*force=*/true );
+          tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)link._medium, geomEdge, u );
+        }
+        else
+        {
+          edge = tgtMesh->AddEdge( newNodes[0], newNodes[1]);
+        }
+        // remove nodes from submesh of theShape
+        for ( unsigned i = 0; i < newNodes.size(); ++i )
+          tgtSM->RemoveNode( newNodes[i], /*isNodeDeleted=*/false );
+        if ( !edge )
+          return false;
+
+        tgtMesh->SetMeshElementOnShape( edge, bndShapes.back() );
+      }
+      else if ( nbFaces > 2 )
+      {
+        return error( "Non-manifold source mesh");
+      }
+    }
+    isFaceMeshed = ( link2Nb == linkCount.end() && !linkCount.empty());
+    if ( isFaceMeshed )
+    {
+      // check that source faces do not overlap:
+      // there must be only two edges sharing each vertex and bound to sub-edges of theShape
+      SMESH_MeshEditor editor( &theMesh );
+      set<int>::iterator subID = subShapeIDs.begin();
+      for ( ; subID != subShapeIDs.end(); ++subID )
+      {
+        const TopoDS_Shape& s = tgtMesh->IndexToShape( *subID );
+        if ( s.ShapeType() != TopAbs_VERTEX ) continue;
+        const SMDS_MeshNode* n = SMESH_Algo::VertexNode( TopoDS::Vertex(s), tgtMesh );
+        SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(SMDSAbs_Edge);
+        int nbEdges = 0;
+        while ( eIt->more() )
+        {
+          const SMDS_MeshElement* edge = eIt->next();
+          int sId = editor.FindShape( edge );
+          nbEdges += subShapeIDs.count( sId );
+        }
+        if ( nbEdges < 2 )
+          return false; // weird
+        if ( nbEdges > 2 )
+          return error( "Source elements overlap one another");
+      }
+    }
+  }
+  if ( !isFaceMeshed )
+    return error( "Source elements don't cover totally the geometrical face" );
+
+  // notify sub-meshes of edges on computation
+  for ( unsigned iE = 0; iE < edges.size(); ++iE )
+    theMesh.GetSubMesh( edges[iE] )->ComputeStateEngine(SMESH_subMesh::CHECK_COMPUTE_STATE);
+
+  // ============
+  // Copy meshes
+  // ============
+
+  vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
+  for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+    StdMeshers_Import_1D::importMesh( srcMeshes[i], theMesh, _sourceHyp, theShape );
+
+  return true;
+}
+
+//=============================================================================
+/*!
+ * \brief Set needed event listeners and create a submesh for a copied mesh
+ *
+ * This method is called only if a submesh has HYP_OK algo_state.
+ */
+//=============================================================================
+
+void StdMeshers_Import_1D2D::SetEventListener(SMESH_subMesh* subMesh)
+{
+  if ( !_sourceHyp )
+  {
+    const TopoDS_Shape& tgtShape = subMesh->GetSubShape();
+    SMESH_Mesh*         tgtMesh  = subMesh->GetFather();
+    Hypothesis_Status aStatus;
+    CheckHypothesis( *tgtMesh, tgtShape, aStatus );
+  }
+  StdMeshers_Import_1D::setEventListener( subMesh, _sourceHyp );
+}
+void StdMeshers_Import_1D2D::SubmeshRestored(SMESH_subMesh* subMesh)
+{
+  SetEventListener(subMesh);
+}
+
+//=============================================================================
+/*!
+ * Predict nb of mesh entities created by Compute()
+ */
+//=============================================================================
+
+bool StdMeshers_Import_1D2D::Evaluate(SMESH_Mesh &         theMesh,
+                                      const TopoDS_Shape & theShape,
+                                      MapShapeNbElems&     aResMap)
+{
+  if ( !_sourceHyp ) return false;
+
+  const vector<SMESH_Group*>& srcGroups = _sourceHyp->GetGroups();
+  if ( srcGroups.empty() )
+    return error("Invalid source groups");
+
+  vector<int> aVec(SMDSEntity_Last,0);
+
+  bool toCopyMesh, toCopyGroups;
+  _sourceHyp->GetCopySourceMesh(toCopyMesh, toCopyGroups);
+  if ( toCopyMesh ) // the whole mesh is copied
+  {
+    vector<SMESH_Mesh*> srcMeshes = _sourceHyp->GetSourceMeshes();
+    for ( unsigned i = 0; i < srcMeshes.size(); ++i )
+    {
+      SMESH_subMesh* sm = StdMeshers_Import_1D::getSubMeshOfCopiedMesh( theMesh, *srcMeshes[i]);
+      if ( !sm || aResMap.count( sm )) continue; // already counted
+      const SMDS_MeshInfo& aMeshInfo = srcMeshes[i]->GetMeshDS()->GetMeshInfo();
+      for (int i = 0; i < SMDSEntity_Last; i++)
+        aVec[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
+    }
+  }
+  else
+  {
+    // std-like iterator used to get coordinates of nodes of mesh element
+    typedef SMDS_StdIterator< SMESH_MeshEditor::TNodeXYZ, SMDS_ElemIteratorPtr > TXyzIterator;
+
+    SMESH_MesherHelper helper(theMesh);
+    helper.SetSubShape(theShape);
+
+    const TopoDS_Face& geomFace = TopoDS::Face( theShape );
+    const double faceTol = helper.MaxTolerance( geomFace );
+
+    // take into account nodes on vertices
+    TopExp_Explorer exp( theShape, TopAbs_VERTEX );
+    for ( ; exp.More(); exp.Next() )
+      theMesh.GetSubMesh( exp.Current())->Evaluate( aResMap );
+
+    // to count now many times a link between nodes encounters,
+    // negative nb additionally means that a link is quadratic
+    map<SMESH_TLink, int> linkCount;
+    map<SMESH_TLink, int>::iterator link2Nb;
+
+    // count faces and nodes imported from groups
+    set<const SMDS_MeshNode* > allNodes;
+    gp_XY uv;
+    for ( int iG = 0; iG < srcGroups.size(); ++iG )
+    {
+      const SMESHDS_GroupBase* srcGroup = srcGroups[iG]->GetGroupDS();
+      SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements();
+      SMDS_MeshNode tmpNode(0,0,0);
+      while ( srcElems->more() ) // loop on group contents
+      {
+        const SMDS_MeshElement* face = srcElems->next();
+        // find out if face is located on geomEdge by projecting
+        // a gravity center of face to geomFace
+        gp_XYZ gc(0,0,0);
+        gc = accumulate( TXyzIterator(face->nodesIterator()), TXyzIterator(), gc)/face->NbNodes();
+        tmpNode.setXYZ( gc.X(), gc.Y(), gc.Z());
+        if ( helper.CheckNodeUV( geomFace, &tmpNode, uv, 10 * faceTol, /*force=*/true ))
+        {
+          ++aVec[ face->GetEntityType() ];
+
+          // collect links
+          int nbConers = face->NbCornerNodes();
+          for ( int i = 0; i < face->NbNodes(); ++i )
+          {
+            const SMDS_MeshNode* n1 = face->GetNode(i);
+            allNodes.insert( n1 );
+            if ( i < nbConers )
+            {
+              const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbConers );
+              link2Nb = linkCount.insert( make_pair( SMESH_TLink( n1, n2 ), 0)).first;
+              if ( (*link2Nb).second )
+                link2Nb->second += (link2Nb->second < 0 ) ? -1 : 1;
+              else
+                link2Nb->second += ( face->IsQuadratic() ) ? -1 : 1;
+            }
+          }
+        }
+      }
+    }
+
+    int nbNodes = allNodes.size();
+    allNodes.clear();
+
+    // count nodes and edges on geom edges
+
+    double u;
+    for ( exp.Init(theShape, TopAbs_EDGE); exp.More(); exp.Next() )
+    {
+      TopoDS_Edge geomEdge = TopoDS::Edge( exp.Current() );
+      SMESH_subMesh* sm = theMesh.GetSubMesh( geomEdge );
+      vector<int>& edgeVec = aResMap[sm];
+      if ( edgeVec.empty() )
+      {
+        edgeVec.resize(SMDSEntity_Last,0);
+        for ( link2Nb = linkCount.begin(); link2Nb != linkCount.end(); )
+        {
+          const SMESH_TLink& link = (*link2Nb).first;
+          int nbFacesOfLink = Abs( link2Nb->second );
+          bool eraseLink = ( nbFacesOfLink != 1 );
+          if ( nbFacesOfLink == 1 )
+          {
+            if ( helper.CheckNodeU( geomEdge, link.node1(), u, 10*faceTol, /*force=*/true )&&
+                 helper.CheckNodeU( geomEdge, link.node2(), u, 10*faceTol, /*force=*/true ))
+            {
+              bool isQuadratic = ( link2Nb->second < 0 );
+              ++edgeVec[ isQuadratic ? SMDSEntity_Quad_Edge : SMDSEntity_Edge ];
+              ++edgeVec[ SMDSEntity_Node ];
+              --nbNodes;
+              eraseLink = true;
+            }
+          }
+          if ( eraseLink )
+            linkCount.erase(link2Nb++);
+          else
+            link2Nb++;
+        }
+        if ( edgeVec[ SMDSEntity_Node] > 0 )
+          --edgeVec[ SMDSEntity_Node ]; // for one node on vertex
+      }
+      else if ( !helper.IsSeamShape( geomEdge ) ||
+                geomEdge.Orientation() == TopAbs_FORWARD )
+      {
+        nbNodes -= 1+edgeVec[ SMDSEntity_Node ];
+      }
+    }
+
+    aVec[SMDSEntity_Node] = nbNodes;
+  }
+
+  SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
+  aResMap.insert(make_pair(sm,aVec));
+
+  return true;
+}
diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.hxx b/src/StdMeshers/StdMeshers_Import_1D2D.hxx
new file mode 100644 (file)
index 0000000..5733c2f
--- /dev/null
@@ -0,0 +1,60 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Module : SMESH
+//
+#ifndef _SMESH_Import_2D_HXX_
+#define _SMESH_Import_2D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+
+#include "SMESH_2D_Algo.hxx"
+#include "SMDS_MeshElement.hxx"
+
+class StdMeshers_ImportSource1D;
+
+/*!
+ * \brief Copy elements from other the mesh
+ */
+class STDMESHERS_EXPORT StdMeshers_Import_1D2D: public SMESH_2D_Algo
+{
+public:
+  StdMeshers_Import_1D2D(int hypId, int studyId, SMESH_Gen* gen);
+
+  virtual bool CheckHypothesis(SMESH_Mesh& aMesh,
+                               const TopoDS_Shape& aShape,
+                               SMESH_Hypothesis::Hypothesis_Status& aStatus);
+
+  virtual bool Compute (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape);
+  virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape,
+                        MapShapeNbElems& aResMap);
+
+  virtual void SetEventListener(SMESH_subMesh* subMesh);
+  virtual void SubmeshRestored(SMESH_subMesh* subMesh);
+
+ private:
+  
+  StdMeshers_ImportSource1D* _sourceHyp;
+};
+
+#endif