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 =
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 =
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
+
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
+
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
+
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
+
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
+
--- /dev/null
+// 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();
--- /dev/null
+// 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
--- /dev/null
+// 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 );
+ }
+}
+
--- /dev/null
+// 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
--- /dev/null
+// 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 );
+ }
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 );
+ }
+}
+
--- /dev/null
+// 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
--- /dev/null
+// 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");
+}
--- /dev/null
+// 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