Salome HOME
PAL13330( When mesh generation does not success, trace where )
[modules/smesh.git] / src / StdMeshers / StdMeshers_Prism_3D.hxx
1 //  SMESH SMESH : implementaion of SMESH idl descriptions
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : StdMeshers_Prism_3D.hxx
25 //  Module : SMESH
26
27 #ifndef _SMESH_Prism_3D_HXX_
28 #define _SMESH_Prism_3D_HXX_
29
30 #include "SMESH_3D_Algo.hxx"
31 #include "SMDS_TypeOfPosition.hxx"
32 #include "SMDS_MeshNode.hxx"
33 #include "SMESH_Block.hxx"
34 #include "SMESH_Mesh.hxx"
35 #include "SMESHDS_Mesh.hxx"
36 #include "SMESH_subMesh.hxx"
37 #include "SMESH_MesherHelper.hxx"
38
39 #include <vector.h>
40 #include <map.h>
41
42 #include <Adaptor3d_Curve.hxx>
43 #include <Adaptor3d_Surface.hxx>
44 #include <Adaptor2d_Curve2d.hxx>
45 #include <BRepAdaptor_Surface.hxx>
46 #include <TopTools_IndexedMapOfOrientedShape.hxx>
47 #include <gp_XYZ.hxx>
48
49
50 class SMESHDS_SubMesh;
51 class TopoDS_Edge;
52 class TopoDS_Faces;
53 struct TNode;
54
55 //typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> TNodeNodeMap;
56 typedef std::vector<const SMDS_MeshNode* > TNodeColumn;
57
58 // map of bottom nodes to the column of nodes above them
59 // (the column includes the bottom nodes)
60 typedef std::map< TNode, TNodeColumn > TNode2ColumnMap;
61 typedef std::map< double, TNodeColumn > TParam2ColumnMap;
62 typedef std::map< double, TNodeColumn >::const_iterator TParam2ColumnIt;
63
64 typedef TopTools_IndexedMapOfOrientedShape TBlockShapes;
65
66 // ===============================================
67 /*!
68  * \brief Structure containing node relative data
69  */
70 // ===============================================
71
72 struct TNode
73 {
74   const SMDS_MeshNode* myNode;
75   gp_XYZ               myParams;
76
77   gp_XYZ GetCoords() const { return gp_XYZ( myNode->X(), myNode->Y(), myNode->Z() ); }
78   gp_XYZ GetParams() const { return myParams; }
79   gp_XYZ& ChangeParams() { return myParams; }
80   SMDS_TypeOfPosition GetPositionType() const
81   { return myNode ? myNode->GetPosition()->GetTypeOfPosition() : SMDS_TOP_UNSPEC; }
82
83   TNode(const SMDS_MeshNode* node = 0): myNode(node) {}
84   bool operator < (const TNode& other) const { return myNode < other.myNode; }
85 };
86
87 // ===============================================================
88 /*!
89  * \brief Tool analyzing and giving access to a prism geometry 
90  *  treating it like a block, i.e. the four side faces are
91  *  emulated by division/uniting of missing/excess faces.
92  *  It also manage associations between block subshapes and a mesh.
93  */
94 // ===============================================================
95
96 class StdMeshers_PrismAsBlock: public SMESH_Block
97 {
98 public:
99   /*!
100    * \brief Constructor. Initialization is needed
101    */
102   StdMeshers_PrismAsBlock();
103
104   ~StdMeshers_PrismAsBlock();
105
106   /*!
107    * \brief Initialization.
108     * \param helper - helper loaded with mesh and 3D shape
109     * \param shape3D - a closed shell or solid
110     * \retval bool - false if a mesh or a shape are KO
111     *
112     * Analyse shape geometry and mesh.
113     * If there are triangles on one of faces, it becomes 'bottom'
114    */
115   bool Init(SMESH_MesherHelper* helper, const TopoDS_Shape& shape3D);
116
117   /*!
118    * \brief Return number of nodes on every vertical edge
119     * \retval int - number of nodes including end nodes
120    */
121   int VerticalSize() const { return myParam2ColumnMaps[0].begin()->second.size(); }
122
123   bool HasNotQuadElemOnTop() const { return myNotQuadOnTop; }
124
125   /*!
126    * \brief Return pointer to column of nodes
127     * \param node - bottom node from which the returned column goes up
128     * \retval const TNodeColumn* - the found column
129    */
130   const TNodeColumn* GetNodeColumn(const SMDS_MeshNode* node) const;
131
132   /*!
133    * \brief Return TParam2ColumnMap for a base edge
134     * \param baseEdgeID - base edge SMESHDS Index
135     * \param isReverse - columns in-block orientation
136     * \retval const TParam2ColumnMap& - map
137    */
138   const TParam2ColumnMap& GetParam2ColumnMap(const int baseEdgeID,
139                                              bool &    isReverse)
140   {
141     std::pair< TParam2ColumnMap*, bool > & col_frw =
142       myShapeIndex2ColumnMap[ baseEdgeID ];
143     isReverse = !col_frw.second;
144     return * col_frw.first;
145   }
146   
147   /*!
148    * \brief Return pointer to mesh
149     * \retval SMESH_Mesh - mesh
150    */
151   SMESH_Mesh* Mesh() const { return myHelper->GetMesh(); }
152
153   /*!
154    * \brief Return pointer to mesh DS
155     * \retval SMESHDS_Mesh - mesh DS
156    */
157   SMESHDS_Mesh* MeshDS() const { return Mesh()->GetMeshDS(); }
158
159   /*!
160    * \brief Return submesh of a shape
161     * \param shapeID - shape given by in-block index
162     * \retval SMESH_subMesh* - found submesh
163    */
164   SMESH_subMesh* SubMesh(const int shapeID) const
165   { return Mesh()->GetSubMesh( Shape( shapeID )); }
166
167   /*!
168    * \brief Return submesh DS of a shape
169     * \param shapeID - shape given by in-block index
170     * \retval SMESHDS_SubMesh* - found submesh DS
171    */
172   SMESHDS_SubMesh* SubMeshDS(const int shapeID) const
173   { return SubMesh(shapeID)->GetSubMeshDS(); }
174
175   /*!
176    * \brief Return a in-block shape
177     * \param shapeID - shape given by in-block index
178     * \retval SMESHDS_SubMesh* - found submesh
179    */
180   const TopoDS_Shape& Shape(const int shapeID) const
181   { return myShapeIDMap( shapeID ); }
182
183   /*!
184    * \brief Return in-block ID of a shape
185     * \param shape - block subshape
186     * \retval int - ID or zero if the shape has no ID
187    */
188   int ShapeID(const TopoDS_Shape& shape) const
189   { return myShapeIDMap.FindIndex( shape ); }
190
191   /*!
192    * \brief Check curve orientation of a bootom edge
193    *  \param meshDS - mesh DS
194    *  \param columnsMap - node columns map of side face
195    *  \param bottomEdge - the bootom edge
196    *  \param sideFaceID - side face in-block ID
197    *  \retval bool - true if orienation coinside with in-block froward orienation
198    */
199   static bool IsForwardEdge(SMESHDS_Mesh*           meshDS,
200                             const TParam2ColumnMap& columnsMap,
201                             const TopoDS_Edge &     bottomEdge,
202                             const int               sideFaceID);
203   /*!
204    * \brief Find wall faces by bottom edges
205     * \param mesh - the mesh
206     * \param mainShape - the prism
207     * \param bottomFace - the bottom face
208     * \param bottomEdges - edges bounding the bottom face
209     * \param wallFaces - faces list to fill in
210    */
211   static bool GetWallFaces( SMESH_Mesh*                     mesh,
212                             const TopoDS_Shape &            mainShape,
213                             const TopoDS_Shape &            bottomFace,
214                             const std::list< TopoDS_Edge >& bottomEdges,
215                             std::list< TopoDS_Face >&       wallFaces);
216
217 private:
218
219   // --------------------------------------------------------------------
220   /*!
221    * \brief Class representing a part of a geom face or
222    * a union of seleral faces. Or just an ordinary geom face
223    *
224    * It's parametrization is within [0,1] range.
225    * It redefines Adaptor3d_Surface::Value(U,V) where U and V are within [0,1]
226    */
227   // --------------------------------------------------------------------
228   class TSideFace: public Adaptor3d_Surface
229   {
230     int                             myID; //!< in-block ID
231     // map used to find out real UV by it's normalized UV
232     TParam2ColumnMap*               myParamToColumnMap;
233     BRepAdaptor_Surface             mySurface;
234     TopoDS_Edge                     myBaseEdge;
235     // first and last normalized params and orientaion for each component or it-self
236     vector< pair< double, double> > myParams;
237     bool                            myIsForward;
238     vector< TSideFace* >            myComponents;
239     SMESH_MesherHelper *            myHelper;
240   public:
241     TSideFace( SMESH_MesherHelper* helper,
242                const int           faceID,
243                const TopoDS_Face&  face,
244                const TopoDS_Edge&  baseEdge,
245                TParam2ColumnMap*   columnsMap,
246                const double        first = 0.0,
247                const double        last = 1.0);
248     TSideFace( const std::vector< TSideFace* >&             components,
249                const std::vector< pair< double, double> > & params);
250     TSideFace( const TSideFace& other );
251     ~TSideFace();
252     bool IsComplex() const
253     { return ( NbComponents() > 0 || myParams[0].first != 0. || myParams[0].second != 1. ); }
254     int FaceID() const { return myID; }
255     TParam2ColumnMap* GetColumns() const { return myParamToColumnMap; }
256     gp_XY GetNodeUV(const TopoDS_Face& F, const SMDS_MeshNode* n) const
257     { return myHelper->GetNodeUV( F, n ); }
258     const TopoDS_Edge & BaseEdge() const { return myBaseEdge; }
259     int ColumnHeight() const {
260       if ( NbComponents() ) return GetComponent(0)->GetColumns()->begin()->second.size();
261       else                  return GetColumns()->begin()->second.size(); }
262     double GetColumns(const double U, TParam2ColumnIt & col1, TParam2ColumnIt& col2 ) const;
263     int NbComponents() const { return myComponents.size(); }
264     TSideFace* GetComponent(const int i) const { return myComponents.at( i ); }
265     void SetComponent(const int i, TSideFace* c)
266     { if ( myComponents[i] ) delete myComponents[i]; myComponents[i]=c; }
267     TSideFace* GetComponent(const double U, double& localU) const;
268     bool IsForward() const { return myIsForward; }
269     // boundary geometry for a face
270     Adaptor3d_Surface* Surface() const { return new TSideFace( *this ); }
271     bool GetPCurves(Adaptor2d_Curve2d* pcurv[4]) const;
272     Adaptor2d_Curve2d* HorizPCurve(const bool isTop, const TopoDS_Face& horFace) const;
273     Adaptor3d_Curve* HorizCurve(const bool isTop) const;
274     Adaptor3d_Curve* VertiCurve(const bool isMax) const;
275     TopoDS_Edge GetEdge( const int edge ) const;
276     int InsertSubShapes( TBlockShapes& shapeMap ) const;
277     // redefine Adaptor methods
278     gp_Pnt Value(const Standard_Real U,const Standard_Real V) const;
279   };
280
281   // --------------------------------------------------------------------
282   /*!
283    * \brief Class emulating geometry of a vertical edge
284    */
285   // --------------------------------------------------------------------
286   class TVerticalEdgeAdaptor: public Adaptor3d_Curve
287   {
288     const TNodeColumn* myNodeColumn;
289   public:
290     TVerticalEdgeAdaptor( const TParam2ColumnMap* columnsMap, const double parameter );
291     gp_Pnt Value(const Standard_Real U) const;
292     Standard_Real FirstParameter() const { return 0; }
293     Standard_Real LastParameter() const { return 1; }
294   };
295
296   // --------------------------------------------------------------------
297   /*!
298    * \brief Class emulating geometry of a hirizontal edge
299    */
300   // --------------------------------------------------------------------
301   class THorizontalEdgeAdaptor: public Adaptor3d_Curve
302   {
303     const TSideFace* mySide;
304     double           myV;
305   public:
306     THorizontalEdgeAdaptor( const TSideFace* sideFace, const bool isTop)
307       :mySide(sideFace), myV( isTop ? 1.0 : 0.0 ) {}
308     gp_Pnt Value(const Standard_Real U) const;
309     Standard_Real FirstParameter() const { return 0; }
310     Standard_Real LastParameter() const { return 1; }
311   };
312
313   // --------------------------------------------------------------------
314   /*!
315    * \brief Class emulating pcurve on a hirizontal face
316    */
317   // --------------------------------------------------------------------
318   class TPCurveOnHorFaceAdaptor: public Adaptor2d_Curve2d
319   {
320     const TSideFace*  mySide;
321     int               myZ;
322     TopoDS_Face       myFace;
323   public:
324     TPCurveOnHorFaceAdaptor( const TSideFace*   sideFace,
325                              const bool         isTop,
326                              const TopoDS_Face& horFace)
327       : mySide(sideFace), myFace(horFace), myZ(isTop ? mySide->ColumnHeight() - 1 : 0 ) {}
328     gp_Pnt2d Value(const Standard_Real U) const;
329     Standard_Real FirstParameter() const { return 0; }
330     Standard_Real LastParameter() const { return 1; }
331   };
332   // --------------------------------------------------------------------
333
334   bool myNotQuadOnTop;
335   SMESH_MesherHelper* myHelper;
336   TBlockShapes myShapeIDMap;
337
338   // container of 4 side faces
339   TSideFace*                 mySide; 
340   // node columns for each base edge
341   vector< TParam2ColumnMap > myParam2ColumnMaps;
342   // to find a column for a node by edge SMESHDS Index
343   map< int, pair< TParam2ColumnMap*, bool > > myShapeIndex2ColumnMap;
344
345   
346   //vector< SMESH_subMesh* >           mySubMeshesVec; // submesh by in-block id
347 };
348
349 // =============================================
350 /*!
351  * \brief Algo building prisms on a prism shape
352  */
353 // =============================================
354
355 class StdMeshers_Prism_3D: public SMESH_3D_Algo
356 {
357 public:
358   StdMeshers_Prism_3D(int hypId, int studyId, SMESH_Gen* gen);
359   virtual ~StdMeshers_Prism_3D();
360
361   virtual bool CheckHypothesis(SMESH_Mesh&                          aMesh,
362                                const TopoDS_Shape&                  aShape,
363                                SMESH_Hypothesis::Hypothesis_Status& aStatus);
364
365   virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape);
366
367   /*!
368    * \brief Enable removal of quadrangles from the bottom face and
369    * triangles creation there by projection from the top
370    * (sole face meshed with triangles is considered to be a bottom one).
371    * If there are two faces with triangles, triangles must
372    * be of the same topology, else the algo fails.
373    * The method must be called before Compute()
374    */
375   void ProjectTriangles() { myProjectTriangles = true; }
376
377   /*!
378    * \brief Create prisms
379     * \param nodeColumns - columns of nodes generated from nodes of a mesh face
380     * \param helper - helper initialized by mesh and shape to add prisms to
381    */
382   static void AddPrisms( vector<const TNodeColumn*> & nodeColumns,
383                          SMESH_MesherHelper*          helper);
384
385 private:
386
387   /*!
388    * \brief Find correspondence between bottom and top nodes.
389    *  If elements on the bottom and top faces are topologically different,
390    *  and projection is possible and allowed, perform the projection
391     * \retval bool - is a success or not
392    */
393   bool assocOrProjBottom2Top();
394
395   /*!
396    * \brief Remove quadrangles from the top face and
397    * create triangles there by projection from the bottom
398     * \retval bool - a success or not
399    */
400   bool projectBottomToTop();
401
402   /*!
403    * \brief Set projection coordinates of a node to a face and it's subshapes
404     * \param faceID - the face given by in-block ID
405     * \param params - node normalized parameters
406     * \retval bool - is a success
407    */
408   bool setFaceAndEdgesXYZ( const int faceID, const gp_XYZ& params, int z );
409
410 private:
411
412   bool myProjectTriangles;
413
414   StdMeshers_PrismAsBlock myBlock;
415   SMESH_MesherHelper*     myHelper;
416
417   vector<gp_XYZ>            myShapeXYZ; // point on each sub-shape
418
419   // map of bottom nodes to the column of nodes above them
420   // (the column includes the bottom node)
421   typedef std::map< TNode, TNodeColumn > TNode2ColumnMap;
422   TNode2ColumnMap  myBotToColumnMap;
423 };
424
425 #endif