0030754: Coding - the array of weights should begin with Lower, not the constant...
[occt.git] / src / BRepMesh / BRepMesh_DefaultRangeSplitter.cxx
1 // Created on: 2016-07-07
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_DefaultRangeSplitter.hxx>
17
18 #include <GCPnts_AbscissaPoint.hxx>
19 #include <GeomAdaptor_Curve.hxx>
20 #include <GeomAbs_IsoType.hxx>
21
22 //=======================================================================
23 // Function: Reset
24 // Purpose : 
25 //=======================================================================
26 void BRepMesh_DefaultRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace,
27                                           const IMeshTools_Parameters& /*theParameters*/)
28 {
29   myDFace = theDFace;
30   myRangeU.first  = myRangeV.first  =  1.e100;
31   myRangeU.second = myRangeV.second = -1.e100;
32   myDelta.first   = myDelta.second  = 1.;
33   myTolerance.first = myTolerance.second = Precision::Confusion();
34 }
35
36 //=======================================================================
37 // Function: AddPoint
38 // Purpose : 
39 //=======================================================================
40 void BRepMesh_DefaultRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
41 {
42   myRangeU.first  = Min(thePoint.X(), myRangeU.first);
43   myRangeU.second = Max(thePoint.X(), myRangeU.second);
44   myRangeV.first  = Min(thePoint.Y(), myRangeV.first);
45   myRangeV.second = Max(thePoint.Y(), myRangeV.second);
46 }
47
48 //=======================================================================
49 // Function: AdjustRange
50 // Purpose : 
51 //=======================================================================
52 void BRepMesh_DefaultRangeSplitter::AdjustRange()
53 {
54   const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface();
55   updateRange(aSurface->FirstUParameter(), aSurface->LastUParameter(),
56               aSurface->IsUPeriodic(), myRangeU.first, myRangeU.second);
57
58   if (myRangeU.second < myRangeU.first)
59   {
60     myIsValid = Standard_False;
61     return;
62   }
63
64   updateRange(aSurface->FirstVParameter(), aSurface->LastVParameter(),
65               aSurface->IsVPeriodic(), myRangeV.first, myRangeV.second);
66
67   if (myRangeV.second < myRangeV.first)
68   {
69     myIsValid = Standard_False;
70     return;
71   }
72
73   const Standard_Real aLengthU = computeLengthU();
74   const Standard_Real aLengthV = computeLengthV();
75   myIsValid = aLengthU > Precision::PConfusion () && aLengthV > Precision::PConfusion ();
76
77   if (myIsValid)
78   {
79     computeTolerance(aLengthU, aLengthV);
80     computeDelta    (aLengthU, aLengthV);
81   }
82 }
83
84 //=======================================================================
85 // Function: IsValid
86 // Purpose : 
87 //=======================================================================
88 Standard_Boolean BRepMesh_DefaultRangeSplitter::IsValid()
89 {
90   return myIsValid;
91 }
92
93 //=======================================================================
94 // Function: Scale
95 // Purpose : 
96 //=======================================================================
97 gp_Pnt2d BRepMesh_DefaultRangeSplitter::Scale(const gp_Pnt2d&        thePoint,
98                                               const Standard_Boolean isToFaceBasis) const
99 {
100   return isToFaceBasis ?
101     gp_Pnt2d ((thePoint.X () - myRangeU.first) / myDelta.first,
102               (thePoint.Y () - myRangeV.first) / myDelta.second) :
103     gp_Pnt2d (thePoint.X () * myDelta.first  + myRangeU.first,
104               thePoint.Y () * myDelta.second + myRangeV.first);
105 }
106
107 //=======================================================================
108 // Function: GenerateSurfaceNodes
109 // Purpose : 
110 //=======================================================================
111 Handle(IMeshData::ListOfPnt2d) BRepMesh_DefaultRangeSplitter::GenerateSurfaceNodes(
112   const IMeshTools_Parameters& /*theParameters*/) const
113 {
114   return Handle(IMeshData::ListOfPnt2d)();
115 }
116
117 //=======================================================================
118 // Function: computeTolerance
119 // Purpose : 
120 //=======================================================================
121 void BRepMesh_DefaultRangeSplitter::computeTolerance(
122   const Standard_Real /*theLenU*/,
123   const Standard_Real /*theLenV*/)
124 {
125   const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
126   const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
127
128   const Standard_Real aDeflectionUV = 1.e-05;
129   myTolerance.first  = Max(aDeflectionUV, Precision::Confusion() * aDiffU);
130   myTolerance.second = Max(aDeflectionUV, Precision::Confusion() * aDiffV);
131 }
132
133 //=======================================================================
134 // Function: computeDelta
135 // Purpose : 
136 //=======================================================================
137 void BRepMesh_DefaultRangeSplitter::computeDelta(
138   const Standard_Real theLengthU,
139   const Standard_Real theLengthV)
140 {
141   const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
142   const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
143
144   myDelta.first  = aDiffU / (theLengthU < myTolerance.first  ? 1. : theLengthU);
145   myDelta.second = aDiffV / (theLengthV < myTolerance.second ? 1. : theLengthV);
146 }
147
148 //=======================================================================
149 // Function: computeLengthU
150 // Purpose : 
151 //=======================================================================
152 Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthU()
153 {
154   Standard_Real longu = 0.0;
155   gp_Pnt P11, P12, P21, P22, P31, P32;
156
157   Standard_Real du     = 0.05 * (myRangeU.second - myRangeU.first);
158   Standard_Real dfvave = 0.5  * (myRangeV.second + myRangeV.first);
159   Standard_Real dfucur;
160   Standard_Integer i1;
161
162   const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
163   gFace->D0(myRangeU.first, myRangeV.first,  P11);
164   gFace->D0(myRangeU.first, dfvave,          P21);
165   gFace->D0(myRangeU.first, myRangeV.second, P31);
166   for (i1 = 1, dfucur = myRangeU.first + du; i1 <= 20; i1++, dfucur += du)
167   {
168     gFace->D0(dfucur, myRangeV.first,  P12);
169     gFace->D0(dfucur, dfvave,          P22);
170     gFace->D0(dfucur, myRangeV.second, P32);
171     longu += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
172     P11 = P12;
173     P21 = P22;
174     P31 = P32;
175   }
176
177   return longu / 3.;
178 }
179
180 //=======================================================================
181 // Function: computeLengthV
182 // Purpose : 
183 //=======================================================================
184 Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthV()
185 {
186   Standard_Real longv = 0.0;
187   gp_Pnt P11, P12, P21, P22, P31, P32;
188
189   Standard_Real dv     = 0.05 * (myRangeV.second - myRangeV.first);
190   Standard_Real dfuave = 0.5  * (myRangeU.second + myRangeU.first);
191   Standard_Real dfvcur;
192   Standard_Integer i1;
193
194   const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
195   gFace->D0(myRangeU.first,  myRangeV.first, P11);
196   gFace->D0(dfuave,          myRangeV.first, P21);
197   gFace->D0(myRangeU.second, myRangeV.first, P31);
198   for (i1 = 1, dfvcur = myRangeV.first + dv; i1 <= 20; i1++, dfvcur += dv)
199   {
200     gFace->D0(myRangeU.first,  dfvcur, P12);
201     gFace->D0(dfuave,          dfvcur, P22);
202     gFace->D0(myRangeU.second, dfvcur, P32);
203     longv += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
204     P11 = P12;
205     P21 = P22;
206     P31 = P32;
207   }
208
209   return longv / 3.;
210 }
211
212 //=======================================================================
213 // Function: updateRange
214 // Purpose : 
215 //=======================================================================
216 void BRepMesh_DefaultRangeSplitter::updateRange(
217   const Standard_Real     theGeomFirst,
218   const Standard_Real     theGeomLast,
219   const Standard_Boolean  isPeriodic,
220   Standard_Real&          theDiscreteFirst,
221   Standard_Real&          theDiscreteLast)
222 {
223   if (theDiscreteFirst < theGeomFirst ||
224       theDiscreteLast  > theGeomLast)
225   {
226     if (isPeriodic)
227     {
228       if ((theDiscreteLast - theDiscreteFirst) > (theGeomLast - theGeomFirst))
229       {
230         theDiscreteLast = theDiscreteFirst + (theGeomLast - theGeomFirst);
231       }
232     }
233     else
234     {
235       if ((theDiscreteFirst < theGeomLast) && (theDiscreteLast > theGeomFirst))
236       {
237         //Protection against the faces whose pcurve is out of the surface's domain
238         //(see issue #23675 and test cases "bugs iges buc60820*")
239
240         if (theGeomFirst > theDiscreteFirst)
241         {
242           theDiscreteFirst = theGeomFirst;
243         }
244
245         if (theGeomLast < theDiscreteLast)
246         {
247           theDiscreteLast = theGeomLast;
248         }
249       }
250     }
251   }
252 }