Salome HOME
Merge from V5_1_4_BR (5_1_4rc2) 09/06/2010
[modules/smesh.git] / src / SMESH / SMESH_MesherHelper.hxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
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 // File:      SMESH_MesherHelper.hxx
24 // Created:   15.02.06 14:48:09
25 // Author:    Sergey KUUL
26 //
27 #ifndef SMESH_MesherHelper_HeaderFile
28 #define SMESH_MesherHelper_HeaderFile
29
30 #include "SMESH_SMESH.hxx"
31
32 #include "SMESH_MeshEditor.hxx" // needed for many meshers
33 #include <SMDS_MeshNode.hxx>
34 #include <SMDS_QuadraticEdge.hxx>
35
36 #include <Geom_Surface.hxx>
37 #include <TopoDS_Face.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <gp_Pnt2d.hxx>
40
41 #include <map>
42
43 class GeomAPI_ProjectPointOnSurf;
44
45 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>           TLinkNodeMap;
46 typedef std::map<SMESH_TLink, const SMDS_MeshNode*>::iterator ItTLinkNode;
47
48 typedef SMDS_Iterator<const TopoDS_Shape*>  PShapeIterator;
49 typedef boost::shared_ptr< PShapeIterator > PShapeIteratorPtr;
50   
51 typedef std::vector<const SMDS_MeshNode* > TNodeColumn;
52 typedef std::map< double, TNodeColumn >    TParam2ColumnMap;
53
54 typedef gp_XY (*xyFunPtr)(const gp_XY& uv1, const gp_XY& uv2);
55
56 //=======================================================================
57 /*!
58  * \brief It helps meshers to add elements
59  *
60  * It allow meshers not to care about creation of medium nodes
61  * when filling a quadratic mesh. Helper does it itself.
62  * It defines degree of elements to create when IsQuadraticSubMesh()
63  * is called.
64  */
65 //=======================================================================
66
67 class SMESH_EXPORT SMESH_MesherHelper
68 {
69 public:
70   // ---------- PUBLIC UTILITIES ----------
71   
72   /*!
73    * \brief Returns true if given node is medium
74     * \param n - node to check
75     * \param typeToCheck - type of elements containing the node to ask about node status
76     * \retval bool - check result
77    */
78   static bool IsMedium(const SMDS_MeshNode*      node,
79                        const SMDSAbs_ElementType typeToCheck = SMDSAbs_All);
80
81   /*!
82    * \brief Load nodes bound to face into a map of node columns
83     * \param theParam2ColumnMap - map of node columns to fill
84     * \param theFace - the face on which nodes are searched for
85     * \param theBaseEdge - the edge nodes of which are columns' bases
86     * \param theMesh - the mesh containing nodes
87     * \retval bool - false if something is wrong
88    * 
89    * The key of the map is a normalized parameter of each
90    * base node on theBaseEdge.
91    * This method works in supposition that nodes on the face
92    * forms a rectangular grid and elements can be quardrangles or triangles
93    */
94   static bool LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
95                               const TopoDS_Face& theFace,
96                               const TopoDS_Edge& theBaseEdge,
97                               SMESHDS_Mesh*      theMesh);
98   /*!
99    * \brief Return support shape of a node
100    * \param node - the node
101    * \param meshDS - mesh DS
102    * \retval TopoDS_Shape - found support shape
103    */
104   static TopoDS_Shape GetSubShapeByNode(const SMDS_MeshNode* node,
105                                         SMESHDS_Mesh*        meshDS);
106
107   /*!
108    * \brief Return a valid node index, fixing the given one if necessary
109     * \param ind - node index
110     * \param nbNodes - total nb of nodes
111     * \retval int - valid node index
112    */
113   static int WrapIndex(const int ind, const int nbNodes) {
114     if ( ind < 0 ) return nbNodes + ind % nbNodes;
115     if ( ind >= nbNodes ) return ind % nbNodes;
116     return ind;
117   }
118
119   /*!
120    * \brief Return number of unique ancestors of the shape
121    */
122   static int NbAncestors(const TopoDS_Shape& shape,
123                          const SMESH_Mesh&   mesh,
124                          TopAbs_ShapeEnum    ancestorType=TopAbs_SHAPE);
125   /*!
126    * \brief Return iterator on ancestors of the given type
127    */
128   static PShapeIteratorPtr GetAncestors(const TopoDS_Shape& shape,
129                                         const SMESH_Mesh&   mesh,
130                                         TopAbs_ShapeEnum    ancestorType);
131
132   /*!
133    * \brief Return orientation of sub-shape in the main shape
134    */
135   static TopAbs_Orientation GetSubShapeOri(const TopoDS_Shape& shape,
136                                            const TopoDS_Shape& subShape);
137
138   static bool IsSubShape( const TopoDS_Shape& shape, const TopoDS_Shape& mainShape );
139
140   static bool IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh );
141
142
143 public:
144   // ---------- PUBLIC INSTANCE METHODS ----------
145
146   // constructor
147   SMESH_MesherHelper(SMESH_Mesh& theMesh);
148
149   SMESH_Mesh* GetMesh() const { return myMesh; }
150     
151   SMESHDS_Mesh* GetMeshDS() const { return GetMesh()->GetMeshDS(); }
152     
153   /*!
154    * Check submesh for given shape: if all elements on this shape are quadratic,
155    * quadratic elements will be created. Also fill myTLinkNodeMap
156    */
157   bool IsQuadraticSubMesh(const TopoDS_Shape& theShape);
158   /*!
159    * \brief Set order of elements to create without calling IsQuadraticSubMesh()
160    */
161   void SetIsQuadratic(const bool theBuildQuadratic)
162   { myCreateQuadratic = theBuildQuadratic; }
163   /*!
164    * \brief Return myCreateQuadratic flag
165    */
166   bool GetIsQuadratic() const { return myCreateQuadratic; }
167
168   /*!
169    * \brief Move medium nodes of faces and volumes to fix distorted elements
170    * \param volumeOnly - fix nodes on geom faces or not if the shape is solid
171    */
172   void FixQuadraticElements(bool volumeOnly=true);
173
174   /*!
175    * \brief To set created elements on the shape set by IsQuadraticSubMesh()
176    *        or the next methods. By defaul elements are set on the shape if
177    *        a mesh has no shape to be meshed
178    */
179   void SetElementsOnShape(bool toSet) { mySetElemOnShape = toSet; }
180
181   /*!
182    * \brief Set shape to make elements on without calling IsQuadraticSubMesh()
183    */
184   void SetSubShape(const int           subShapeID);//!==SMESHDS_Mesh::ShapeToIndex(shape)
185   void SetSubShape(const TopoDS_Shape& subShape);
186   /*!
187    * \brief Return ID of the shape set by IsQuadraticSubMesh() or SetSubShape() 
188     * \retval int - shape index in SMESHDS
189    */
190   int GetSubShapeID() const { return myShapeID; }
191   /*!
192    * \brief Return the shape set by IsQuadraticSubMesh() or SetSubShape() 
193    */
194   const TopoDS_Shape& GetSubShape() const  { return myShape; }
195
196   /*!
197    * Creates a node
198    */
199   SMDS_MeshNode* AddNode(double x, double y, double z, int ID = 0);
200   /*!
201    * Creates quadratic or linear edge
202    */
203   SMDS_MeshEdge* AddEdge(const SMDS_MeshNode* n1,
204                          const SMDS_MeshNode* n2,
205                          const int id = 0, 
206                          const bool force3d = true);
207   /*!
208    * Creates quadratic or linear triangle
209    */
210   SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1,
211                          const SMDS_MeshNode* n2,
212                          const SMDS_MeshNode* n3,
213                          const int id=0, 
214                          const bool force3d = false);
215   /*!
216    * Creates quadratic or linear quadrangle
217    */
218   SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1,
219                          const SMDS_MeshNode* n2,
220                          const SMDS_MeshNode* n3,
221                          const SMDS_MeshNode* n4,
222                          const int id = 0,
223                          const bool force3d = false);
224   /*!
225    * Creates quadratic or linear tetraahedron
226    */
227   SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
228                              const SMDS_MeshNode* n2,
229                              const SMDS_MeshNode* n3,
230                              const SMDS_MeshNode* n4,
231                              const int id = 0,
232                              const bool force3d = true);
233   /*!
234    * Creates quadratic or linear pyramid
235    */
236   SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
237                              const SMDS_MeshNode* n2,
238                              const SMDS_MeshNode* n3,
239                              const SMDS_MeshNode* n4,
240                              const SMDS_MeshNode* n5,
241                              const int id = 0,
242                              const bool force3d = true);
243   /*!
244    * Creates quadratic or linear pentahedron
245    */
246   SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
247                              const SMDS_MeshNode* n2,
248                              const SMDS_MeshNode* n3,
249                              const SMDS_MeshNode* n4,
250                              const SMDS_MeshNode* n5,
251                              const SMDS_MeshNode* n6,
252                              const int id = 0, 
253                              const bool force3d = true);
254   /*!
255    * Creates quadratic or linear hexahedron
256    */
257   SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
258                              const SMDS_MeshNode* n2,
259                              const SMDS_MeshNode* n3,
260                              const SMDS_MeshNode* n4,
261                              const SMDS_MeshNode* n5,
262                              const SMDS_MeshNode* n6,
263                              const SMDS_MeshNode* n7,
264                              const SMDS_MeshNode* n8,
265                              const int id = 0, 
266                              bool force3d = true);
267   /*!
268    * \brief Return U of the given node on the edge
269    */
270   double GetNodeU(const TopoDS_Edge&   theEdge,
271                   const SMDS_MeshNode* theNode,
272                   const SMDS_MeshNode* inEdgeNode=0,
273                   bool*                check=0);
274   /*!
275    * \brief Return node UV on face
276    *  \param inFaceNode - a node of element being created located inside a face
277    */
278   gp_XY GetNodeUV(const TopoDS_Face&   F,
279                   const SMDS_MeshNode* n,
280                   const SMDS_MeshNode* inFaceNode=0,
281                   bool*                check=0) const;
282   /*!
283    * \brief Check and fix node UV on a face
284    *  \param force - check even if checks of other nodes on this face passed OK
285    *  \retval bool - false if UV is bad and could not be fixed
286    */
287   bool CheckNodeUV(const TopoDS_Face&   F,
288                    const SMDS_MeshNode* n,
289                    gp_XY&               uv,
290                    const double         tol,
291                    const bool           force=false) const;
292   /*!
293    * \brief Check and fix node U on an edge
294    *  \param force - check even if checks of other nodes on this edge passed OK
295    *  \retval bool - false if U is bad and could not be fixed
296    */
297   bool CheckNodeU(const TopoDS_Edge&   E,
298                   const SMDS_MeshNode* n,
299                   double&              u,
300                   const double         tol,
301                   const bool           force=false) const;
302   /*!
303    * \brief Return middle UV taking in account surface period
304    */
305   static gp_XY GetMiddleUV(const Handle(Geom_Surface)& surface,
306                            const gp_XY&                uv1,
307                            const gp_XY&                uv2);
308   /*!
309    * \brief Define a pointer to wrapper over a function of gp_XY class,
310    *       suitable to pass as xyFunPtr to applyIn2D().
311    *       For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function
312    *       calling gp_XY::Added(gp_XY), which is to be used like following
313    *       applyIn2D(surf, uv1, uv2, gp_XY_Added)
314    */
315 #define gp_XY_FunPtr(meth) \
316   static gp_XY __gpXY_##meth (const gp_XY& uv1, const gp_XY& uv2) { return uv1.meth( uv2 ); } \
317   static xyFunPtr gp_XY_##meth = & __gpXY_##meth
318
319   /*!
320    * \brief Perform given operation on two 2d points in parameric space of given surface.
321    *        It takes into account period of the surface. Use gp_XY_FunPtr macro
322    *        to easily define pointer to function of gp_XY class.
323    */
324   static gp_XY applyIn2D(const Handle(Geom_Surface)& surface,
325                          const gp_XY&                uv1,
326                          const gp_XY&                uv2,
327                          xyFunPtr                    fun,
328                          const bool                  resultInPeriod=true);
329                           
330   /*!
331    * \brief Check if inFaceNode argument is necessary for call GetNodeUV(F,..)
332     * \retval bool - return true if the face is periodic
333     *
334     * If F is Null, answer about subshape set through IsQuadraticSubMesh() or
335     * SetSubShape()
336    */
337   bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const;
338
339   /*!
340    * \brief Return projector intitialized by given face without location, which is returned
341    */
342   GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
343                                            TopLoc_Location&   loc,
344                                            double             tol=0 ) const; 
345
346   /*!
347    * \brief Check if shape is a degenerated edge or it's vertex
348     * \param subShape - edge or vertex index in SMESHDS
349     * \retval bool - true if subShape is a degenerated shape
350     *
351     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called
352    */
353   bool IsDegenShape(const int subShape) const
354   { return myDegenShapeIds.find( subShape ) != myDegenShapeIds.end(); }
355   /*!
356    * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
357    *        has a degenerated edges
358     * \retval bool - true if it has
359    */
360   bool HasDegeneratedEdges() const { return !myDegenShapeIds.empty(); }
361
362   /*!
363    * \brief Check if shape is a seam edge or it's vertex
364     * \param subShape - edge or vertex index in SMESHDS
365     * \retval bool - true if subShape is a seam shape
366     *
367     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called.
368     * Seam shape has two 2D alternative represenations on the face
369    */
370   bool IsSeamShape(const int subShape) const
371   { return mySeamShapeIds.find( subShape ) != mySeamShapeIds.end(); }
372   /*!
373    * \brief Check if shape is a seam edge or it's vertex
374     * \param subShape - edge or vertex
375     * \retval bool - true if subShape is a seam shape
376     *
377     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called.
378     * Seam shape has two 2D alternative represenations on the face
379    */
380   bool IsSeamShape(const TopoDS_Shape& subShape) const
381   { return IsSeamShape( GetMeshDS()->ShapeToIndex( subShape )); }
382   /*!
383    * \brief Return true if an edge or a vertex encounters twice in face wire
384    *  \param subShape - Id of edge or vertex
385    */
386   bool IsRealSeam(const int subShape) const
387   { return mySeamShapeIds.find( -subShape ) != mySeamShapeIds.end(); }
388   /*!
389    * \brief Return true if an edge or a vertex encounters twice in face wire
390    *  \param subShape - edge or vertex
391    */
392   bool IsRealSeam(const TopoDS_Shape& subShape) const
393   { return IsRealSeam( GetMeshDS()->ShapeToIndex( subShape)); }
394   /*!
395    * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
396    *        has a seam edge
397     * \retval bool - true if it has
398    */
399   bool HasSeam() const { return !mySeamShapeIds.empty(); }
400   /*!
401    * \brief Return index of periodic parametric direction of a closed face
402     * \retval int - 1 for U, 2 for V direction
403    */
404   int GetPeriodicIndex() const { return myParIndex; }
405   /*!
406    * \brief Return an alternative parameter for a node on seam
407    */
408   double GetOtherParam(const double param) const;
409
410   /*!
411    * \brief Return existing or create new medium nodes between given ones
412    *  \param force3d - true means node creation at the middle between the
413    *                   two given nodes, else node position is found on its
414    *                   supporting geometrical shape, if any.
415    */
416   const SMDS_MeshNode* GetMediumNode(const SMDS_MeshNode* n1,
417                                      const SMDS_MeshNode* n2,
418                                      const bool force3d);
419   /*!
420    * \brief Add a link in my data structure
421    */
422   void AddTLinkNode(const SMDS_MeshNode* n1,
423                     const SMDS_MeshNode* n2,
424                     const SMDS_MeshNode* n12);
425   /*!
426    * \brief Add many links in my data structure
427    */
428   void AddTLinkNodeMap(const TLinkNodeMap& aMap)
429     { myTLinkNodeMap.insert(aMap.begin(), aMap.end()); }
430
431   /**
432    * Returns myTLinkNodeMap
433    */
434   const TLinkNodeMap& GetTLinkNodeMap() const { return myTLinkNodeMap; }
435
436   /**
437    * Check mesh without geometry for: if all elements on this shape are quadratic,
438    * quadratic elements will be created.
439    * Used then generated 3D mesh without geometry.
440    */
441   enum MType{ LINEAR, QUADRATIC, COMP };
442   MType IsQuadraticMesh();
443   
444   virtual ~SMESH_MesherHelper();
445
446 protected:
447
448   /*!
449    * \brief Select UV on either of 2 pcurves of a seam edge, closest to the given UV
450     * \param uv1 - UV on the seam
451     * \param uv2 - UV within a face
452     * \retval gp_Pnt2d - selected UV
453    */
454   gp_Pnt2d GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const;
455
456  private:
457
458   // Forbiden copy constructor
459   SMESH_MesherHelper (const SMESH_MesherHelper& theOther) {};
460
461   // special map for using during creation of quadratic elements
462   TLinkNodeMap    myTLinkNodeMap;
463
464   std::set< int > myDegenShapeIds;
465   std::set< int > mySeamShapeIds;
466   double          myPar1[2], myPar2[2]; // U and V bounds of a closed periodic surface
467   int             myParIndex;     // bounds' index (1-U, 2-V, 3-both)
468
469   typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2Projector;
470   TID2Projector   myFace2Projector;
471
472   TopoDS_Shape    myShape;
473   SMESH_Mesh*     myMesh;
474   int             myShapeID;
475
476   // to create quadratic elements
477   bool            myCreateQuadratic;
478   bool            mySetElemOnShape;
479   std::set< int > myOkNodePosShapes;
480
481 };
482
483
484 #endif