Salome HOME
Merge from V5_1_main 14/05/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                   bool*                check=0);
273   /*!
274    * \brief Return node UV on face
275    *  \param inFaceNode - a node of element being created located inside a face
276    */
277   gp_XY GetNodeUV(const TopoDS_Face&   F,
278                   const SMDS_MeshNode* n,
279                   const SMDS_MeshNode* inFaceNode=0,
280                   bool*                check=0) const;
281   /*!
282    * \brief Check and fix node UV on a face
283    *  \param force - check even if checks of other nodes on this face passed OK
284    *  \retval bool - false if UV is bad and could not be fixed
285    */
286   bool CheckNodeUV(const TopoDS_Face&   F,
287                    const SMDS_MeshNode* n,
288                    gp_XY&               uv,
289                    const double         tol,
290                    const bool           force=false) const;
291   /*!
292    * \brief Check and fix node U on an edge
293    *  \param force - check even if checks of other nodes on this edge passed OK
294    *  \retval bool - false if U is bad and could not be fixed
295    */
296   bool CheckNodeU(const TopoDS_Edge&   E,
297                   const SMDS_MeshNode* n,
298                   double&              u,
299                   const double         tol,
300                   const bool           force=false) const;
301   /*!
302    * \brief Return middle UV taking in account surface period
303    */
304   static gp_XY GetMiddleUV(const Handle(Geom_Surface)& surface,
305                            const gp_XY&                uv1,
306                            const gp_XY&                uv2);
307   /*!
308    * \brief Define a pointer to wrapper over a function of gp_XY class,
309    *       suitable to pass as xyFunPtr to applyIn2D().
310    *       For exaple gp_XY_FunPtr(Added) defines pointer gp_XY_Added to function
311    *       calling gp_XY::Added(gp_XY), which is to be used like following
312    *       applyIn2D(surf, uv1, uv2, gp_XY_Added)
313    */
314 #define gp_XY_FunPtr(meth) \
315   static gp_XY __gpXY_##meth (const gp_XY& uv1, const gp_XY& uv2) { return uv1.meth( uv2 ); } \
316   static xyFunPtr gp_XY_##meth = & __gpXY_##meth
317
318   /*!
319    * \brief Perform given operation on two 2d points in parameric space of given surface.
320    *        It takes into account period of the surface. Use gp_XY_FunPtr macro
321    *        to easily define pointer to function of gp_XY class.
322    */
323   static gp_XY applyIn2D(const Handle(Geom_Surface)& surface,
324                          const gp_XY&                uv1,
325                          const gp_XY&                uv2,
326                          xyFunPtr                    fun,
327                          const bool                  resultInPeriod=true);
328                           
329   /*!
330    * \brief Check if inFaceNode argument is necessary for call GetNodeUV(F,..)
331     * \retval bool - return true if the face is periodic
332     *
333     * If F is Null, answer about subshape set through IsQuadraticSubMesh() or
334     * SetSubShape()
335    */
336   bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const;
337
338   /*!
339    * \brief Return projector intitialized by given face without location, which is returned
340    */
341   GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F,
342                                            TopLoc_Location&   loc,
343                                            double             tol=0 ) const; 
344
345   /*!
346    * \brief Check if shape is a degenerated edge or it's vertex
347     * \param subShape - edge or vertex index in SMESHDS
348     * \retval bool - true if subShape is a degenerated shape
349     *
350     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called
351    */
352   bool IsDegenShape(const int subShape) const
353   { return myDegenShapeIds.find( subShape ) != myDegenShapeIds.end(); }
354   /*!
355    * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
356    *        has a degenerated edges
357     * \retval bool - true if it has
358    */
359   bool HasDegeneratedEdges() const { return !myDegenShapeIds.empty(); }
360
361   /*!
362    * \brief Check if shape is a seam edge or it's vertex
363     * \param subShape - edge or vertex index in SMESHDS
364     * \retval bool - true if subShape is a seam shape
365     *
366     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called.
367     * Seam shape has two 2D alternative represenations on the face
368    */
369   bool IsSeamShape(const int subShape) const
370   { return mySeamShapeIds.find( subShape ) != mySeamShapeIds.end(); }
371   /*!
372    * \brief Check if shape is a seam edge or it's vertex
373     * \param subShape - edge or vertex
374     * \retval bool - true if subShape is a seam shape
375     *
376     * It works only if IsQuadraticSubMesh() or SetSubShape() has been called.
377     * Seam shape has two 2D alternative represenations on the face
378    */
379   bool IsSeamShape(const TopoDS_Shape& subShape) const
380   { return IsSeamShape( GetMeshDS()->ShapeToIndex( subShape )); }
381   /*!
382    * \brief Return true if an edge or a vertex encounters twice in face wire
383    *  \param subShape - Id of edge or vertex
384    */
385   bool IsRealSeam(const int subShape) const
386   { return mySeamShapeIds.find( -subShape ) != mySeamShapeIds.end(); }
387   /*!
388    * \brief Return true if an edge or a vertex encounters twice in face wire
389    *  \param subShape - edge or vertex
390    */
391   bool IsRealSeam(const TopoDS_Shape& subShape) const
392   { return IsRealSeam( GetMeshDS()->ShapeToIndex( subShape)); }
393   /*!
394    * \brief Check if the shape set through IsQuadraticSubMesh() or SetSubShape()
395    *        has a seam edge
396     * \retval bool - true if it has
397    */
398   bool HasSeam() const { return !mySeamShapeIds.empty(); }
399   /*!
400    * \brief Return index of periodic parametric direction of a closed face
401     * \retval int - 1 for U, 2 for V direction
402    */
403   int GetPeriodicIndex() const { return myParIndex; }
404   /*!
405    * \brief Return an alternative parameter for a node on seam
406    */
407   double GetOtherParam(const double param) const;
408
409   /*!
410    * \brief Return existing or create new medium nodes between given ones
411    *  \param force3d - true means node creation at the middle between the
412    *                   two given nodes, else node position is found on its
413    *                   supporting geometrical shape, if any.
414    */
415   const SMDS_MeshNode* GetMediumNode(const SMDS_MeshNode* n1,
416                                      const SMDS_MeshNode* n2,
417                                      const bool force3d);
418   /*!
419    * \brief Add a link in my data structure
420    */
421   void AddTLinkNode(const SMDS_MeshNode* n1,
422                     const SMDS_MeshNode* n2,
423                     const SMDS_MeshNode* n12);
424   /*!
425    * \brief Add many links in my data structure
426    */
427   void AddTLinkNodeMap(const TLinkNodeMap& aMap)
428     { myTLinkNodeMap.insert(aMap.begin(), aMap.end()); }
429
430   /**
431    * Returns myTLinkNodeMap
432    */
433   const TLinkNodeMap& GetTLinkNodeMap() const { return myTLinkNodeMap; }
434
435   /**
436    * Check mesh without geometry for: if all elements on this shape are quadratic,
437    * quadratic elements will be created.
438    * Used then generated 3D mesh without geometry.
439    */
440   enum MType{ LINEAR, QUADRATIC, COMP };
441   MType IsQuadraticMesh();
442   
443   virtual ~SMESH_MesherHelper();
444
445 protected:
446
447   /*!
448    * \brief Select UV on either of 2 pcurves of a seam edge, closest to the given UV
449     * \param uv1 - UV on the seam
450     * \param uv2 - UV within a face
451     * \retval gp_Pnt2d - selected UV
452    */
453   gp_Pnt2d GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const;
454
455  private:
456
457   // Forbiden copy constructor
458   SMESH_MesherHelper (const SMESH_MesherHelper& theOther) {};
459
460   // special map for using during creation of quadratic elements
461   TLinkNodeMap    myTLinkNodeMap;
462
463   std::set< int > myDegenShapeIds;
464   std::set< int > mySeamShapeIds;
465   double          myPar1[2], myPar2[2]; // U and V bounds of a closed periodic surface
466   int             myParIndex;     // bounds' index (1-U, 2-V, 3-both)
467
468   typedef std::map< int, GeomAPI_ProjectPointOnSurf* > TID2Projector;
469   TID2Projector   myFace2Projector;
470
471   TopoDS_Shape    myShape;
472   SMESH_Mesh*     myMesh;
473   int             myShapeID;
474
475   // to create quadratic elements
476   bool            myCreateQuadratic;
477   bool            mySetElemOnShape;
478   std::set< int > myOkNodePosShapes;
479
480 };
481
482
483 #endif