Salome HOME
enable ComputeParameters() to find a better solution in hard cases
[modules/smesh.git] / src / SMESHUtils / SMESH_Block.hxx
1 // Copyright (C) 2007-2013  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_Block.hxx
24 // Created   : Tue Nov 30 12:42:18 2004
25 // Author    : Edward AGAPOV (eap)
26 //
27 #ifndef SMESH_Block_HeaderFile
28 #define SMESH_Block_HeaderFile
29
30 #include "SMESH_Utils.hxx"
31
32 //#include <Geom2d_Curve.hxx>
33 //#include <Geom_Curve.hxx>
34 //#include <Geom_Surface.hxx>
35
36 #include <TopExp.hxx>
37 #include <TopTools_IndexedMapOfOrientedShape.hxx>
38 #include <TopoDS_Edge.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <TopoDS_Shell.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <gp_XY.hxx>
43 #include <gp_XYZ.hxx>
44 #include <math_FunctionSetWithDerivatives.hxx>
45
46 #include <ostream>
47 #include <vector>
48 #include <list>
49
50 class SMDS_MeshVolume;
51 class SMDS_MeshNode;
52 class Adaptor3d_Surface;
53 class Adaptor2d_Curve2d;
54 class Adaptor3d_Curve;
55 class gp_Pnt;
56
57 // =========================================================
58 // class calculating coordinates of 3D points by normalized
59 // parameters inside the block and vice versa
60 // =========================================================
61
62 class SMESHUtils_EXPORT SMESH_Block: public math_FunctionSetWithDerivatives
63 {
64  public:
65   enum TShapeID {
66     // ----------------------------
67     // Ids of the block sub-shapes
68     // ----------------------------
69     ID_NONE = 0,
70
71     ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111,
72
73     ID_Ex00, ID_Ex10, ID_Ex01, ID_Ex11,
74     ID_E0y0, ID_E1y0, ID_E0y1, ID_E1y1,
75     ID_E00z, ID_E10z, ID_E01z, ID_E11z,
76
77     ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz,
78
79     ID_Shell
80     };
81   enum { // to use TShapeID for indexing certain type subshapes
82
83     ID_FirstV = ID_V000, ID_FirstE = ID_Ex00, ID_FirstF = ID_Fxy0
84
85   };
86
87
88  public:
89   // -------------------------------------------------
90   // Block topology in terms of block sub-shapes' ids
91   // -------------------------------------------------
92
93   static int NbVertices()  { return  8; }
94   static int NbEdges()     { return 12; }
95   static int NbFaces()     { return  6; }
96   static int NbSubShapes() { return ID_Shell; }
97   // to avoid magic numbers when allocating memory for subshapes
98
99   static inline bool IsVertexID( int theShapeID )
100   { return ( theShapeID >= ID_V000 && theShapeID <= ID_V111 ); }
101
102   static inline bool IsEdgeID( int theShapeID )
103   { return ( theShapeID >= ID_Ex00 && theShapeID <= ID_E11z ); }
104
105   static inline bool IsFaceID( int theShapeID )
106   { return ( theShapeID >= ID_Fxy0 && theShapeID <= ID_F1yz ); }
107
108   static int ShapeIndex( int theShapeID )
109   {
110     if ( IsVertexID( theShapeID )) return theShapeID - ID_V000;
111     if ( IsEdgeID( theShapeID ))   return theShapeID - ID_Ex00;
112     if ( IsFaceID( theShapeID ))   return theShapeID - ID_Fxy0;
113     return 0;
114   }
115   // return index [0-...] for each type of sub-shapes,
116   // for example :
117   // ShapeIndex( ID_Ex00 ) == 0
118   // ShapeIndex( ID_Ex10 ) == 1
119
120   static void GetFaceEdgesIDs (const int faceID, std::vector< int >& edgeVec );
121   // return edges IDs of a face in the order u0, u1, 0v, 1v
122
123   static void GetEdgeVertexIDs (const int edgeID, std::vector< int >& vertexVec );
124   // return vertex IDs of an edge
125
126   static int GetCoordIndOnEdge (const int theEdgeID)
127   { return (theEdgeID < ID_E0y0) ? 1 : (theEdgeID < ID_E00z) ? 2 : 3; }
128   // return an index of a coordinate which varies along the edge
129
130   static double* GetShapeCoef (const int theShapeID);
131   // for theShapeID( TShapeID ), returns 3 coefficients used
132   // to compute an addition of an on-theShape point to coordinates
133   // of an in-shell point. If an in-shell point has parameters (Px,Py,Pz),
134   // then the addition of a point P is computed as P*kx*ky*kz and ki is
135   // defined by the returned coef like this:
136   // ki = (coef[i] == 0) ? 1 : (coef[i] < 0) ? 1 - Pi : Pi
137
138   static int GetShapeIDByParams ( const gp_XYZ& theParams );
139   // define an id of the block sub-shape by point parameters
140
141   static std::ostream& DumpShapeID (const int theBlockShapeID, std::ostream& stream);
142   // DEBUG: dump an id of a block sub-shape
143
144
145  public:
146   // ---------------
147   // Initialization
148   // ---------------
149
150   SMESH_Block();
151
152   bool LoadBlockShapes(const TopoDS_Shell&         theShell,
153                        const TopoDS_Vertex&        theVertex000,
154                        const TopoDS_Vertex&        theVertex001,
155                        TopTools_IndexedMapOfOrientedShape& theShapeIDMap );
156   // Initialize block geometry with theShell,
157   // add sub-shapes of theBlock to theShapeIDMap so that they get
158   // IDs acoording to enum TShapeID
159
160   bool LoadBlockShapes(const TopTools_IndexedMapOfOrientedShape& theShapeIDMap);
161   // Initialize block geometry with shapes from theShapeIDMap
162
163   bool LoadMeshBlock(const SMDS_MeshVolume*        theVolume,
164                      const int                     theNode000Index,
165                      const int                     theNode001Index,
166                      std::vector<const SMDS_MeshNode*>& theOrderedNodes);
167   // prepare to work with theVolume and
168   // return nodes in theVolume corners in the order of TShapeID enum
169
170   bool LoadFace(const TopoDS_Face& theFace,
171                 const int          theFaceID,
172                 const TopTools_IndexedMapOfOrientedShape& theShapeIDMap);
173   // Load face geometry.
174   // It is enough to compute params or coordinates on the face.
175   // Face subshapes must be loaded into theShapeIDMap before
176
177   static bool Insert(const TopoDS_Shape& theShape,
178                      const int           theShapeID,
179                      TopTools_IndexedMapOfOrientedShape& theShapeIDMap);
180   // Insert theShape into theShapeIDMap with theShapeID,
181   // Not yet set shapes preceding theShapeID are filled with compounds
182   // Return true if theShape was successfully bound to theShapeID
183
184   static bool FindBlockShapes(const TopoDS_Shell&         theShell,
185                               const TopoDS_Vertex&        theVertex000,
186                               const TopoDS_Vertex&        theVertex001,
187                               TopTools_IndexedMapOfOrientedShape& theShapeIDMap );
188   // add sub-shapes of theBlock to theShapeIDMap so that they get
189   // IDs acoording to enum TShapeID
190
191 public:
192   // ---------------------------------
193   // Define coordinates by parameters
194   // ---------------------------------
195
196   bool VertexPoint( const int theVertexID, gp_XYZ& thePoint ) const {
197     if ( !IsVertexID( theVertexID ))           return false;
198     thePoint = myPnt[ theVertexID - ID_FirstV ]; return true;
199   }
200   // return vertex coordinates, parameters are defined by theVertexID
201
202   bool EdgePoint( const int theEdgeID, const gp_XYZ& theParams, gp_XYZ& thePoint ) const {
203     if ( !IsEdgeID( theEdgeID ))                                 return false;
204     thePoint = myEdge[ theEdgeID - ID_FirstE ].Point( theParams ); return true;
205   }
206   // return coordinates of a point on edge
207
208   bool EdgeU( const int theEdgeID, const gp_XYZ& theParams, double& theU ) const {
209     if ( !IsEdgeID( theEdgeID ))                              return false;
210     theU = myEdge[ theEdgeID - ID_FirstE ].GetU( theParams ); return true;
211   }
212   // return parameter on edge by in-block parameters
213
214   bool FacePoint( const int theFaceID, const gp_XYZ& theParams, gp_XYZ& thePoint ) const {
215     if ( !IsFaceID ( theFaceID ))                                return false;
216     thePoint = myFace[ theFaceID - ID_FirstF ].Point( theParams ); return true;
217   }
218   // return coordinates of a point on face
219
220   bool FaceUV( const int theFaceID, const gp_XYZ& theParams, gp_XY& theUV ) const {
221     if ( !IsFaceID ( theFaceID ))                               return false;
222     theUV = myFace[ theFaceID - ID_FirstF ].GetUV( theParams ); return true;
223   }
224   // return UV coordinates on a face by in-block parameters
225
226   bool ShellPoint( const gp_XYZ& theParams, gp_XYZ& thePoint ) const;
227   // return coordinates of a point in shell
228
229   static bool ShellPoint(const gp_XYZ&         theParams,
230                          const std::vector<gp_XYZ>& thePointOnShape,
231                          gp_XYZ&               thePoint );
232   // computes coordinates of a point in shell by points on sub-shapes
233   // and point parameters.
234   // thePointOnShape[ subShapeID ] must be a point on a subShape;
235   // thePointOnShape.size() == ID_Shell, thePointOnShape[0] not used
236
237
238  public:
239   // ---------------------------------
240   // Define parameters by coordinates
241   // ---------------------------------
242
243   bool ComputeParameters (const gp_Pnt& thePoint,
244                           gp_XYZ&       theParams,
245                           const int     theShapeID    = ID_Shell,
246                           const gp_XYZ& theParamsHint = gp_XYZ(-1,-1,-1));
247   // compute point parameters in the block.
248   // Note: for edges, it is better to use EdgeParameters()
249   // Return false only in case of "hard" failure, use IsToleranceReached() etc
250   // to evaluate quality of the found solution
251
252   bool VertexParameters(const int theVertexID, gp_XYZ& theParams);
253   // return parameters of a vertex given by TShapeID
254
255   bool EdgeParameters(const int theEdgeID, const double theU, gp_XYZ& theParams);
256   // return parameters of a point given by theU on edge
257
258   void SetTolerance(const double tol);
259   // set tolerance for ComputeParameters()
260
261   double GetTolerance() const { return myTolerance; }
262   // return current tolerance of ComputeParameters()
263
264   bool IsToleranceReached() const;
265   // return true if solution found by ComputeParameters() is within the tolerance
266
267   double DistanceReached() const { return distance(); }
268   // return distance between solution found by ComputeParameters() and thePoint
269
270  public:
271   // ---------
272   // Services
273   // ---------
274
275   static bool IsForwardEdge (const TopoDS_Edge &                       theEdge,
276                              const TopTools_IndexedMapOfOrientedShape& theShapeIDMap) {
277     int v1ID = theShapeIDMap.FindIndex( TopExp::FirstVertex( theEdge ).Oriented( TopAbs_FORWARD ));
278     int v2ID = theShapeIDMap.FindIndex( TopExp::LastVertex( theEdge ).Oriented( TopAbs_FORWARD ));
279     return ( v1ID < v2ID );
280   }
281   // Return true if an in-block parameter increases along theEdge curve
282
283   static int GetOrderedEdges (const TopoDS_Face&        theFace,
284                               std::list< TopoDS_Edge >& theEdges,
285                               std::list< int >  &       theNbEdgesInWires,
286                               TopoDS_Vertex             theFirstVertex=TopoDS_Vertex(),
287                               const bool                theShapeAnalysisAlgo=false);
288   // Return nb wires and a list of oredered edges.
289   // It is used to assign indices to subshapes.
290   // theFirstVertex may be NULL.
291   // Always try to set a seam edge first
292   // if (theShapeAnalysisAlgo) then ShapeAnalysis::OuterWire() is used to find the outer
293   // wire else BRepTools::OuterWire() is used
294
295  public:
296   // -----------------------------------------------------------
297   // Methods of math_FunctionSetWithDerivatives used internally
298   // to define parameters by coordinates
299   // -----------------------------------------------------------
300   Standard_Integer NbVariables() const;
301   Standard_Integer NbEquations() const;
302   Standard_Boolean Value(const math_Vector& X,math_Vector& F) ;
303   Standard_Boolean Derivatives(const math_Vector& X,math_Matrix& D) ;
304   Standard_Boolean Values(const math_Vector& X,math_Vector& F,math_Matrix& D) ;
305   Standard_Integer GetStateNumber ();
306
307  protected:
308
309   /*!
310    * \brief Call it after geometry initialisation
311    */
312   void init();
313
314   // Note: to compute params of a point on a face, it is enough to set
315   // TFace, TEdge's and points for that face only
316
317   // Note 2: curve adaptors need to have only Value(double), FirstParameter() and
318   // LastParameter() defined to be used by Block algoritms
319
320   class SMESHUtils_EXPORT TEdge {
321     int                myCoordInd;
322     double             myFirst;
323     double             myLast;
324     Adaptor3d_Curve*   myC3d;
325     // if mesh volume
326     gp_XYZ             myNodes[2];
327   public:
328     void Set( const int edgeID, Adaptor3d_Curve* curve, const bool isForward );
329     void Set( const int edgeID, const gp_XYZ& node1, const gp_XYZ& node2 );
330     Adaptor3d_Curve* GetCurve() const { return myC3d; }
331     double EndParam(int i) const { return i ? myLast : myFirst; }
332     int CoordInd() const { return myCoordInd; }
333     const gp_XYZ& NodeXYZ(int i) const { return i ? myNodes[1] : myNodes[0]; }
334     gp_XYZ Point( const gp_XYZ& theParams ) const; // Return coord by params
335     double GetU( const gp_XYZ& theParams ) const;  // Return U by params
336     TEdge(): myC3d(0) {}
337     ~TEdge();
338   };
339
340   class SMESHUtils_EXPORT TFace {
341     // 4 edges in the order u0, u1, 0v, 1v
342     int                  myCoordInd[ 4 ];
343     double               myFirst   [ 4 ];
344     double               myLast    [ 4 ];
345     Adaptor2d_Curve2d*   myC2d     [ 4 ];
346     // 4 corner points in the order 00, 10, 11, 01
347     gp_XY                myCorner  [ 4 ];
348     // surface
349     Adaptor3d_Surface*   myS;
350     // if mesh volume
351     gp_XYZ               myNodes[4];
352   public:
353     void Set( const int faceID, Adaptor3d_Surface* S, // must be in GetFaceEdgesIDs() order:
354               Adaptor2d_Curve2d* c2d[4], const bool isForward[4] );
355     void Set( const int faceID, const TEdge& edgeU0, const TEdge& edgeU1 );
356     gp_XY  GetUV( const gp_XYZ& theParams ) const;
357     gp_XYZ Point( const gp_XYZ& theParams ) const;
358     int GetUInd() const { return myCoordInd[ 0 ]; }
359     int GetVInd() const { return myCoordInd[ 2 ]; }
360     void GetCoefs( int i, const gp_XYZ& theParams, double& eCoef, double& vCoef ) const;
361     const Adaptor3d_Surface* Surface() const { return myS; }
362     bool IsUVInQuad( const gp_XY& uv,
363                      const gp_XYZ& param0, const gp_XYZ& param1,
364                      const gp_XYZ& param2, const gp_XYZ& param3 ) const;
365     TFace(): myS(0) { myC2d[0]=myC2d[1]=myC2d[2]=myC2d[3]=0; }
366     ~TFace();
367   };
368
369   // geometry in the order as in TShapeID:
370   // 8 vertices
371   gp_XYZ myPnt[ 8 ];
372   // 12 edges
373   TEdge  myEdge[ 12 ];
374   // 6 faces
375   TFace  myFace[ 6 ];
376
377   // for param computation
378
379   enum { SQUARE_DIST = 0, DRV_1, DRV_2, DRV_3 };
380   double distance () const { return sqrt( myValues[ SQUARE_DIST ]); }
381   double funcValue(double sqDist) const { return mySquareFunc ? sqDist : sqrt(sqDist); }
382   bool computeParameters(const gp_Pnt& thePoint, gp_XYZ& theParams, const gp_XYZ& theParamsHint, int);
383   void refineParametersOnFace( const gp_Pnt& thePoint, gp_XYZ& theParams, int theFaceID );
384   bool saveBetterSolution( const gp_XYZ& theNewParams, gp_XYZ& theParams, double sqDistance );
385
386   int      myFaceIndex;
387   double   myFaceParam;
388   int      myNbIterations;
389   double   mySumDist;
390   double   myTolerance;
391   bool     mySquareFunc;
392
393   gp_XYZ   myPoint; // the given point
394   gp_XYZ   myParam; // the best parameters guess
395   double   myValues[ 4 ]; // values computed at myParam: square distance and 3 derivatives
396
397   typedef std::pair<gp_XYZ,gp_XYZ> TxyzPair;
398   TxyzPair my3x3x3GridNodes[ 1000 ]; // to compute the first param guess
399   bool     myGridComputed;
400 };
401
402
403 #endif