1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SMESH_Block.hxx
24 // Created : Tue Nov 30 12:42:18 2004
25 // Author : Edward AGAPOV (eap)
27 #ifndef SMESH_Block_HeaderFile
28 #define SMESH_Block_HeaderFile
30 #include "SMESH_Utils.hxx"
32 //#include <Geom2d_Curve.hxx>
33 //#include <Geom_Curve.hxx>
34 //#include <Geom_Surface.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>
44 #include <math_FunctionSetWithDerivatives.hxx>
50 class SMDS_MeshVolume;
52 class Adaptor3d_Surface;
53 class Adaptor2d_Curve2d;
54 class Adaptor3d_Curve;
57 // =========================================================
58 // class calculating coordinates of 3D points by normalized
59 // parameters inside the block and vice versa
60 // =========================================================
62 class SMESHUtils_EXPORT SMESH_Block: public math_FunctionSetWithDerivatives
66 // ----------------------------
67 // Ids of the block sub-shapes
68 // ----------------------------
71 ID_V000 = 1, ID_V100, ID_V010, ID_V110, ID_V001, ID_V101, ID_V011, ID_V111,
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,
77 ID_Fxy0, ID_Fxy1, ID_Fx0z, ID_Fx1z, ID_F0yz, ID_F1yz,
81 enum { // to use TShapeID for indexing certain type subshapes
83 ID_FirstV = ID_V000, ID_FirstE = ID_Ex00, ID_FirstF = ID_Fxy0
89 // -------------------------------------------------
90 // Block topology in terms of block sub-shapes' ids
91 // -------------------------------------------------
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
99 static inline bool IsVertexID( int theShapeID )
100 { return ( theShapeID >= ID_V000 && theShapeID <= ID_V111 ); }
102 static inline bool IsEdgeID( int theShapeID )
103 { return ( theShapeID >= ID_Ex00 && theShapeID <= ID_E11z ); }
105 static inline bool IsFaceID( int theShapeID )
106 { return ( theShapeID >= ID_Fxy0 && theShapeID <= ID_F1yz ); }
108 static int ShapeIndex( int theShapeID )
110 if ( IsVertexID( theShapeID )) return theShapeID - ID_V000;
111 if ( IsEdgeID( theShapeID )) return theShapeID - ID_Ex00;
112 if ( IsFaceID( theShapeID )) return theShapeID - ID_Fxy0;
115 // return index [0-...] for each type of sub-shapes,
117 // ShapeIndex( ID_Ex00 ) == 0
118 // ShapeIndex( ID_Ex10 ) == 1
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
123 static void GetEdgeVertexIDs (const int edgeID, std::vector< int >& vertexVec );
124 // return vertex IDs of an edge
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
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
138 static int GetShapeIDByParams ( const gp_XYZ& theParams );
139 // define an id of the block sub-shape by point parameters
141 static std::ostream& DumpShapeID (const int theBlockShapeID, std::ostream& stream);
142 // DEBUG: dump an id of a block sub-shape
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
160 bool LoadBlockShapes(const TopTools_IndexedMapOfOrientedShape& theShapeIDMap);
161 // Initialize block geometry with shapes from theShapeIDMap
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
170 bool LoadFace(const TopoDS_Face& theFace,
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
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
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
192 // ---------------------------------
193 // Define coordinates by parameters
194 // ---------------------------------
196 bool VertexPoint( const int theVertexID, gp_XYZ& thePoint ) const {
197 if ( !IsVertexID( theVertexID )) return false;
198 thePoint = myPnt[ theVertexID - ID_FirstV ]; return true;
200 // return vertex coordinates, parameters are defined by theVertexID
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;
206 // return coordinates of a point on edge
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;
212 // return parameter on edge by in-block parameters
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;
218 // return coordinates of a point on face
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;
224 // return UV coordinates on a face by in-block parameters
226 bool ShellPoint( const gp_XYZ& theParams, gp_XYZ& thePoint ) const;
227 // return coordinates of a point in shell
229 static bool ShellPoint(const gp_XYZ& theParams,
230 const std::vector<gp_XYZ>& thePointOnShape,
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
239 // ---------------------------------
240 // Define parameters by coordinates
241 // ---------------------------------
243 bool ComputeParameters (const gp_Pnt& thePoint,
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
252 bool VertexParameters(const int theVertexID, gp_XYZ& theParams);
253 // return parameters of a vertex given by TShapeID
255 bool EdgeParameters(const int theEdgeID, const double theU, gp_XYZ& theParams);
256 // return parameters of a point given by theU on edge
258 void SetTolerance(const double tol);
259 // set tolerance for ComputeParameters()
261 double GetTolerance() const { return myTolerance; }
262 // return current tolerance of ComputeParameters()
264 bool IsToleranceReached() const;
265 // return true if solution found by ComputeParameters() is within the tolerance
267 double DistanceReached() const { return distance(); }
268 // return distance between solution found by ComputeParameters() and thePoint
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 );
281 // Return true if an in-block parameter increases along theEdge curve
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
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 ();
310 * \brief Call it after geometry initialisation
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
317 // Note 2: curve adaptors need to have only Value(double), FirstParameter() and
318 // LastParameter() defined to be used by Block algoritms
320 class SMESHUtils_EXPORT TEdge {
324 Adaptor3d_Curve* myC3d;
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
340 class SMESHUtils_EXPORT TFace {
341 // 4 edges in the order u0, u1, 0v, 1v
343 double myFirst [ 4 ];
345 Adaptor2d_Curve2d* myC2d [ 4 ];
346 // 4 corner points in the order 00, 10, 11, 01
347 gp_XY myCorner [ 4 ];
349 Adaptor3d_Surface* myS;
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; }
369 // geometry in the order as in TShapeID:
377 // for param computation
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 );
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
397 typedef std::pair<gp_XYZ,gp_XYZ> TxyzPair;
398 TxyzPair my3x3x3GridNodes[ 1000 ]; // to compute the first param guess