Salome HOME
PAL13473 (Build repetitive mesh):
authoreap <eap@opencascade.com>
Wed, 6 Dec 2006 15:23:10 +0000 (15:23 +0000)
committereap <eap@opencascade.com>
Wed, 6 Dec 2006 15:23:10 +0000 (15:23 +0000)
New meshers implemented

23 files changed:
src/StdMeshers/Makefile.in
src/StdMeshers/StdMeshers_LayerDistribution.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_LayerDistribution.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_NumberOfLayers.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_NumberOfLayers.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Prism_3D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Prism_3D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource1D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource1D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource2D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource2D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource3D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionSource3D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionUtils.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_ProjectionUtils.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_1D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_1D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_2D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_2D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_3D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Projection_3D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_RadialPrism_3D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_RadialPrism_3D.hxx [new file with mode: 0644]

index b2a3fa7ffa09e058efda73214d40e980a9589044..d81355de98dd14c9ecab388d49f8acd91b41274d 100644 (file)
@@ -51,7 +51,18 @@ EXPORT_HEADERS = \
        StdMeshers_AutomaticLength.hxx \
        StdMeshers_Distribution.hxx \
        StdMeshers_QuadranglePreference.hxx \
-       StdMeshers_QuadraticMesh.hxx
+       StdMeshers_QuadraticMesh.hxx \
+       StdMeshers_NumberOfLayers.hxx \
+       StdMeshers_Prism_3D.hxx \
+       StdMeshers_ProjectionSource1D.hxx \
+       StdMeshers_ProjectionSource2D.hxx \
+       StdMeshers_ProjectionSource3D.hxx \
+       StdMeshers_Projection_1D.hxx \
+       StdMeshers_Projection_2D.hxx \
+       StdMeshers_Projection_3D.hxx \
+       StdMeshers_RadialPrism_3D.hxx  \
+       StdMeshers_ProjectionUtils.hxx \
+       StdMeshers_LayerDistribution.hxx
 
 EXPORT_PYSCRIPTS =
 
@@ -78,7 +89,18 @@ LIB_SRC = \
        StdMeshers_AutomaticLength.cxx \
        StdMeshers_Distribution.cxx \
        StdMeshers_QuadranglePreference.cxx \
-       StdMeshers_QuadraticMesh.cxx
+       StdMeshers_QuadraticMesh.cxx \
+       StdMeshers_NumberOfLayers.cxx \
+       StdMeshers_Prism_3D.cxx \
+       StdMeshers_ProjectionSource1D.cxx \
+       StdMeshers_ProjectionSource2D.cxx \
+       StdMeshers_ProjectionSource3D.cxx \
+       StdMeshers_Projection_1D.cxx \
+       StdMeshers_Projection_2D.cxx \
+       StdMeshers_Projection_3D.cxx \
+       StdMeshers_RadialPrism_3D.cxx \
+       StdMeshers_ProjectionUtils.cxx \
+       StdMeshers_LayerDistribution.cxx
 
 LIB_SERVER_IDL = 
 
diff --git a/src/StdMeshers/StdMeshers_LayerDistribution.cxx b/src/StdMeshers/StdMeshers_LayerDistribution.cxx
new file mode 100644 (file)
index 0000000..42d99c8
--- /dev/null
@@ -0,0 +1,148 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_LayerDistribution.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#include "StdMeshers_LayerDistribution.hxx"
+
+#include "utilities.h"
+
+using namespace std;
+
+
+//=============================================================================
+/*!
+ *  StdMeshers_LayerDistribution::StdMeshers_LayerDistribution
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_LayerDistribution::StdMeshers_LayerDistribution(int hypId, int studyId,
+                                                           SMESH_Gen * gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _name = "LayerDistribution"; // used by RadialPrism_3D
+  _param_algo_dim = 3; // 3D
+  myHyp = 0;
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_LayerDistribution::~StdMeshers_LayerDistribution
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_LayerDistribution::~StdMeshers_LayerDistribution()
+{
+  MESSAGE( "StdMeshers_LayerDistribution::~StdMeshers_LayerDistribution" );
+}
+
+//=============================================================================
+  /*!
+   * \brief Sets  1D hypothesis specifying distribution of layers
+    * \param hyp1D - 1D hypothesis
+   */
+//=============================================================================
+
+void StdMeshers_LayerDistribution::SetLayerDistribution(SMESH_Hypothesis* hyp1D)
+  throw ( SALOME_Exception )
+{
+  if ( myHyp != hyp1D ) {
+    if ( myHyp && hyp1D->GetDim() != 1 )
+      throw SALOME_Exception(LOCALIZED("1D hypothesis is expected"));
+    myHyp = hyp1D;
+  }
+  std::ostringstream os;
+  if ( myHyp )
+    myHyp->SaveTo( os );
+
+  if ( mySavedHyp != os.str() )
+    NotifySubMeshesHypothesisModification();
+
+  mySavedHyp = os.str();
+}
+
+//=============================================================================
+/*!
+ *  Servant saves and loads my hypothesis
+ */
+//=============================================================================
+
+ostream & StdMeshers_LayerDistribution::SaveTo(ostream & save)
+{
+  return save;
+}
+
+//=============================================================================
+/*!
+ *   Servant saves and loads my hypothesis
+ */
+//=============================================================================
+
+istream & StdMeshers_LayerDistribution::LoadFrom(istream & load)
+{
+  return load;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & operator <<(ostream & save, StdMeshers_LayerDistribution & hyp)
+{
+  return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & operator >>(istream & load, StdMeshers_LayerDistribution & hyp)
+{
+  return hyp.LoadFrom( load );
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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_LayerDistribution::SetParametersByMesh(const SMESH_Mesh*   ,
+                                                       const TopoDS_Shape& )
+{
+  return false;
+}
diff --git a/src/StdMeshers/StdMeshers_LayerDistribution.hxx b/src/StdMeshers/StdMeshers_LayerDistribution.hxx
new file mode 100644 (file)
index 0000000..08c2269
--- /dev/null
@@ -0,0 +1,91 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_LayerDistribution.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#ifndef _SMESH_LayerDistribution_HXX_
+#define _SMESH_LayerDistribution_HXX_
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <string>
+
+class SMESH_Gen;
+
+// =========================================================
+// =========================================================
+/*!
+ * This hypothesis is used by "Radial prism" algorithm.
+ * It specifies 1D hypothesis defining distribution of segments between the internal 
+ * and the external surfaces.
+ */
+// =========================================================
+// =========================================================
+
+class StdMeshers_LayerDistribution:  public SMESH_Hypothesis
+{
+public:
+  // Constructor
+  StdMeshers_LayerDistribution( int hypId, int studyId, SMESH_Gen * gen );
+  // Destructor
+  virtual ~StdMeshers_LayerDistribution();
+
+  /*!
+   * \brief Sets  1D hypothesis specifying distribution of layers
+    * \param hyp1D - 1D hypothesis
+   */
+  void SetLayerDistribution(SMESH_Hypothesis* hyp1D)
+    throw ( SALOME_Exception );
+
+  /*!
+   * \brief Returns 1D hypothesis specifying distribution of layers
+    * \retval SMESH::SMESH_Hypothesis_ptr - 1D hypothesis
+   */
+  SMESH_Hypothesis* GetLayerDistribution() const { return myHyp; }
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  friend std::ostream & operator <<(std::ostream & save, StdMeshers_LayerDistribution & hyp);
+  friend std::istream & operator >>(std::istream & load, StdMeshers_LayerDistribution & hyp);
+
+  /*!
+   * \brief Initialize parameters 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
+    *
+    * Implementation does noting
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+protected:
+  SMESH_Hypothesis* myHyp;
+  std::string       mySavedHyp;
+};
+
+#endif
+
diff --git a/src/StdMeshers/StdMeshers_NumberOfLayers.cxx b/src/StdMeshers/StdMeshers_NumberOfLayers.cxx
new file mode 100644 (file)
index 0000000..c1bab0f
--- /dev/null
@@ -0,0 +1,162 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_NumberOfLayers.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#include "StdMeshers_NumberOfLayers.hxx"
+
+
+#include "utilities.h"
+
+using namespace std;
+
+
+//=============================================================================
+/*!
+ *  StdMeshers_NumberOfLayers::StdMeshers_NumberOfLayers
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_NumberOfLayers::StdMeshers_NumberOfLayers(int hypId, int studyId,
+                                                     SMESH_Gen * gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _name = "NumberOfLayers"; // used by RadialPrism_3D
+  _param_algo_dim = 3; // 3D
+  _nbLayers = 1;
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_NumberOfLayers::~StdMeshers_NumberOfLayers
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_NumberOfLayers::~StdMeshers_NumberOfLayers()
+{
+  MESSAGE( "StdMeshers_NumberOfLayers::~StdMeshers_NumberOfLayers" );
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_NumberOfLayers::SetNumberOfLayers
+ *
+ *  Sets <number of segments> parameter value
+ */
+//=============================================================================
+
+void StdMeshers_NumberOfLayers::SetNumberOfLayers(int numberOfLayers)
+  throw ( SALOME_Exception )
+{
+  if ( _nbLayers != numberOfLayers ) {
+    if ( numberOfLayers <= 0 )
+      throw SALOME_Exception(LOCALIZED("numberOfLayers must be positive"));
+    _nbLayers = numberOfLayers;
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_NumberOfLayers::GetNumberOfLayers
+ *
+ *  Returns <number of layers> parameter value
+ */
+//=============================================================================
+
+int StdMeshers_NumberOfLayers::GetNumberOfLayers() const
+{
+  return _nbLayers;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & StdMeshers_NumberOfLayers::SaveTo(ostream & save)
+{
+  save << _nbLayers;
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & StdMeshers_NumberOfLayers::LoadFrom(istream & load)
+{
+  bool isOK = true;
+  isOK = (load >> _nbLayers);
+  if (!isOK)
+    load.clear(ios::badbit | load.rdstate());
+  return load;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & operator <<(ostream & save, StdMeshers_NumberOfLayers & hyp)
+{
+  return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & operator >>(istream & load, StdMeshers_NumberOfLayers & hyp)
+{
+  return hyp.LoadFrom( load );
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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_NumberOfLayers::SetParametersByMesh(const SMESH_Mesh*   ,
+                                                    const TopoDS_Shape& )
+{
+  return false;
+}
diff --git a/src/StdMeshers/StdMeshers_NumberOfLayers.hxx b/src/StdMeshers/StdMeshers_NumberOfLayers.hxx
new file mode 100644 (file)
index 0000000..d897255
--- /dev/null
@@ -0,0 +1,81 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_NumberOfLayers.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#ifndef _SMESH_NumberOfLayers_HXX_
+#define _SMESH_NumberOfLayers_HXX_
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+class SMESH_Gen;
+
+// =========================================================
+// =========================================================
+/*!
+ * This hypothesis is used by "Radial prism" algorithm.
+ * It specifies number of segments between the internal 
+ * and the external surfaces.
+ */
+// =========================================================
+// =========================================================
+
+class StdMeshers_NumberOfLayers:  public SMESH_Hypothesis
+{
+public:
+  // Constructor
+  StdMeshers_NumberOfLayers( int hypId, int studyId, SMESH_Gen * gen );
+  // Destructor
+  virtual ~StdMeshers_NumberOfLayers();
+
+  // Sets <number of segments> parameter value
+  void SetNumberOfLayers(int numberOfLayers) throw ( SALOME_Exception );
+
+  // Returns <number of layers> parameter value
+  int GetNumberOfLayers() const;
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  friend std::ostream & operator <<(std::ostream & save, StdMeshers_NumberOfLayers & hyp);
+  friend std::istream & operator >>(std::istream & load, StdMeshers_NumberOfLayers & hyp);
+
+  /*!
+   * \brief Initialize parameters 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
+    *
+    * Implementation does noting
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+protected:
+  int _nbLayers;
+};
+
+#endif
+
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx
new file mode 100644 (file)
index 0000000..85b4180
--- /dev/null
@@ -0,0 +1,1750 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_Prism_3D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_Prism_3D.hxx"
+
+#include "StdMeshers_ProjectionUtils.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMDS_VolumeOfNodes.hxx"
+#include "SMDS_EdgePosition.hxx"
+
+#include "utilities.h"
+
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_Curve2d.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2d_Line.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+using namespace std;
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
+#define SHOWYXZ(msg, xyz) // {\
+// gp_Pnt p (xyz); \
+// cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
+// }
+
+typedef StdMeshers_ProjectionUtils TAssocTool;
+
+enum { ID_BOT_FACE = SMESH_Block::ID_Fxy0,
+       ID_TOP_FACE = SMESH_Block::ID_Fxy1,
+       BOTTOM_EDGE = 0, TOP_EDGE, V0_EDGE, V1_EDGE, // edge IDs in face
+       NB_WALL_FACES = 4 }; //
+
+namespace {
+
+  //================================================================================
+  /*!
+   * \brief Return iterator pointing to node column for the given parameter
+   * \param columnsMap - node column map
+   * \param parameter - parameter
+   * \retval TParam2ColumnMap::iterator - result
+   *
+   * it returns closest left column
+   */
+  //================================================================================
+
+  TParam2ColumnIt getColumn( const TParam2ColumnMap* columnsMap,
+                             const double            parameter )
+  {
+    TParam2ColumnIt u_col = columnsMap->upper_bound( parameter );
+    if ( u_col != columnsMap->begin() )
+      --u_col;
+    return u_col; // return left column
+  }
+
+  //================================================================================
+  /*!
+   * \brief Return nodes around given parameter and a ratio
+   * \param column - node column
+   * \param param - parameter
+   * \param node1 - lower node
+   * \param node2 - upper node
+   * \retval double - ratio
+   */
+  //================================================================================
+
+  double getRAndNodes( const TNodeColumn*     column,
+                       const double           param,
+                       const SMDS_MeshNode* & node1,
+                       const SMDS_MeshNode* & node2)
+  {
+    if ( param == 1.0 || column->size() == 1) {
+      node1 = node2 = column->back();
+      return 0;
+    }
+
+    int i = int( param * ( column->size() - 1 ));
+    double u0 = double( i )/ double( column->size() - 1 );
+    double r = ( param - u0 ) * ( column->size() - 1 );
+
+    node1 = (*column)[ i ];
+    node2 = (*column)[ i + 1];
+    return r;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Compute boundary parameters of face parts
+    * \param nbParts - nb of parts to split columns into
+    * \param columnsMap - node columns of the face to split
+    * \param params - computed parameters
+   */
+  //================================================================================
+
+  void splitParams( const int               nbParts,
+                    const TParam2ColumnMap* columnsMap,
+                    vector< double > &      params)
+  {
+    params.clear();
+    params.reserve( nbParts + 1 );
+    TParam2ColumnIt last_par_col = --columnsMap->end();
+    double par = columnsMap->begin()->first; // 0.
+    double parLast = last_par_col->first;
+    params.push_back( par );
+    for ( int i = 0; i < nbParts - 1; ++ i )
+    {
+      double partSize = ( parLast - par ) / double ( nbParts - i );
+      TParam2ColumnIt par_col = getColumn( columnsMap, par + partSize );
+      if ( par_col->first == par ) {
+        ++par_col;
+        if ( par_col == last_par_col ) {
+          while ( i < nbParts - 1 )
+            params.push_back( par + partSize * i++ );
+          break;
+        }
+      }
+      par = par_col->first;
+      params.push_back( par );
+    }
+    params.push_back( parLast ); // 1.
+  }
+}
+
+//=======================================================================
+//function : StdMeshers_Prism_3D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_Prism_3D::StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen)
+  :SMESH_3D_Algo(hypId, studyId, gen)
+{
+  _name = "Prism_3D";
+  _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);      // 1 bit per shape type
+  myProjectTriangles = false;
+}
+
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_Prism_3D::~StdMeshers_Prism_3D()
+{}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Prism_3D::CheckHypothesis(SMESH_Mesh&                          aMesh,
+                                          const TopoDS_Shape&                  aShape,
+                                          SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  // no hypothesis
+  aStatus = SMESH_Hypothesis::HYP_OK;
+  return true;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
+{
+  myHelper = new SMESH_MesherHelper( theMesh );
+  // to delete helper at exit from Compute()
+  std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+
+  myHelper->IsQuadraticSubMesh( theShape );
+
+  // Analyse mesh and geomerty to find block subshapes and submeshes
+  if ( !myBlock.Init( myHelper, theShape ))
+    return false;
+
+  SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
+
+  int volumeID = meshDS->ShapeToIndex( theShape );
+
+
+  // To compute coordinates of a node inside a block, it is necessary to know
+  // 1. normalized parameters of the node by which
+  // 2. coordinates of node projections on all block sub-shapes are computed
+
+  // So we fill projections on vertices at once as they are same for all nodes
+  myShapeXYZ.resize( myBlock.NbSubShapes() );
+  for ( int iV = SMESH_Block::ID_FirstV; iV < SMESH_Block::ID_FirstE; ++iV ) {
+    myBlock.VertexPoint( iV, myShapeXYZ[ iV ]);
+    SHOWYXZ("V point " <<iV << " ", myShapeXYZ[ iV ]);
+  }
+
+  // Projections on the top and bottom faces are taken from nodes existing
+  // on these faces; find correspondence between bottom and top nodes
+  myBotToColumnMap.clear();
+  if ( !assocOrProjBottom2Top() ) // it also fill myBotToColumnMap
+    return false;
+
+
+  // Create nodes inside the block
+
+  // loop on nodes inside the bottom face
+  TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
+  for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
+  {
+    const TNode& tBotNode = bot_column->first; // bottom TNode
+    if ( tBotNode.GetPositionType() != SMDS_TOP_FACE )
+      continue; // node is not inside face 
+
+    // column nodes; middle part of the column are zero pointers
+    TNodeColumn& column = bot_column->second;
+
+    // bottom node parameters and coords
+    gp_XYZ botParams          = tBotNode.GetParams();
+    myShapeXYZ[ ID_BOT_FACE ] = tBotNode.GetCoords();
+
+    // compute top node parameters
+    gp_XYZ topParams;
+    myShapeXYZ[ ID_TOP_FACE ] = gpXYZ( column.back() );
+    gp_Pnt topCoords = myShapeXYZ[ ID_TOP_FACE ];
+    if ( !myBlock.ComputeParameters( topCoords, topParams, ID_TOP_FACE ))
+      RETURN_BAD_RESULT("ComputeParameters() on the top face failed");
+
+    // vertical loop
+    TNodeColumn::iterator columnNodes = column.begin();
+    for ( int z = 0; columnNodes != column.end(); ++columnNodes, ++z)
+    {
+      const SMDS_MeshNode* & node = *columnNodes;
+      if ( node ) continue; // skip bottom or top node
+
+      // params of a node to create
+      double rz = (double) z / (double) ( column.size() - 1 );
+      gp_XYZ params = botParams * ( 1 - rz ) + topParams * rz;
+
+      // set coords on all faces and nodes
+      const int nbSideFaces = 4;
+      int sideFaceIDs[nbSideFaces] = { SMESH_Block::ID_Fx0z,
+                                       SMESH_Block::ID_Fx1z,
+                                       SMESH_Block::ID_F0yz,
+                                       SMESH_Block::ID_F1yz };
+      for ( int iF = 0; iF < nbSideFaces; ++iF )
+        if ( !setFaceAndEdgesXYZ( sideFaceIDs[ iF ], params, z ))
+          return false;
+
+      // compute coords for a new node
+      gp_XYZ coords;
+      if ( !SMESH_Block::ShellPoint( params, myShapeXYZ, coords ))
+        RETURN_BAD_RESULT("SMESH_Block::ShellPoint() failed");
+
+      // create a node
+      node = meshDS->AddNode( coords.X(), coords.Y(), coords.Z() );
+      meshDS->SetNodeInVolume( node, volumeID );
+    }
+  } // loop on bottom nodes
+
+
+  // Create volumes
+
+  SMESHDS_SubMesh* smDS = myBlock.SubMeshDS( ID_BOT_FACE );
+  if ( !smDS ) RETURN_BAD_RESULT("Null submesh");
+
+  // loop on bottom mesh faces
+  SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
+  while ( faceIt->more() )
+  {
+    const SMDS_MeshElement* face = faceIt->next();
+    if ( !face || face->GetType() != SMDSAbs_Face )
+      continue;
+    int nbNodes = face->NbNodes();
+    if ( face->IsQuadratic() )
+      nbNodes /= 2;
+
+    // find node columns for each node
+    vector< const TNodeColumn* > columns( nbNodes );
+    for ( int i = 0; i < nbNodes; ++i )
+    {
+      const SMDS_MeshNode* n = face->GetNode( i );
+      if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
+        bot_column = myBotToColumnMap.find( n );
+        if ( bot_column == myBotToColumnMap.end() )
+          RETURN_BAD_RESULT(" node column for a node not found");
+        columns[ i ] = & bot_column->second;
+      }
+      else {
+        columns[ i ] = myBlock.GetNodeColumn( n );
+        if ( !columns[ i ] )
+          RETURN_BAD_RESULT(" node column not found for a node " << n->GetID() );
+      }
+    }
+    // create prisms
+    AddPrisms( columns, myHelper );
+
+  } // loop on bottom mesh faces
+        
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Create prisms
+ * \param columns - columns of nodes generated from nodes of a mesh face
+ * \param helper - helper initialized by mesh and shape to add prisms to
+ */
+//================================================================================
+
+void StdMeshers_Prism_3D::AddPrisms( vector<const TNodeColumn*> & columns,
+                                     SMESH_MesherHelper*          helper)
+{
+  SMESHDS_Mesh * meshDS = helper->GetMeshDS();
+  int shapeID = helper->GetSubShapeID();
+
+  int nbNodes = columns.size();
+
+  // vertical loop on columns
+  for ( int z = 1; z < columns[0]->size(); ++z)
+  {
+    SMDS_MeshElement* vol = 0;
+    SMDS_VolumeTool vTool;
+    switch ( nbNodes ) {
+
+    case 3: {
+      const SMDS_MeshNode* botNodes[3] = { (*columns[0])[z-1],
+                                           (*columns[1])[z-1],
+                                           (*columns[2])[z-1] };
+      const SMDS_MeshNode* topNodes[3] = { (*columns[0])[z],
+                                           (*columns[1])[z],
+                                           (*columns[2])[z] };
+      // assure good orientation
+      SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2],
+                                  topNodes[0], topNodes[1], topNodes[2]);
+      vTool.Set( &tmpVol );
+      if ( vTool.IsForward() )
+        vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2],
+                                 topNodes[0], topNodes[1], topNodes[2]);
+      else
+        vol = helper->AddVolume( topNodes[0], topNodes[1], topNodes[2],
+                                 botNodes[0], botNodes[1], botNodes[2]);
+      break;
+      }
+    case 4: {
+      const SMDS_MeshNode* botNodes[4] = { (*columns[0])[z-1], (*columns[1])[z-1],
+                                           (*columns[2])[z-1], (*columns[3])[z-1] };
+      const SMDS_MeshNode* topNodes[4] = { (*columns[0])[z], (*columns[1])[z],
+                                           (*columns[2])[z], (*columns[3])[z] };
+      // assure good orientation
+      SMDS_VolumeOfNodes tmpVol ( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
+                                  topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
+      vTool.Set( &tmpVol );
+      if ( vTool.IsForward() )
+        vol = helper->AddVolume( botNodes[0], botNodes[1], botNodes[2], botNodes[3],
+                                 topNodes[0], topNodes[1], topNodes[2], topNodes[3]);
+      else
+        vol = helper->AddVolume( topNodes[0], topNodes[1], topNodes[2], topNodes[3],
+                                 botNodes[0], botNodes[1], botNodes[2], botNodes[3]);
+      break;
+      }
+    default:
+      // polyhedron
+      vector<const SMDS_MeshNode*> nodes( 2*nbNodes + 4*nbNodes);
+      vector<int> quantities( 2 + nbNodes, 4 );
+      quantities[0] = quantities[1] = nbNodes;
+      columns.resize( nbNodes + 1 );
+      columns[ nbNodes ] = columns[ 0 ];
+      for ( int i = 0; i < nbNodes; ++i ) {
+        nodes[ i         ] = (*columns[ i ])[z-1]; // bottom
+        nodes[ i+nbNodes ] = (*columns[ i ])[z  ]; // top
+        // side
+        int di = 2*nbNodes + 4*i - 1;
+        nodes[ di   ] = (*columns[i  ])[z-1];
+        nodes[ di+1 ] = (*columns[i+1])[z-1];
+        nodes[ di+2 ] = (*columns[i+1])[z  ];
+        nodes[ di+3 ] = (*columns[i  ])[z  ];
+      }
+      vol = meshDS->AddPolyhedralVolume( nodes, quantities );
+    }
+    if ( vol && shapeID > 0 )
+      meshDS->SetMeshElementOnShape( vol, shapeID );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Find correspondence between bottom and top nodes
+ *  If elements on the bottom and top faces are topologically different,
+ *  and projection is possible and allowed, perform the projection
+ *  \retval bool - is a success or not
+ */
+//================================================================================
+
+bool StdMeshers_Prism_3D::assocOrProjBottom2Top()
+{
+  SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
+  SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+
+  SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
+  SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
+
+  if ( !botSMDS || botSMDS->NbElements() == 0 )
+    RETURN_BAD_RESULT("Empty horiz submesh");
+
+  bool needProject = false;
+  if ( !topSMDS || 
+       botSMDS->NbElements() != topSMDS->NbElements() ||
+       botSMDS->NbNodes()    != topSMDS->NbNodes())
+  {
+    if ( myBlock.HasNotQuadElemOnTop() )
+      RETURN_BAD_RESULT("Different triangles on 2 sides");
+    needProject = true;
+  }
+
+  if ( 0/*needProject && !myProjectTriangles*/ )
+    RETURN_BAD_RESULT("Need to project but not allowed");
+
+  if ( needProject )
+  {
+    return projectBottomToTop();
+  }
+
+  TopoDS_Face botFace = TopoDS::Face( myBlock.Shape( ID_BOT_FACE ));
+  TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE ));
+  // associate top and bottom faces
+  TAssocTool::TShapeShapeMap shape2ShapeMap;
+  if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(),
+                                             topFace, myBlock.Mesh(),
+                                             shape2ShapeMap) )
+    RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+
+  // Find matching nodes of in and out faces
+  TNodeNodeMap n2nMap;
+  if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(),
+                                               topFace, myBlock.Mesh(),
+                                               shape2ShapeMap, n2nMap ))
+    RETURN_BAD_RESULT("Different mesh on top and bottom faces");
+
+  // Fill myBotToColumnMap
+
+  int zSize = myBlock.VerticalSize();
+  TNodeNodeMap::iterator bN_tN = n2nMap.begin();
+  for ( ; bN_tN != n2nMap.end(); ++bN_tN )
+  {
+    const SMDS_MeshNode* botNode = bN_tN->first;
+    const SMDS_MeshNode* topNode = bN_tN->second;
+    if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE )
+      continue; // wall columns are contained in myBlock
+    // compute bottom node params
+    TNode bN( botNode );
+    if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE ))
+      RETURN_BAD_RESULT("ComputeParameters() on the bottom face failed");
+    // create node column
+    TNode2ColumnMap::iterator bN_col = 
+      myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
+    TNodeColumn & column = bN_col->second;
+    column.resize( zSize );
+    column.front() = botNode;
+    column.back()  = topNode;
+  }
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Remove quadrangles from the top face and
+ * create triangles there by projection from the bottom
+ * \retval bool - a success or not
+ */
+//================================================================================
+
+bool StdMeshers_Prism_3D::projectBottomToTop()
+{
+  SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE );
+  SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE );
+
+  SMESHDS_SubMesh * botSMDS = botSM->GetSubMeshDS();
+  SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
+
+  if ( topSMDS )
+    topSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
+
+  SMESHDS_Mesh* meshDS = myBlock.MeshDS();
+  int shapeID = myHelper->GetSubShapeID();
+  int topFaceID = meshDS->ShapeToIndex( topSM->GetSubShape() );
+
+  // Fill myBotToColumnMap
+
+  int zSize = myBlock.VerticalSize();
+  SMDS_NodeIteratorPtr nIt = botSMDS->GetNodes();
+  while ( nIt->more() )
+  {
+    const SMDS_MeshNode* botNode = nIt->next();
+    if ( botNode->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE )
+      continue; // strange
+    // compute bottom node params
+    TNode bN( botNode );
+    if ( !myBlock.ComputeParameters( bN.GetCoords(), bN.ChangeParams(), ID_BOT_FACE ))
+      RETURN_BAD_RESULT("ComputeParameters() on the bottom face failed");
+    // compute top node coords
+    gp_XYZ topXYZ; gp_XY topUV;
+    if ( !myBlock.FacePoint( ID_TOP_FACE, bN.GetParams(), topXYZ ) ||
+         !myBlock.FaceUV   ( ID_TOP_FACE, bN.GetParams(), topUV ))
+      RETURN_BAD_RESULT("SMESH_Block::FacePoint() on the top face failed");
+    SMDS_MeshNode * topNode = meshDS->AddNode( topXYZ.X(),topXYZ.Y(),topXYZ.Z() );
+    meshDS->SetNodeOnFace( topNode, topFaceID, topUV.X(), topUV.Y() );
+    // create node column
+    TNode2ColumnMap::iterator bN_col = 
+      myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
+    TNodeColumn & column = bN_col->second;
+    column.resize( zSize );
+    column.front() = botNode;
+    column.back()  = topNode;
+  }
+
+  // Create top faces
+
+  // loop on bottom mesh faces
+  SMDS_ElemIteratorPtr faceIt = botSMDS->GetElements();
+  while ( faceIt->more() )
+  {
+    const SMDS_MeshElement* face = faceIt->next();
+    if ( !face || face->GetType() != SMDSAbs_Face )
+      continue;
+    int nbNodes = face->NbNodes();
+    if ( face->IsQuadratic() )
+      nbNodes /= 2;
+
+    // find top node in columns for each bottom node
+    vector< const SMDS_MeshNode* > nodes( nbNodes );
+    for ( int i = 0; i < nbNodes; ++i )
+    {
+      const SMDS_MeshNode* n = face->GetNode( nbNodes - i - 1 );
+      if ( n->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
+        TNode2ColumnMap::iterator bot_column = myBotToColumnMap.find( n );
+        if ( bot_column == myBotToColumnMap.end() )
+          RETURN_BAD_RESULT(" node column for a node not found");
+        nodes[ i ] = bot_column->second.back();
+      }
+      else {
+        const TNodeColumn* column = myBlock.GetNodeColumn( n );
+        if ( !column )
+          RETURN_BAD_RESULT(" node column not found for a node " << n->GetID() );
+        nodes[ i ] = column->back();
+      }
+    }
+    // create a face, with reversed orientation
+    SMDS_MeshElement* newFace = 0;
+    switch ( nbNodes ) {
+
+    case 3: {
+      newFace = myHelper->AddFace(nodes[0], nodes[1], nodes[2]);
+      break;
+      }
+    case 4: {
+      newFace = myHelper->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
+      break;
+      }
+    default:
+      newFace = meshDS->AddPolygonalFace( nodes );
+    }
+    if ( newFace && shapeID > 0 )
+      meshDS->SetMeshElementOnShape( newFace, shapeID );
+  }
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Set projection coordinates of a node to a face and it's subshapes
+ * \param faceID - the face given by in-block ID
+ * \param params - node normalized parameters
+ * \retval bool - is a success
+ */
+//================================================================================
+
+bool StdMeshers_Prism_3D::setFaceAndEdgesXYZ( const int faceID, const gp_XYZ& params, int z )
+{
+  // find base and top edges of the face
+  enum { BASE = 0, TOP, LEFT, RIGHT };
+  vector< int > edgeVec; // 0-base, 1-top
+  SMESH_Block::GetFaceEdgesIDs( faceID, edgeVec );
+
+  myBlock.EdgePoint( edgeVec[ BASE ], params, myShapeXYZ[ edgeVec[ BASE ]]);
+  myBlock.EdgePoint( edgeVec[ TOP ], params, myShapeXYZ[ edgeVec[ TOP ]]);
+
+  SHOWYXZ("\nparams ", params);
+  SHOWYXZ("TOP is "<<edgeVec[ TOP], myShapeXYZ[ edgeVec[ TOP]]);
+  SHOWYXZ("BASE is "<<edgeVec[ BASE], myShapeXYZ[ edgeVec[ BASE]]);
+
+  if ( faceID == SMESH_Block::ID_Fx0z || faceID == SMESH_Block::ID_Fx1z )
+  {
+    myBlock.EdgePoint( edgeVec[ LEFT ], params, myShapeXYZ[ edgeVec[ LEFT ]]);
+    myBlock.EdgePoint( edgeVec[ RIGHT ], params, myShapeXYZ[ edgeVec[ RIGHT ]]);
+
+    SHOWYXZ("VER "<<edgeVec[ LEFT], myShapeXYZ[ edgeVec[ LEFT]]);
+    SHOWYXZ("VER "<<edgeVec[ RIGHT], myShapeXYZ[ edgeVec[ RIGHT]]);
+  }
+  myBlock.FacePoint( faceID, params, myShapeXYZ[ faceID ]);
+  SHOWYXZ("FacePoint "<<faceID, myShapeXYZ[ faceID]);
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Constructor. Initialization is needed
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::StdMeshers_PrismAsBlock()
+{
+  mySide = 0;
+}
+
+StdMeshers_PrismAsBlock::~StdMeshers_PrismAsBlock()
+{
+  if ( mySide ) {
+    delete mySide; mySide = 0;
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Initialization.
+ * \param helper - helper loaded with mesh and 3D shape
+ * \param shape3D - a closed shell or solid
+ * \retval bool - false if a mesh or a shape are KO
+ */
+//================================================================================
+
+bool StdMeshers_PrismAsBlock::Init(SMESH_MesherHelper* helper,
+                                   const TopoDS_Shape& shape3D)
+{
+  if ( mySide ) {
+    delete mySide; mySide = 0;
+  }
+  vector< TSideFace* > sideFaces( NB_WALL_FACES, 0 );
+  vector< pair< double, double> > params ( NB_WALL_FACES );
+  mySide = new TSideFace( sideFaces, params );
+
+  myHelper = helper;
+  SMESHDS_Mesh* meshDS = myHelper->GetMesh()->GetMeshDS();
+
+  int wallFaceIds[ NB_WALL_FACES ] = { // to walk around a block
+    SMESH_Block::ID_Fx0z, SMESH_Block::ID_F1yz,
+    SMESH_Block::ID_Fx1z, SMESH_Block::ID_F0yz
+  };
+  SMESH_Block::init();
+
+  // -------------------------------------------------------------
+  // Look for top and bottom faces: not quadrangle ones or meshed
+  // with not quadrangle elements
+  // -------------------------------------------------------------
+
+  list< SMESH_subMesh* > notQuadGeomSubMesh;
+  list< SMESH_subMesh* > notQuadElemSubMesh;
+  int nbFaces = 0;
+  //
+  SMESH_subMesh* mainSubMesh = myHelper->GetMesh()->GetSubMeshContaining( shape3D );
+  if ( !mainSubMesh ) RETURN_BAD_RESULT("Null submesh of shape3D");
+  //
+  const map< int, SMESH_subMesh * >& subSM = mainSubMesh->DependsOn();
+  map< int, SMESH_subMesh * >::const_iterator i_subSM = subSM.begin();
+  for ( ; i_subSM != subSM.end(); ++i_subSM )
+  {
+    SMESH_subMesh* sm = i_subSM->second;
+    const TopoDS_Shape& face = sm->GetSubShape();
+    if ( face.ShapeType() != TopAbs_FACE )
+      continue;
+    nbFaces++;
+
+    // is quadrangle face?
+    if ( TAssocTool::Count( face, TopAbs_EDGE, 0 ) != 4 ||
+         TAssocTool::Count( face, TopAbs_WIRE, 0 ) != 1 )
+      notQuadGeomSubMesh.push_back( sm );
+
+    // count not quadrangle mesh elements
+    if ( SMESHDS_SubMesh* smDS = sm->GetSubMeshDS() ) {
+      SMDS_ElemIteratorPtr eIt = smDS->GetElements();
+      bool hasNotQuad = false;
+      while ( eIt->more() && !hasNotQuad ) {
+        const SMDS_MeshElement* elem = eIt->next();
+        if ( elem->GetType() == SMDSAbs_Face ) {
+          int nbNodes = elem->NbNodes();
+          if ( elem->IsQuadratic() )
+            nbNodes /= 2;
+          hasNotQuad = ( nbNodes != 4 );
+        }
+      }
+      if ( hasNotQuad )
+        notQuadElemSubMesh.push_back( sm );
+    }
+    else {
+      RETURN_BAD_RESULT("not meshed face");
+    }
+  }
+
+  // ----------------------------------------------------------------------
+  // Analyse faces mesh and topology: choose the bottom submesh.
+  // If there are not quadrangle geom faces, they are top and bottom ones.
+  // Not quadrangle geom faces must be only on top and bottom.
+  // ----------------------------------------------------------------------
+
+  SMESH_subMesh * botSM = 0;
+  SMESH_subMesh * topSM = 0;
+
+  int nbNotQuad       = notQuadGeomSubMesh.size();
+  int nbNotQuadMeshed = notQuadElemSubMesh.size();
+  bool hasNotQuad = ( nbNotQuad || nbNotQuadMeshed );
+
+  // detect bad cases
+  if ( nbNotQuad > 0 && nbNotQuad != 2 )
+    RETURN_BAD_RESULT("Wrong shape geometry");
+  if ( nbNotQuadMeshed > 2 )
+    RETURN_BAD_RESULT("More then 2 faces meshed with not quadrangle elements");
+
+  // get found submeshes
+  if ( hasNotQuad )
+  {
+    if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front();
+    else                       botSM = notQuadGeomSubMesh.front();
+    if ( nbNotQuadMeshed > 1 ) topSM = notQuadElemSubMesh.back();
+    else if ( nbNotQuad  > 1 ) topSM = notQuadGeomSubMesh.back();
+  }
+  // detect other bad cases
+  if ( nbNotQuad == 2 && nbNotQuadMeshed > 0 ) {
+    bool ok = false;
+    if ( nbNotQuadMeshed == 1 )
+      ok = ( find( notQuadGeomSubMesh.begin(),
+                   notQuadGeomSubMesh.end(), botSM ) != notQuadGeomSubMesh.end() );
+    else
+      ok = ( notQuadGeomSubMesh == notQuadElemSubMesh );
+    if ( !ok )
+      RETURN_BAD_RESULT("Side face meshed with not quadrangle elements");
+  }
+
+  myNotQuadOnTop = ( nbNotQuadMeshed > 1 );
+    
+  // ----------------------------------------------------------
+
+  if ( nbNotQuad == 0 ) // Standard block of 6 quadrangle faces ?
+  {
+    // SMESH_Block will perform geometry analysis, we need just to find 2
+    // connected vertices on top and bottom
+
+    TopoDS_Vertex Vbot, Vtop;
+    if ( nbNotQuadMeshed > 0 ) // Look for vertices
+    {
+      TopTools_IndexedMapOfShape edgeMap;
+      TopExp::MapShapes( botSM->GetSubShape(), TopAbs_EDGE, edgeMap );
+      // vertex 1 is any vertex of the bottom face
+      Vbot = TopExp::FirstVertex( TopoDS::Edge( edgeMap( 1 )));
+      // vertex 2 is end vertex of edge sharing Vbot and not belonging to the bottom face
+      TopTools_ListIteratorOfListOfShape ancestIt = Mesh()->GetAncestors( Vbot );
+      for ( ; Vtop.IsNull() && ancestIt.More(); ancestIt.Next() )
+      {
+        const TopoDS_Shape & ancestor = ancestIt.Value();
+        if ( ancestor.ShapeType() == TopAbs_EDGE && !edgeMap.FindIndex( ancestor ))
+        {
+          Vtop = TopExp::LastVertex( TopoDS::Edge( ancestor ));
+          if ( Vbot.IsSame ( Vtop ))
+            Vtop = TopExp::FirstVertex( TopoDS::Edge( ancestor ));
+        }
+      }
+    }
+    // get shell from shape3D
+    TopoDS_Shell shell;
+    TopExp_Explorer exp( shape3D, TopAbs_SHELL );
+    int nbShell = 0;
+    for ( ; exp.More(); exp.Next(), ++nbShell )
+      shell = TopoDS::Shell( exp.Current() );
+//     if ( nbShell != 1 )
+//       RETURN_BAD_RESULT("There must be 1 shell in the block");
+
+    // Load geometry in SMESH_Block
+    myShapeIDMap.Clear();
+    if ( !SMESH_Block::FindBlockShapes( shell, Vbot, Vtop, myShapeIDMap )) {
+      if ( !hasNotQuad )
+        RETURN_BAD_RESULT("Can not detect top and bottom");
+    }
+    else {
+      if ( !botSM ) botSM = Mesh()->GetSubMeshContaining( myShapeIDMap( ID_BOT_FACE ));
+      if ( !topSM ) topSM = Mesh()->GetSubMeshContaining( myShapeIDMap( ID_TOP_FACE ));
+    }
+
+  } // end  Standard block of 6 quadrangle faces
+  // --------------------------------------------------------
+
+  // Here the top and bottom faces are found
+  if ( nbNotQuadMeshed == 2 ) // roughly check correspondence of horiz meshes
+  {
+//     SMESHDS_SubMesh* topSMDS = topSM->GetSubMeshDS();
+//     SMESHDS_SubMesh* botSMDS = botSM->GetSubMeshDS();
+//     if ( topSMDS->NbNodes() != botSMDS->NbNodes() ||
+//          topSMDS->NbElements() != botSMDS->NbElements() )
+//       RETURN_BAD_RESULT("Top mesh doesn't correspond to bottom one");
+  }
+
+  // ---------------------------------------------------------
+  // If there are not quadrangle geom faces, we emulate
+  // a block of 6 quadrangle faces.
+  // Load SMESH_Block with faces and edges geometry
+  // ---------------------------------------------------------
+
+  
+  // find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
+  TopoDS_Vertex V000;
+  double minVal = DBL_MAX, minX, val;
+  for ( TopExp_Explorer exp( botSM->GetSubShape(), TopAbs_VERTEX );
+        exp.More(); exp.Next() )
+  {
+    const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() );
+    gp_Pnt P = BRep_Tool::Pnt( v );
+    val = P.X() + P.Y() + P.Z();
+    if ( val < minVal || ( val == minVal && P.X() < minX )) {
+      V000 = v;
+      minVal = val;
+      minX = P.X();
+    }
+  }
+
+  // Get ordered bottom edges
+  list< TopoDS_Edge > orderedEdges;
+  list< int >         nbVertexInWires;
+  SMESH_Block::GetOrderedEdges( TopoDS::Face( botSM->GetSubShape().Reversed() ),
+                                V000, orderedEdges, nbVertexInWires );
+//   if ( nbVertexInWires.size() != 1 )
+//     RETURN_BAD_RESULT("Wrong prism geometry");
+
+  // Get Wall faces corresponding to the ordered bottom edges
+  list< TopoDS_Face > wallFaces;
+  if ( !GetWallFaces( Mesh(), shape3D, botSM->GetSubShape(), orderedEdges, wallFaces))
+    RETURN_BAD_RESULT("GetWallFaces() failed");
+
+  // Find columns of wall nodes and calculate edges' lengths
+  // --------------------------------------------------------
+
+  myParam2ColumnMaps.clear();
+  myParam2ColumnMaps.resize( orderedEdges.size() ); // total nb edges
+
+  int iE, nbEdges = nbVertexInWires.front(); // nb outer edges
+  vector< double > edgeLength( nbEdges );
+  map< double, int > len2edgeMap;
+
+  list< TopoDS_Edge >::iterator edgeIt = orderedEdges.begin();
+  list< TopoDS_Face >::iterator faceIt = wallFaces.begin();
+  for ( iE = 0; iE < nbEdges; ++edgeIt, ++faceIt )
+  {
+    TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
+    if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
+      RETURN_BAD_RESULT("SMESH_MesherHelper::LoadNodeColumns() failed");
+
+    SHOWYXZ("\np1 F "<<iE, gpXYZ(faceColumns.begin()->second.front() ));
+    SHOWYXZ("p2 F "<<iE, gpXYZ(faceColumns.rbegin()->second.front() ));
+    SHOWYXZ("V First "<<iE, BRep_Tool::Pnt( TopExp::FirstVertex(*edgeIt,true )));
+
+    edgeLength[ iE ] = SMESH_Algo::EdgeLength( *edgeIt );
+
+    if ( nbEdges < NB_WALL_FACES ) // fill map used to split faces
+    {
+      SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edgeIt);
+      if ( !smDS )
+        RETURN_BAD_RESULT("Null submesh on a bottom edge");
+      // assure length uniqueness
+      edgeLength[ iE ] *= smDS->NbNodes() + edgeLength[ iE ] / ( 1000 + iE );
+      len2edgeMap[ edgeLength[ iE ]] = iE;
+    }
+    ++iE;
+  }
+  // Load columns of internal edges (forming holes)
+  // and fill map ShapeIndex to TParam2ColumnMap for them
+  for ( ; edgeIt != orderedEdges.end() ; ++edgeIt, ++faceIt )
+  {
+    TParam2ColumnMap & faceColumns = myParam2ColumnMaps[ iE ];
+    if ( !myHelper->LoadNodeColumns( faceColumns, *faceIt, *edgeIt, meshDS ))
+      RETURN_BAD_RESULT("SMESH_MesherHelper::LoadNodeColumns() failed");
+    // edge columns
+    int id = MeshDS()->ShapeToIndex( *edgeIt );
+    bool isForward = true; // meaningless for intenal wires
+    myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
+    // columns for vertices
+    // 1
+    const SMDS_MeshNode* n0 = faceColumns.begin()->second.front();
+    id = n0->GetPosition()->GetShapeId();
+    myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
+    // 2
+    const SMDS_MeshNode* n1 = faceColumns.rbegin()->second.front();
+    id = n1->GetPosition()->GetShapeId();
+    myShapeIndex2ColumnMap[ id ] = make_pair( & faceColumns, isForward );
+//     SHOWYXZ("\np1 F "<<iE, gpXYZ(faceColumns.begin()->second.front() ));
+//     SHOWYXZ("p2 F "<<iE, gpXYZ(faceColumns.rbegin()->second.front() ));
+//     SHOWYXZ("V First "<<iE, BRep_Tool::Pnt( TopExp::FirstVertex(*edgeIt,true )));
+    ++iE;
+  }
+
+  // Create 4 wall faces of a block
+  // -------------------------------
+
+  if ( nbEdges <= NB_WALL_FACES ) // ************* Split faces if necessary
+  {
+    map< int, int > iE2nbSplit;
+    if ( nbEdges != NB_WALL_FACES ) // define how to split
+    {
+      if ( len2edgeMap.size() != nbEdges )
+        RETURN_BAD_RESULT("Uniqueness of edge lengths not assured");
+      map< double, int >::reverse_iterator maxLen_i = len2edgeMap.rbegin();
+      map< double, int >::reverse_iterator midLen_i = ++len2edgeMap.rbegin();
+      double maxLen = maxLen_i->first;
+      double midLen = ( len2edgeMap.size() == 1 ) ? 0 : midLen_i->first;
+      switch ( nbEdges ) {
+      case 1: // 0-th edge is split into 4 parts
+        iE2nbSplit.insert( make_pair( 0, 4 )); break;
+      case 2: // either the longest edge is split into 3 parts, or both edges into halves
+        if ( maxLen / 3 > midLen / 2 ) {
+          iE2nbSplit.insert( make_pair( maxLen_i->second, 3 ));
+        }
+        else {
+          iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
+          iE2nbSplit.insert( make_pair( midLen_i->second, 2 ));
+        }
+        break;
+      case 3:
+        // split longest into halves
+        iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
+      }
+    }
+    // Create TSideFace's
+    faceIt = wallFaces.begin();
+    edgeIt = orderedEdges.begin();
+    int iSide = 0;
+    for ( iE = 0; iE < nbEdges; ++edgeIt, ++faceIt )
+    {
+     // split?
+      map< int, int >::iterator i_nb = iE2nbSplit.find( iE );
+      if ( i_nb != iE2nbSplit.end() ) {
+        // split!
+        int nbSplit = i_nb->second;
+        vector< double > params;
+        splitParams( nbSplit, &myParam2ColumnMaps[ iE ], params );
+        bool isForward = ( edgeIt->Orientation() == TopAbs_FORWARD );
+        for ( int i = 0; i < nbSplit; ++i ) {
+          double f = ( isForward ? params[ i ] : params[ nbSplit - i-1 ]);
+          double l = ( isForward ? params[ i+1 ] : params[ nbSplit - i ]);
+          TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
+                                           *faceIt, *edgeIt,
+                                           &myParam2ColumnMaps[ iE ], f, l );
+          mySide->SetComponent( iSide++, comp );
+        }
+      }
+      else {
+        TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
+                                         *faceIt, *edgeIt,
+                                         &myParam2ColumnMaps[ iE ]);
+        mySide->SetComponent( iSide++, comp );
+      }
+      ++iE;
+    }
+  }
+  else { // **************************** Unite faces
+
+    // unite first faces
+    int nbExraFaces = nbEdges - 3;
+    int iSide = 0, iE;
+    double u0 = 0, sumLen = 0;
+    for ( iE = 0; iE < nbExraFaces; ++iE )
+      sumLen += edgeLength[ iE ];
+
+    vector< TSideFace* > components( nbExraFaces );
+    vector< pair< double, double> > params( nbExraFaces );
+    faceIt = wallFaces.begin();
+    edgeIt = orderedEdges.begin();
+    for ( iE = 0; iE < nbExraFaces; ++edgeIt, ++faceIt )
+    {
+      components[ iE ] = new TSideFace( myHelper, wallFaceIds[ iSide ],
+                                        *faceIt, *edgeIt,
+                                        &myParam2ColumnMaps[ iE ]);
+      double u1 = u0 + edgeLength[ iE ] / sumLen;
+      params[ iE ] = make_pair( u0 , u1 );
+      u0 = u1;
+      ++iE;
+    }
+    mySide->SetComponent( iSide++, new TSideFace( components, params ));
+
+    // fill the rest faces
+    for ( ; iE < nbEdges; ++faceIt, ++edgeIt )
+    {
+      TSideFace* comp = new TSideFace( myHelper, wallFaceIds[ iSide ],
+                                       *faceIt, *edgeIt,
+                                       &myParam2ColumnMaps[ iE ]);
+      mySide->SetComponent( iSide++, comp );
+      ++iE;
+    }
+  }
+
+
+  // Fill geometry fields of SMESH_Block
+  // ------------------------------------
+
+  TopoDS_Face botF = TopoDS::Face( botSM->GetSubShape() );
+  TopoDS_Face topF = TopoDS::Face( topSM->GetSubShape() );
+
+  vector< int > botEdgeIdVec;
+  SMESH_Block::GetFaceEdgesIDs( ID_BOT_FACE, botEdgeIdVec );
+
+  bool isForward[NB_WALL_FACES] = { true, true, true, true };
+  Adaptor2d_Curve2d* botPcurves[NB_WALL_FACES];
+  Adaptor2d_Curve2d* topPcurves[NB_WALL_FACES];
+
+  for ( int iF = 0; iF < NB_WALL_FACES; ++iF )
+  {
+    TSideFace * sideFace = mySide->GetComponent( iF );
+    if ( !sideFace )
+      RETURN_BAD_RESULT("NULL TSideFace");
+    int fID = sideFace->FaceID();
+
+    // fill myShapeIDMap
+    if ( sideFace->InsertSubShapes( myShapeIDMap ) != 8 &&
+         !sideFace->IsComplex())
+      MESSAGE( ": Warning : InsertSubShapes() < 8 on side " << iF );
+
+    // side faces geometry
+    Adaptor2d_Curve2d* pcurves[NB_WALL_FACES];
+    if ( !sideFace->GetPCurves( pcurves ))
+      RETURN_BAD_RESULT("TSideFace::GetPCurves() failed");
+
+    SMESH_Block::TFace& tFace = myFace[ fID - ID_FirstF ];
+    tFace.Set( fID, sideFace->Surface(), pcurves, isForward );
+
+    SHOWYXZ( endl<<"F "<< iF << " id " << fID << " FRW " << sideFace->IsForward(), );
+    // edges 3D geometry
+    vector< int > edgeIdVec;
+    SMESH_Block::GetFaceEdgesIDs( fID, edgeIdVec );
+    for ( int isMax = 0; isMax < 2; ++isMax ) {
+      {
+        int eID = edgeIdVec[ isMax ];
+        SMESH_Block::TEdge& tEdge = myEdge[ eID - ID_FirstE ];
+        tEdge.Set( eID, sideFace->HorizCurve(isMax), true);
+        SHOWYXZ(eID<<" HOR"<<isMax<<"(0)", sideFace->HorizCurve(isMax)->Value(0));
+        SHOWYXZ(eID<<" HOR"<<isMax<<"(1)", sideFace->HorizCurve(isMax)->Value(1));
+      }
+      {
+        int eID = edgeIdVec[ isMax+2 ];
+        SMESH_Block::TEdge& tEdge = myEdge[ eID - ID_FirstE  ];
+        tEdge.Set( eID, sideFace->VertiCurve(isMax), true);
+        SHOWYXZ(eID<<" VER"<<isMax<<"(0)", sideFace->VertiCurve(isMax)->Value(0));
+        SHOWYXZ(eID<<" VER"<<isMax<<"(1)", sideFace->VertiCurve(isMax)->Value(1));
+
+        // corner points
+        vector< int > vertexIdVec;
+        SMESH_Block::GetEdgeVertexIDs( eID, vertexIdVec );
+        myPnt[ vertexIdVec[0] - ID_FirstV ] = tEdge.GetCurve()->Value(0).XYZ();
+        myPnt[ vertexIdVec[1] - ID_FirstV ] = tEdge.GetCurve()->Value(1).XYZ();
+      }
+    }
+    // pcurves on horizontal faces
+    for ( iE = 0; iE < NB_WALL_FACES; ++iE ) {
+      if ( edgeIdVec[ BOTTOM_EDGE ] == botEdgeIdVec[ iE ] ) {
+        botPcurves[ iE ] = sideFace->HorizPCurve( false, botF );
+        topPcurves[ iE ] = sideFace->HorizPCurve( true,  topF );
+        break;
+      }
+    }
+  }
+  // horizontal faces geometry
+  {
+    SMESH_Block::TFace& tFace = myFace[ ID_BOT_FACE - ID_FirstF ];
+    tFace.Set( ID_BOT_FACE, new BRepAdaptor_Surface( botF ), botPcurves, isForward );
+    SMESH_Block::Insert( botF, ID_BOT_FACE, myShapeIDMap );
+  }
+  {
+    SMESH_Block::TFace& tFace = myFace[ ID_TOP_FACE - ID_FirstF ];
+    tFace.Set( ID_TOP_FACE, new BRepAdaptor_Surface( topF ), topPcurves, isForward );
+    SMESH_Block::Insert( topF, ID_TOP_FACE, myShapeIDMap );
+  }
+
+  // Fill map ShapeIndex to TParam2ColumnMap
+  // ----------------------------------------
+
+  list< TSideFace* > fList;
+  list< TSideFace* >::iterator fListIt;
+  fList.push_back( mySide );
+  for ( fListIt = fList.begin(); fListIt != fList.end(); ++fListIt)
+  {
+    int nb = (*fListIt)->NbComponents();
+    for ( int i = 0; i < nb; ++i ) {
+      if ( TSideFace* comp = (*fListIt)->GetComponent( i ))
+        fList.push_back( comp );
+    }
+    if ( TParam2ColumnMap* cols = (*fListIt)->GetColumns()) {
+      // columns for a base edge
+      int id = MeshDS()->ShapeToIndex( (*fListIt)->BaseEdge() );
+      bool isForward = (*fListIt)->IsForward();
+      myShapeIndex2ColumnMap[ id ] = make_pair( cols, isForward );
+
+      // columns for vertices
+      const SMDS_MeshNode* n0 = cols->begin()->second.front();
+      id = n0->GetPosition()->GetShapeId();
+      myShapeIndex2ColumnMap[ id ] = make_pair( cols, isForward );
+
+      const SMDS_MeshNode* n1 = cols->rbegin()->second.front();
+      id = n1->GetPosition()->GetShapeId();
+      myShapeIndex2ColumnMap[ id ] = make_pair( cols, !isForward );
+    }
+  }
+
+//   gp_XYZ testPar(0.25, 0.25, 0), testCoord;
+//   if ( !FacePoint( ID_BOT_FACE, testPar, testCoord ))
+//     RETURN_BAD_RESULT("TEST FacePoint() FAILED");
+//   SHOWYXZ("IN TEST PARAM" , testPar);
+//   SHOWYXZ("OUT TEST CORD" , testCoord);
+//   if ( !ComputeParameters( testCoord, testPar , ID_BOT_FACE))
+//     RETURN_BAD_RESULT("TEST ComputeParameters() FAILED");
+//   SHOWYXZ("OUT TEST PARAM" , testPar);
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return pointer to column of nodes
+ * \param node - bottom node from which the returned column goes up
+ * \retval const TNodeColumn* - the found column
+ */
+//================================================================================
+
+const TNodeColumn* StdMeshers_PrismAsBlock::GetNodeColumn(const SMDS_MeshNode* node) const
+{
+  int sID = node->GetPosition()->GetShapeId();
+
+  map<int, pair< TParam2ColumnMap*, bool > >::const_iterator col_frw =
+    myShapeIndex2ColumnMap.find( sID );
+  if ( col_frw != myShapeIndex2ColumnMap.end() ) {
+    const TParam2ColumnMap* cols = col_frw->second.first;
+    TParam2ColumnIt u_col = cols->begin();
+    for ( ; u_col != cols->end(); ++u_col )
+      if ( u_col->second[ 0 ] == node )
+        return & u_col->second;
+  }
+  return 0;
+}
+
+//================================================================================
+/*!
+ * \brief Check curve orientation of a bootom edge
+  * \param meshDS - mesh DS
+  * \param columnsMap - node columns map of side face
+  * \param bottomEdge - the bootom edge
+  * \param sideFaceID - side face in-block ID
+  * \retval bool - true if orientation coinside with in-block froward orientation
+ */
+//================================================================================
+
+bool StdMeshers_PrismAsBlock::IsForwardEdge(SMESHDS_Mesh*           meshDS,
+                                            const TParam2ColumnMap& columnsMap,
+                                            const TopoDS_Edge &     bottomEdge,
+                                            const int               sideFaceID)
+{
+  bool isForward = false;
+  if ( TAssocTool::IsClosedEdge( bottomEdge ))
+  {
+    isForward = ( bottomEdge.Orientation() == TopAbs_FORWARD );
+  }
+  else
+  {
+    const TNodeColumn& firstCol = columnsMap.begin()->second;
+    const SMDS_MeshNode* bottomNode = firstCol[0];
+    TopoDS_Shape firstVertex = SMESH_MesherHelper::GetSubShapeByNode( bottomNode, meshDS );
+    isForward = ( firstVertex.IsSame( TopExp::FirstVertex( bottomEdge, true )));
+  }
+  // on 2 of 4 sides first vertex is end
+  if ( sideFaceID == ID_Fx1z || sideFaceID == ID_F0yz )
+    isForward = !isForward;
+  return isForward;
+}
+
+//================================================================================
+  /*!
+   * \brief Find wall faces by bottom edges
+    * \param mesh - the mesh
+    * \param mainShape - the prism
+    * \param bottomFace - the bottom face
+    * \param bottomEdges - edges bounding the bottom face
+    * \param wallFaces - faces list to fill in
+   */
+//================================================================================
+
+bool StdMeshers_PrismAsBlock::GetWallFaces( SMESH_Mesh*                     mesh,
+                                            const TopoDS_Shape &            mainShape,
+                                            const TopoDS_Shape &            bottomFace,
+                                            const std::list< TopoDS_Edge >& bottomEdges,
+                                            std::list< TopoDS_Face >&       wallFaces)
+{
+  wallFaces.clear();
+
+  TopTools_IndexedMapOfShape faceMap;
+  TopExp::MapShapes( mainShape, TopAbs_FACE, faceMap );
+
+  list< TopoDS_Edge >::const_iterator edge = bottomEdges.begin();
+  for ( ; edge != bottomEdges.end(); ++edge )
+  {
+    TopTools_ListIteratorOfListOfShape ancestIt = mesh->GetAncestors( *edge );
+    for ( ; ancestIt.More(); ancestIt.Next() )
+    {
+      const TopoDS_Shape& ancestor = ancestIt.Value();
+      if ( ancestor.ShapeType() == TopAbs_FACE && // face
+           !bottomFace.IsSame( ancestor ) &&      // not bottom
+           faceMap.FindIndex( ancestor ))         // belongs to the prism
+      {
+        wallFaces.push_back( TopoDS::Face( ancestor ));
+        break;
+      }
+    }
+  }
+  return ( wallFaces.size() == bottomEdges.size() );
+}
+
+//================================================================================
+/*!
+ * \brief Constructor
+  * \param faceID - in-block ID
+  * \param face - geom face
+  * \param columnsMap - map of node columns
+  * \param first - first normalized param
+  * \param last - last normalized param
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TSideFace::TSideFace(SMESH_MesherHelper* helper,
+                                              const int           faceID,
+                                              const TopoDS_Face&  face,
+                                              const TopoDS_Edge&  baseEdge,
+                                              TParam2ColumnMap*   columnsMap,
+                                              const double        first,
+                                              const double        last):
+  myID( faceID ),
+  myParamToColumnMap( columnsMap ),
+  myBaseEdge( baseEdge ),
+  myHelper( helper )
+{
+  mySurface.Initialize( face );
+  myParams.resize( 1 );
+  myParams[ 0 ] = make_pair( first, last );
+  myIsForward = StdMeshers_PrismAsBlock::IsForwardEdge( myHelper->GetMeshDS(),
+                                                        *myParamToColumnMap,
+                                                        myBaseEdge, myID );
+}
+
+//================================================================================
+/*!
+ * \brief Constructor of complex side face
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TSideFace::
+TSideFace(const vector< TSideFace* >&             components,
+          const vector< pair< double, double> > & params)
+  :myID( components[0] ? components[0]->myID : 0 ),
+   myParamToColumnMap( 0 ),
+   myParams( params ),
+   myIsForward( true ),
+   myComponents( components ),
+   myHelper( components[0] ? components[0]->myHelper : 0 )
+{}
+//================================================================================
+/*!
+ * \brief Copy constructor
+  * \param other - other side
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TSideFace::TSideFace( const TSideFace& other )
+{
+  myID               = other.myID;
+  mySurface          = other.mySurface;
+  myBaseEdge         = other.myBaseEdge;
+  myParams           = other.myParams;
+  myIsForward        = other.myIsForward;
+  myHelper           = other.myHelper;
+  myParamToColumnMap = other.myParamToColumnMap;
+
+  myComponents.resize( other.myComponents.size());
+  for (int i = 0 ; i < myComponents.size(); ++i )
+    myComponents[ i ] = new TSideFace( *other.myComponents[ i ]);
+}
+
+//================================================================================
+/*!
+ * \brief Deletes myComponents
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TSideFace::~TSideFace()
+{
+  for (int i = 0 ; i < myComponents.size(); ++i )
+    if ( myComponents[ i ] )
+      delete myComponents[ i ];
+}
+
+//================================================================================
+/*!
+ * \brief Return geometry of the vertical curve
+  * \param isMax - true means curve located closer to (1,1,1) block point
+  * \retval Adaptor3d_Curve* - curve adaptor
+ */
+//================================================================================
+
+Adaptor3d_Curve* StdMeshers_PrismAsBlock::TSideFace::VertiCurve(const bool isMax) const
+{
+  if ( !myComponents.empty() ) {
+    if ( isMax )
+      return myComponents.back()->VertiCurve(isMax);
+    else
+      return myComponents.front()->VertiCurve(isMax);
+  }
+  double f = myParams[0].first, l = myParams[0].second;
+  if ( !myIsForward ) std::swap( f, l );
+  return new TVerticalEdgeAdaptor( myParamToColumnMap, isMax ? l : f );
+}
+
+//================================================================================
+/*!
+ * \brief Return geometry of the top or bottom curve
+  * \param isTop - 
+  * \retval Adaptor3d_Curve* - 
+ */
+//================================================================================
+
+Adaptor3d_Curve* StdMeshers_PrismAsBlock::TSideFace::HorizCurve(const bool isTop) const
+{
+  return new THorizontalEdgeAdaptor( this, isTop );
+}
+
+//================================================================================
+/*!
+ * \brief Return pcurves
+  * \param pcurv - array of 4 pcurves
+  * \retval bool - is a success
+ */
+//================================================================================
+
+bool StdMeshers_PrismAsBlock::TSideFace::GetPCurves(Adaptor2d_Curve2d* pcurv[4]) const
+{
+  int iEdge[ 4 ] = { BOTTOM_EDGE, TOP_EDGE, V0_EDGE, V1_EDGE };
+
+  for ( int i = 0 ; i < 4 ; ++i ) {
+    Handle(Geom2d_Line) line;
+    switch ( iEdge[ i ] ) {
+    case TOP_EDGE:
+      line = new Geom2d_Line( gp_Pnt2d( 0, 1 ), gp::DX2d() ); break;
+    case BOTTOM_EDGE:
+      line = new Geom2d_Line( gp::Origin2d(), gp::DX2d() ); break;
+    case V0_EDGE:
+      line = new Geom2d_Line( gp::Origin2d(), gp::DY2d() ); break;
+    case V1_EDGE:
+      line = new Geom2d_Line( gp_Pnt2d( 1, 0 ), gp::DY2d() ); break;
+    }
+    pcurv[ i ] = new Geom2dAdaptor_Curve( line, 0, 1 );
+  }
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Returns geometry of pcurve on a horizontal face
+  * \param isTop - is top or bottom face
+  * \param horFace - a horizontal face
+  * \retval Adaptor2d_Curve2d* - curve adaptor
+ */
+//================================================================================
+
+Adaptor2d_Curve2d*
+StdMeshers_PrismAsBlock::TSideFace::HorizPCurve(const bool         isTop,
+                                                const TopoDS_Face& horFace) const
+{
+  return new TPCurveOnHorFaceAdaptor( this, isTop, horFace );
+}
+
+//================================================================================
+/*!
+ * \brief Return a component corresponding to parameter
+  * \param U - parameter along a horizontal size
+  * \param localU - parameter along a horizontal size of a component
+  * \retval TSideFace* - found component
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TSideFace*
+StdMeshers_PrismAsBlock::TSideFace::GetComponent(const double U,double & localU) const
+{
+  localU = U;
+  if ( myComponents.empty() )
+    return const_cast<TSideFace*>( this );
+
+  int i;
+  for ( i = 0; i < myComponents.size(); ++i )
+    if ( U < myParams[ i ].second )
+      break;
+  if ( i >= myComponents.size() )
+    i = myComponents.size() - 1;
+
+  double f = myParams[ i ].first, l = myParams[ i ].second;
+  localU = ( U - f ) / ( l - f );
+  return myComponents[ i ];
+}
+
+//================================================================================
+/*!
+ * \brief Find node columns for a parameter
+  * \param U - parameter along a horizontal edge
+  * \param col1 - the 1st found column
+  * \param col2 - the 2nd found column
+  * \retval r - normalized position of U between the found columns
+ */
+//================================================================================
+
+double StdMeshers_PrismAsBlock::TSideFace::GetColumns(const double      U,
+                                                      TParam2ColumnIt & col1,
+                                                      TParam2ColumnIt & col2) const
+{
+  double u = U, r = 0;
+  if ( !myComponents.empty() ) {
+    TSideFace * comp = GetComponent(U,u);
+    return comp->GetColumns( u, col1, col2 );
+  }
+
+  if ( !myIsForward )
+    u = 1 - u;
+  double f = myParams[0].first, l = myParams[0].second;
+  u = f + u * ( l - f );
+
+  col1 = col2 = getColumn( myParamToColumnMap, u );
+  if ( ++col2 == myParamToColumnMap->end() ) {
+    --col2;
+    r = 0.5;
+  }
+  else {
+//     if ( !myIsForward )
+//       std::swap( col1, col2 );
+    double uf = col1->first;
+    double ul = col2->first;
+    r = ( u - uf ) / ( ul - uf );
+  }
+  return r;
+}
+
+//================================================================================
+/*!
+ * \brief Return coordinates by normalized params
+  * \param U - horizontal param
+  * \param V - vertical param
+  * \retval gp_Pnt - result point
+ */
+//================================================================================
+
+gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
+                                                 const Standard_Real V) const
+{
+  double u;
+  if ( !myComponents.empty() ) {
+    TSideFace * comp = GetComponent(U,u);
+    return comp->Value( u, V );
+  }
+
+  TParam2ColumnIt u_col1, u_col2;
+  double vR, hR = GetColumns( U, u_col1, u_col2 );
+
+  const SMDS_MeshNode* n1 = 0;
+  const SMDS_MeshNode* n2 = 0;
+  const SMDS_MeshNode* n3 = 0;
+  const SMDS_MeshNode* n4 = 0;
+  gp_XYZ pnt;
+
+  vR = getRAndNodes( & u_col1->second, V, n1, n2 );
+  vR = getRAndNodes( & u_col2->second, V, n3, n4 );
+  
+  gp_XY uv1 = myHelper->GetNodeUV( mySurface.Face(), n1, n4);
+  gp_XY uv2 = myHelper->GetNodeUV( mySurface.Face(), n2, n3);
+  gp_XY uv12 = uv1 * ( 1 - vR ) + uv2 * vR;
+
+  gp_XY uv3 = myHelper->GetNodeUV( mySurface.Face(), n3, n2);
+  gp_XY uv4 = myHelper->GetNodeUV( mySurface.Face(), n4, n1);
+  gp_XY uv34 = uv3 * ( 1 - vR ) + uv4 * vR;
+
+  gp_XY uv = uv12 * ( 1 - hR ) + uv34 * hR;
+  
+  return mySurface.Value( uv.X(), uv.Y() );
+}
+
+
+//================================================================================
+/*!
+ * \brief Return boundary edge
+  * \param edge - edge index
+  * \retval TopoDS_Edge - found edge
+ */
+//================================================================================
+
+TopoDS_Edge StdMeshers_PrismAsBlock::TSideFace::GetEdge(const int iEdge) const
+{
+  if ( !myComponents.empty() ) {
+    switch ( iEdge ) {
+    case V0_EDGE : return myComponents.front()->GetEdge( iEdge );
+    case V1_EDGE : return myComponents.back() ->GetEdge( iEdge );
+    default: return TopoDS_Edge();
+    }
+  }
+  TopoDS_Shape edge;
+  const SMDS_MeshNode* node = 0;
+  SMESHDS_Mesh * meshDS = myHelper->GetMesh()->GetMeshDS();
+  TNodeColumn* column;
+
+  switch ( iEdge ) {
+  case TOP_EDGE:
+  case BOTTOM_EDGE:
+    column = & (( ++myParamToColumnMap->begin())->second );
+    node = ( iEdge == TOP_EDGE ) ? column->back() : column->front();
+    edge = myHelper->GetSubShapeByNode ( node, meshDS );
+    if ( edge.ShapeType() == TopAbs_VERTEX ) {
+      column = & ( myParamToColumnMap->begin()->second );
+      node = ( iEdge == TOP_EDGE ) ? column->back() : column->front();
+    }
+    break;
+  case V0_EDGE:
+  case V1_EDGE: {
+    bool back = ( iEdge == V1_EDGE );
+    if ( !myIsForward ) back = !back;
+    if ( back )
+      column = & ( myParamToColumnMap->rbegin()->second );
+    else
+      column = & ( myParamToColumnMap->begin()->second );
+    if ( column->size() > 0 )
+      edge = myHelper->GetSubShapeByNode( (*column)[ 1 ], meshDS );
+    if ( edge.IsNull() || edge.ShapeType() == TopAbs_VERTEX )
+      node = column->front();
+    break;
+  }
+  default:;
+  }
+  if ( !edge.IsNull() || edge.ShapeType() == TopAbs_EDGE )
+    return TopoDS::Edge( edge );
+
+  // find edge by 2 vertices
+  TopoDS_Shape V1 = edge;
+  TopoDS_Shape V2 = myHelper->GetSubShapeByNode( node, meshDS );
+  if ( V2.ShapeType() == TopAbs_VERTEX && !V2.IsSame( V1 ))
+  {
+    TopTools_ListIteratorOfListOfShape ancestIt =
+      myHelper->GetMesh()->GetAncestors( V1 );
+    for ( ; ancestIt.More(); ancestIt.Next() )
+    {
+      const TopoDS_Shape & ancestor = ancestIt.Value();
+      if ( ancestor.ShapeType() == TopAbs_EDGE )
+        for ( TopExp_Explorer e( ancestor, TopAbs_VERTEX ); e.More(); e.Next() )
+          if ( V2.IsSame( e.Current() ))
+            return TopoDS::Edge( ancestor );
+    }
+  }
+  return TopoDS_Edge();
+}
+
+//================================================================================
+/*!
+ * \brief Fill block subshapes
+  * \param shapeMap - map to fill in
+  * \retval int - nb inserted subshapes
+ */
+//================================================================================
+
+int StdMeshers_PrismAsBlock::TSideFace::InsertSubShapes(TBlockShapes& shapeMap) const
+{
+  int nbInserted = 0;
+
+  // Insert edges
+  vector< int > edgeIdVec;
+  SMESH_Block::GetFaceEdgesIDs( myID, edgeIdVec );
+
+  for ( int i = BOTTOM_EDGE; i <=V1_EDGE ; ++i ) {
+    TopoDS_Edge e = GetEdge( i );
+    if ( !e.IsNull() ) {
+      nbInserted += SMESH_Block::Insert( e, edgeIdVec[ i ], shapeMap);
+    }
+  }
+
+  // Insert corner vertices
+
+  TParam2ColumnIt col1, col2 ;
+  vector< int > vertIdVec;
+
+  // from V0 column
+  SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ V0_EDGE ], vertIdVec);
+  GetColumns(0, col1, col2 );
+  const SMDS_MeshNode* node0 = col1->second.front();
+  const SMDS_MeshNode* node1 = col1->second.back();
+  TopoDS_Shape v0 = myHelper->GetSubShapeByNode( node0, myHelper->GetMeshDS());
+  TopoDS_Shape v1 = myHelper->GetSubShapeByNode( node1, myHelper->GetMeshDS());
+  if ( v0.ShapeType() == TopAbs_VERTEX ) {
+    nbInserted += SMESH_Block::Insert( v0, vertIdVec[ 0 ], shapeMap);
+  }
+  if ( v1.ShapeType() == TopAbs_VERTEX ) {
+    nbInserted += SMESH_Block::Insert( v1, vertIdVec[ 1 ], shapeMap);
+  }
+  
+  // from V1 column
+  SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ V1_EDGE ], vertIdVec);
+  GetColumns(1, col1, col2 );
+  node0 = col2->second.front();
+  node1 = col2->second.back();
+  v0 = myHelper->GetSubShapeByNode( node0, myHelper->GetMeshDS());
+  v1 = myHelper->GetSubShapeByNode( node1, myHelper->GetMeshDS());
+  if ( v0.ShapeType() == TopAbs_VERTEX ) {
+    nbInserted += SMESH_Block::Insert( v0, vertIdVec[ 0 ], shapeMap);
+  }
+  if ( v1.ShapeType() == TopAbs_VERTEX ) {
+    nbInserted += SMESH_Block::Insert( v1, vertIdVec[ 1 ], shapeMap);
+  }
+
+//   TopoDS_Vertex V0, V1, Vcom;
+//   TopExp::Vertices( myBaseEdge, V0, V1, true );
+//   if ( !myIsForward ) std::swap( V0, V1 );
+
+//   // bottom vertex IDs
+//   SMESH_Block::GetEdgeVertexIDs( edgeIdVec[ _u0 ], vertIdVec);
+//   SMESH_Block::Insert( V0, vertIdVec[ 0 ], shapeMap);
+//   SMESH_Block::Insert( V1, vertIdVec[ 1 ], shapeMap);
+
+//   TopoDS_Edge sideEdge = GetEdge( V0_EDGE );
+//   if ( sideEdge.IsNull() || !TopExp::CommonVertex( botEdge, sideEdge, Vcom ))
+//     return false;
+
+//   // insert one side edge
+//   int edgeID;
+//   if ( Vcom.IsSame( V0 )) edgeID = edgeIdVec[ _v0 ];
+//   else                    edgeID = edgeIdVec[ _v1 ];
+//   SMESH_Block::Insert( sideEdge, edgeID, shapeMap);
+
+//   // top vertex of the side edge
+//   SMESH_Block::GetEdgeVertexIDs( edgeID, vertIdVec);
+//   TopoDS_Vertex Vtop = TopExp::FirstVertex( sideEdge );
+//   if ( Vcom.IsSame( Vtop ))
+//     Vtop = TopExp::LastVertex( sideEdge );
+//   SMESH_Block::Insert( Vtop, vertIdVec[ 1 ], shapeMap);
+
+//   // other side edge
+//   sideEdge = GetEdge( V1_EDGE );
+//   if ( sideEdge.IsNull() )
+//     return false;
+//   if ( edgeID = edgeIdVec[ _v1 ]) edgeID = edgeIdVec[ _v0 ];
+//   else                            edgeID = edgeIdVec[ _v1 ];
+//   SMESH_Block::Insert( sideEdge, edgeID, shapeMap);
+  
+//   // top edge
+//   TopoDS_Edge topEdge = GetEdge( TOP_EDGE );
+//   SMESH_Block::Insert( topEdge, edgeIdVec[ _u1 ], shapeMap);
+
+//   // top vertex of the other side edge
+//   if ( !TopExp::CommonVertex( topEdge, sideEdge, Vcom ))
+//     return false;
+//   SMESH_Block::GetEdgeVertexIDs( edgeID, vertIdVec );
+//   SMESH_Block::Insert( Vcom, vertIdVec[ 1 ], shapeMap);
+
+  return nbInserted;
+}
+
+//================================================================================
+/*!
+ * \brief Creates TVerticalEdgeAdaptor 
+  * \param columnsMap - node column map
+  * \param parameter - normalized parameter
+ */
+//================================================================================
+
+StdMeshers_PrismAsBlock::TVerticalEdgeAdaptor::
+TVerticalEdgeAdaptor( const TParam2ColumnMap* columnsMap, const double parameter)
+{
+  myNodeColumn = & getColumn( columnsMap, parameter )->second;
+}
+
+//================================================================================
+/*!
+ * \brief Return coordinates for the given normalized parameter
+  * \param U - normalized parameter
+  * \retval gp_Pnt - coordinates
+ */
+//================================================================================
+
+gp_Pnt StdMeshers_PrismAsBlock::TVerticalEdgeAdaptor::Value(const Standard_Real U) const
+{
+  const SMDS_MeshNode* n1;
+  const SMDS_MeshNode* n2;
+  double r = getRAndNodes( myNodeColumn, U, n1, n2 );
+  return gpXYZ(n1) * ( 1 - r ) + gpXYZ(n2) * r;
+}
+
+//================================================================================
+/*!
+ * \brief Return coordinates for the given normalized parameter
+  * \param U - normalized parameter
+  * \retval gp_Pnt - coordinates
+ */
+//================================================================================
+
+gp_Pnt StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::Value(const Standard_Real U) const
+{
+  return mySide->TSideFace::Value( U, myV );
+}
+
+//================================================================================
+/*!
+ * \brief Return UV on pcurve for the given normalized parameter
+  * \param U - normalized parameter
+  * \retval gp_Pnt - coordinates
+ */
+//================================================================================
+
+gp_Pnt2d StdMeshers_PrismAsBlock::TPCurveOnHorFaceAdaptor::Value(const Standard_Real U) const
+{
+  TParam2ColumnIt u_col1, u_col2;
+  double r = mySide->GetColumns( U, u_col1, u_col2 );
+  gp_XY uv1 = mySide->GetNodeUV( myFace, u_col1->second[ myZ ]);
+  gp_XY uv2 = mySide->GetNodeUV( myFace, u_col2->second[ myZ ]);
+  return uv1 * ( 1 - r ) + uv2 * r;
+}
diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx
new file mode 100644 (file)
index 0000000..e4e12eb
--- /dev/null
@@ -0,0 +1,425 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_Prism_3D.hxx
+//  Module : SMESH
+
+#ifndef _SMESH_Prism_3D_HXX_
+#define _SMESH_Prism_3D_HXX_
+
+#include "SMESH_3D_Algo.hxx"
+#include "SMDS_TypeOfPosition.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+
+#include <vector.h>
+#include <map.h>
+
+#include <Adaptor3d_Curve.hxx>
+#include <Adaptor3d_Surface.hxx>
+#include <Adaptor2d_Curve2d.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <TopTools_IndexedMapOfOrientedShape.hxx>
+#include <gp_XYZ.hxx>
+
+
+class SMESHDS_SubMesh;
+class TopoDS_Edge;
+class TopoDS_Faces;
+struct TNode;
+
+//typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
+typedef std::vector<const SMDS_MeshNode* > TNodeColumn;
+
+// map of bottom nodes to the column of nodes above them
+// (the column includes the bottom nodes)
+typedef std::map< TNode, TNodeColumn > TNode2ColumnMap;
+typedef std::map< double, TNodeColumn > TParam2ColumnMap;
+typedef std::map< double, TNodeColumn >::const_iterator TParam2ColumnIt;
+
+typedef TopTools_IndexedMapOfOrientedShape TBlockShapes;
+
+// ===============================================
+/*!
+ * \brief Structure containing node relative data
+ */
+// ===============================================
+
+struct TNode
+{
+  const SMDS_MeshNode* myNode;
+  gp_XYZ               myParams;
+
+  gp_XYZ GetCoords() const { return gp_XYZ( myNode->X(), myNode->Y(), myNode->Z() ); }
+  gp_XYZ GetParams() const { return myParams; }
+  gp_XYZ& ChangeParams() { return myParams; }
+  SMDS_TypeOfPosition GetPositionType() const
+  { return myNode ? myNode->GetPosition()->GetTypeOfPosition() : SMDS_TOP_UNSPEC; }
+
+  TNode(const SMDS_MeshNode* node = 0): myNode(node) {}
+  bool operator < (const TNode& other) const { return myNode < other.myNode; }
+};
+
+// ===============================================================
+/*!
+ * \brief Tool analyzing and giving access to a prism geometry 
+ *  treating it like a block, i.e. the four side faces are
+ *  emulated by division/uniting of missing/excess faces.
+ *  It also manage associations between block subshapes and a mesh.
+ */
+// ===============================================================
+
+class StdMeshers_PrismAsBlock: public SMESH_Block
+{
+public:
+  /*!
+   * \brief Constructor. Initialization is needed
+   */
+  StdMeshers_PrismAsBlock();
+
+  ~StdMeshers_PrismAsBlock();
+
+  /*!
+   * \brief Initialization.
+    * \param helper - helper loaded with mesh and 3D shape
+    * \param shape3D - a closed shell or solid
+    * \retval bool - false if a mesh or a shape are KO
+    *
+    * Analyse shape geometry and mesh.
+    * If there are triangles on one of faces, it becomes 'bottom'
+   */
+  bool Init(SMESH_MesherHelper* helper, const TopoDS_Shape& shape3D);
+
+  /*!
+   * \brief Return number of nodes on every vertical edge
+    * \retval int - number of nodes including end nodes
+   */
+  int VerticalSize() const { return myParam2ColumnMaps[0].begin()->second.size(); }
+
+  bool HasNotQuadElemOnTop() const { return myNotQuadOnTop; }
+
+  /*!
+   * \brief Return pointer to column of nodes
+    * \param node - bottom node from which the returned column goes up
+    * \retval const TNodeColumn* - the found column
+   */
+  const TNodeColumn* GetNodeColumn(const SMDS_MeshNode* node) const;
+
+  /*!
+   * \brief Return TParam2ColumnMap for a base edge
+    * \param baseEdgeID - base edge SMESHDS Index
+    * \param isReverse - columns in-block orientation
+    * \retval const TParam2ColumnMap& - map
+   */
+  const TParam2ColumnMap& GetParam2ColumnMap(const int baseEdgeID,
+                                             bool &    isReverse)
+  {
+    std::pair< TParam2ColumnMap*, bool > & col_frw =
+      myShapeIndex2ColumnMap[ baseEdgeID ];
+    isReverse = !col_frw.second;
+    return * col_frw.first;
+  }
+  
+  /*!
+   * \brief Return pointer to mesh
+    * \retval SMESH_Mesh - mesh
+   */
+  SMESH_Mesh* Mesh() const { return myHelper->GetMesh(); }
+
+  /*!
+   * \brief Return pointer to mesh DS
+    * \retval SMESHDS_Mesh - mesh DS
+   */
+  SMESHDS_Mesh* MeshDS() const { return Mesh()->GetMeshDS(); }
+
+  /*!
+   * \brief Return submesh of a shape
+    * \param shapeID - shape given by in-block index
+    * \retval SMESH_subMesh* - found submesh
+   */
+  SMESH_subMesh* SubMesh(const int shapeID) const
+  { return Mesh()->GetSubMesh( Shape( shapeID )); }
+
+  /*!
+   * \brief Return submesh DS of a shape
+    * \param shapeID - shape given by in-block index
+    * \retval SMESHDS_SubMesh* - found submesh DS
+   */
+  SMESHDS_SubMesh* SubMeshDS(const int shapeID) const
+  { return SubMesh(shapeID)->GetSubMeshDS(); }
+
+  /*!
+   * \brief Return a in-block shape
+    * \param shapeID - shape given by in-block index
+    * \retval SMESHDS_SubMesh* - found submesh
+   */
+  const TopoDS_Shape& Shape(const int shapeID) const
+  { return myShapeIDMap( shapeID ); }
+
+  /*!
+   * \brief Return in-block ID of a shape
+    * \param shape - block subshape
+    * \retval int - ID or zero if the shape has no ID
+   */
+  int ShapeID(const TopoDS_Shape& shape) const
+  { return myShapeIDMap.FindIndex( shape ); }
+
+  /*!
+   * \brief Check curve orientation of a bootom edge
+   *  \param meshDS - mesh DS
+   *  \param columnsMap - node columns map of side face
+   *  \param bottomEdge - the bootom edge
+   *  \param sideFaceID - side face in-block ID
+   *  \retval bool - true if orienation coinside with in-block froward orienation
+   */
+  static bool IsForwardEdge(SMESHDS_Mesh*           meshDS,
+                            const TParam2ColumnMap& columnsMap,
+                            const TopoDS_Edge &     bottomEdge,
+                            const int               sideFaceID);
+  /*!
+   * \brief Find wall faces by bottom edges
+    * \param mesh - the mesh
+    * \param mainShape - the prism
+    * \param bottomFace - the bottom face
+    * \param bottomEdges - edges bounding the bottom face
+    * \param wallFaces - faces list to fill in
+   */
+  static bool GetWallFaces( SMESH_Mesh*                     mesh,
+                            const TopoDS_Shape &            mainShape,
+                            const TopoDS_Shape &            bottomFace,
+                            const std::list< TopoDS_Edge >& bottomEdges,
+                            std::list< TopoDS_Face >&       wallFaces);
+
+private:
+
+  // --------------------------------------------------------------------
+  /*!
+   * \brief Class representing a part of a geom face or
+   * a union of seleral faces. Or just an ordinary geom face
+   *
+   * It's parametrization is within [0,1] range.
+   * It redefines Adaptor3d_Surface::Value(U,V) where U and V are within [0,1]
+   */
+  // --------------------------------------------------------------------
+  class TSideFace: public Adaptor3d_Surface
+  {
+    int                             myID; //!< in-block ID
+    // map used to find out real UV by it's normalized UV
+    TParam2ColumnMap*               myParamToColumnMap;
+    BRepAdaptor_Surface             mySurface;
+    TopoDS_Edge                     myBaseEdge;
+    // first and last normalized params and orientaion for each component or it-self
+    vector< pair< double, double> > myParams;
+    bool                            myIsForward;
+    vector< TSideFace* >            myComponents;
+    SMESH_MesherHelper *            myHelper;
+  public:
+    TSideFace( SMESH_MesherHelper* helper,
+               const int           faceID,
+               const TopoDS_Face&  face,
+               const TopoDS_Edge&  baseEdge,
+               TParam2ColumnMap*   columnsMap,
+               const double        first = 0.0,
+               const double        last = 1.0);
+    TSideFace( const std::vector< TSideFace* >&             components,
+               const std::vector< pair< double, double> > & params);
+    TSideFace( const TSideFace& other );
+    ~TSideFace();
+    bool IsComplex() const
+    { return ( NbComponents() > 0 || myParams[0].first != 0. || myParams[0].second != 1. ); }
+    int FaceID() const { return myID; }
+    TParam2ColumnMap* GetColumns() const { return myParamToColumnMap; }
+    gp_XY GetNodeUV(const TopoDS_Face& F, const SMDS_MeshNode* n) const
+    { return myHelper->GetNodeUV( F, n ); }
+    const TopoDS_Edge & BaseEdge() const { return myBaseEdge; }
+    int ColumnHeight() const {
+      if ( NbComponents() ) return GetComponent(0)->GetColumns()->begin()->second.size();
+      else                  return GetColumns()->begin()->second.size(); }
+    double GetColumns(const double U, TParam2ColumnIt & col1, TParam2ColumnIt& col2 ) const;
+    int NbComponents() const { return myComponents.size(); }
+    TSideFace* GetComponent(const int i) const { return myComponents.at( i ); }
+    void SetComponent(const int i, TSideFace* c)
+    { if ( myComponents[i] ) delete myComponents[i]; myComponents[i]=c; }
+    TSideFace* GetComponent(const double U, double& localU) const;
+    bool IsForward() const { return myIsForward; }
+    // boundary geometry for a face
+    Adaptor3d_Surface* Surface() const { return new TSideFace( *this ); }
+    bool GetPCurves(Adaptor2d_Curve2d* pcurv[4]) const;
+    Adaptor2d_Curve2d* HorizPCurve(const bool isTop, const TopoDS_Face& horFace) const;
+    Adaptor3d_Curve* HorizCurve(const bool isTop) const;
+    Adaptor3d_Curve* VertiCurve(const bool isMax) const;
+    TopoDS_Edge GetEdge( const int edge ) const;
+    int InsertSubShapes( TBlockShapes& shapeMap ) const;
+    // redefine Adaptor methods
+    gp_Pnt Value(const Standard_Real U,const Standard_Real V) const;
+  };
+
+  // --------------------------------------------------------------------
+  /*!
+   * \brief Class emulating geometry of a vertical edge
+   */
+  // --------------------------------------------------------------------
+  class TVerticalEdgeAdaptor: public Adaptor3d_Curve
+  {
+    const TNodeColumn* myNodeColumn;
+  public:
+    TVerticalEdgeAdaptor( const TParam2ColumnMap* columnsMap, const double parameter );
+    gp_Pnt Value(const Standard_Real U) const;
+    Standard_Real FirstParameter() const { return 0; }
+    Standard_Real LastParameter() const { return 1; }
+  };
+
+  // --------------------------------------------------------------------
+  /*!
+   * \brief Class emulating geometry of a hirizontal edge
+   */
+  // --------------------------------------------------------------------
+  class THorizontalEdgeAdaptor: public Adaptor3d_Curve
+  {
+    const TSideFace* mySide;
+    double           myV;
+  public:
+    THorizontalEdgeAdaptor( const TSideFace* sideFace, const bool isTop)
+      :mySide(sideFace), myV( isTop ? 1.0 : 0.0 ) {}
+    gp_Pnt Value(const Standard_Real U) const;
+    Standard_Real FirstParameter() const { return 0; }
+    Standard_Real LastParameter() const { return 1; }
+  };
+
+  // --------------------------------------------------------------------
+  /*!
+   * \brief Class emulating pcurve on a hirizontal face
+   */
+  // --------------------------------------------------------------------
+  class TPCurveOnHorFaceAdaptor: public Adaptor2d_Curve2d
+  {
+    const TSideFace*  mySide;
+    int               myZ;
+    TopoDS_Face       myFace;
+  public:
+    TPCurveOnHorFaceAdaptor( const TSideFace*   sideFace,
+                             const bool         isTop,
+                             const TopoDS_Face& horFace)
+      : mySide(sideFace), myFace(horFace), myZ(isTop ? mySide->ColumnHeight() - 1 : 0 ) {}
+    gp_Pnt2d Value(const Standard_Real U) const;
+    Standard_Real FirstParameter() const { return 0; }
+    Standard_Real LastParameter() const { return 1; }
+  };
+  // --------------------------------------------------------------------
+
+  bool myNotQuadOnTop;
+  SMESH_MesherHelper* myHelper;
+  TBlockShapes myShapeIDMap;
+
+  // container of 4 side faces
+  TSideFace*                 mySide; 
+  // node columns for each base edge
+  vector< TParam2ColumnMap > myParam2ColumnMaps;
+  // to find a column for a node by edge SMESHDS Index
+  map< int, pair< TParam2ColumnMap*, bool > > myShapeIndex2ColumnMap;
+
+  
+  //vector< SMESH_subMesh* >           mySubMeshesVec; // submesh by in-block id
+};
+
+// =============================================
+/*!
+ * \brief Algo building prisms on a prism shape
+ */
+// =============================================
+
+class StdMeshers_Prism_3D: public SMESH_3D_Algo
+{
+public:
+  StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen);
+  virtual ~StdMeshers_Prism_3D();
+
+  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);
+
+  /*!
+   * \brief Enable removal of quadrangles from the bottom face and
+   * triangles creation there by projection from the top
+   * (sole face meshed with triangles is considered to be a bottom one).
+   * If there are two faces with triangles, triangles must
+   * be of the same topology, else the algo fails.
+   * The method must be called before Compute()
+   */
+  void ProjectTriangles() { myProjectTriangles = true; }
+
+  /*!
+   * \brief Create prisms
+    * \param nodeColumns - columns of nodes generated from nodes of a mesh face
+    * \param helper - helper initialized by mesh and shape to add prisms to
+   */
+  static void AddPrisms( vector<const TNodeColumn*> & nodeColumns,
+                         SMESH_MesherHelper*          helper);
+
+private:
+
+  /*!
+   * \brief Find correspondence between bottom and top nodes.
+   *  If elements on the bottom and top faces are topologically different,
+   *  and projection is possible and allowed, perform the projection
+    * \retval bool - is a success or not
+   */
+  bool assocOrProjBottom2Top();
+
+  /*!
+   * \brief Remove quadrangles from the top face and
+   * create triangles there by projection from the bottom
+    * \retval bool - a success or not
+   */
+  bool projectBottomToTop();
+
+  /*!
+   * \brief Set projection coordinates of a node to a face and it's subshapes
+    * \param faceID - the face given by in-block ID
+    * \param params - node normalized parameters
+    * \retval bool - is a success
+   */
+  bool setFaceAndEdgesXYZ( const int faceID, const gp_XYZ& params, int z );
+
+private:
+
+  bool myProjectTriangles;
+
+  StdMeshers_PrismAsBlock myBlock;
+  SMESH_MesherHelper*     myHelper;
+
+  vector<gp_XYZ>            myShapeXYZ; // point on each sub-shape
+
+  // map of bottom nodes to the column of nodes above them
+  // (the column includes the bottom node)
+  typedef std::map< TNode, TNodeColumn > TNode2ColumnMap;
+  TNode2ColumnMap  myBotToColumnMap;
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource1D.cxx b/src/StdMeshers/StdMeshers_ProjectionSource1D.cxx
new file mode 100644 (file)
index 0000000..18a25a3
--- /dev/null
@@ -0,0 +1,219 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource1D.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#include "StdMeshers_ProjectionSource1D.hxx"
+
+#include "SMESH_Mesh.hxx"
+
+#include "utilities.h"
+
+#include <TopoDS.hxx>
+
+using namespace std;
+
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource1D::StdMeshers_ProjectionSource1D
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource1D::StdMeshers_ProjectionSource1D(int hypId, int studyId,
+                                                             SMESH_Gen * gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _name = "ProjectionSource1D"; // used by Projection_1D
+  _param_algo_dim = 1; // 1D
+  _sourceMesh = 0;
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource1D::~StdMeshers_ProjectionSource1D
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource1D::~StdMeshers_ProjectionSource1D()
+{
+  MESSAGE( "StdMeshers_ProjectionSource1D::~StdMeshers_ProjectionSource1D" );
+}
+
+//=============================================================================
+  /*!
+   * Sets source <edge> to take a mesh pattern from
+   */
+//=============================================================================
+
+void StdMeshers_ProjectionSource1D::SetSourceEdge(const TopoDS_Shape& edge)
+  throw ( SALOME_Exception )
+{
+  if ( edge.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Null edge is not allowed"));
+
+  if ( edge.ShapeType() != TopAbs_EDGE )
+    throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+
+  if ( !_sourceEdge.IsSame( edge ) )
+  {
+    _sourceEdge = TopoDS::Edge( edge );
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Sets vertex association between the source edge and the target one.
+ * This parameter is optional
+ */
+//=============================================================================
+
+void StdMeshers_ProjectionSource1D::SetVertexAssociation(const TopoDS_Shape& sourceVertex,
+                                                         const TopoDS_Shape& targetVertex)
+  throw ( SALOME_Exception )
+{
+  if ( sourceVertex.IsNull() != targetVertex.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Two or none vertices must be provided"));
+
+  if ( !sourceVertex.IsNull() ) {
+    if ( sourceVertex.ShapeType() != TopAbs_VERTEX ||
+         targetVertex.ShapeType() != TopAbs_VERTEX )
+      throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+  }
+
+  if ( !_sourceVertex.IsSame( sourceVertex ) ||
+       !_targetVertex.IsSame( targetVertex ) )
+  {
+    _sourceVertex = TopoDS::Vertex( sourceVertex );
+    _targetVertex = TopoDS::Vertex( targetVertex );
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & StdMeshers_ProjectionSource1D::SaveTo(ostream & save)
+{
+  // we store it in order to be able to detect that hypo is really modified
+  save << " " << _sourceEdge.TShape().operator->()  ;
+  save << " " << _sourceVertex.TShape().operator->();
+  save << " " << _targetVertex.TShape().operator->();
+  save << " " << ( _sourceMesh ? _sourceMesh->GetId() : -1 );
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & StdMeshers_ProjectionSource1D::LoadFrom(istream & load)
+{
+  // impossible to restore w/o any context
+  return load;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & operator <<(ostream & save, StdMeshers_ProjectionSource1D & hyp)
+{
+  return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & operator >>(istream & load, StdMeshers_ProjectionSource1D & hyp)
+{
+  return hyp.LoadFrom( load );
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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_ProjectionSource1D::SetParametersByMesh(const SMESH_Mesh*   ,
+                                                        const TopoDS_Shape& )
+{
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Return all parameters
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource1D::GetStoreParams(TopoDS_Shape& s1,
+                                                   TopoDS_Shape& s2,
+                                                   TopoDS_Shape& s3) const
+{
+  s1 = _sourceEdge;
+  s2 = _sourceVertex;
+  s3 = _targetVertex;
+}
+
+//================================================================================
+/*!
+ * \brief Set all parameters without notifying on modification
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource1D::RestoreParams(const TopoDS_Shape& s1,
+                                                  const TopoDS_Shape& s2,
+                                                  const TopoDS_Shape& s3,
+                                                  SMESH_Mesh*         mesh)
+{
+  _sourceEdge   = TopoDS::Edge( s1 );
+  _sourceVertex = TopoDS::Vertex( s2 );
+  _targetVertex = TopoDS::Vertex( s3 );
+  _sourceMesh   = mesh;
+}
+
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource1D.hxx b/src/StdMeshers/StdMeshers_ProjectionSource1D.hxx
new file mode 100644 (file)
index 0000000..e1d019a
--- /dev/null
@@ -0,0 +1,142 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource1D.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#ifndef _SMESH_ProjectionSource1D_HXX_
+#define _SMESH_ProjectionSource1D_HXX_
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+
+class SMESH_Gen;
+
+// =========================================================
+  /*!
+   * This hypothesis specifies a meshed edge to take a mesh pattern from
+   * and optionally association of vertices between the source edge and a
+   * target one (where a hipothesis is assigned to)
+   */
+// =========================================================
+
+class StdMeshers_ProjectionSource1D: public SMESH_Hypothesis
+{
+public:
+  // Constructor
+  StdMeshers_ProjectionSource1D( int hypId, int studyId, SMESH_Gen * gen );
+  // Destructor
+  virtual ~StdMeshers_ProjectionSource1D();
+
+  /*!
+   * Sets source <edge> to take a mesh pattern from
+   */
+  void SetSourceEdge(const TopoDS_Shape& edge)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the source edge
+   */
+  TopoDS_Edge GetSourceEdge() const { return _sourceEdge; }
+
+  /*!
+   * Sets source <mesh> to take a mesh pattern from
+   */
+  void SetSourceMesh(SMESH_Mesh* mesh) { _sourceMesh = mesh; }
+
+  /*!
+   * Return source mesh
+   */
+  SMESH_Mesh* GetSourceMesh() const { return _sourceMesh; }
+
+  /*!
+   * Sets vertex association between the source edge and the target one.
+   * This parameter is optional
+   */
+  void SetVertexAssociation(const TopoDS_Shape& sourceVertex,
+                            const TopoDS_Shape& targetVertex)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the vertex associated with the target vertex.
+   * Result may be nil if association not set
+   */
+  TopoDS_Vertex GetSourceVertex() const { return _sourceVertex; }
+
+  /*!
+   * Returns the vertex associated with the source vertex.
+   * Result may be nil if association not set
+   */
+  TopoDS_Vertex GetTargetVertex() const { return _targetVertex; }
+
+  /*!
+   * \brief Test if vertex association defined
+    * \retval bool - test result
+   */
+  bool HasVertexAssociation() const
+  { return ( !_sourceVertex.IsNull() && !_targetVertex.IsNull() ); }
+
+  /*!
+   * \brief Return all parameters
+   */
+  void GetStoreParams(TopoDS_Shape& s1,
+                      TopoDS_Shape& s2,
+                      TopoDS_Shape& s3) const;
+
+  /*!
+   * \brief Set all parameters without notifying on modification
+   */
+  void RestoreParams(const TopoDS_Shape& s1,
+                     const TopoDS_Shape& s2,
+                     const TopoDS_Shape& s3,
+                     SMESH_Mesh*         mesh);
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  friend std::ostream & operator <<(std::ostream & save, StdMeshers_ProjectionSource1D & hyp);
+  friend std::istream & operator >>(std::istream & load, StdMeshers_ProjectionSource1D & hyp);
+
+  /*!
+   * \brief Initialize parameters 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
+    *
+    * Implementation does noting
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+protected:
+
+  TopoDS_Edge   _sourceEdge;
+  SMESH_Mesh*   _sourceMesh;
+  TopoDS_Vertex _sourceVertex;
+  TopoDS_Vertex _targetVertex;
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource2D.cxx b/src/StdMeshers/StdMeshers_ProjectionSource2D.cxx
new file mode 100644 (file)
index 0000000..909b903
--- /dev/null
@@ -0,0 +1,287 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource2D.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+
+#include "StdMeshers_ProjectionSource2D.hxx"
+
+#include "SMESH_Mesh.hxx"
+
+#include "utilities.h"
+
+#include <TopoDS.hxx>
+
+using namespace std;
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource2D::StdMeshers_ProjectionSource2D
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource2D::StdMeshers_ProjectionSource2D(int hypId, int studyId,
+                                                             SMESH_Gen * gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _name = "ProjectionSource2D"; // used by Projection_2D
+  _param_algo_dim = 2; // 2D
+  _sourceMesh = 0;
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource2D::~StdMeshers_ProjectionSource2D
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource2D::~StdMeshers_ProjectionSource2D()
+{
+  MESSAGE( "StdMeshers_ProjectionSource2D::~StdMeshers_ProjectionSource2D" );
+}
+
+//=============================================================================
+  /*!
+   * Sets a source <face> to take a mesh pattern from
+   */
+//=============================================================================
+
+void StdMeshers_ProjectionSource2D::SetSourceFace(const TopoDS_Shape& Face)
+  throw ( SALOME_Exception )
+{
+  if ( Face.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Null Face is not allowed"));
+
+  if ( Face.ShapeType() != TopAbs_FACE )
+    throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+
+  if ( !_sourceFace.IsSame( Face ) )
+  {
+    _sourceFace = TopoDS::Face( Face );
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Sets vertex association between the source face and the target one.
+ * This parameter is optional.
+ * Two vertices must belong to one edge of a face
+ */
+//=============================================================================
+
+void StdMeshers_ProjectionSource2D::SetVertexAssociation(const TopoDS_Shape& sourceVertex1,
+                                                         const TopoDS_Shape& sourceVertex2,
+                                                         const TopoDS_Shape& targetVertex1,
+                                                         const TopoDS_Shape& targetVertex2)
+  throw ( SALOME_Exception )
+{
+  if ( sourceVertex1.IsNull() != targetVertex1.IsNull() ||
+       sourceVertex2.IsNull() != targetVertex2.IsNull() ||
+       sourceVertex1.IsNull() != targetVertex2.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Two or none pairs of vertices must be provided"));
+
+  if ( !sourceVertex1.IsNull() ) {
+    if ( sourceVertex1.ShapeType() != TopAbs_VERTEX ||
+         sourceVertex2.ShapeType() != TopAbs_VERTEX ||
+         targetVertex1.ShapeType() != TopAbs_VERTEX ||
+         targetVertex2.ShapeType() != TopAbs_VERTEX )
+      throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+  }
+
+  if ( !_sourceVertex1.IsSame( sourceVertex1 ) ||
+       !_sourceVertex2.IsSame( sourceVertex2 ) ||
+       !_targetVertex1.IsSame( targetVertex1 ) ||
+       !_targetVertex2.IsSame( targetVertex2 ) )
+  {
+    _sourceVertex1 = TopoDS::Vertex( sourceVertex1 );
+    _sourceVertex2 = TopoDS::Vertex( sourceVertex2 );
+    _targetVertex1 = TopoDS::Vertex( targetVertex1 );
+    _targetVertex2 = TopoDS::Vertex( targetVertex2 );
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Returns the source face
+ */
+//=============================================================================
+
+TopoDS_Face StdMeshers_ProjectionSource2D::GetSourceFace() const
+{
+  return _sourceFace;
+}
+
+//=============================================================================
+/*!
+ * Returns the vertex associated with the target vertex.
+ * Result may be nil if association not set
+ */
+//=============================================================================
+
+TopoDS_Vertex StdMeshers_ProjectionSource2D::GetSourceVertex(int i) const
+  throw ( SALOME_Exception )
+{
+  if ( i == 1 )
+    return _sourceVertex1;
+  else if ( i == 2 )
+    return _sourceVertex2;
+  else
+    throw SALOME_Exception(LOCALIZED("Wrong vertex index"));
+}
+
+//=============================================================================
+/*!
+ * Returns the <i>-th target vertex associated with the <i>-th source vertex.
+ * Result may be nil if association not set.
+ */
+//=============================================================================
+
+TopoDS_Vertex StdMeshers_ProjectionSource2D::GetTargetVertex(int i) const
+  throw ( SALOME_Exception )
+{
+  if ( i == 1 )
+    return _targetVertex1;
+  else if ( i == 2 )
+    return _targetVertex2;
+  else
+    throw SALOME_Exception(LOCALIZED("Wrong vertex index"));
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & StdMeshers_ProjectionSource2D::SaveTo(ostream & save)
+{
+  // we store it in order to be able to detect that hypo is really modified
+  save << " " << _sourceFace.TShape().operator->()  ;
+  save << " " << _sourceVertex1.TShape().operator->();
+  save << " " << _targetVertex1.TShape().operator->();
+  save << " " << _sourceVertex2.TShape().operator->();
+  save << " " << _targetVertex2.TShape().operator->();
+  save << " " << ( _sourceMesh ? _sourceMesh->GetId() : -1 );
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & StdMeshers_ProjectionSource2D::LoadFrom(istream & load)
+{
+  // impossible to restore w/o any context
+  // It is done by servant
+  return load;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & operator <<(ostream & save, StdMeshers_ProjectionSource2D & hyp)
+{
+  return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & operator >>(istream & load, StdMeshers_ProjectionSource2D & hyp)
+{
+  return hyp.LoadFrom( load );
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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_ProjectionSource2D::SetParametersByMesh(const SMESH_Mesh*   ,
+                                                        const TopoDS_Shape& )
+{
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Return all parameters
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource2D::GetStoreParams(TopoDS_Shape& s1,
+                                                   TopoDS_Shape& s2,
+                                                   TopoDS_Shape& s3,
+                                                   TopoDS_Shape& s4,
+                                                   TopoDS_Shape& s5) const
+{
+  s1 = _sourceFace;
+  s2 = _sourceVertex1;
+  s3 = _sourceVertex2;
+  s4 = _targetVertex1;
+  s5 = _targetVertex2;
+}
+
+//================================================================================
+/*!
+ * \brief Set all parameters without notifying on modification
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource2D::RestoreParams(const TopoDS_Shape& s1,
+                                                  const TopoDS_Shape& s2,
+                                                  const TopoDS_Shape& s3,
+                                                  const TopoDS_Shape& s4,
+                                                  const TopoDS_Shape& s5,
+                                                  SMESH_Mesh*         mesh)
+{
+  _sourceFace    = TopoDS::Face( s1 );
+  _sourceVertex1 = TopoDS::Vertex( s2 );
+  _sourceVertex2 = TopoDS::Vertex( s3 );
+  _targetVertex1 = TopoDS::Vertex( s4 );
+  _targetVertex2 = TopoDS::Vertex( s5 );
+  _sourceMesh   = mesh;
+}
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource2D.hxx b/src/StdMeshers/StdMeshers_ProjectionSource2D.hxx
new file mode 100644 (file)
index 0000000..ec4a33e
--- /dev/null
@@ -0,0 +1,155 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource2D.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#ifndef _SMESH_ProjectionSource2D_HXX_
+#define _SMESH_ProjectionSource2D_HXX_
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+
+class SMESH_Gen;
+
+// =========================================================
+/*!
+ * This hypothesis specifies a meshed face to take a mesh pattern from
+ * and optionally association of vertices between the source face and a
+ * target one (where a hipothesis is assigned to)
+ */
+// =========================================================
+
+class StdMeshers_ProjectionSource2D: public SMESH_Hypothesis
+{
+public:
+  // Constructor
+  StdMeshers_ProjectionSource2D( int hypId, int studyId, SMESH_Gen * gen );
+  // Destructor
+  virtual ~StdMeshers_ProjectionSource2D();
+
+  /*!
+   * Sets a source <face> to take a mesh pattern from
+   */
+  void SetSourceFace(const TopoDS_Shape& face)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the source face
+   */
+  TopoDS_Face GetSourceFace() const;
+
+  /*!
+   * Sets source <mesh> to take a mesh pattern from
+   */
+  void SetSourceMesh(SMESH_Mesh* mesh) { _sourceMesh = mesh; }
+
+  /*!
+   * Return source mesh
+   */
+  SMESH_Mesh* GetSourceMesh() const { return _sourceMesh; }
+
+  /*!
+   * Sets vertex association between the source face and the target one.
+   * This parameter is optional.
+   * Two vertices must belong to one edge of a face
+   */
+  void SetVertexAssociation(const TopoDS_Shape& sourceVertex1,
+                            const TopoDS_Shape& sourceVertex2,
+                            const TopoDS_Shape& targetVertex1,
+                            const TopoDS_Shape& targetVertex2)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the <i>-th source vertex associated with the <i>-th target vertex.
+   * Result may be nil if association not set.
+   * Valid indices are 1 and 2
+   */
+  TopoDS_Vertex GetSourceVertex(int i) const throw ( SALOME_Exception );
+
+  /*!
+   * Returns the <i>-th target vertex associated with the <i>-th source vertex.
+   * Result may be nil if association not set.
+   * Valid indices are 1 and 2
+   */
+  TopoDS_Vertex GetTargetVertex(int i) const throw ( SALOME_Exception );
+
+  /*!
+   * \brief Test if vertex association defined
+    * \retval bool - test result
+   */
+  bool HasVertexAssociation() const
+  { return ( !_sourceVertex1.IsNull() && !_targetVertex1.IsNull() &&
+             !_sourceVertex2.IsNull() && !_targetVertex2.IsNull()); }
+
+  /*!
+   * \brief Return all parameters
+   */
+  void GetStoreParams(TopoDS_Shape& s1,
+                      TopoDS_Shape& s2,
+                      TopoDS_Shape& s3,
+                      TopoDS_Shape& s4,
+                      TopoDS_Shape& s5) const;
+
+  /*!
+   * \brief Set all parameters without notifying on modification
+   */
+  void RestoreParams(const TopoDS_Shape& s1,
+                     const TopoDS_Shape& s2,
+                     const TopoDS_Shape& s3,
+                     const TopoDS_Shape& s4,
+                     const TopoDS_Shape& s5,
+                     SMESH_Mesh*         mesh);
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  friend std::ostream & operator <<(std::ostream & save, StdMeshers_ProjectionSource2D & hyp);
+  friend std::istream & operator >>(std::istream & load, StdMeshers_ProjectionSource2D & hyp);
+
+  /*!
+   * \brief Initialize parameters 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
+    *
+    * Implementation does noting
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+protected:
+
+  TopoDS_Face   _sourceFace;
+  SMESH_Mesh*   _sourceMesh;
+  TopoDS_Vertex _sourceVertex1;
+  TopoDS_Vertex _sourceVertex2;
+  TopoDS_Vertex _targetVertex1;
+  TopoDS_Vertex _targetVertex2;
+};
+
+#endif
+
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource3D.cxx b/src/StdMeshers/StdMeshers_ProjectionSource3D.cxx
new file mode 100644 (file)
index 0000000..3e4c33e
--- /dev/null
@@ -0,0 +1,286 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource3D.cxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#include "StdMeshers_ProjectionSource3D.hxx"
+
+#include "utilities.h"
+#include "SMESH_Gen.hxx"
+
+#include <TopoDS.hxx>
+
+using namespace std;
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource3D::StdMeshers_ProjectionSource3D
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource3D::StdMeshers_ProjectionSource3D(int hypId, int studyId,
+                                                             SMESH_Gen * gen)
+  : SMESH_Hypothesis(hypId, studyId, gen)
+{
+  _name = "ProjectionSource3D"; // used by Projection_3D
+  _param_algo_dim = 3; // 3D
+  _sourceMesh = 0;
+}
+
+//=============================================================================
+/*!
+ *  StdMeshers_ProjectionSource3D::~StdMeshers_ProjectionSource3D
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+StdMeshers_ProjectionSource3D::~StdMeshers_ProjectionSource3D()
+{
+  MESSAGE( "StdMeshers_ProjectionSource3D::~StdMeshers_ProjectionSource3D" );
+}
+
+//=============================================================================
+  /*!
+   * Sets a source <face> to take a mesh pattern from
+   */
+//=============================================================================
+
+void StdMeshers_ProjectionSource3D::SetSource3DShape(const TopoDS_Shape& Shape)
+  throw ( SALOME_Exception )
+{
+  if ( Shape.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Null Shape is not allowed"));
+
+  if ( SMESH_Gen::GetShapeDim( Shape ) != 3 )
+    throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+
+  if ( !_sourceShape.IsSame( Shape ) )
+  {
+    _sourceShape = Shape;
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Sets vertex association between the source shape and the target one.
+ * This parameter is optional.
+ * Two vertices must belong to one edge of a shape
+ */
+//=============================================================================
+
+void StdMeshers_ProjectionSource3D::SetVertexAssociation(const TopoDS_Shape& sourceVertex1,
+                                                         const TopoDS_Shape& sourceVertex2,
+                                                         const TopoDS_Shape& targetVertex1,
+                                                         const TopoDS_Shape& targetVertex2)
+  throw ( SALOME_Exception )
+{
+  if ( sourceVertex1.IsNull() != targetVertex1.IsNull() ||
+       sourceVertex2.IsNull() != targetVertex2.IsNull() ||
+       sourceVertex1.IsNull() != targetVertex2.IsNull() )
+    throw SALOME_Exception(LOCALIZED("Two or none pairs of vertices must be provided"));
+
+  if ( !sourceVertex1.IsNull() ) {
+    if ( sourceVertex1.ShapeType() != TopAbs_VERTEX ||
+         sourceVertex2.ShapeType() != TopAbs_VERTEX ||
+         targetVertex1.ShapeType() != TopAbs_VERTEX ||
+         targetVertex2.ShapeType() != TopAbs_VERTEX )
+      throw SALOME_Exception(LOCALIZED("Wrong shape type"));
+  }
+
+  if ( !_sourceVertex1.IsSame( sourceVertex1 ) ||
+       !_sourceVertex2.IsSame( sourceVertex2 ) ||
+       !_targetVertex1.IsSame( targetVertex1 ) ||
+       !_targetVertex2.IsSame( targetVertex2 ) )
+  {
+    _sourceVertex1 = TopoDS::Vertex( sourceVertex1 );
+    _sourceVertex2 = TopoDS::Vertex( sourceVertex2 );
+    _targetVertex1 = TopoDS::Vertex( targetVertex1 );
+    _targetVertex2 = TopoDS::Vertex( targetVertex2 );
+
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+/*!
+ * Returns the source face
+ */
+//=============================================================================
+
+TopoDS_Shape StdMeshers_ProjectionSource3D::GetSource3DShape() const
+{
+  return _sourceShape;
+}
+
+//=============================================================================
+/*!
+ * Returns the vertex associated with the target vertex.
+ * Result may be nil if association not set
+ */
+//=============================================================================
+
+TopoDS_Vertex StdMeshers_ProjectionSource3D::GetSourceVertex(int i) const
+  throw ( SALOME_Exception )
+{
+  if ( i == 1 )
+    return _sourceVertex1;
+  else if ( i == 2 )
+    return _sourceVertex2;
+  else
+    throw SALOME_Exception(LOCALIZED("Wrong vertex index"));
+}
+
+//=============================================================================
+/*!
+ * Returns the <i>-th target vertex associated with the <i>-th source vertex.
+ * Result may be nil if association not set.
+ */
+//=============================================================================
+
+TopoDS_Vertex StdMeshers_ProjectionSource3D::GetTargetVertex(int i) const
+  throw ( SALOME_Exception )
+{
+  if ( i == 1 )
+    return _targetVertex1;
+  else if ( i == 2 )
+    return _targetVertex2;
+  else
+    throw SALOME_Exception(LOCALIZED("Wrong vertex index"));
+}
+
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & StdMeshers_ProjectionSource3D::SaveTo(ostream & save)
+{
+  // we store it in order to be able to detect that hypo is really modified
+  save << " " << _sourceShape.TShape().operator->()  ;
+  save << " " << _sourceVertex1.TShape().operator->();
+  save << " " << _targetVertex1.TShape().operator->();
+  save << " " << _sourceVertex2.TShape().operator->();
+  save << " " << _targetVertex2.TShape().operator->();
+  save << " " << ( _sourceMesh ? _sourceMesh->GetId() : -1 );
+  return save;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & StdMeshers_ProjectionSource3D::LoadFrom(istream & load)
+{
+  // impossible to restore w/o any context
+  // It is done by servant
+  return load;
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+ostream & operator <<(ostream & save, StdMeshers_ProjectionSource3D & hyp)
+{
+  return hyp.SaveTo( save );
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+istream & operator >>(istream & load, StdMeshers_ProjectionSource3D & hyp)
+{
+  return hyp.LoadFrom( load );
+}
+
+//================================================================================
+/*!
+ * \brief Initialize start and end length 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_ProjectionSource3D::SetParametersByMesh(const SMESH_Mesh*   ,
+                                                        const TopoDS_Shape& )
+{
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Return all parameters
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource3D::GetStoreParams(TopoDS_Shape& s1,
+                                                   TopoDS_Shape& s2,
+                                                   TopoDS_Shape& s3,
+                                                   TopoDS_Shape& s4,
+                                                   TopoDS_Shape& s5) const
+{
+  s1 = _sourceShape;
+  s2 = _sourceVertex1;
+  s3 = _sourceVertex2;
+  s4 = _targetVertex1;
+  s5 = _targetVertex2;
+}
+
+//================================================================================
+/*!
+ * \brief Set all parameters without notifying on modification
+ */
+//================================================================================
+
+void StdMeshers_ProjectionSource3D::RestoreParams(const TopoDS_Shape& s1,
+                                                  const TopoDS_Shape& s2,
+                                                  const TopoDS_Shape& s3,
+                                                  const TopoDS_Shape& s4,
+                                                  const TopoDS_Shape& s5,
+                                                  SMESH_Mesh*         mesh)
+{
+  _sourceShape   = s1;
+  _sourceVertex1 = TopoDS::Vertex( s2 );
+  _sourceVertex2 = TopoDS::Vertex( s3 );
+  _targetVertex1 = TopoDS::Vertex( s4 );
+  _targetVertex2 = TopoDS::Vertex( s5 );
+  _sourceMesh   = mesh;
+}
diff --git a/src/StdMeshers/StdMeshers_ProjectionSource3D.hxx b/src/StdMeshers/StdMeshers_ProjectionSource3D.hxx
new file mode 100644 (file)
index 0000000..493851a
--- /dev/null
@@ -0,0 +1,153 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_ProjectionSource3D.hxx
+//  Author : Edward AGAPOV
+//  Module : SMESH
+//  $Header$
+
+#ifndef _SMESH_ProjectionSource3D_HXX_
+#define _SMESH_ProjectionSource3D_HXX_
+
+#include "SMESH_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <TopoDS_Vertex.hxx>
+
+class SMESH_Gen;
+
+// =========================================================
+/*!
+ * This hypothesis specifies a meshed shell or solid to take a mesh pattern from
+ * and optionally association of vertices between the source shape and a
+ * target one (where a hipothesis is assigned to)
+ */
+// =========================================================
+
+class StdMeshers_ProjectionSource3D:  public SMESH_Hypothesis
+{
+public:
+  // Constructor
+  StdMeshers_ProjectionSource3D( int hypId, int studyId, SMESH_Gen * gen );
+  // Destructor
+  virtual ~StdMeshers_ProjectionSource3D();
+
+  /*!
+   * Sets a source <shape> to take a mesh pattern from
+   */
+  void SetSource3DShape(const TopoDS_Shape& shape)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the source shape
+   */
+  TopoDS_Shape GetSource3DShape() const;
+
+  /*!
+   * Sets source <mesh> to take a mesh pattern from
+   */
+  void SetSourceMesh(SMESH_Mesh* mesh) { _sourceMesh = mesh; }
+
+  /*!
+   * Return source mesh
+   */
+  SMESH_Mesh* GetSourceMesh() const { return _sourceMesh; }
+
+  /*!
+   * Sets vertex association between the source shape and the target one.
+   * This parameter is optional.
+   * Two vertices must belong to one edge of a shape
+   */
+  void SetVertexAssociation(const TopoDS_Shape& sourceVertex1,
+                            const TopoDS_Shape& sourceVertex2,
+                            const TopoDS_Shape& targetVertex1,
+                            const TopoDS_Shape& targetVertex2)
+    throw ( SALOME_Exception );
+
+  /*!
+   * Returns the <i>-th source vertex associated with the <i>-th target vertex.
+   * Result may be nil if association not set.
+   */
+  TopoDS_Vertex GetSourceVertex(int i) const throw ( SALOME_Exception );
+
+  /*!
+   * Returns the <i>-th target vertex associated with the <i>-th source vertex.
+   * Result may be nil if association not set.
+   */
+  TopoDS_Vertex GetTargetVertex(int i) const throw ( SALOME_Exception );
+
+  /*!
+   * \brief Test if vertex association defined
+    * \retval bool - test result
+   */
+  bool HasVertexAssociation() const
+  { return ( !_sourceVertex1.IsNull() && !_targetVertex1.IsNull() &&
+             !_sourceVertex2.IsNull() && !_targetVertex2.IsNull()); }
+
+  /*!
+   * \brief Return all parameters
+   */
+  void GetStoreParams(TopoDS_Shape& s1,
+                      TopoDS_Shape& s2,
+                      TopoDS_Shape& s3,
+                      TopoDS_Shape& s4,
+                      TopoDS_Shape& s5) const;
+
+  /*!
+   * \brief Set all parameters without notifying on modification
+   */
+  void RestoreParams(const TopoDS_Shape& s1,
+                     const TopoDS_Shape& s2,
+                     const TopoDS_Shape& s3,
+                     const TopoDS_Shape& s4,
+                     const TopoDS_Shape& s5,
+                     SMESH_Mesh*         mesh);
+
+  virtual std::ostream & SaveTo(std::ostream & save);
+  virtual std::istream & LoadFrom(std::istream & load);
+  friend std::ostream & operator <<(std::ostream & save, StdMeshers_ProjectionSource3D & hyp);
+  friend std::istream & operator >>(std::istream & load, StdMeshers_ProjectionSource3D & hyp);
+
+  /*!
+   * \brief Initialize parameters 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
+    *
+    * Implementation does noting
+   */
+  virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape);
+
+protected:
+
+  TopoDS_Shape  _sourceShape;
+  SMESH_Mesh*   _sourceMesh;
+  TopoDS_Vertex _sourceVertex1;
+  TopoDS_Vertex _sourceVertex2;
+  TopoDS_Vertex _targetVertex1;
+  TopoDS_Vertex _targetVertex2;
+
+};
+
+#endif
+
diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx
new file mode 100644 (file)
index 0000000..2afedd4
--- /dev/null
@@ -0,0 +1,1241 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_ProjectionUtils.cxx
+// Created   : Fri Oct 27 10:24:28 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_ProjectionUtils.hxx"
+
+#include "StdMeshers_ProjectionSource1D.hxx"
+#include "StdMeshers_ProjectionSource2D.hxx"
+#include "StdMeshers_ProjectionSource3D.hxx"
+
+#include "SMESH_Algo.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_IndexedDataMapOfShapeIndexedMapOfShape.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMDS_EdgePosition.hxx"
+
+#include "utilities.h"
+
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <BRep_Tool.hxx>
+#include <Bnd_Box.hxx>
+#include <TopAbs.hxx>
+#include <TopTools_Array1OfShape.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS_Shape.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Trsf.hxx>
+#include <gp_Vec.hxx>
+
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define SHOW_VERTEX(v,msg) // { \
+//  if ( v.IsNull() ) cout << msg << " NULL SHAPE" << endl; \
+// else if (v.ShapeType() == TopAbs_VERTEX) {\
+//   gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( v ));\
+//   cout << msg << (v).TShape().operator->()<<" ( " <<p.X()<<", "<<p.Y()<<", "<<p.Z()<<" )"<<endl;}\
+// else {\
+// cout << msg << " "; TopAbs::Print(v.ShapeType(),cout) <<" "<<(v).TShape().operator->()<<endl;}\
+// }
+#define SHOW_LIST(msg,l) \
+// { \
+//     cout << msg << " ";\
+//     list< TopoDS_Edge >::const_iterator e = l.begin();\
+//     for ( int i = 0; e != l.end(); ++e, ++i ) {\
+//       cout << i << "V (" << TopExp::FirstVertex( *e, true ).TShape().operator->() << ") "\
+//            << i << "E (" << e->TShape().operator->() << "); "; }\
+//     cout << endl;\
+//   }
+
+namespace {
+  //================================================================================
+  /*!
+   * \brief Reverse order of edges in a list and their orientation
+    * \param edges - list of edges to reverse
+    * \param nbEdges - number of edges to reverse
+   */
+  //================================================================================
+
+  void Reverse( list< TopoDS_Edge > & edges, const int nbEdges )
+  {
+    SHOW_LIST("BEFORE REVERSE", edges);
+
+    list< TopoDS_Edge >::iterator eIt = edges.begin();
+    if ( edges.size() == nbEdges )
+    {
+      edges.reverse();
+    }
+    else  // reverse only the given nb of edges
+    {
+      // look for the last edge to be reversed
+      list< TopoDS_Edge >::iterator eBackIt = edges.begin();
+      for ( int i = 1; i < nbEdges; ++i )
+        ++eBackIt;
+      // reverse
+      while ( eIt != eBackIt ) {
+        std::swap( *eIt, *eBackIt );
+        SHOW_LIST("# AFTER SWAP", edges)
+        if ( (++eIt) != eBackIt )
+          --eBackIt;
+      }
+    }
+    for ( eIt = edges.begin(); eIt != edges.end(); ++eIt )
+      eIt->Reverse();
+    SHOW_LIST("ATFER REVERSE", edges)
+  }
+
+  //================================================================================
+  /*!
+   * \brief Check if propagation is possible
+    * \param theMesh1 - source mesh
+    * \param theMesh2 - target mesh
+    * \retval bool - true if possible
+   */
+  //================================================================================
+
+  bool IsPropagationPossible( SMESH_Mesh* theMesh1, SMESH_Mesh* theMesh2 )
+  {
+    if ( theMesh1 != theMesh2 ) {
+      TopoDS_Shape mainShape1 = theMesh1->GetMeshDS()->ShapeToMesh();
+      TopoDS_Shape mainShape2 = theMesh2->GetMeshDS()->ShapeToMesh();
+      return mainShape1.IsSame( mainShape2 );
+    }
+    return true;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Fix up association of edges in faces by possible propagation
+    * \param nbEdges - nb of edges in an outer wire
+    * \param edges1 - edges of one face
+    * \param edges2 - matching edges of another face
+    * \param theMesh1 - mesh 1
+    * \param theMesh2 - mesh 2
+   */
+  //================================================================================
+
+  void FixAssocByPropagation( const int             nbEdges,
+                              list< TopoDS_Edge > & edges1,
+                              list< TopoDS_Edge > & edges2,
+                              SMESH_Mesh*           theMesh1,
+                              SMESH_Mesh*           theMesh2)
+  {
+    if ( nbEdges == 2 && IsPropagationPossible( theMesh1, theMesh2 ) )
+    {
+      list< TopoDS_Edge >::iterator eIt2 = ++edges2.begin(); // 2nd edge of the 2nd face
+      TopoDS_Edge edge2 =
+        StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() );
+      if ( !edge2.IsNull() ) // propagation found for the second edge
+        Reverse( edges2, nbEdges );
+    }
+  }
+}
+
+//=======================================================================
+/*!
+ * \brief Looks for association of all subshapes of two shapes
+ * \param theShape1 - shape 1
+ * \param theMesh1 - mesh built on shape 1
+ * \param theShape2 - shape 2
+ * \param theMesh2 - mesh built on shape 2
+ * \param theAssociation - association map to be filled that may
+ *                         contain association of one or two pairs of vertices
+ * \retval bool - true if association found
+ */
+//=======================================================================
+
+bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& theShape1,
+                                                         SMESH_Mesh*         theMesh1,
+                                                         const TopoDS_Shape& theShape2,
+                                                         SMESH_Mesh*         theMesh2,
+                                                         TShapeShapeMap &    theMap)
+{
+  if ( theShape1.ShapeType() != theShape2.ShapeType() )
+    RETURN_BAD_RESULT("Different shape types");
+
+  bool bidirect = ( !theShape1.IsSame( theShape2 ));
+  if ( !theMap.IsEmpty())
+  {
+    switch ( theShape1.ShapeType() ) {
+
+    case TopAbs_EDGE: {
+      // ----------------------------------------------------------------------
+      if ( theMap.Extent() != 2 )
+        RETURN_BAD_RESULT("Wrong map extent " << theMap.Extent() );
+      TopoDS_Edge edge1 = TopoDS::Edge( theShape1 );
+      TopoDS_Edge edge2 = TopoDS::Edge( theShape2 );
+      TopoDS_Vertex VV1[2], VV2[2];
+      TopExp::Vertices( edge1, VV1[0], VV1[1] );
+      TopExp::Vertices( edge2, VV2[0], VV2[1] );
+      int i1 = 0, i2 = 0;
+      if ( theMap.IsBound( VV1[ i1 ] )) i1 = 1;
+      if ( theMap.IsBound( VV2[ i2 ] )) i2 = 1;
+      InsertAssociation( VV1[ i1 ], VV2[ i2 ], theMap, bidirect);
+      return true;
+    }
+
+    case TopAbs_FACE: {
+      // ----------------------------------------------------------------------
+      TopoDS_Face face1 = TopoDS::Face( theShape1 );
+      TopoDS_Face face2 = TopoDS::Face( theShape2 );
+
+      TopoDS_Vertex VV1[2], VV2[2];
+      // find a not closed edge of face1 both vertices of which are associated
+      int nbEdges = 0;
+      TopExp_Explorer exp ( face1, TopAbs_EDGE );
+      for ( ; VV2[ 1 ].IsNull() && exp.More(); exp.Next(), ++nbEdges ) {
+        TopExp::Vertices( TopoDS::Edge( exp.Current() ), VV1[0], VV1[1] );
+        if ( theMap.IsBound( VV1[0] ) ) {
+          VV2[ 0 ] = TopoDS::Vertex( theMap( VV1[0] ));
+          if ( theMap.IsBound( VV1[1] ) && !VV1[0].IsSame( VV1[1] ))
+            VV2[ 1 ] = TopoDS::Vertex( theMap( VV1[1] ));
+        }
+      }
+      if ( VV2[ 1 ].IsNull() ) { // 2 bound vertices not found
+        if ( nbEdges > 1 ) {
+          RETURN_BAD_RESULT("2 bound vertices not found" );
+        } else {
+          VV2[ 1 ] = VV2[ 0 ];
+        }
+      }
+      list< TopoDS_Edge > edges1, edges2;
+      int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 );
+      if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed");
+      FixAssocByPropagation( nbE, edges1, edges2, theMesh1, theMesh2 );
+
+      list< TopoDS_Edge >::iterator eIt1 = edges1.begin();
+      list< TopoDS_Edge >::iterator eIt2 = edges2.begin();
+      for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
+      {
+        InsertAssociation( *eIt1, *eIt2, theMap, bidirect);
+        VV1[0] = TopExp::FirstVertex( *eIt1, true );
+        VV2[0] = TopExp::FirstVertex( *eIt2, true );
+        InsertAssociation( VV1[0], VV2[0], theMap, bidirect);
+      }
+      return true;
+    }
+
+    case TopAbs_SHELL:
+    case TopAbs_SOLID: {
+      // ----------------------------------------------------------------------
+      TopoDS_Vertex VV1[2], VV2[2];
+      // find a not closed edge of shape1 both vertices of which are associated
+      TopoDS_Edge edge1;
+      TopExp_Explorer exp ( theShape1, TopAbs_EDGE );
+      for ( ; VV2[ 1 ].IsNull() && exp.More(); exp.Next() ) {
+        edge1 = TopoDS::Edge( exp.Current() );
+        TopExp::Vertices( edge1 , VV1[0], VV1[1] );
+        if ( theMap.IsBound( VV1[0] )) {
+          VV2[ 0 ] = TopoDS::Vertex( theMap( VV1[0] ));
+          if ( theMap.IsBound( VV1[1] ) && !VV1[0].IsSame( VV1[1] ))
+            VV2[ 1 ] = TopoDS::Vertex( theMap( VV1[1] ));
+        }
+      }
+      if ( VV2[ 1 ].IsNull() ) // 2 bound vertices not found
+        RETURN_BAD_RESULT("2 bound vertices not found" );
+      TopoDS_Edge edge2 = GetEdgeByVertices( theMesh2, VV2[ 0 ], VV2[ 1 ]);
+      if ( edge2.IsNull() )
+        RETURN_BAD_RESULT("GetEdgeByVertices() failed");
+
+      // get a face sharing edge1
+      TopoDS_Shape F1, F2, FF2[2];
+      TopTools_ListIteratorOfListOfShape ancestIt = theMesh1->GetAncestors( edge1 );
+      for ( ; F1.IsNull() && ancestIt.More(); ancestIt.Next() )
+        if ( ancestIt.Value().ShapeType() == TopAbs_FACE )
+          F1 = ancestIt.Value().Oriented( TopAbs_FORWARD );
+      if ( F1.IsNull() )
+        RETURN_BAD_RESULT(" Face1 not found");
+
+      // get 2 faces sharing edge2
+      ancestIt = theMesh2->GetAncestors( edge2 );
+      for ( int i = 0; FF2[1].IsNull() && ancestIt.More(); ancestIt.Next() )
+        if ( ancestIt.Value().ShapeType() == TopAbs_FACE )
+          FF2[ i++ ] = ancestIt.Value().Oriented( TopAbs_FORWARD );
+      if ( FF2[1].IsNull() )
+        RETURN_BAD_RESULT("2 faces not found");
+
+      // get oriented edge1 and edge2 from F1 and FF2[0]
+      for ( exp.Init( F1, TopAbs_EDGE ); exp.More(); exp.Next() )
+        if ( edge1.IsSame( exp.Current() )) {
+          edge1 = TopoDS::Edge( exp.Current() );
+          break;
+        }
+      
+      for ( exp.Init( FF2[ 0 ], TopAbs_EDGE ); exp.More(); exp.Next() )
+        if ( edge2.IsSame( exp.Current() )) {
+          edge2 = TopoDS::Edge( exp.Current() );
+          break;
+        }
+
+      // compare first vertices of edge1 and edge2
+      TopExp::Vertices( edge1, VV1[0], VV1[1], true );
+      TopExp::Vertices( edge2, VV2[0], VV2[1], true );
+      F2 = FF2[ 0 ];
+      if ( !VV1[ 0 ].IsSame( theMap( VV2[ 0 ]))) {
+        F2 = FF2[ 1 ];
+        edge2.Reverse();
+      }
+
+      TopTools_MapOfShape boundEdges; 
+
+      // association of face subshapes and neighbour faces
+      list< pair < TopoDS_Face, TopoDS_Edge > > FE1, FE2;
+      list< pair < TopoDS_Face, TopoDS_Edge > >::iterator fe1, fe2;
+      FE1.push_back( make_pair( TopoDS::Face( F1 ), edge1 ));
+      FE2.push_back( make_pair( TopoDS::Face( F2 ), edge2 ));
+      for ( fe1 = FE1.begin(), fe2 = FE2.begin(); fe1 != FE1.end(); ++fe1, ++fe2 )
+      {
+        const TopoDS_Face& face1 = fe1->first;
+        if ( theMap.IsBound( face1 ) ) continue;
+        const TopoDS_Face& face2 = fe2->first;
+        edge1 = fe1->second;
+        edge2 = fe2->second;
+        TopExp::Vertices( edge1, VV1[0], VV1[1], true );
+        TopExp::Vertices( edge2, VV2[0], VV2[1], true );
+        list< TopoDS_Edge > edges1, edges2;
+        int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 );
+        if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed");
+        FixAssocByPropagation( nbE, edges1, edges2, theMesh1, theMesh2 );
+        
+        InsertAssociation( face1, face2, theMap, bidirect); // assoc faces
+        list< TopoDS_Edge >::iterator eIt1 = edges1.begin();
+        list< TopoDS_Edge >::iterator eIt2 = edges2.begin();
+        for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
+        {
+          if ( !boundEdges.Add( *eIt1 )) continue; // already associated
+          InsertAssociation( *eIt1, *eIt2, theMap, bidirect);  // assoc edges
+          VV1[0] = TopExp::FirstVertex( *eIt1, true );
+          VV2[0] = TopExp::FirstVertex( *eIt2, true );
+          InsertAssociation( VV1[0], VV2[0], theMap, bidirect); // assoc vertices
+
+          // add adjacent faces to process
+          TopoDS_Face nextFace1 = GetNextFace( theMesh1, *eIt1, face1 );
+          TopoDS_Face nextFace2 = GetNextFace( theMesh2, *eIt2, face2 );
+          if ( !nextFace1.IsNull() && !nextFace2.IsNull() ) {
+            FE1.push_back( make_pair( nextFace1, *eIt1 ));
+            FE2.push_back( make_pair( nextFace2, *eIt2 ));
+          }
+        }
+      }
+      return true;
+    }
+    default:
+      RETURN_BAD_RESULT("Unexpected shape type");
+
+    } // end switch by shape type
+  } // end case of available initial vertex association
+
+  //----------------------------------------------------------------------
+  // NO INITIAL VERTEX ASSOCIATION
+  //----------------------------------------------------------------------
+
+  switch ( theShape1.ShapeType() ) {
+
+  case TopAbs_EDGE: {
+    // ----------------------------------------------------------------------
+    TopoDS_Edge edge1 = TopoDS::Edge( theShape1 );
+    TopoDS_Edge edge2 = TopoDS::Edge( theShape2 );
+    if ( IsPropagationPossible( theMesh1, theMesh2 ))
+    {
+      TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 );
+      if ( !prpEdge.IsNull() )
+      {
+        TopoDS_Vertex VV1[2], VV2[2];
+        TopExp::Vertices( edge1,   VV1[0], VV1[1], true );
+        TopExp::Vertices( prpEdge, VV2[0], VV2[1], true );
+        InsertAssociation( VV1[ 0 ], VV2[ 0 ], theMap, bidirect);
+        InsertAssociation( VV1[ 1 ], VV2[ 1 ], theMap, bidirect);
+        if ( VV1[0].IsSame( VV1[1] ) || // one of edges is closed
+             VV2[0].IsSame( VV2[1] ) )
+        {
+          InsertAssociation( edge1, prpEdge, theMap, bidirect); // insert with a proper orientation
+        }
+        return true; // done
+      }
+    }
+    if ( IsClosedEdge( edge1 ) && IsClosedEdge( edge2 ))
+    {
+      // TODO: find out a proper orientation (is it possible?)
+      InsertAssociation( edge1, edge2, theMap, bidirect); // insert with a proper orientation
+      InsertAssociation( TopExp::FirstVertex(edge1), TopExp::FirstVertex(edge2),
+                         theMap, bidirect);
+      return true; // done
+    }
+    break; // try by vertex closeness
+  }
+
+  case TopAbs_FACE: {
+    // ----------------------------------------------------------------------
+    if ( IsPropagationPossible( theMesh1, theMesh2 )) // try by propagation in one mesh
+    {
+      TopoDS_Face face1 = TopoDS::Face(theShape1);
+      TopoDS_Face face2 = TopoDS::Face(theShape2);
+      // get outer edge of theShape1
+      TopoDS_Edge edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE ));
+      // find out if any edge of face2 is a propagation edge of outer edge1
+      for ( TopExp_Explorer exp( face2, TopAbs_EDGE ); exp.More(); exp.Next() ) {
+        TopoDS_Edge edge2 = TopoDS::Edge( exp.Current() );
+        edge2 = GetPropagationEdge( theMesh1, edge2, edge1 );
+        if ( !edge2.IsNull() ) // propagation found
+        {
+          TopoDS_Vertex VV1[2], VV2[2];
+          TopExp::Vertices( edge1, VV1[0], VV1[1], true );
+          TopExp::Vertices( edge2, VV2[0], VV2[1], true );
+          list< TopoDS_Edge > edges1, edges2;
+          int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 );
+          if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed");
+          if ( nbE == 2 ) // only 2 edges
+          {
+            // take care of proper association of propagated edges
+            bool same1 = edge1.IsSame( edges1.front() );
+            bool same2 = edge2.IsSame( edges2.front() );
+            if ( same1 != same2 )
+              Reverse(edges2, nbE);
+          }
+          // store association
+          list< TopoDS_Edge >::iterator eIt1 = edges1.begin();
+          list< TopoDS_Edge >::iterator eIt2 = edges2.begin();
+          for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
+          {
+            InsertAssociation( *eIt1, *eIt2, theMap, bidirect);
+            VV1[0] = TopExp::FirstVertex( *eIt1, true );
+            VV2[0] = TopExp::FirstVertex( *eIt2, true );
+            InsertAssociation( VV1[0], VV2[0], theMap, bidirect);
+          }
+          return true;
+        }
+      }
+    }
+    break; // try by vertex closeness
+  }
+  default:;
+  }
+
+  // Find association by closeness of vertices
+  // ------------------------------------------
+
+  TopTools_IndexedMapOfShape vMap1, vMap2;
+  TopExp::MapShapes( theShape1, TopAbs_VERTEX, vMap1 );
+  TopExp::MapShapes( theShape2, TopAbs_VERTEX, vMap2 );
+
+  if ( vMap1.Extent() != vMap2.Extent() )
+    RETURN_BAD_RESULT("Different nb of vertices");
+
+  if ( vMap1.Extent() == 1 ) {
+    InsertAssociation( vMap1(1), vMap2(1), theMap, bidirect);
+    if ( theShape1.ShapeType() == TopAbs_EDGE )
+      return true;
+    return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap);
+  }
+
+  // Find transformation to make the shapes be of similar size at same location
+
+  Bnd_Box box[2];
+  for ( int i = 1; i <= vMap1.Extent(); ++i ) {
+    box[ 0 ].Add( BRep_Tool::Pnt ( TopoDS::Vertex( vMap1( i ))));
+    box[ 1 ].Add( BRep_Tool::Pnt ( TopoDS::Vertex( vMap2( i ))));
+  }
+
+  gp_Pnt gc[2]; // box center
+  double x0,y0,z0, x1,y1,z1;
+  box[0].Get( x0,y0,z0, x1,y1,z1 );
+  gc[0] = 0.5 * ( gp_XYZ( x0,y0,z0 ) + gp_XYZ( x1,y1,z1 ));
+  box[1].Get( x0,y0,z0, x1,y1,z1 );
+  gc[1] = 0.5 * ( gp_XYZ( x0,y0,z0 ) + gp_XYZ( x1,y1,z1 ));
+
+  // 1 -> 2
+  gp_Vec vec01( gc[0], gc[1] );
+  double scale = sqrt( box[1].SquareExtent() / box[0].SquareExtent() );
+
+  // Find 2 closest vertices
+
+  TopoDS_Vertex VV1[2], VV2[2];
+  // get 2 linked vertices of shape 1 not belonging to an inner wire of a face
+  TopoDS_Shape edge = theShape1;
+  TopExp_Explorer expF( theShape1, TopAbs_FACE ), expE;
+  for ( ; expF.More(); expF.Next() ) {
+    edge.Nullify();
+    TopoDS_Shape wire = OuterShape( TopoDS::Face( expF.Current() ), TopAbs_WIRE );
+    for ( expE.Init( wire, TopAbs_EDGE ); edge.IsNull() && expE.More(); expE.Next() )
+      if ( !IsClosedEdge( TopoDS::Edge( expE.Current() )))
+        edge = expE.Current();
+    if ( !edge.IsNull() )
+      break;
+  }
+  if ( edge.IsNull() || edge.ShapeType() != TopAbs_EDGE )
+    RETURN_BAD_RESULT("Edge not found");
+
+  TopExp::Vertices( TopoDS::Edge( edge ), VV1[0], VV1[1]);
+  if ( VV1[0].IsSame( VV1[1] ))
+    RETURN_BAD_RESULT("Only closed edges");
+
+  // find vertices closest to 2 linked vertices of shape 1
+  for ( int i1 = 0; i1 < 2; ++i1 )
+  {
+    double dist2 = DBL_MAX;
+    gp_Pnt p1 = BRep_Tool::Pnt( VV1[ i1 ]);
+    p1.Translate( vec01 );
+    p1.Scale( gc[1], scale );
+    for ( int i2 = 1; i2 <= vMap2.Extent(); ++i2 )
+    {
+      TopoDS_Vertex V2 = TopoDS::Vertex( vMap2( i2 ));
+      gp_Pnt p2 = BRep_Tool::Pnt ( V2 );
+      double d2 = p1.SquareDistance( p2 );
+      if ( d2 < dist2 && !V2.IsSame( VV2[ 0 ])) {
+        VV2[ i1 ] = V2; dist2 = d2;
+      }
+    }
+  }
+
+  InsertAssociation( VV1[ 0 ], VV2 [ 0 ], theMap, bidirect);
+  InsertAssociation( VV1[ 1 ], VV2 [ 1 ], theMap, bidirect);
+  if ( theShape1.ShapeType() == TopAbs_EDGE )
+    return true;
+
+  return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap );
+}
+
+//================================================================================
+/*!
+ * \brief Find association of edges of faces
+ * \param face1 - face 1
+ * \param VV1 - vertices of face 1
+ * \param face2 - face 2
+ * \param VV2 - vertices of face 2 associated with oned of face 1
+ * \param edges1 - out list of edges of face 1
+ * \param edges2 - out list of edges of face 2
+ * \retval int - nb of edges in an outer wire in a success case, else zero
+ */
+//================================================================================
+
+int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1,
+                                                    TopoDS_Vertex      VV1[2],
+                                                    const TopoDS_Face& face2,
+                                                    TopoDS_Vertex      VV2[2],
+                                                    list< TopoDS_Edge > & edges1,
+                                                    list< TopoDS_Edge > & edges2)
+{
+  edges1.clear();
+  edges2.clear();
+
+  list< int > nbVInW1, nbVInW2;
+  if ( SMESH_Block::GetOrderedEdges( face1, VV1[0], edges1, nbVInW1) !=
+       SMESH_Block::GetOrderedEdges( face2, VV2[0], edges2, nbVInW2) )
+    RETURN_BAD_RESULT("Different number of wires in faces ");
+
+  if ( nbVInW1.front() != nbVInW2.front() )
+    RETURN_BAD_RESULT("Different number of edges in faces: " <<
+                      nbVInW1.front() << " != " << nbVInW2.front());
+
+  // Define if we need to reverse one of wires to make edges in lists match each other
+
+  bool reverse = false;
+
+  list< TopoDS_Edge >::iterator eBackIt;
+  if ( !VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) {
+    eBackIt = --edges1.end();
+    // check if the second vertex belongs to the first or last edge in the wire
+    if ( !VV1[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) {
+      bool KO = true; // belongs to none
+      if ( nbVInW1.size() > 1 ) { // several wires
+        eBackIt = edges1.begin();
+        for ( int i = 1; i < nbVInW1.front(); ++i ) ++eBackIt;
+        KO = !VV1[1].IsSame( TopExp::FirstVertex( *eBackIt, true ));
+      }
+      if ( KO )
+        RETURN_BAD_RESULT("GetOrderedEdges() failed");
+    }
+    reverse = true;
+  }
+  eBackIt = --edges2.end();
+  if ( !VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))) {
+    // check if the second vertex belongs to the first or last edge in the wire
+    if ( !VV2[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) {
+      bool KO = true; // belongs to none
+      if ( nbVInW2.size() > 1 ) { // several wires
+        eBackIt = edges2.begin();
+        for ( int i = 1; i < nbVInW2.front(); ++i ) ++eBackIt;
+        KO = !VV2[1].IsSame( TopExp::FirstVertex( *eBackIt, true ));
+      }
+      if ( KO )
+        RETURN_BAD_RESULT("GetOrderedEdges() failed");
+    }
+    reverse = !reverse;
+  }
+  if ( reverse )
+  {
+    Reverse( edges2 , nbVInW2.front());
+    if (( VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) !=
+        ( VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))))
+      RETURN_BAD_RESULT("GetOrderedEdges() failed");
+  }
+  return nbVInW2.front();
+}
+
+//=======================================================================
+//function : InitVertexAssociation
+//purpose  : 
+//=======================================================================
+
+void StdMeshers_ProjectionUtils::InitVertexAssociation( const SMESH_Hypothesis* theHyp,
+                                                        TShapeShapeMap &        theAssociationMap)
+{
+  string hypName = theHyp->GetName();
+  if ( hypName == "ProjectionSource1D" ) {
+    const StdMeshers_ProjectionSource1D * hyp =
+      static_cast<const StdMeshers_ProjectionSource1D*>( theHyp );
+    if ( hyp->HasVertexAssociation() ) {
+      InsertAssociation( hyp->GetSourceVertex(),hyp->GetTargetVertex(),theAssociationMap);
+    }
+  }
+  else if ( hypName == "ProjectionSource2D" ) {
+    const StdMeshers_ProjectionSource2D * hyp =
+      static_cast<const StdMeshers_ProjectionSource2D*>( theHyp );
+    if ( hyp->HasVertexAssociation() ) {
+      InsertAssociation( hyp->GetSourceVertex(1),hyp->GetTargetVertex(1),theAssociationMap);
+      InsertAssociation( hyp->GetSourceVertex(2),hyp->GetTargetVertex(2),theAssociationMap);
+    }
+  }
+  else if ( hypName == "ProjectionSource3D" ) {
+    const StdMeshers_ProjectionSource3D * hyp =
+      static_cast<const StdMeshers_ProjectionSource3D*>( theHyp );
+    if ( hyp->HasVertexAssociation() ) {
+      InsertAssociation( hyp->GetSourceVertex(1),hyp->GetTargetVertex(1),theAssociationMap);
+      InsertAssociation( hyp->GetSourceVertex(2),hyp->GetTargetVertex(2),theAssociationMap);
+    }
+  }
+}
+
+//=======================================================================
+/*!
+ * \brief Inserts association theShape1 <-> theShape2 to TShapeShapeMap
+ * \param theShape1 - shape 1
+ * \param theShape2 - shape 2
+ * \param theAssociationMap - association map 
+ * \retval bool - true if there was no association for these shapes before
+ */
+//=======================================================================
+
+bool StdMeshers_ProjectionUtils::InsertAssociation( const TopoDS_Shape& theShape1,
+                                                    const TopoDS_Shape& theShape2,
+                                                    TShapeShapeMap &    theAssociationMap,
+                                                    const bool          theBidirectional)
+{
+  if ( !theShape1.IsNull() && !theShape2.IsNull() ) {
+    SHOW_VERTEX(theShape1,"Assoc ");
+    SHOW_VERTEX(theShape2," to ");
+    bool isNew = ( theAssociationMap.Bind( theShape1, theShape2 ));
+    if ( theBidirectional )
+      theAssociationMap.Bind( theShape2, theShape1 );
+    return isNew;
+  }
+  return false;
+}
+
+//=======================================================================
+//function : IsSubShape
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_ProjectionUtils::IsSubShape( const TopoDS_Shape& shape,
+                                             SMESH_Mesh*         aMesh )
+{
+  if ( shape.IsNull() || !aMesh )
+    return false;
+  return aMesh->GetMeshDS()->ShapeToIndex( shape );
+}
+
+//=======================================================================
+//function : IsSubShape
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_ProjectionUtils::IsSubShape( const TopoDS_Shape& shape,
+                                             const TopoDS_Shape& mainShape )
+{
+  if ( !shape.IsNull() && !mainShape.IsNull() )
+  {
+    for ( TopExp_Explorer exp( mainShape, shape.ShapeType());
+          exp.More();
+          exp.Next() )
+      if ( shape.IsSame( exp.Current() ))
+        return true;
+  }
+  SCRUTE((shape.IsNull()));
+  SCRUTE((mainShape.IsNull()));
+  return false;
+}
+
+
+//=======================================================================
+/*!
+ * \brief Finds an edge by its vertices in a main shape of the mesh
+ * \param aMesh - the mesh
+ * \param V1 - vertex 1
+ * \param V2 - vertex 2
+ * \retval TopoDS_Edge - found edge
+ */
+//=======================================================================
+
+TopoDS_Edge StdMeshers_ProjectionUtils::GetEdgeByVertices( SMESH_Mesh*          theMesh,
+                                                           const TopoDS_Vertex& theV1,
+                                                           const TopoDS_Vertex& theV2)
+{
+  if ( theMesh && !theV1.IsNull() && !theV2.IsNull() )
+  {
+    TopTools_ListIteratorOfListOfShape ancestorIt( theMesh->GetAncestors( theV1 ));
+    for ( ; ancestorIt.More(); ancestorIt.Next() )
+      if ( ancestorIt.Value().ShapeType() == TopAbs_EDGE )
+        for ( TopExp_Explorer expV ( ancestorIt.Value(), TopAbs_VERTEX );
+              expV.More();
+              expV.Next() )
+          if ( theV2.IsSame( expV.Current() ))
+            return TopoDS::Edge( ancestorIt.Value() );
+  }
+  return TopoDS_Edge();
+}
+
+//================================================================================
+/*!
+ * \brief Return another face sharing an edge
+ * \param aMesh - mesh
+ * \param edge - edge
+ * \param face - face
+ * \retval TopoDS_Face - found face
+ */
+//================================================================================
+
+TopoDS_Face StdMeshers_ProjectionUtils::GetNextFace( SMESH_Mesh*        mesh,
+                                                     const TopoDS_Edge& edge,
+                                                     const TopoDS_Face& face)
+{
+  if ( mesh && !edge.IsNull() && !face.IsNull() )
+  {
+    TopTools_ListIteratorOfListOfShape ancestorIt( mesh->GetAncestors( edge ));
+    for ( ; ancestorIt.More(); ancestorIt.Next() )
+      if ( ancestorIt.Value().ShapeType() == TopAbs_FACE &&
+           !face.IsSame( ancestorIt.Value() ))
+        return TopoDS::Face( ancestorIt.Value() );
+  }
+  return TopoDS_Face();
+  
+}
+
+//================================================================================
+/*!
+ * \brief Return a propagation edge
+ * \param aMesh - mesh
+ * \param theEdge - edge to find by propagation
+ * \param fromEdge - start edge for propagation
+ * \retval TopoDS_Edge - found edge
+ */
+//================================================================================
+
+TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh*        aMesh,
+                                                            const TopoDS_Edge& theEdge,
+                                                            const TopoDS_Edge& fromEdge)
+{
+  SMESH_IndexedMapOfShape aChain;
+  //aChain.Add(fromEdge);
+
+  // List of edges, added to chain on the previous cycle pass
+  TopTools_ListOfShape listPrevEdges;
+  listPrevEdges.Append(fromEdge/*.Oriented( TopAbs_FORWARD )*/);
+
+  // Collect all edges pass by pass
+  while (listPrevEdges.Extent() > 0) {
+    // List of edges, added to chain on this cycle pass
+    TopTools_ListOfShape listCurEdges;
+
+    // Find the next portion of edges
+    TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
+    for (; itE.More(); itE.Next()) {
+      TopoDS_Shape anE = itE.Value();
+
+      // Iterate on faces, having edge <anE>
+      TopTools_ListIteratorOfListOfShape itA (aMesh->GetAncestors(anE));
+      for (; itA.More(); itA.Next()) {
+        TopoDS_Shape aW = itA.Value();
+
+        // There are objects of different type among the ancestors of edge
+        if (aW.ShapeType() == TopAbs_WIRE) {
+          TopoDS_Shape anOppE;
+
+          BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
+          Standard_Integer nb = 1, found = 0;
+          TopTools_Array1OfShape anEdges (1,4);
+          for (; aWE.More(); aWE.Next(), nb++) {
+            if (nb > 4) {
+              found = 0;
+              break;
+            }
+            anEdges(nb) = aWE.Current();
+            if (anEdges(nb).IsSame(anE)) found = nb;
+          }
+
+          if (nb == 5 && found > 0) {
+            // Quadrangle face found, get an opposite edge
+            Standard_Integer opp = found + 2;
+            if (opp > 4) opp -= 4;
+            anOppE = anEdges(opp);
+
+            // add anOppE to aChain if ...
+            if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
+              // Add found edge to the chain oriented so that to
+              // have it co-directed with a forward MainEdge
+              TopAbs_Orientation ori = anE.Orientation();
+              if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
+                ori = TopAbs::Reverse( ori );
+              anOppE.Orientation( ori );
+              if ( anOppE.IsSame( theEdge ))
+                return TopoDS::Edge( anOppE );
+              aChain.Add(anOppE);
+              listCurEdges.Append(anOppE);
+            }
+          } // if (nb == 5 && found > 0)
+        } // if (aF.ShapeType() == TopAbs_WIRE)
+      } // for (; itF.More(); itF.Next())
+    } // for (; itE.More(); itE.Next())
+
+    listPrevEdges = listCurEdges;
+  } // while (listPrevEdges.Extent() > 0)
+
+  return TopoDS_Edge();
+}
+
+//================================================================================
+  /*!
+   * \brief Find corresponding nodes on two faces
+    * \param face1 - the first face
+    * \param mesh1 - mesh containing elements on the first face
+    * \param face2 - the second face
+    * \param mesh2 - mesh containing elements on the second face
+    * \param assocMap - map associating subshapes of the faces
+    * \param node1To2Map - map containing found matching nodes
+    * \retval bool - is a success
+   */
+//================================================================================
+
+bool StdMeshers_ProjectionUtils::
+FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
+                          SMESH_Mesh*            mesh1,
+                          const TopoDS_Face&     face2,
+                          SMESH_Mesh*            mesh2,
+                          const TShapeShapeMap & assocMap,
+                          TNodeNodeMap &         node1To2Map)
+{
+  SMESHDS_Mesh* meshDS1 = mesh1->GetMeshDS();
+  SMESHDS_Mesh* meshDS2 = mesh2->GetMeshDS();
+  
+  SMESH_MesherHelper helper1( *mesh1 );
+  SMESH_MesherHelper helper2( *mesh2 );
+
+  // Get corresponding submeshes and roughly check match of meshes
+
+  SMESHDS_SubMesh * SM2 = meshDS2->MeshElements( face2 );
+  SMESHDS_SubMesh * SM1 = meshDS1->MeshElements( face1 );
+  if ( !SM2 || !SM1 )
+    RETURN_BAD_RESULT("Empty submeshes");
+  if ( SM2->NbNodes()    != SM1->NbNodes() ||
+       SM2->NbElements() != SM1->NbElements() )
+    RETURN_BAD_RESULT("Different meshes on corresponding faces "
+                      << meshDS1->ShapeToIndex( face1 ) << " and "
+                      << meshDS2->ShapeToIndex( face2 ));
+  if ( SM2->NbElements() == 0 )
+    RETURN_BAD_RESULT("Empty submeshes");
+
+  helper1.SetSubShape( face1 );
+  helper2.SetSubShape( face2 );
+  if ( helper1.HasSeam() != helper2.HasSeam() )
+    RETURN_BAD_RESULT("Different faces' geometry");
+
+  // Data to call SMESH_MeshEditor::FindMatchingNodes():
+
+  // 1. Nodes of corresponding links:
+
+  // get 2 matching edges, not seam ones
+  TopoDS_Edge edge1, edge2;
+  TopExp_Explorer eE( OuterShape( face2, TopAbs_WIRE ), TopAbs_EDGE );
+  do {
+    edge2 = TopoDS::Edge( eE.Current() );
+    eE.Next();
+  } while ( BRep_Tool::IsClosed( edge2, face2 ) && eE.More());
+  if ( !assocMap.IsBound( edge2 ))
+    RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( edge2 ));
+  edge1 = TopoDS::Edge( assocMap( edge2 ));
+  if ( !IsSubShape( edge1, face1 ))
+    RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( edge1 ) <<
+                      " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 ));
+
+  // get 2 matching vertices
+  TopoDS_Shape V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 ));
+  if ( !assocMap.IsBound( V2 ))
+    RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
+  TopoDS_Shape V1 = assocMap( V2 );
+
+  // nodes on vertices
+  SMESHDS_SubMesh * vSM1 = meshDS1->MeshElements( V1 );
+  SMESHDS_SubMesh * vSM2 = meshDS2->MeshElements( V2 );
+  if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 )
+    RETURN_BAD_RESULT("Bad node submesh");
+  const SMDS_MeshNode* vNode1 = vSM1->GetNodes()->next();
+  const SMDS_MeshNode* vNode2 = vSM2->GetNodes()->next();
+
+  // nodes on edges linked with nodes on vertices
+  const SMDS_MeshNode* nullNode = 0;
+  vector< const SMDS_MeshNode*> eNode1( 2, nullNode );
+  vector< const SMDS_MeshNode*> eNode2( 2, nullNode );
+  int nbNodeToGet = 1;
+  if ( IsClosedEdge( edge1 ) || IsClosedEdge( edge2 ) )
+    nbNodeToGet = 2;
+  for ( int is2 = 0; is2 < 2; ++is2 )
+  {
+    TopoDS_Edge &     edge  = is2 ? edge2 : edge1;
+    SMESHDS_Mesh *    smDS  = is2 ? meshDS2 : meshDS1;
+    SMESHDS_SubMesh* edgeSM = smDS->MeshElements( edge );
+    // nodes linked with ones on vertices
+    const SMDS_MeshNode*           vNode = is2 ? vNode2 : vNode1;
+    vector< const SMDS_MeshNode*>& eNode = is2 ? eNode2 : eNode1;
+    int nbGotNode = 0;
+    SMDS_ElemIteratorPtr vElem = vNode->GetInverseElementIterator();
+    while ( vElem->more() && nbGotNode != nbNodeToGet ) {
+      const SMDS_MeshElement* elem = vElem->next();
+      if ( elem->GetType() == SMDSAbs_Edge && edgeSM->Contains( elem ))
+        eNode[ nbGotNode++ ] = 
+          ( elem->GetNode(0) == vNode ) ? elem->GetNode(1) : elem->GetNode(0);
+    }
+    if ( nbGotNode > 1 ) // sort found nodes by param on edge
+    {
+      SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
+      double u0 = helper->GetNodeU( edge, eNode[ 0 ]);
+      double u1 = helper->GetNodeU( edge, eNode[ 1 ]);
+      if ( u0 > u1 ) std::swap( eNode[ 0 ], eNode[ 1 ]);
+    }
+    if ( nbGotNode == 0 )
+      RETURN_BAD_RESULT("Found no nodes on edge " << smDS->ShapeToIndex( edge ) <<
+                        " linked to " << vNode );
+  }
+
+  // 2. face sets
+
+  set<const SMDS_MeshElement*> Elems1, Elems2;
+  for ( int is2 = 0; is2 < 2; ++is2 )
+  {
+    set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
+    SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
+    SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
+    const TopoDS_Face &             face = is2 ? face2 : face1;
+    SMDS_ElemIteratorPtr eIt = sm->GetElements();
+
+    if ( !helper->IsSeamShape( is2 ? edge2 : edge1 ))
+    {
+      while ( eIt->more() ) elems.insert( eIt->next() );
+    }
+    else
+    {
+      // there is only seam edge in a face, i.e. it is a sphere.
+      // FindMatchingNodes() will not know which way to go from any edge.
+      // So we ignore all faces having nodes on edges or vertices except
+      // one of faces sharing current start nodes
+
+      // find a face to keep
+      const SMDS_MeshElement* faceToKeep = 0;
+      const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+      const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
+      std::map<int,const SMDS_MeshElement*> inSet, notInSet;
+
+      const SMDS_MeshElement* f1 =
+        SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet );
+      if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
+      SMESH_MeshEditor::Insert( f1, notInSet );
+
+      const SMDS_MeshElement* f2 =
+        SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet );
+      if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
+
+      // select a face with less UV of vNode
+      const SMDS_MeshNode* notSeamNode[2] = {0, 0};
+      for ( int iF = 0; iF < 2; ++iF ) {
+        const SMDS_MeshElement* f = ( iF ? f2 : f1 );
+        for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
+          const SMDS_MeshNode* node = f->GetNode( i );
+          if ( !helper->IsSeamShape( node->GetPosition()->GetShapeId() ))
+            notSeamNode[ iF ] = node;
+        }
+      }
+      gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
+      gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
+      if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
+        faceToKeep = f2;
+      else
+        faceToKeep = f1;
+
+      // fill elem set
+      elems.insert( faceToKeep );
+      while ( eIt->more() ) {
+        const SMDS_MeshElement* f = eIt->next();
+        int nbNodes = f->NbNodes();
+        if ( f->IsQuadratic() )
+          nbNodes /= 2;
+        bool onBnd = false;
+        for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
+          const SMDS_MeshNode* node = f->GetNode( i );
+          onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
+        }
+        if ( !onBnd )
+          elems.insert( f );
+      }
+    } // case on a sphere
+  } // loop on 2 faces
+
+  node1To2Map.clear();
+  int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
+                                                 vNode1, vNode2,
+                                                 eNode1[0], eNode2[0],
+                                                 node1To2Map);
+  if ( res != SMESH_MeshEditor::SEW_OK )
+    RETURN_BAD_RESULT("FindMatchingNodes() result " << res );
+
+
+  // On a sphere, add matching nodes on the edge
+
+  if ( helper1.IsSeamShape( edge1 ))
+  {
+    // sort nodes on edges by param on edge
+    map< double, const SMDS_MeshNode* > u2nodesMaps[2];
+    for ( int is2 = 0; is2 < 2; ++is2 )
+    {
+      TopoDS_Edge &     edge  = is2 ? edge2 : edge1;
+      SMESHDS_Mesh *    smDS  = is2 ? meshDS2 : meshDS1;
+      SMESHDS_SubMesh* edgeSM = smDS->MeshElements( edge );
+      map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[ is2 ];
+
+      SMDS_NodeIteratorPtr nIt = edgeSM->GetNodes();
+      while ( nIt->more() ) {
+        const SMDS_MeshNode* node = nIt->next();
+        const SMDS_EdgePosition* pos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
+      }
+      if ( pos2nodes.size() != edgeSM->NbNodes() )
+        RETURN_BAD_RESULT("Equal params of nodes on edge "
+                          << smDS->ShapeToIndex( edge ) << " of face " << is2 );
+    }
+    if ( u2nodesMaps[0].size() != u2nodesMaps[1].size() )
+      RETURN_BAD_RESULT("Different nb of new nodes on edges or wrong params");
+
+    // compare edge orientation
+    double u1 = helper1.GetNodeU( edge1, vNode1 );
+    double u2 = helper2.GetNodeU( edge2, vNode2 );
+    bool isFirst1 = ( u1 < u2nodesMaps[0].begin()->first );
+    bool isFirst2 = ( u2 < u2nodesMaps[1].begin()->first );
+    bool reverse ( isFirst1 != isFirst2 );
+
+    // associate matching nodes
+    map< double, const SMDS_MeshNode* >::iterator u_Node1, u_Node2, end1;
+    map< double, const SMDS_MeshNode* >::reverse_iterator uR_Node2;
+    u_Node1 = u2nodesMaps[0].begin();
+    u_Node2 = u2nodesMaps[1].begin();
+    uR_Node2 = u2nodesMaps[1].rbegin();
+    end1 = u2nodesMaps[0].end();
+    for ( ; u_Node1 != end1; ++u_Node1 ) {
+      const SMDS_MeshNode* n1 = u_Node1->second;
+      const SMDS_MeshNode* n2 = ( reverse ? (uR_Node2++)->second : (u_Node2++)->second );
+      node1To2Map.insert( make_pair( n1, n2 ));
+    }
+
+    // associate matching nodes on the last vertices
+    V2 = TopExp::LastVertex( TopoDS::Edge( edge2 ));
+    if ( !assocMap.IsBound( V2 ))
+      RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
+    V1 = assocMap( V2 );
+    vSM1 = meshDS1->MeshElements( V1 );
+    vSM2 = meshDS2->MeshElements( V2 );
+    if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 )
+      RETURN_BAD_RESULT("Bad node submesh");
+    vNode1 = vSM1->GetNodes()->next();
+    vNode2 = vSM2->GetNodes()->next();
+    node1To2Map.insert( make_pair( vNode1, vNode2 ));
+  }
+  
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Check if the first and last vertices of an edge are the same
+ * \param anEdge - the edge to check
+ * \retval bool - true if same
+ */
+//================================================================================
+
+bool StdMeshers_ProjectionUtils::IsClosedEdge( const TopoDS_Edge& anEdge )
+{
+  return TopExp::FirstVertex( anEdge ).IsSame( TopExp::LastVertex( anEdge ));
+}
+
+//================================================================================
+  /*!
+   * \brief Return any subshape of a face belonging to the outer wire
+    * \param face - the face
+    * \param type - type of subshape to return
+    * \retval TopoDS_Shape - the found subshape
+   */
+//================================================================================
+
+TopoDS_Shape StdMeshers_ProjectionUtils::OuterShape( const TopoDS_Face& face,
+                                                     TopAbs_ShapeEnum   type)
+{
+  TopExp_Explorer exp( BRepTools::OuterWire( face ), type );
+  if ( exp.More() )
+    return exp.Current();
+  return TopoDS_Shape();
+}
+
+//================================================================================
+  /*!
+   * \brief Check that submeshis is computed and try to compute it if is not
+    * \param sm - submesh to compute
+    * \param iterationNb - int used to stop infinite recursive call
+    * \retval bool - true if computed
+   */
+//================================================================================
+
+bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iterationNb)
+{
+  if ( iterationNb > 10 )
+    RETURN_BAD_RESULT("Infinite recursive projection");
+  if ( !sm )
+    RETURN_BAD_RESULT("NULL submesh");
+  if ( sm->IsMeshComputed() )
+    return true;
+
+  SMESH_Mesh* mesh = sm->GetFather();
+  SMESH_Gen* gen   = mesh->GetGen();
+  SMESH_Algo* algo = gen->GetAlgo( *mesh, sm->GetSubShape() );
+  if ( !algo )
+    RETURN_BAD_RESULT("No algo assigned to submesh " << sm->GetId());
+
+  string algoType = algo->GetName();
+  if ( algoType.substr(0, 11) != "Projection_")
+    return gen->Compute( *mesh, sm->GetSubShape() );
+
+  // try to compute source mesh
+
+  const list <const SMESHDS_Hypothesis *> & hyps =
+    algo->GetUsedHypothesis( *mesh, sm->GetSubShape() );
+
+  TopoDS_Shape srcShape;
+  SMESH_Mesh* srcMesh = 0;
+  list <const SMESHDS_Hypothesis*>::const_iterator hIt = hyps.begin();
+  for ( ; srcShape.IsNull() && hIt != hyps.end(); ++hIt ) {
+    string hypName = (*hIt)->GetName();
+    if ( hypName == "ProjectionSource1D" ) {
+      const StdMeshers_ProjectionSource1D * hyp =
+        static_cast<const StdMeshers_ProjectionSource1D*>( *hIt );
+      srcShape = hyp->GetSourceEdge();
+      srcMesh = hyp->GetSourceMesh();
+    }
+    else if ( hypName == "ProjectionSource2D" ) {
+      const StdMeshers_ProjectionSource2D * hyp =
+        static_cast<const StdMeshers_ProjectionSource2D*>( *hIt );
+      srcShape = hyp->GetSourceFace();
+      srcMesh = hyp->GetSourceMesh();
+    }
+    else if ( hypName == "ProjectionSource3D" ) {
+      const StdMeshers_ProjectionSource3D * hyp =
+        static_cast<const StdMeshers_ProjectionSource3D*>( *hIt );
+      srcShape = hyp->GetSource3DShape();
+      srcMesh = hyp->GetSourceMesh();
+    }
+  }
+  if ( srcShape.IsNull() ) // no projection source defined
+    return gen->Compute( *mesh, sm->GetSubShape() );
+
+  if ( srcShape.IsSame( sm->GetSubShape() ))
+    RETURN_BAD_RESULT("Projection from self");
+    
+  if ( !srcMesh )
+    srcMesh = mesh;
+
+  return MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 );
+}
+
+//================================================================================
+  /*!
+   * \brief Count nb of subshapes
+    * \param shape - the shape
+    * \param type - the type of subshapes to count
+    * \retval int - the calculated number
+   */
+//================================================================================
+
+int StdMeshers_ProjectionUtils::Count(const TopoDS_Shape&    shape,
+                                      const TopAbs_ShapeEnum type,
+                                      const bool             ignoreSame)
+{
+  if ( ignoreSame ) {
+    TopTools_IndexedMapOfShape map;
+    TopExp::MapShapes( shape, type, map );
+    return map.Extent();
+  }
+  else {
+    int nb = 0;
+    for ( TopExp_Explorer exp( shape, type ); exp.More(); exp.Next() )
+      ++nb;
+    return nb;
+  }
+}
+
+      // bull shit
+//       Standard_Real f1,l1, f2,l2;
+//       BRep_Tool::Range( edge1, f1,l1 );
+//       BRep_Tool::Range( edge2, f2,l2 );
+//       BRepAdaptor_Curve e1( edge1 ), e2( edge2 );
+//       gp_Pnt pf1, pf2;
+//       gp_Vec dirX1, dirX2; // 1st derivatives
+//       e1.D1( f1, pf1, dirX1 );
+//       e2.D1( f2, pf2, dirX2 );
+//       gp_Pnt pm1 = e1.Value( 0.5 * ( f1 + l1 ));
+//       gp_Pnt pm2 = e2.Value( 0.5 * ( f2 + l2 ));
+//       gp_Vec dirZ1( pf1, pm1 ), dirZ2( pf2, pm2 );
+//       gp_Trsf trsf;
+//       gp_Ax3 fromSys( pf1, dirZ1, dirX1 ), toSys( pf2, dirZ2, dirX2 );
+//       trsf.SetTransformation( fromSys, toSys );
+//       dirX1.Transform( trsf );
+//       bool reverse = ( dirX1 * dirX2 < 0 );
+//       if ( reverse ) edge2.Reverse();
diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.hxx b/src/StdMeshers/StdMeshers_ProjectionUtils.hxx
new file mode 100644 (file)
index 0000000..52d11dc
--- /dev/null
@@ -0,0 +1,198 @@
+//  SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_ProjectionUtils.hxx
+// Created   : Thu Oct 26 15:37:24 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#ifndef StdMeshers_ProjectionUtils_HeaderFile
+#define StdMeshers_ProjectionUtils_HeaderFile
+
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Face.hxx>
+
+#include <list>
+#include <map>
+
+class TopoDS_Shape;
+class SMDS_MeshNode;
+class SMESH_Mesh;
+class SMESH_Hypothesis;
+class SMESH_subMesh;
+
+/*!
+ * \brief Class encapsulating methods common to Projection algorithms
+ */
+class StdMeshers_ProjectionUtils
+{
+ public:
+
+  typedef TopTools_DataMapOfShapeShape                         TShapeShapeMap;
+  typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
+
+  /*!
+   * \brief Looks for association of all subshapes of two shapes
+    * \param theShape1 - shape 1
+    * \param theMesh1 - mesh built on shape 1
+    * \param theShape2 - shape 2
+    * \param theMesh2 - mesh built on shape 2
+    * \param theAssociation - association map to be filled that may
+    *                         contain association of one or two pairs of vertices
+    * \retval bool - true if association found
+   */
+  static bool FindSubShapeAssociation(const TopoDS_Shape& theShape1,
+                                      SMESH_Mesh*         theMesh1,
+                                      const TopoDS_Shape& theShape2,
+                                      SMESH_Mesh*         theMesh2,
+                                      TShapeShapeMap &    theAssociationMap);
+
+  /*!
+   * \brief Find association of edges of faces
+    * \param face1 - face 1
+    * \param VV1 - vertices of face 1
+    * \param face2 - face 2
+    * \param VV2 - vertices of face 2 associated with oned of face 1
+    * \param edges1 - out list of edges of face 1
+    * \param edges2 - out list of edges of face 2
+    * \retval int - nb of edges in an outer wire in a success case, else zero
+   */
+  static int FindFaceAssociation(const TopoDS_Face&    face1,
+                                 TopoDS_Vertex         VV1[2],
+                                 const TopoDS_Face&    face2,
+                                 TopoDS_Vertex         VV2[2],
+                                 list< TopoDS_Edge > & edges1,
+                                 list< TopoDS_Edge > & edges2);
+
+  /*!
+   * \brief Insert vertex association defined by a hypothesis into a map
+    * \param theHyp - hypothesis
+    * \param theAssociationMap - association map
+   */
+  static void InitVertexAssociation( const SMESH_Hypothesis* theHyp,
+                                     TShapeShapeMap &        theAssociationMap);
+
+  /*!
+   * \brief Inserts association theShape1 <-> theShape2 to TShapeShapeMap
+    * \param theShape1 - shape 1
+    * \param theShape2 - shape 2
+    * \param theAssociationMap - association map 
+    * \param theBidirectional - if false, inserts theShape1 -> theShape2 association
+    * \retval bool - true if there was no association for these shapes before
+   */
+  static bool InsertAssociation( const TopoDS_Shape& theShape1,
+                                 const TopoDS_Shape& theShape2,
+                                 TShapeShapeMap &    theAssociationMap,
+                                 const bool          theBidirectional=true);
+
+  static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh );
+
+  static bool IsSubShape( const TopoDS_Shape& shape, const TopoDS_Shape& mainShape );
+
+  /*!
+   * \brief Finds an edge by its vertices in a main shape of the mesh
+    * \param aMesh - the mesh
+    * \param V1 - vertex 1
+    * \param V2 - vertex 2
+    * \retval TopoDS_Edge - found edge
+   */
+  static TopoDS_Edge GetEdgeByVertices( SMESH_Mesh*          aMesh,
+                                        const TopoDS_Vertex& V1,
+                                        const TopoDS_Vertex& V2);
+                                        
+  /*!
+   * \brief Return another face sharing an edge
+    * \param aMesh - mesh
+    * \param edge - edge
+    * \param face - face
+    * \retval TopoDS_Face - found face
+   */
+  static TopoDS_Face GetNextFace( SMESH_Mesh*        aMesh,
+                                  const TopoDS_Edge& edge,
+                                  const TopoDS_Face& face);
+
+  /*!
+   * \brief Return an oriented propagation edge
+    * \param aMesh - mesh
+    * \param fromEdge - start edge for propagation
+    * \retval TopoDS_Edge - found edge
+   */
+  static TopoDS_Edge GetPropagationEdge( SMESH_Mesh*        aMesh,
+                                         const TopoDS_Edge& anEdge,
+                                         const TopoDS_Edge& fromEdge);
+
+  /*!
+   * \brief Find corresponding nodes on two faces
+    * \param face1 - the first face
+    * \param mesh1 - mesh containing elements on the first face
+    * \param face2 - the second face
+    * \param mesh2 - mesh containing elements on the second face
+    * \param assocMap - map associating subshapes of the faces
+    * \param nodeIn2OutMap - map containing found matching nodes
+    * \retval bool - is a success
+   */
+  static bool FindMatchingNodesOnFaces( const TopoDS_Face&     face1,
+                                        SMESH_Mesh*            mesh1,
+                                        const TopoDS_Face&     face2,
+                                        SMESH_Mesh*            mesh2,
+                                        const TShapeShapeMap & assocMap,
+                                        TNodeNodeMap &         nodeIn2OutMap);
+  /*!
+   * \brief Check if the first and last vertices of an edge are the same
+    * \param anEdge - the edge to check
+    * \retval bool - true if same
+   */
+  static bool IsClosedEdge( const TopoDS_Edge& anEdge );
+
+  /*!
+   * \brief Return any subshape of a face belonging to the outer wire
+    * \param face - the face
+    * \param type - type of subshape to return
+    * \retval TopoDS_Shape - the found subshape
+   */
+  static TopoDS_Shape OuterShape( const TopoDS_Face& face,
+                                  TopAbs_ShapeEnum   type);
+
+  /*!
+   * \brief Check that submeshis is computed and try to compute it if is not
+    * \param sm - submesh to compute
+    * \param iterationNb - int used to stop infinite recursive call
+    * \retval bool - true if computed
+   */
+  static bool MakeComputed(SMESH_subMesh * sm, const int iterationNb = 0);
+
+  /*!
+   * \brief Count nb of subshapes
+    * \param shape - the shape
+    * \param type - the type of subshapes to count
+    * \param ignoreSame - if true, use map not to count same shapes, esle use explorer
+    * \retval int - the calculated number
+   */
+  static int Count(const TopoDS_Shape&    shape,
+                   const TopAbs_ShapeEnum type,
+                   const bool             ignoreSame);
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_Projection_1D.cxx b/src/StdMeshers/StdMeshers_Projection_1D.cxx
new file mode 100644 (file)
index 0000000..acf8966
--- /dev/null
@@ -0,0 +1,362 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_Projection_1D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_Projection_1D.hxx"
+
+#include "StdMeshers_ProjectionSource1D.hxx"
+#include "StdMeshers_ProjectionUtils.hxx"
+
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_MeshElement.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESHDS_SubMesh.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Gen.hxx"
+
+#include <BRepAdaptor_Curve.hxx>
+#include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <TopoDS.hxx>
+#include <gp_Pnt.hxx>
+
+#include "utilities.h"
+
+
+using namespace std;
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+
+typedef StdMeshers_ProjectionUtils TAssocTool;
+
+//=======================================================================
+//function : StdMeshers_Projection_1D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_Projection_1D::StdMeshers_Projection_1D(int hypId, int studyId, SMESH_Gen* gen)
+  :SMESH_1D_Algo(hypId, studyId, gen)
+{
+  _name = "Projection_1D";
+  _shapeType = (1 << TopAbs_EDGE);     // 1 bit per shape type
+
+  _compatibleHypothesis.push_back("ProjectionSource1D");
+  _sourceHypo = 0;
+}
+
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_Projection_1D::~StdMeshers_Projection_1D()
+{}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_1D::CheckHypothesis(SMESH_Mesh&                          aMesh,
+                                               const TopoDS_Shape&                  aShape,
+                                               SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  _sourceHypo = 0;
+  list <const SMESHDS_Hypothesis * >::const_iterator itl;
+
+  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();
+
+  aStatus = SMESH_Hypothesis::HYP_OK;
+
+  if (hypName == "ProjectionSource1D")
+  {
+    _sourceHypo = static_cast<const StdMeshers_ProjectionSource1D *>(theHyp);
+
+    // Check hypo parameters
+
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    SMESH_Mesh* tgtMesh = & aMesh;
+    if ( !srcMesh )
+      srcMesh = tgtMesh;
+
+    // check vertices
+    if ( _sourceHypo->HasVertexAssociation() )
+    {
+      // source and target vertices
+      if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh ) ||
+           !TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh ) ||
+           !TAssocTool::IsSubShape( _sourceHypo->GetTargetVertex(), aShape )  ||
+           !TAssocTool::IsSubShape( _sourceHypo->GetSourceVertex(),
+                                    _sourceHypo->GetSourceEdge() ))
+        aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
+    }
+    // check source edge
+    if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh ))
+      aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
+  }
+  else
+  {
+    aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  }
+  return ( aStatus == HYP_OK );
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
+{
+  if ( !_sourceHypo )
+    return false;
+
+  TopoDS_Edge tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
+  TopoDS_Edge srcEdge = TopoDS::Edge( _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD));
+
+  TopoDS_Vertex tgtV[2], srcV[2];
+  TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
+  TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
+
+  SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); 
+  SMESH_Mesh * tgtMesh = & theMesh;
+  if ( !srcMesh )
+    srcMesh = tgtMesh;
+
+  SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
+
+  // ---------------------------
+  // Make subshapes association
+  // ---------------------------
+
+  TAssocTool::TShapeShapeMap shape2ShapeMap;
+  TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
+  if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcEdge, srcMesh,
+                                             shape2ShapeMap) )
+    RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+
+  // ----------------------------------------------
+  // Assure that mesh on a source edge is computed
+  // ----------------------------------------------
+
+  SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
+  //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtEdge );
+
+  if ( tgtMesh == srcMesh ) {
+    if ( !TAssocTool::MakeComputed( srcSubMesh ))
+      RETURN_BAD_RESULT("Impossible to compute the source mesh");
+  }
+  else {
+    if ( !srcSubMesh->IsMeshComputed() )
+      RETURN_BAD_RESULT("Source mesh is not computed");
+  }
+  // -----------------------------------------------
+  // Find out nodes distribution on the source edge
+  // -----------------------------------------------
+
+  double srcLength = EdgeLength( srcEdge );
+  double tgtLength = EdgeLength( tgtEdge );
+  
+  vector< double > params; // sorted parameters of nodes on the source edge
+  if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
+    RETURN_BAD_RESULT("Bad node params on the source edge");
+
+  int i, nbNodes = params.size();
+
+  vector< double > lengths( nbNodes - 1 ); // lengths of segments of the source edge
+  if ( srcLength > 0 )
+  {
+    BRepAdaptor_Curve curveAdaptor( srcEdge );
+    for ( i = 1; i < nbNodes; ++i )
+      lengths[ i-1 ] = GCPnts_AbscissaPoint::Length( curveAdaptor, params[i-1], params[i]);
+  }
+  else // degenerated source edge
+  {
+    for ( i = 1; i < nbNodes; ++i )
+      lengths[ i-1 ] = params[i] - params[i-1];
+    srcLength = params.back() - params[0];
+  }
+
+  bool reverse = ( srcV[0].IsSame( shape2ShapeMap( tgtV[1] )));
+  if ( shape2ShapeMap.IsBound( tgtEdge )) // case of closed edge
+    reverse = ( shape2ShapeMap( tgtEdge ).Orientation() == TopAbs_REVERSED );
+  if ( reverse ) // reverse lengths of segments
+    std::reverse( lengths.begin(), lengths.end() );
+
+  // ----------
+  // Make mesh
+  // ----------
+
+  // vector of target nodes
+  vector< const SMDS_MeshNode* > nodes ( nbNodes );
+
+  // Get the first and last nodes
+  // -----------------------------
+
+  SMESHDS_SubMesh* smV0 = meshDS->MeshElements( tgtV[0] );
+  SMESHDS_SubMesh* smV1 = meshDS->MeshElements( tgtV[1] );
+  if ( !smV0 || !smV1 )
+    RETURN_BAD_RESULT("No submeshes on vertices");
+
+  SMDS_NodeIteratorPtr nItV0 = smV0->GetNodes();
+  SMDS_NodeIteratorPtr nItV1 = smV1->GetNodes();
+  if ( !nItV0->more() || !nItV1->more() )
+    RETURN_BAD_RESULT("No nodes on vertices");
+
+  nodes.front() = nItV0->next();
+  nodes.back()  = nItV1->next();
+
+  // Compute parameters on the target edge and make internal nodes
+  // --------------------------------------------------------------
+
+  vector< double > tgtParams( nbNodes );
+
+  BRep_Tool::Range( tgtEdge, tgtParams.front(), tgtParams.back() );
+  if ( tgtLength <= 0 )
+    tgtLength = tgtParams.back() - tgtParams.front();
+  double dl = tgtLength / srcLength;
+
+  if ( tgtLength > 0 )
+  {
+    BRepAdaptor_Curve curveAdaptor( tgtEdge );
+
+    // compute params on internal nodes
+    for ( i = 1; i < nbNodes - 1; ++i )
+    {
+      // computes a point on a <curveAdaptor> at the given distance
+      // from the point at given parameter.
+      GCPnts_AbscissaPoint Discret( curveAdaptor, dl * lengths[ i-1 ], tgtParams[ i-1 ] );
+      if ( !Discret.IsDone() )
+        RETURN_BAD_RESULT(" GCPnts_AbscissaPoint failed");
+      tgtParams[ i ] = Discret.Parameter();
+    }
+    // make internal nodes 
+    for ( i = 1; i < nbNodes - 1; ++i )
+    {
+      gp_Pnt P = curveAdaptor.Value( tgtParams[ i ]);
+      SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+      meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
+      nodes[ i ] = node;
+    }
+  }
+  else // degenerated target edge
+  {
+    // compute params and make internal nodes
+    gp_Pnt P = BRep_Tool::Pnt( tgtV[0] );
+
+    for ( i = 1; i < nbNodes - 1; ++i )
+    {
+      SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+      tgtParams[ i ] = tgtParams[ i-1 ] + dl * lengths[ i-1 ];
+      meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
+      nodes[ i ] = node;
+    }
+  }
+
+  // Quadratic mesh?
+  // ----------------
+
+  bool quadratic = false;
+  SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
+  if ( elemIt->more() )
+    quadratic = elemIt->next()->IsQuadratic();
+  else {
+    SMDS_NodeIteratorPtr nodeIt = srcSubMesh->GetSubMeshDS()->GetNodes();
+    while ( nodeIt->more() && !quadratic )
+      quadratic = SMESH_MesherHelper::IsMedium( nodeIt->next() );
+  }
+  // enough nodes to make all edges quadratic?
+  if ( quadratic && ( nbNodes < 3 || ( nbNodes % 2 != 1 )))
+    RETURN_BAD_RESULT("Wrong nb nodes to make quadratic mesh");
+
+  // Create edges
+  // -------------
+
+  SMDS_MeshElement* edge = 0;
+  int di = quadratic ? 2 : 1;
+  for ( i = di; i < nbNodes; i += di)
+  {
+    if ( quadratic )
+      edge = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
+    else
+      edge = meshDS->AddEdge( nodes[i-1], nodes[i] );
+    meshDS->SetMeshElementOnShape(edge, tgtEdge );
+  }
+
+  return true;
+}
+
+//=============================================================================
+/*!
+ * \brief Sets a default event listener to submesh of the source edge
+  * \param subMesh - submesh where algo is set
+ *
+ * This method is called when a submesh gets HYP_OK algo_state.
+ * After being set, event listener is notified on each event of a submesh.
+ * Arranges that CLEAN event is translated from source submesh to
+ * the submesh
+ */
+//=============================================================================
+
+void StdMeshers_Projection_1D::SetEventListener(SMESH_subMesh* subMesh)
+{
+  if ( _sourceHypo && ! _sourceHypo->GetSourceEdge().IsNull() )
+  {
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    if ( !srcMesh )
+      srcMesh = subMesh->GetFather();
+
+    SMESH_subMesh* srcEdgeSM =
+      srcMesh->GetSubMesh( _sourceHypo->GetSourceEdge() );
+
+    if ( srcEdgeSM != subMesh )
+      subMesh->SetEventListener( new SMESH_subMeshEventListener(),
+                                 SMESH_subMeshEventListenerData::MakeData( subMesh ),
+                                 srcEdgeSM );
+  }
+}
+  
diff --git a/src/StdMeshers/StdMeshers_Projection_1D.hxx b/src/StdMeshers/StdMeshers_Projection_1D.hxx
new file mode 100644 (file)
index 0000000..3134580
--- /dev/null
@@ -0,0 +1,64 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_Projection_1D.hxx
+//  Module : SMESH
+
+#ifndef _SMESH_Projection_1D_HXX_
+#define _SMESH_Projection_1D_HXX_
+
+#include "SMESH_1D_Algo.hxx"
+
+
+class StdMeshers_ProjectionSource1D;
+
+class StdMeshers_Projection_1D: public SMESH_1D_Algo
+{
+public:
+  StdMeshers_Projection_1D(int hypId, int studyId, SMESH_Gen* gen);
+  virtual ~StdMeshers_Projection_1D();
+
+  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);
+
+  /*!
+   * \brief Sets a default event listener to submesh of the source edge
+   *  \param whenSetToSubMesh - submesh where algo is set
+   *
+   * After being set, event listener is notified on each event of a submesh.
+   * This method is called when a submesh gets HYP_OK algo_state.
+   * Arranges that CLEAN event is translated from source submesh to
+   * the whenSetToSubMesh submesh.
+   */
+  virtual void SetEventListener(SMESH_subMesh* whenSetToSubMesh);
+  
+protected:
+
+  const StdMeshers_ProjectionSource1D* _sourceHypo;
+
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx
new file mode 100644 (file)
index 0000000..5e10f6d
--- /dev/null
@@ -0,0 +1,638 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_Projection_2D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_Projection_2D.hxx"
+
+#include "StdMeshers_ProjectionSource2D.hxx"
+#include "StdMeshers_ProjectionUtils.hxx"
+
+#include "SMESHDS_Hypothesis.hxx"
+#include "SMESHDS_SubMesh.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_Pattern.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+#include "SMDS_EdgePosition.hxx"
+
+#include "utilities.h"
+
+#include <TopExp.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <BRep_Tool.hxx>
+
+
+
+using namespace std;
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+
+typedef StdMeshers_ProjectionUtils TAssocTool;
+
+//=======================================================================
+//function : StdMeshers_Projection_2D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_Projection_2D::StdMeshers_Projection_2D(int hypId, int studyId, SMESH_Gen* gen)
+  :SMESH_2D_Algo(hypId, studyId, gen)
+{
+  _name = "Projection_2D";
+  _shapeType = (1 << TopAbs_FACE);     // 1 bit per shape type
+
+  _compatibleHypothesis.push_back("ProjectionSource2D");
+  _sourceHypo = 0;
+}
+
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_Projection_2D::~StdMeshers_Projection_2D()
+{}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_2D::CheckHypothesis(SMESH_Mesh&                          theMesh,
+                                               const TopoDS_Shape&                  theShape,
+                                               SMESH_Hypothesis::Hypothesis_Status& theStatus)
+{
+  list <const SMESHDS_Hypothesis * >::const_iterator itl;
+
+  const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(theMesh, theShape);
+  if ( hyps.size() == 0 )
+  {
+    theStatus = HYP_MISSING;
+    return false;  // can't work with no hypothesis
+  }
+
+  if ( hyps.size() > 1 )
+  {
+    theStatus = HYP_ALREADY_EXIST;
+    return false;
+  }
+
+  const SMESHDS_Hypothesis *theHyp = hyps.front();
+
+  string hypName = theHyp->GetName();
+
+  theStatus = HYP_OK;
+
+  if (hypName == "ProjectionSource2D")
+  {
+    _sourceHypo = static_cast<const StdMeshers_ProjectionSource2D *>(theHyp);
+
+    // Check hypo parameters
+
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    SMESH_Mesh* tgtMesh = & theMesh;
+    if ( !srcMesh )
+      srcMesh = tgtMesh;
+
+    // check vertices
+    if ( _sourceHypo->HasVertexAssociation() )
+    {
+      // source vertices
+      TopoDS_Shape edge = TAssocTool::GetEdgeByVertices
+        ( srcMesh, _sourceHypo->GetSourceVertex(1), _sourceHypo->GetSourceVertex(2) );
+      if ( edge.IsNull() ||
+           !TAssocTool::IsSubShape( edge, srcMesh ) ||
+           !TAssocTool::IsSubShape( edge, _sourceHypo->GetSourceFace() ))
+      {
+        SCRUTE((edge.IsNull()));
+        SCRUTE((TAssocTool::IsSubShape( edge, srcMesh )));
+        SCRUTE((TAssocTool::IsSubShape( edge, _sourceHypo->GetSourceFace() )));
+        theStatus = HYP_BAD_PARAMETER;
+      }
+      else
+      {
+        // target vertices
+        edge = TAssocTool::GetEdgeByVertices
+          ( tgtMesh, _sourceHypo->GetTargetVertex(1), _sourceHypo->GetTargetVertex(2) );
+        if ( edge.IsNull() ||
+             !TAssocTool::IsSubShape( edge, tgtMesh ) ||
+             !TAssocTool::IsSubShape( edge, theShape ))
+        {
+          SCRUTE((edge.IsNull()));
+          SCRUTE((TAssocTool::IsSubShape( edge, tgtMesh )));
+          SCRUTE((TAssocTool::IsSubShape( edge, theShape )));
+          theStatus = HYP_BAD_PARAMETER;
+        }
+      }
+    }
+    // check a source face
+    if ( !TAssocTool::IsSubShape( _sourceHypo->GetSourceFace(), srcMesh )) {
+      MESSAGE("Bad source face"); 
+      theStatus = HYP_BAD_PARAMETER;
+    }
+  }
+  else
+  {
+    theStatus = HYP_INCOMPATIBLE;
+  }
+  return ( theStatus == HYP_OK );
+}
+
+namespace {
+
+
+  //================================================================================
+  /*!
+   * \brief define if a node is new or old
+    * \param node - node to check
+    * \retval bool - true if the node existed before Compute() is called
+   */
+  //================================================================================
+
+  bool isOldNode( const SMDS_MeshNode* node )
+  {
+    // old nodes are shared by edges and new ones are shared
+    // only by faces created by mapper
+    bool isOld = false;
+    SMDS_ElemIteratorPtr invElem = node->GetInverseElementIterator();
+    while ( !isOld && invElem->more() )
+      isOld = ( invElem->next()->GetType() == SMDSAbs_Edge );
+    return isOld;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Class to remove mesh built by pattern mapper on edges
+   * and vertices in the case of failure of projection algo.
+   * It does it's job at destruction
+   */
+  //================================================================================
+
+  class MeshCleaner {
+    SMESH_subMesh* sm;
+  public:
+    MeshCleaner( SMESH_subMesh* faceSubMesh ): sm(faceSubMesh) {}
+    ~MeshCleaner() { Clean(sm); }
+    void Release() { sm = 0; } // mesh will not be removed
+    static void Clean( SMESH_subMesh* sm )
+    {
+      if ( !sm ) return;
+      switch ( sm->GetSubShape().ShapeType() ) {
+      case TopAbs_VERTEX:
+      case TopAbs_EDGE: {
+        SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
+        SMESHDS_Mesh* mesh = sm->GetFather()->GetMeshDS();
+        while ( nIt->more() ) {
+          const SMDS_MeshNode* node = nIt->next();
+          if ( !isOldNode( node ) )
+            mesh->RemoveNode( node );
+        }
+        // do not break but iterate over DependsOn()
+      }
+      default:
+        const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
+        map< int, SMESH_subMesh * >::const_iterator i_sm = subSM.begin();
+        for ( ; i_sm != subSM.end(); ++i_sm )
+          Clean( i_sm->second );
+      }
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief find new nodes belonging to one free border of mesh on face
+    * \param sm - submesh on edge or vertex containg nodes to choose from
+    * \param face - the face bound the submesh
+    * \param u2nodes - map to fill with nodes
+    * \param seamNodes - set of found nodes
+    * \retval bool - is a success
+   */
+  //================================================================================
+
+  bool getBoundaryNodes ( SMESH_subMesh*                        sm,
+                          const TopoDS_Face&                    face,
+                          map< double, const SMDS_MeshNode* > & u2nodes,
+                          set< const SMDS_MeshNode* > &         seamNodes)
+  {
+    u2nodes.clear();
+    seamNodes.clear();
+    if ( !sm || !sm->GetSubMeshDS() )
+      RETURN_BAD_RESULT("Null submesh");
+
+    SMDS_NodeIteratorPtr nIt = sm->GetSubMeshDS()->GetNodes();
+    switch ( sm->GetSubShape().ShapeType() ) {
+
+    case TopAbs_VERTEX: {
+      while ( nIt->more() ) {
+        const SMDS_MeshNode* node = nIt->next();
+        if ( isOldNode( node ) ) continue;
+        u2nodes.insert( make_pair( 0., node ));
+        seamNodes.insert( node );
+        return true;
+      }
+      break;
+    }
+    case TopAbs_EDGE: {
+      
+      // Get submeshes of sub-vertices
+      const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
+      if ( subSM.size() != 2 )
+        RETURN_BAD_RESULT("there must be 2 submeshes of sub-vertices"
+                          " but we have " << subSM.size());
+      SMESH_subMesh* smV1 = subSM.begin()->second;
+      SMESH_subMesh* smV2 = subSM.rbegin()->second;
+      if ( !smV1->IsMeshComputed() || !smV2->IsMeshComputed() )
+        RETURN_BAD_RESULT("Empty vertex submeshes");
+
+      // Look for a new node on V1
+      nIt = smV1->GetSubMeshDS()->GetNodes();
+      const SMDS_MeshNode* nV1 = 0;
+      while ( nIt->more() && !nV1 ) {
+        const SMDS_MeshNode* node = nIt->next();
+        if ( !isOldNode( node ) ) nV1 = node;
+      }
+      if ( !nV1 )
+        RETURN_BAD_RESULT("No new node found on V1");
+
+      // Find a new node connected to nV1 and belonging to edge submesh;
+      const SMDS_MeshNode* nE = 0;
+      SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+      SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator();
+      while ( vElems->more() && !nE ) {
+        const SMDS_MeshElement* elem = vElems->next();
+        if ( elem->GetType() != SMDSAbs_Face )
+          continue; // new nodes are shared by faces
+        int nbNodes = elem->NbNodes();
+        if ( elem->IsQuadratic() )
+          nbNodes /= 2;
+        int iV1 = elem->GetNodeIndex( nV1 );
+        // try next aftre nV1
+        int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
+        if ( smDS->Contains( elem->GetNode( iE ) ))
+          nE = elem->GetNode( iE );
+        if ( !nE ) {
+          // try node before nV1
+          iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
+          if ( smDS->Contains( elem->GetNode( iE )))
+            nE = elem->GetNode( iE );
+        }
+        if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
+          if ( Abs( iV1 - iE ) == 1 )
+            nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
+          else
+            nE = elem->GetNode( elem->NbNodes() - 1 );
+        }
+      }
+      if ( !nE )
+        RETURN_BAD_RESULT("new node on edge not found");
+
+      // Get the whole free border of a face
+      list< const SMDS_MeshNode* > bordNodes;
+      list< const SMDS_MeshElement* > bordFaces;
+      if ( !SMESH_MeshEditor::FindFreeBorder (nV1, nE, nV1, bordNodes, bordFaces ))
+        RETURN_BAD_RESULT("free border of a face not found by nodes " <<
+                          nV1->GetID() << " " << nE->GetID() );
+
+      // Insert nodes of the free border to the map until node on V2 encountered
+      SMESHDS_SubMesh* v2smDS = smV2->GetSubMeshDS();
+      list< const SMDS_MeshNode* >::iterator bordIt = bordNodes.begin();
+      bordIt++; // skip nV1
+      for ( ; bordIt != bordNodes.end(); ++bordIt ) {
+        const SMDS_MeshNode* node = *bordIt;
+        if ( v2smDS->Contains( node ))
+          break;
+        if ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_EDGE )
+          RETURN_BAD_RESULT("Bad node position type: node " << node->GetID() <<
+                            " pos type " << node->GetPosition()->GetTypeOfPosition());
+        const SMDS_EdgePosition* pos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        u2nodes.insert( make_pair( pos->GetUParameter(), node ));
+        seamNodes.insert( node );
+      }
+      if ( u2nodes.size() != seamNodes.size() )
+        RETURN_BAD_RESULT("Bad node params on edge " << sm->GetId() <<
+                          ", " << u2nodes.size() << " != " << seamNodes.size() );
+      return true;
+    }
+    default:;
+    }
+    RETURN_BAD_RESULT ("Unexpected submesh type");
+
+  } // bool getBoundaryNodes()
+
+} // namespace
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
+{
+  if ( !_sourceHypo )
+    return false;
+
+  TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
+  TopoDS_Face srcFace = TopoDS::Face( _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD));
+
+  SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); 
+  SMESH_Mesh * tgtMesh = & theMesh;
+  if ( !srcMesh )
+    srcMesh = tgtMesh;
+
+  SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
+
+  SMESH_MesherHelper helper( theMesh );
+  helper.SetSubShape( tgtFace );
+
+  // ---------------------------
+  // Make subshapes association
+  // ---------------------------
+
+  TAssocTool::TShapeShapeMap shape2ShapeMap;
+  TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
+  if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcFace, srcMesh,
+                                             shape2ShapeMap) )
+    RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+
+  // ----------------------------------------------
+  // Assure that mesh on a source Face is computed
+  // ----------------------------------------------
+
+  SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
+  SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace );
+
+  if ( tgtMesh == srcMesh ) {
+    if ( !TAssocTool::MakeComputed( srcSubMesh ))
+      RETURN_BAD_RESULT("Impossible to compute the source mesh");
+  }
+  else {
+    if ( !srcSubMesh->IsMeshComputed() )
+      RETURN_BAD_RESULT("Source mesh is not computed");
+  }
+
+  // --------------------
+  // Prepare to mapping 
+  // --------------------
+
+  // Load pattern from the source face
+  SMESH_Pattern mapper;
+  mapper.Load( srcMesh, srcFace );
+  if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+    RETURN_BAD_RESULT("SMESH_Pattern::Load() failed");
+
+  // Find the first target vertex corresponding to first vertex of the <mapper>
+  // and <theReverse> flag needed to call mapper.Apply()
+
+  TopoDS_Vertex srcV1 = TopoDS::Vertex( mapper.GetSubShape( 1 ));
+  if ( srcV1.IsNull() )
+    RETURN_BAD_RESULT("Mesh is not bound to the face");
+  if ( !shape2ShapeMap.IsBound( srcV1 ))
+    RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() );
+  TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1 ));
+
+  if ( !TAssocTool::IsSubShape( srcV1, srcFace ))
+    RETURN_BAD_RESULT("Wrong srcV1 " << srcV1.TShape().operator->());
+  if ( !TAssocTool::IsSubShape( tgtV1, tgtFace ))
+    RETURN_BAD_RESULT("Wrong tgtV1 " << tgtV1.TShape().operator->());
+
+  // try to find out orientation by order of edges
+  bool reverse = false;
+  list< TopoDS_Edge > tgtEdges, srcEdges;
+  list< int > nbEdgesInWires;
+  SMESH_Block::GetOrderedEdges( tgtFace, tgtV1, tgtEdges, nbEdgesInWires);
+  SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires);
+  if ( nbEdgesInWires.front() > 1 ) // possible to find out
+  {
+    TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
+    reverse = ( ! srcE1.IsSame( shape2ShapeMap( tgtE1 )));
+    if ( BRep_Tool::IsClosed( tgtE1, tgtFace )) {
+      reverse = ( srcE1.Orientation() == tgtE1.Orientation() );
+      if ( _sourceHypo->GetSourceFace().Orientation() != theShape.Orientation() )
+        reverse = !reverse;
+    }
+  }
+  else if ( nbEdgesInWires.front() == 1 )
+  {
+    // TODO::Compare orientation of curves in a sole edge
+    //RETURN_BAD_RESULT("Not implemented case");
+  }
+  else
+  {
+    RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
+  }
+
+  // --------------------
+  // Perform 2D mapping 
+  // --------------------
+
+  // Compute mesh on a target face
+
+  mapper.Apply( tgtFace, tgtV1, reverse );
+  if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+    RETURN_BAD_RESULT("SMESH_Pattern::Apply() failed");
+
+  // Create the mesh
+
+  const bool toCreatePolygons = false, toCreatePolyedrs = false;
+  mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
+  if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+    RETURN_BAD_RESULT("SMESH_Pattern::MakeMesh() failed");
+
+  // it will remove mesh built by pattern mapper on edges and vertices
+  // in failure case
+  MeshCleaner cleaner( tgtSubMesh );
+
+  // -------------------------------------------------------------------------
+  // mapper doesn't take care of nodes already existing on edges and vertices,
+  // so we must merge nodes created by it with existing ones 
+  // -------------------------------------------------------------------------
+
+  SMESH_MeshEditor editor( tgtMesh );
+  SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
+
+  // Make groups of nodes to merge
+
+  // loop on edge and vertex submeshes of a target face
+  const map< int, SMESH_subMesh * >& subSM = tgtSubMesh->DependsOn();
+  map< int, SMESH_subMesh * >::const_iterator i_subSM = subSM.begin();
+  for ( ; i_subSM != subSM.end(); ++i_subSM )
+  {
+    SMESH_subMesh*     sm = i_subSM->second;
+    SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+
+    // Sort new and old nodes of a submesh separately
+
+    bool isSeam = helper.IsSeamShape( sm->GetId() );
+
+    enum { NEW_NODES, OLD_NODES };
+    map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
+    map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
+    set< const SMDS_MeshNode* > seamNodes;
+
+    // mapper puts on a seam edge nodes from 2 edges
+    if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
+      RETURN_BAD_RESULT("getBoundaryNodes() failed");
+
+    SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+    while ( nIt->more() )
+    {
+      const SMDS_MeshNode* node = nIt->next();
+      bool isOld = isOldNode( node );
+
+      if ( !isOld && isSeam ) { // new node on a seam edge
+        if ( seamNodes.find( node ) != seamNodes.end())
+          continue; // node is already in the map
+      }
+
+      // sort nodes on edges by its position
+      map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[ isOld ];
+      switch ( node->GetPosition()->GetTypeOfPosition() )
+      {
+      case  SMDS_TOP_VERTEX: {
+        pos2nodes.insert( make_pair( 0, node ));
+        break;
+      }
+      case  SMDS_TOP_EDGE:   {
+        const SMDS_EdgePosition* pos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
+        break;
+      }
+      default:
+        RETURN_BAD_RESULT("Wrong node position type: "<<
+                          node->GetPosition()->GetTypeOfPosition());
+      }
+    }
+    if ( u2nodesMaps[ OLD_NODES ].size() != u2nodesMaps[ NEW_NODES ].size() )
+      RETURN_BAD_RESULT("Different nb of old and new nodes " <<
+                        u2nodesMaps[ OLD_NODES ].size() << " != " <<
+                        u2nodesMaps[ NEW_NODES ].size());
+    if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() )
+      RETURN_BAD_RESULT("Different nb of old and seam nodes " <<
+                        u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
+
+    // Make groups of nodes to merge
+    u_oldNode = u2nodesMaps[ OLD_NODES ].begin(); 
+    u_newNode = u2nodesMaps[ NEW_NODES ].begin();
+    newEnd    = u2nodesMaps[ NEW_NODES ].end();
+    u_newOnSeam = u2nodesOnSeam.begin();
+    for ( ; u_newNode != newEnd; ++u_newNode, ++u_oldNode ) {
+      groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
+      groupsOfNodes.back().push_back( u_oldNode->second );
+      groupsOfNodes.back().push_back( u_newNode->second );
+      if ( isSeam )
+        groupsOfNodes.back().push_back( (u_newOnSeam++)->second );
+    }
+  }
+
+  // Merge
+
+  editor.MergeNodes( groupsOfNodes );
+
+  // ---------------------------
+  // Check elements orientation
+  // ---------------------------
+
+  TopoDS_Face face = tgtFace;
+  if ( !theMesh.IsMainShape( tgtFace ))
+  {
+    // find the main shape
+    TopoDS_Shape mainShape = meshDS->ShapeToMesh();
+    switch ( mainShape.ShapeType() ) {
+    case TopAbs_SHELL:
+    case TopAbs_SOLID: break;
+    default:
+      TopTools_ListIteratorOfListOfShape ancestIt = theMesh.GetAncestors( face );
+      for ( ; ancestIt.More(); ancestIt.Next() ) {
+        TopAbs_ShapeEnum type = ancestIt.Value().ShapeType();
+        if ( type == TopAbs_SOLID ) {
+          mainShape = ancestIt.Value();
+          break;
+        } else if ( type == TopAbs_SHELL ) {
+          mainShape = ancestIt.Value();
+        }
+      }
+    }
+    // find tgtFace in the main solid or shell to know it's true orientation.
+    TopExp_Explorer exp( mainShape, TopAbs_FACE );
+    for ( ; exp.More(); exp.Next() ) {
+      if ( tgtFace.IsSame( exp.Current() )) {
+        face = TopoDS::Face( exp.Current() );
+        break;
+      }
+    }
+  }
+  // Fix orientation
+  if ( SMESH_Algo::IsReversedSubMesh( face, meshDS ))
+  {
+    SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();
+    while ( eIt->more() ) {
+      const SMDS_MeshElement* e = eIt->next();
+      if ( e->GetType() == SMDSAbs_Face && !editor.Reorient( e ))
+        RETURN_BAD_RESULT("Pb of SMESH_MeshEditor::Reorient()");
+    }
+  }
+
+  cleaner.Release(); // do not remove mesh
+
+  return true;
+}
+
+//=============================================================================
+/*!
+ * \brief Sets a default event listener to submesh of the source face
+  * \param subMesh - submesh where algo is set
+ *
+ * This method is called when a submesh gets HYP_OK algo_state.
+ * After being set, event listener is notified on each event of a submesh.
+ * Arranges that CLEAN event is translated from source submesh to
+ * the submesh
+ */
+//=============================================================================
+
+void StdMeshers_Projection_2D::SetEventListener(SMESH_subMesh* subMesh)
+{
+  if ( _sourceHypo && ! _sourceHypo->GetSourceFace().IsNull() )
+  {
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    if ( !srcMesh )
+      srcMesh = subMesh->GetFather();
+
+    SMESH_subMesh* srcFaceSM =
+      srcMesh->GetSubMesh( _sourceHypo->GetSourceFace() );
+
+    subMesh->SetEventListener( new SMESH_subMeshEventListener(),
+                               SMESH_subMeshEventListenerData::MakeData( subMesh ),
+                               srcFaceSM );
+  }
+}
diff --git a/src/StdMeshers/StdMeshers_Projection_2D.hxx b/src/StdMeshers/StdMeshers_Projection_2D.hxx
new file mode 100644 (file)
index 0000000..efa1c6e
--- /dev/null
@@ -0,0 +1,63 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_Projection_2D.hxx
+//  Module : SMESH
+
+#ifndef _SMESH_Projection_2D_HXX_
+#define _SMESH_Projection_2D_HXX_
+
+#include "SMESH_2D_Algo.hxx"
+
+class StdMeshers_ProjectionSource2D;
+
+class StdMeshers_Projection_2D: public SMESH_2D_Algo
+{
+public:
+  StdMeshers_Projection_2D(int hypId, int studyId, SMESH_Gen* gen);
+  virtual ~StdMeshers_Projection_2D();
+
+  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);
+
+  /*!
+   * \brief Sets a default event listener to submesh of the source face
+   *  \param whenSetToSubMesh - submesh where algo is set
+   *
+   * After being set, event listener is notified on each event of a submesh.
+   * This method is called when a submesh gets HYP_OK algo_state.
+   * Arranges that CLEAN event is translated from source submesh to
+   * the whenSetToSubMesh submesh.
+   */
+  virtual void SetEventListener(SMESH_subMesh* whenSetToSubMesh);
+  
+protected:
+
+  const StdMeshers_ProjectionSource2D* _sourceHypo;
+
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_Projection_3D.cxx b/src/StdMeshers/StdMeshers_Projection_3D.cxx
new file mode 100644 (file)
index 0000000..44b4395
--- /dev/null
@@ -0,0 +1,438 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_Projection_3D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_Projection_3D.hxx"
+#include "StdMeshers_ProjectionSource3D.hxx"
+
+#include "StdMeshers_ProjectionUtils.hxx"
+
+#include "SMESHDS_Hypothesis.hxx"
+#include "SMESHDS_SubMesh.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_Pattern.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMDS_PolyhedralVolumeOfNodes.hxx"
+
+#include "utilities.h"
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
+#define SHOWYXZ(msg, xyz) // {\
+// gp_Pnt p (xyz); \
+// cout << msg << " ("<< p.X() << "; " <<p.Y() << "; " <<p.Z() << ") " <<endl;\
+// }
+
+typedef StdMeshers_ProjectionUtils TAssocTool;
+
+
+//=======================================================================
+//function : StdMeshers_Projection_3D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_Projection_3D::StdMeshers_Projection_3D(int hypId, int studyId, SMESH_Gen* gen)
+  :SMESH_3D_Algo(hypId, studyId, gen)
+{
+  _name = "Projection_3D";
+  _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);      // 1 bit per shape type
+
+  _compatibleHypothesis.push_back("ProjectionSource3D");
+  _sourceHypo = 0;
+}
+
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_Projection_3D::~StdMeshers_Projection_3D()
+{}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_3D::CheckHypothesis(SMESH_Mesh&                          aMesh,
+                                               const TopoDS_Shape&                  aShape,
+                                               SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  // check aShape that must be a 6 faces block
+  if ( TAssocTool::Count( aShape, TopAbs_SHELL, 1 ) != 1 ||
+       TAssocTool::Count( aShape, TopAbs_FACE , 1 ) != 6 ||
+       TAssocTool::Count( aShape, TopAbs_EDGE , 1 ) != 12 ||
+       TAssocTool::Count( aShape, TopAbs_WIRE , 1 ) != 6 )
+  {
+    aStatus = HYP_BAD_GEOMETRY;
+    return false;
+  }
+
+  list <const SMESHDS_Hypothesis * >::const_iterator itl;
+
+  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();
+
+  aStatus = SMESH_Hypothesis::HYP_OK;
+
+  if (hypName == "ProjectionSource3D")
+  {
+    _sourceHypo = static_cast<const StdMeshers_ProjectionSource3D *>(theHyp);
+    // Check hypo parameters
+
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    SMESH_Mesh* tgtMesh = & aMesh;
+    if ( !srcMesh )
+      srcMesh = tgtMesh;
+
+    // check vertices
+    if ( _sourceHypo->HasVertexAssociation() )
+    {
+      // source vertices
+      TopoDS_Shape edge = TAssocTool::GetEdgeByVertices
+        ( srcMesh, _sourceHypo->GetSourceVertex(1), _sourceHypo->GetSourceVertex(2) );
+      if ( edge.IsNull() ||
+           !TAssocTool::IsSubShape( edge, srcMesh ) ||
+           !TAssocTool::IsSubShape( edge, _sourceHypo->GetSource3DShape() ))
+      {
+        SCRUTE((edge.IsNull()));
+        SCRUTE((TAssocTool::IsSubShape( edge, srcMesh )));
+        SCRUTE((TAssocTool::IsSubShape( edge, _sourceHypo->GetSource3DShape() )));
+        aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
+      }
+      else
+      {
+        // target vertices
+        edge = TAssocTool::GetEdgeByVertices
+          ( tgtMesh, _sourceHypo->GetTargetVertex(1), _sourceHypo->GetTargetVertex(2) );
+        if ( edge.IsNull() ||
+             !TAssocTool::IsSubShape( edge, tgtMesh ) ||
+             !TAssocTool::IsSubShape( edge, aShape ))
+        {
+          SCRUTE((edge.IsNull()));
+          SCRUTE((TAssocTool::IsSubShape( edge, tgtMesh )));
+          SCRUTE((TAssocTool::IsSubShape( edge, aShape )));
+          aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
+        }
+      }
+    }
+    // check a source shape
+    if ( !TAssocTool::IsSubShape( _sourceHypo->GetSource3DShape(), srcMesh ) ||
+         ( srcMesh == tgtMesh && aShape == _sourceHypo->GetSource3DShape()))
+    {
+      SCRUTE((TAssocTool::IsSubShape( _sourceHypo->GetSource3DShape(), srcMesh)));
+      SCRUTE((srcMesh == tgtMesh));
+      SCRUTE((aShape == _sourceHypo->GetSource3DShape()));
+      aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER;
+    }
+  }
+  else
+  {
+    aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  }
+  return ( aStatus == HYP_OK );
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
+{
+  if ( !_sourceHypo )
+    return false;
+
+  SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
+  SMESH_Mesh * tgtMesh = & aMesh;
+  if ( !srcMesh )
+    srcMesh = tgtMesh;
+
+  SMESHDS_Mesh * srcMeshDS = srcMesh->GetMeshDS();
+  SMESHDS_Mesh * tgtMeshDS = tgtMesh->GetMeshDS();
+
+  // get shell from shape3D
+  TopoDS_Shell srcShell, tgtShell;
+  TopExp_Explorer exp( _sourceHypo->GetSource3DShape(), TopAbs_SHELL );
+  int nbShell;
+  for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell )
+    srcShell = TopoDS::Shell( exp.Current() );
+  if ( nbShell != 1 )
+    RETURN_BAD_RESULT("There must be 1 shell in the source shape");
+
+  exp.Init( aShape, TopAbs_SHELL );
+  for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell )
+    tgtShell = TopoDS::Shell( exp.Current() );
+  if ( nbShell != 1 )
+    RETURN_BAD_RESULT("There must be 1 shell in the target shape");
+
+  // Assure that mesh on a source shape is computed
+
+  SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( _sourceHypo->GetSource3DShape() );
+  //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( aShape );
+
+  if ( tgtMesh == srcMesh && !aShape.IsSame( _sourceHypo->GetSource3DShape() )) {
+    if ( !TAssocTool::MakeComputed( srcSubMesh ))
+      RETURN_BAD_RESULT("Impossible to compute the source mesh");
+  }
+  else {
+    if ( !srcSubMesh->IsMeshComputed() )
+      RETURN_BAD_RESULT("Source mesh is not computed");
+  }
+
+  // Find 2 pairs of corresponding vertices
+
+  TopoDS_Vertex tgtV000, tgtV100, srcV000, srcV100;
+  TAssocTool::TShapeShapeMap shape2ShapeMap;
+
+  if ( _sourceHypo->HasVertexAssociation() )
+  {
+    tgtV000 = _sourceHypo->GetTargetVertex(1);
+    tgtV100 = _sourceHypo->GetTargetVertex(2);
+    srcV000 = _sourceHypo->GetSourceVertex(1);
+    srcV100 = _sourceHypo->GetSourceVertex(2);
+  }
+  else
+  {
+    if ( !TAssocTool::FindSubShapeAssociation( tgtShell, tgtMesh, srcShell, srcMesh,
+                                               shape2ShapeMap) )
+      RETURN_BAD_RESULT("FindSubShapeAssociation() failed");
+
+    exp.Init( tgtShell, TopAbs_EDGE );
+    TopExp::Vertices( TopoDS::Edge( exp.Current() ), tgtV000, tgtV100 );
+
+    if ( !shape2ShapeMap.IsBound( tgtV000 ) || !shape2ShapeMap.IsBound( tgtV100 ))
+      RETURN_BAD_RESULT("Shape associating not done");
+    srcV000 = TopoDS::Vertex( shape2ShapeMap( tgtV000 ));
+    srcV100 = TopoDS::Vertex( shape2ShapeMap( tgtV100 ));
+    if ( !TAssocTool::IsSubShape( srcV000, srcShell ) ||
+         !TAssocTool::IsSubShape( srcV100, srcShell ))
+      RETURN_BAD_RESULT("Wrong target vertices");
+  }
+
+  // Load 2 SMESH_Block's with src and tgt shells
+
+  SMESH_Block srcBlock, tgtBlock;
+  TopTools_IndexedMapOfOrientedShape scrShapes, tgtShapes;
+  if ( !tgtBlock.LoadBlockShapes( tgtShell, tgtV000, tgtV100, tgtShapes ))
+    RETURN_BAD_RESULT("SMESH_Block::LoadBlockShapes(tgtShell) failed");
+
+  if ( !srcBlock.LoadBlockShapes( srcShell, srcV000, srcV100, scrShapes ))
+    RETURN_BAD_RESULT("SMESH_Block::LoadBlockShapes(srcShell) failed");
+
+  // Find matching nodes of src and tgt shells
+
+  TNodeNodeMap src2tgtNodeMap;
+  for ( int fId = SMESH_Block::ID_FirstF; fId < SMESH_Block::ID_Shell; ++fId )
+  {
+    // Corresponding subshapes
+    TopoDS_Face srcFace = TopoDS::Face( scrShapes( fId ));
+    TopoDS_Face tgtFace = TopoDS::Face( tgtShapes( fId ));
+    if ( _sourceHypo->HasVertexAssociation() ) { // associate face subshapes
+      shape2ShapeMap.Clear();
+      vector< int > edgeIdVec;
+      SMESH_Block::GetFaceEdgesIDs( fId, edgeIdVec );
+      for ( int i = 0; i < edgeIdVec.size(); ++i ) {
+        int eID = edgeIdVec[ i ];
+        shape2ShapeMap.Bind( tgtShapes( eID ), scrShapes( eID ));
+        if ( i < 2 ) {
+          vector< int > vertexIdVec;
+          SMESH_Block::GetEdgeVertexIDs( eID, vertexIdVec );
+          shape2ShapeMap.Bind( tgtShapes( vertexIdVec[0] ), scrShapes( vertexIdVec[0] ));
+          shape2ShapeMap.Bind( tgtShapes( vertexIdVec[1] ), scrShapes( vertexIdVec[1] ));
+        }
+      }
+    }
+    // Find matching nodes of tgt and src faces
+    TNodeNodeMap faceMatchingNodes;
+    if ( ! TAssocTool::FindMatchingNodesOnFaces( srcFace, srcMesh, tgtFace, tgtMesh, 
+                                                 shape2ShapeMap, faceMatchingNodes ))
+      RETURN_BAD_RESULT("Different mesh on corresponding src and tgt faces: "
+                        << srcMeshDS->ShapeToIndex( srcFace ) << " and "
+                        << tgtMeshDS->ShapeToIndex( tgtFace ));
+
+    // put found matching nodes of 2 faces to the global map
+    src2tgtNodeMap.insert( faceMatchingNodes.begin(), faceMatchingNodes.end() );
+  }
+
+  // ------------------
+  // Make mesh
+  // ------------------
+
+  SMDS_VolumeTool volTool;
+  SMESH_MesherHelper helper( *tgtMesh );
+  helper.IsQuadraticSubMesh( aShape );
+
+  SMESHDS_SubMesh* srcSMDS = srcSubMesh->GetSubMeshDS();
+  SMDS_ElemIteratorPtr volIt = srcSMDS->GetElements();
+  while ( volIt->more() ) // loop on source volumes
+  {
+    const SMDS_MeshElement* srcVol = volIt->next();
+    if ( !srcVol || srcVol->GetType() != SMDSAbs_Volume )
+        continue;
+    int nbNodes = srcVol->NbNodes();
+    SMDS_VolumeTool::VolumeType  volType = volTool.GetType( nbNodes );
+    if ( srcVol->IsQuadratic() )
+      nbNodes = volTool.NbCornerNodes( volType );
+
+    // Find or create a new tgt node for each node of a src volume
+
+    vector< const SMDS_MeshNode* > nodes( nbNodes );
+    for ( int i = 0; i < nbNodes; ++i )
+    {
+      const SMDS_MeshNode* srcNode = srcVol->GetNode( i );
+      const SMDS_MeshNode* tgtNode = 0;
+      TNodeNodeMap::iterator sN_tN = src2tgtNodeMap.find( srcNode );
+      if ( sN_tN != src2tgtNodeMap.end() ) // found
+      {
+        tgtNode = sN_tN->second;
+      }
+      else // Create a new tgt node
+      {
+        // compute normalized parameters of source node in srcBlock
+        gp_Pnt srcCoord = gpXYZ( srcNode );
+        gp_XYZ srcParam;
+        if ( !srcBlock.ComputeParameters( srcCoord, srcParam ))
+          RETURN_BAD_RESULT("srcBlock.ComputeParameters() failed");
+        // compute coordinates of target node by srcParam
+        gp_XYZ tgtXYZ;
+        if ( !tgtBlock.ShellPoint( srcParam, tgtXYZ ))
+          RETURN_BAD_RESULT("tgtBlock.ShellPoint() failed");
+        // add node
+        SMDS_MeshNode* newNode = tgtMeshDS->AddNode( tgtXYZ.X(), tgtXYZ.Y(), tgtXYZ.Z() );
+        tgtMeshDS->SetNodeInVolume( newNode, helper.GetSubShapeID() );
+        tgtNode = newNode;
+        src2tgtNodeMap.insert( make_pair( srcNode, tgtNode ));
+      }
+      nodes[ i ] = tgtNode;
+    }
+
+    // Create a new volume
+
+    SMDS_MeshVolume * tgtVol = 0;
+    switch ( volType ) {
+    case SMDS_VolumeTool::TETRA     :
+    case SMDS_VolumeTool::QUAD_TETRA:
+      tgtVol = helper.AddVolume( nodes[0],
+                                 nodes[1],
+                                 nodes[2],
+                                 nodes[3]); break;
+    case SMDS_VolumeTool::PYRAM     :
+    case SMDS_VolumeTool::QUAD_PYRAM:
+      tgtVol = helper.AddVolume( nodes[0],
+                                 nodes[1],
+                                 nodes[2],
+                                 nodes[3],
+                                 nodes[4]); break;
+    case SMDS_VolumeTool::PENTA     :
+    case SMDS_VolumeTool::QUAD_PENTA:
+      tgtVol = helper.AddVolume( nodes[0],
+                                 nodes[1],
+                                 nodes[2],
+                                 nodes[3],
+                                 nodes[4],
+                                 nodes[5]); break;
+    case SMDS_VolumeTool::HEXA      :
+    case SMDS_VolumeTool::QUAD_HEXA :
+      tgtVol = helper.AddVolume( nodes[0],
+                                 nodes[1],
+                                 nodes[2],
+                                 nodes[3],
+                                 nodes[4],
+                                 nodes[5],
+                                 nodes[6],
+                                 nodes[7]); break;
+    default: // polyhedron
+      const SMDS_PolyhedralVolumeOfNodes * poly =
+        dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>( srcVol );
+      if ( !poly )
+        RETURN_BAD_RESULT("Unexpected volume type");
+      vector<int> quantities( poly->NbFaces(), 0 );
+      for ( int i = 0; i < quantities.size(); ++i )
+        quantities[ i ] = poly->NbFaceNodes( i + 1 );
+      tgtVol = tgtMeshDS->AddPolyhedralVolume( nodes, quantities );
+    }
+    if ( tgtVol ) {
+      tgtMeshDS->SetMeshElementOnShape( tgtVol, helper.GetSubShapeID() );
+    }
+  } // loop on volumes of src shell
+
+  return true;
+}
+
+//=============================================================================
+/*!
+ * \brief Sets a default event listener to submesh of the source shape
+  * \param subMesh - submesh where algo is set
+ *
+ * This method is called when a submesh gets HYP_OK algo_state.
+ * After being set, event listener is notified on each event of a submesh.
+ * Arranges that CLEAN event is translated from source submesh to
+ * the submesh
+ */
+//=============================================================================
+
+void StdMeshers_Projection_3D::SetEventListener(SMESH_subMesh* subMesh)
+{
+  if ( _sourceHypo && ! _sourceHypo->GetSource3DShape().IsNull() )
+  {
+    SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
+    if ( !srcMesh )
+      srcMesh = subMesh->GetFather();
+
+    SMESH_subMesh* srcShapeSM =
+      srcMesh->GetSubMesh( _sourceHypo->GetSource3DShape() );
+
+    if ( srcShapeSM != subMesh )
+      subMesh->SetEventListener( new SMESH_subMeshEventListener(),
+                                 SMESH_subMeshEventListenerData::MakeData( subMesh ),
+                                 srcShapeSM );
+  }
+}
+  
diff --git a/src/StdMeshers/StdMeshers_Projection_3D.hxx b/src/StdMeshers/StdMeshers_Projection_3D.hxx
new file mode 100644 (file)
index 0000000..abc50e7
--- /dev/null
@@ -0,0 +1,61 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_Projection_3D.hxx
+//  Module : SMESH
+
+#ifndef _SMESH_Projection_3D_HXX_
+#define _SMESH_Projection_3D_HXX_
+
+#include "SMESH_3D_Algo.hxx"
+
+class StdMeshers_ProjectionSource3D;
+
+class StdMeshers_Projection_3D: public SMESH_3D_Algo
+{
+public:
+  StdMeshers_Projection_3D(int hypId, int studyId, SMESH_Gen* gen);
+  virtual ~StdMeshers_Projection_3D();
+
+  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);
+
+  /*!
+   * \brief Sets a default event listener to submesh of the source shape
+   *  \param whenSetToSubMesh - submesh where algo is set
+   *
+   * Arranges that CLEAN event is translated from source submesh to
+   * the whenSetToSubMesh submesh.
+   */
+  virtual void SetEventListener(SMESH_subMesh* whenSetToSubMesh);
+  
+protected:
+
+  const StdMeshers_ProjectionSource3D* _sourceHypo;
+
+};
+
+#endif
diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx
new file mode 100644 (file)
index 0000000..4564000
--- /dev/null
@@ -0,0 +1,372 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+// File      : StdMeshers_RadialPrism_3D.cxx
+// Module    : SMESH
+// Created   : Fri Oct 20 11:37:07 2006
+// Author    : Edward AGAPOV (eap)
+
+
+#include "StdMeshers_RadialPrism_3D.hxx"
+
+#include "StdMeshers_ProjectionUtils.hxx"
+#include "StdMeshers_NumberOfLayers.hxx"
+#include "StdMeshers_LayerDistribution.hxx"
+#include "StdMeshers_Prism_3D.hxx"
+#include "StdMeshers_Regular_1D.hxx"
+
+#include "SMDS_MeshNode.hxx"
+#include "SMESHDS_SubMesh.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_subMesh.hxx"
+
+#include "utilities.h"
+
+#include <TopoDS_Solid.hxx>
+#include <TopoDS_Shell.hxx>
+#include <BRepTools.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <gp.hxx>
+#include <gp_Pnt.hxx>
+
+
+using namespace std;
+
+#define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
+#define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
+
+typedef StdMeshers_ProjectionUtils TAssocTool;
+
+//=======================================================================
+//function : StdMeshers_RadialPrism_3D
+//purpose  : 
+//=======================================================================
+
+StdMeshers_RadialPrism_3D::StdMeshers_RadialPrism_3D(int hypId, int studyId, SMESH_Gen* gen)
+  :SMESH_3D_Algo(hypId, studyId, gen)
+{
+  _name = "RadialPrism_3D";
+  _shapeType = (1 << TopAbs_SOLID);    // 1 bit per shape type
+
+  _compatibleHypothesis.push_back("LayerDistribution");
+  _compatibleHypothesis.push_back("NumberOfLayers");
+  myNbLayerHypo = 0;
+  myDistributionHypo = 0;
+}
+
+//================================================================================
+/*!
+ * \brief Destructor
+ */
+//================================================================================
+
+StdMeshers_RadialPrism_3D::~StdMeshers_RadialPrism_3D()
+{}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_RadialPrism_3D::CheckHypothesis(SMESH_Mesh&                          aMesh,
+                                                const TopoDS_Shape&                  aShape,
+                                                SMESH_Hypothesis::Hypothesis_Status& aStatus)
+{
+  // check aShape that must have 2 shells
+  if ( TAssocTool::Count( aShape, TopAbs_SOLID, 0 ) != 1 ||
+       TAssocTool::Count( aShape, TopAbs_SHELL, 0 ) != 2 )
+  {
+    aStatus = HYP_BAD_GEOMETRY;
+    return false;
+  }
+
+  myNbLayerHypo = 0;
+  myDistributionHypo = 0;
+
+  list <const SMESHDS_Hypothesis * >::const_iterator itl;
+
+  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 == "NumberOfLayers")
+  {
+    myNbLayerHypo = static_cast<const StdMeshers_NumberOfLayers *>(theHyp);
+    aStatus = SMESH_Hypothesis::HYP_OK;
+    return true;
+  }
+  if (hypName == "LayerDistribution")
+  {
+    myDistributionHypo = static_cast<const StdMeshers_LayerDistribution *>(theHyp);
+    aStatus = SMESH_Hypothesis::HYP_OK;
+    return true;
+  }
+  aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+  return true;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
+{
+  TopExp_Explorer exp;
+  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+
+  myHelper = new SMESH_MesherHelper( aMesh );
+  myHelper->IsQuadraticSubMesh( aShape );
+  // to delete helper at exit from Compute()
+  std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+
+  // get 2 shells 
+  TopoDS_Solid solid = TopoDS::Solid( aShape );
+  TopoDS_Shell outerShell = BRepTools::OuterShell( solid );
+  TopoDS_Shape innerShell;
+  int nbShells = 0;
+  for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
+    if ( !outerShell.IsSame( It.Value() ))
+      innerShell = It.Value();
+  if ( nbShells != 2 )
+    RETURN_BAD_RESULT("Must be 2 shells");
+
+  // ----------------------------------
+  // Associate subshapes of the shells
+  // ----------------------------------
+
+  TAssocTool::TShapeShapeMap shape2ShapeMap;
+  if ( !TAssocTool::FindSubShapeAssociation( outerShell, &aMesh,
+                                             innerShell, &aMesh,
+                                             shape2ShapeMap) )
+    RETURN_BAD_RESULT("FindSubShapeAssociation failed");
+
+  // ------------------
+  // Make mesh
+  // ------------------
+
+  TNode2ColumnMap node2columnMap;
+  myLayerPositions.clear();
+
+  for ( exp.Init( outerShell, TopAbs_FACE ); exp.More(); exp.Next() )
+  {
+    // Corresponding subshapes
+    TopoDS_Face outFace = TopoDS::Face( exp.Current() );
+    TopoDS_Face inFace;
+    if ( !shape2ShapeMap.IsBound( outFace )) {
+      RETURN_BAD_RESULT("Association not found for face " << meshDS->ShapeToIndex( outFace ));
+    } else {
+      inFace = TopoDS::Face( shape2ShapeMap( outFace ));
+    }
+
+    // Find matching nodes of in and out faces
+    TNodeNodeMap nodeIn2OutMap;
+    if ( ! TAssocTool::FindMatchingNodesOnFaces( inFace, &aMesh, outFace, &aMesh,
+                                                 shape2ShapeMap, nodeIn2OutMap ))
+      RETURN_BAD_RESULT("Different mesh on corresponding out and in faces: "
+                        << meshDS->ShapeToIndex( outFace ) << " and "
+                        << meshDS->ShapeToIndex( inFace ));
+    // Create volumes
+
+    SMDS_ElemIteratorPtr faceIt = meshDS->MeshElements( inFace )->GetElements();
+    while ( faceIt->more() ) // loop on faces on inFace
+    {
+      const SMDS_MeshElement* face = faceIt->next();
+      if ( !face || face->GetType() != SMDSAbs_Face )
+        continue;
+      int nbNodes = face->NbNodes();
+      if ( face->IsQuadratic() )
+        nbNodes /= 2;
+
+      // find node columns for each node
+      vector< const TNodeColumn* > columns( nbNodes );
+      for ( int i = 0; i < nbNodes; ++i )
+      {
+        const SMDS_MeshNode* n = face->GetNode( i );
+        TNode2ColumnMap::iterator n_col = node2columnMap.find( n );
+        if ( n_col != node2columnMap.end() )
+          columns[ i ] = & n_col->second;
+        else
+          columns[ i ] = makeNodeColumn( node2columnMap, n, nodeIn2OutMap[ n ] );
+      }
+
+      StdMeshers_Prism_3D::AddPrisms( columns, myHelper );
+    }
+  } // loop on faces of out shell
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Create a column of nodes from outNode to inNode
+  * \param n2ColMap - map of node columns to add a created column
+  * \param outNode - botton node of a column
+  * \param inNode - top node of a column
+  * \retval const TNodeColumn* - a new column pointer
+ */
+//================================================================================
+
+TNodeColumn* StdMeshers_RadialPrism_3D::makeNodeColumn( TNode2ColumnMap&     n2ColMap,
+                                                        const SMDS_MeshNode* outNode,
+                                                        const SMDS_MeshNode* inNode)
+{
+  SMESHDS_Mesh * meshDS = myHelper->GetMeshDS();
+  int shapeID = myHelper->GetSubShapeID();
+
+  if ( myLayerPositions.empty() )
+    computeLayerPositions( gpXYZ( inNode ), gpXYZ( outNode ));
+
+  int nbSegments = myLayerPositions.size() + 1;
+
+  TNode2ColumnMap::iterator n_col =
+    n2ColMap.insert( make_pair( outNode, TNodeColumn() )).first;
+  TNodeColumn & column = n_col->second;
+  column.resize( nbSegments + 1 );
+  column.front() = outNode;
+  column.back() =  inNode;
+
+  gp_XYZ p1 = gpXYZ( outNode );
+  gp_XYZ p2 = gpXYZ( inNode );
+  for ( int z = 1; z < nbSegments; ++z )
+  {
+    double r = myLayerPositions[ z - 1 ];
+    gp_XYZ p = ( 1 - r ) * p1 + r * p2;
+    SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+    meshDS->SetNodeInVolume( n, shapeID );
+    column[ z ] = n;
+  }
+
+  return & column;
+}
+
+//================================================================================
+//================================================================================
+/*!
+ * \brief Class computing layers distribution using data of
+ *        StdMeshers_LayerDistribution hypothesis
+ */
+//================================================================================
+//================================================================================
+
+class TNodeDistributor: private StdMeshers_Regular_1D
+{
+  list <const SMESHDS_Hypothesis *> myUsedHyps;
+public:
+  // -----------------------------------------------------------------------------
+  static TNodeDistributor* GetDistributor(SMESH_Mesh& aMesh)
+  {
+    const int myID = -1000;
+    map < int, SMESH_1D_Algo * > & algoMap = aMesh.GetGen()->_map1D_Algo;
+    map < int, SMESH_1D_Algo * >::iterator id_algo = algoMap.find( myID );
+    if ( id_algo == algoMap.end() )
+      return new TNodeDistributor( myID, 0, aMesh.GetGen() );
+    return static_cast< TNodeDistributor* >( id_algo->second );
+  }
+  // -----------------------------------------------------------------------------
+  bool Compute( vector< double > &                  positions,
+                gp_Pnt                              pIn,
+                gp_Pnt                              pOut,
+                SMESH_Mesh&                         aMesh,
+                const StdMeshers_LayerDistribution* hyp)
+  {
+    double len = pIn.Distance( pOut );
+    if ( len <= DBL_MIN ) RETURN_BAD_RESULT("Bad points");
+
+    if ( !hyp || !hyp->GetLayerDistribution() )
+      RETURN_BAD_RESULT("Bad StdMeshers_LayerDistribution hypothesis");
+    myUsedHyps.clear();
+    myUsedHyps.push_back( hyp->GetLayerDistribution() );
+
+    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut );
+
+    SMESH_Hypothesis::Hypothesis_Status aStatus;
+    if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
+      RETURN_BAD_RESULT("StdMeshers_Regular_1D::CheckHypothesis() failed with status "<<aStatus);
+
+    list< double > params;
+    if ( !StdMeshers_Regular_1D::computeInternalParameters( edge, params, false ))
+      RETURN_BAD_RESULT("StdMeshers_Regular_1D::computeInternalParameters() failed");
+
+    positions.clear();
+    positions.reserve( params.size() );
+    for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
+      positions.push_back( *itU / len );
+    return true;
+  }
+protected:
+  // -----------------------------------------------------------------------------
+  TNodeDistributor( int hypId, int studyId, SMESH_Gen* gen)
+    : StdMeshers_Regular_1D( hypId, studyId, gen)
+  {
+  }
+  // -----------------------------------------------------------------------------
+  virtual const list <const SMESHDS_Hypothesis *> &
+    GetUsedHypothesis(SMESH_Mesh &, const TopoDS_Shape &, const bool)
+  {
+    return myUsedHyps;
+  }
+  // -----------------------------------------------------------------------------
+};
+
+//================================================================================
+/*!
+ * \brief Compute positions of nodes between the internal and the external surfaces
+  * \retval bool - is a success
+ */
+//================================================================================
+
+bool StdMeshers_RadialPrism_3D::computeLayerPositions(gp_Pnt pIn, gp_Pnt pOut)
+{
+  if ( myNbLayerHypo )
+  {
+    int nbSegments = myNbLayerHypo->GetNumberOfLayers();
+    myLayerPositions.resize( nbSegments - 1 );
+    for ( int z = 1; z < nbSegments; ++z )
+      myLayerPositions[ z - 1 ] = double( z )/ double( nbSegments );
+    return true;
+  }
+  if ( myDistributionHypo ) {
+    SMESH_Mesh * mesh = myHelper->GetMesh();
+    return TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions, pIn, pOut,
+                                                             *mesh, myDistributionHypo );
+  }
+  RETURN_BAD_RESULT("Bad hypothesis");  
+}
diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx
new file mode 100644 (file)
index 0000000..4c604ea
--- /dev/null
@@ -0,0 +1,70 @@
+//  SMESH SMESH : implementaion of SMESH idl descriptions
+//
+//  Copyright (C) 2003  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
+//
+//
+//
+//  File   : StdMeshers_RadialPrism_3D.hxx
+//  Module : SMESH
+
+#ifndef _SMESH_RadialPrism_3D_HXX_
+#define _SMESH_RadialPrism_3D_HXX_
+
+#include "SMESH_3D_Algo.hxx"
+#include "SMDS_MeshNode.hxx"
+
+#include <vector>
+#include <map>
+
+class StdMeshers_NumberOfLayers;
+class StdMeshers_LayerDistribution;
+class SMESH_MesherHelper;
+
+class StdMeshers_RadialPrism_3D: public SMESH_3D_Algo
+{
+public:
+  StdMeshers_RadialPrism_3D(int hypId, int studyId, SMESH_Gen* gen);
+  virtual ~StdMeshers_RadialPrism_3D();
+
+  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);
+
+protected:
+
+  typedef vector<const SMDS_MeshNode* >            TNodeColumn;
+  typedef map< const SMDS_MeshNode*, TNodeColumn > TNode2ColumnMap;
+
+  TNodeColumn* makeNodeColumn( TNode2ColumnMap&     n2ColMap,
+                               const SMDS_MeshNode* outNode,
+                               const SMDS_MeshNode* inNode);
+
+  bool computeLayerPositions(gp_Pnt pIn, gp_Pnt pOut);
+
+
+  const StdMeshers_NumberOfLayers*    myNbLayerHypo;
+  const StdMeshers_LayerDistribution* myDistributionHypo;
+  SMESH_MesherHelper*                 myHelper;
+  vector< double >                    myLayerPositions;
+};
+
+#endif