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