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