0025039: Improvement of code structure of general and supporting tools implemented...
[occt.git] / src / BRepMesh / BRepMesh_GeomTool.cxx
1 // Created on: 1993-09-29
2 // Created by: Isabelle GRIGNON
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepMesh_GeomTool.hxx>
18
19 #include <TopAbs_Orientation.hxx>
20 #include <CSLib.hxx>
21 #include <Precision.hxx>
22 #include <Adaptor3d_IsoCurve.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_HSurface.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <BRep_Tool.hxx>
27
28 //=======================================================================
29 //function : Constructor
30 //purpose  :
31 //=======================================================================
32 BRepMesh_GeomTool::BRepMesh_GeomTool(
33   const BRepAdaptor_Curve& theCurve,
34   const Standard_Real      theFirstParam,
35   const Standard_Real      theLastParam,
36   const Standard_Real      theLinDeflection,
37   const Standard_Real      theAngDeflection,
38   const Standard_Integer   theMinPointsNb)
39   : myEdge(&theCurve.Edge()),
40     myIsoType(GeomAbs_NoneIso)
41 {
42   myDiscretTool.Initialize(theCurve, theFirstParam, theLastParam,
43     theAngDeflection, theLinDeflection, theMinPointsNb);
44 }
45
46 //=======================================================================
47 //function : Constructor
48 //purpose  :
49 //=======================================================================
50 BRepMesh_GeomTool::BRepMesh_GeomTool(
51   const Handle(BRepAdaptor_HSurface)& theSurface,
52   const GeomAbs_IsoType               theIsoType,
53   const Standard_Real                 theParamIso,
54   const Standard_Real                 theFirstParam,
55   const Standard_Real                 theLastParam,
56   const Standard_Real                 theLinDeflection,
57   const Standard_Real                 theAngDeflection,
58   const Standard_Integer              theMinPointsNb)
59   : myEdge(NULL),
60     myIsoType(theIsoType)
61 {
62   Adaptor3d_IsoCurve aIso(theSurface, theIsoType, theParamIso,
63     theFirstParam, theLastParam);
64
65   myDiscretTool.Initialize(aIso, theFirstParam, theLastParam,
66     theAngDeflection, theLinDeflection, theMinPointsNb);
67 }
68
69 //=======================================================================
70 //function : Value
71 //purpose  :
72 //=======================================================================
73 Standard_Boolean BRepMesh_GeomTool::Value(
74   const Standard_Integer              theIndex,
75   const Handle(BRepAdaptor_HSurface)& theSurface,
76   Standard_Real&                      theParam,
77   gp_Pnt&                             thePoint,
78   gp_Pnt2d&                           theUV) const
79 {
80   if (theIndex < 1 || theIndex > NbPoints())
81     return Standard_False;
82
83   if (myEdge == NULL)
84     return Standard_False;
85
86   thePoint = myDiscretTool.Value(theIndex);
87   theParam = myDiscretTool.Parameter(theIndex);
88
89   const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
90
91   Standard_Real aFirst, aLast;
92   Handle(Geom2d_Curve) aCurve = 
93     BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast);
94
95   aCurve->D0(theParam, theUV);
96
97   return Standard_True;
98 }
99
100 //=======================================================================
101 //function : Value
102 //purpose  :
103 //=======================================================================
104 Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex,
105                                           const Standard_Real    theIsoParam,
106                                           Standard_Real&         theParam,
107                                           gp_Pnt&                thePoint,
108                                           gp_Pnt2d&              theUV) const
109 {
110   if (theIndex < 1 || theIndex > NbPoints())
111     return Standard_False;
112
113   thePoint = myDiscretTool.Value(theIndex);
114   theParam = myDiscretTool.Parameter(theIndex);
115
116   if (myIsoType == GeomAbs_IsoU)
117     theUV.SetCoord(theIsoParam, theParam);
118   else
119     theUV.SetCoord(theParam, theIsoParam);
120
121   return Standard_True;
122 }
123
124 //=======================================================================
125 //function : Normal
126 //purpose  :
127 //=======================================================================
128 Standard_Boolean BRepMesh_GeomTool::Normal(
129   const Handle(BRepAdaptor_HSurface)& theSurface,
130   const Standard_Real                 theParamU,
131   const Standard_Real                 theParamV,
132   gp_Pnt&                             thePoint,
133   gp_Dir&                             theNormal)
134 {
135   Standard_Boolean isOK = Standard_True;
136   gp_Vec aD1U, aD1V;
137
138   theSurface->D1(theParamU, theParamV, thePoint, aD1U, aD1V);
139
140   CSLib_DerivativeStatus aStatus;
141   CSLib::Normal(aD1U, aD1V, Precision::Angular(), aStatus, theNormal);
142   if (aStatus != CSLib_Done)
143   {
144     gp_Vec aD2U,aD2V,aD2UV;
145     theSurface->D2(theParamU, theParamV, thePoint, aD1U, aD1V, aD2U, aD2V, aD2UV);
146     CSLib_NormalStatus aNormalStatus;
147     CSLib::Normal(aD1U, aD1V, aD2U, aD2V, aD2UV, Precision::Angular(), 
148       isOK, aNormalStatus, theNormal);
149   }
150
151   if (!isOK)
152     return Standard_False;
153
154   const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
155   TopAbs_Orientation aOri = aFace.Orientation();
156   if (aOri == TopAbs_REVERSED)
157     theNormal.Reverse();
158
159   return Standard_True;
160 }
161
162 //=============================================================================
163 //function : IntLinLin
164 //purpose  : 
165 //=============================================================================
166 BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntLinLin(
167   const gp_XY&  theStartPnt1,
168   const gp_XY&  theEndPnt1,
169   const gp_XY&  theStartPnt2,
170   const gp_XY&  theEndPnt2,
171   gp_XY&        theIntPnt,
172   Standard_Real (&theParamOnSegment)[2])
173 {
174   gp_XY aVec1    = theEndPnt1   - theStartPnt1;
175   gp_XY aVec2    = theEndPnt2   - theStartPnt2;
176   gp_XY aVecO1O2 = theStartPnt2 - theStartPnt1;
177     
178   Standard_Real aCrossD1D2 = aVec1    ^ aVec2;
179   Standard_Real aCrossD1D3 = aVecO1O2 ^ aVec2;
180
181   const Standard_Real aPrec = gp::Resolution();
182   // Are edgegs codirectional
183   if ( Abs( aCrossD1D2 ) < aPrec )
184   {
185     // Just a parallel case?
186     if( Abs( aCrossD1D3 ) < aPrec )
187       return BRepMesh_GeomTool::Same;
188     else
189       return BRepMesh_GeomTool::NoIntersection;
190   }
191
192   theParamOnSegment[0] = aCrossD1D3 / aCrossD1D2;
193   theIntPnt = theStartPnt1 + theParamOnSegment[0] * aVec1;
194
195   Standard_Real aCrossD2D3 = aVecO1O2 ^ aVec1;
196   theParamOnSegment[1] = aCrossD2D3 / aCrossD1D2;
197
198   return BRepMesh_GeomTool::Cross;
199 }
200
201 //=============================================================================
202 //function : IntSegSeg
203 //purpose  : 
204 //=============================================================================
205 BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg(
206   const gp_XY&           theStartPnt1,
207   const gp_XY&           theEndPnt1,
208   const gp_XY&           theStartPnt2,
209   const gp_XY&           theEndPnt2,
210   const Standard_Boolean isConsiderEndPointTouch,
211   const Standard_Boolean isConsiderPointOnSegment,
212   gp_Pnt2d&              theIntPnt)
213 {
214   Standard_Integer aPointHash[] = {
215     classifyPoint(theStartPnt1, theEndPnt1, theStartPnt2),
216     classifyPoint(theStartPnt1, theEndPnt1, theEndPnt2  ),
217     classifyPoint(theStartPnt2, theEndPnt2, theStartPnt1),
218     classifyPoint(theStartPnt2, theEndPnt2, theEndPnt1  )
219   };
220
221   // Consider case when edges have shared vertex
222   if ( isConsiderEndPointTouch )
223   {
224     if ( aPointHash[0] < 0 || aPointHash[1] < 0 )
225       return BRepMesh_GeomTool::EndPointTouch;
226   }
227
228   Standard_Integer aPosHash = 
229     aPointHash[0] + aPointHash[1] + aPointHash[2] + aPointHash[3];
230
231   /*=========================================*/
232   /*  1) hash code == 1:
233
234                     0+
235                     /
236            0      1/         0
237            +======+==========+
238   
239       2) hash code == 2:
240
241            0    1        1   0
242         a) +----+========+---+
243
244            0       1   1     0
245         b) +-------+===+=====+
246
247                                              */
248   /*=========================================*/
249   if ( aPosHash == 1 )
250   {
251     if (isConsiderPointOnSegment)
252     {
253       if (aPointHash[0] == 1)
254         theIntPnt = theStartPnt1;
255       else if (aPointHash[1] == 1)
256         theIntPnt = theEndPnt1;
257       else if (aPointHash[2] == 1)
258         theIntPnt = theStartPnt2;
259       else
260         theIntPnt = theEndPnt2;
261
262       return BRepMesh_GeomTool::PointOnSegment;
263     }
264
265     return BRepMesh_GeomTool::NoIntersection;
266   }
267   else if ( aPosHash == 2 )
268     return BRepMesh_GeomTool::Glued;
269
270   Standard_Real aParam[2];
271   IntFlag aIntFlag = IntLinLin(theStartPnt1, theEndPnt1, 
272     theStartPnt2, theEndPnt2, theIntPnt.ChangeCoord(), aParam);
273
274   if (aIntFlag == BRepMesh_GeomTool::NoIntersection)
275     return BRepMesh_GeomTool::NoIntersection;
276
277   if (aIntFlag == BRepMesh_GeomTool::Same)
278   {
279     if ( aPosHash < -2 )
280       return BRepMesh_GeomTool::Same;
281     else if ( aPosHash == -1 )
282       return BRepMesh_GeomTool::Glued;
283
284     return BRepMesh_GeomTool::NoIntersection;
285   }
286
287   // Cross
288   // Intersection is out of segments ranges
289   const Standard_Real aPrec    = Precision::PConfusion();
290   const Standard_Real aEndPrec = 1 - aPrec;
291   for (Standard_Integer i = 0; i < 2; ++i)
292   {
293     if( aParam[i] < aPrec || aParam[i] > aEndPrec )
294       return BRepMesh_GeomTool::NoIntersection;
295   }
296  
297   return BRepMesh_GeomTool::Cross;
298 }
299
300 //=============================================================================
301 //function : classifyPoint
302 //purpose  : 
303 //=============================================================================
304 Standard_Integer BRepMesh_GeomTool::classifyPoint(
305   const gp_XY& thePoint1,
306   const gp_XY& thePoint2,
307   const gp_XY& thePointToCheck)
308 {
309   gp_XY aP1 = thePoint2       - thePoint1;
310   gp_XY aP2 = thePointToCheck - thePoint1;
311   
312   const Standard_Real aPrec   = Precision::PConfusion();
313   const Standard_Real aSqPrec = aPrec * aPrec;
314   Standard_Real aDist = Abs(aP1 ^ aP2);
315   if (aDist > aPrec)
316   {
317     aDist = (aDist * aDist) / aP1.SquareModulus();
318     if (aDist > aSqPrec)
319       return 0; //out
320   }
321     
322   gp_XY aMult = aP1.Multiplied(aP2);
323   if ( aMult.X() < 0.0 || aMult.Y() < 0.0 )
324     return 0; //out
325     
326   if (aP1.SquareModulus() < aP2.SquareModulus())
327     return 0; //out
328     
329   if (thePointToCheck.IsEqual(thePoint1, aPrec) || 
330       thePointToCheck.IsEqual(thePoint2, aPrec))
331   {
332     return -1; //coinsides with an end point
333   }
334     
335   return 1;
336 }