d660a72a |
1 | // Created on: 2015-09-21 |
2 | // Copyright (c) 2015 OPEN CASCADE SAS |
3 | // |
4 | // This file is part of Open CASCADE Technology software library. |
5 | // |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
11 | // |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
14 | |
15 | #include <Geom2dEvaluator_OffsetCurve.hxx> |
68ad329c |
16 | #include <Geom2dEvaluator.hxx> |
d660a72a |
17 | #include <Geom2dAdaptor_HCurve.hxx> |
18 | #include <Standard_NullValue.hxx> |
19 | |
20 | |
92efcf78 |
21 | IMPLEMENT_STANDARD_RTTIEXT(Geom2dEvaluator_OffsetCurve,Geom2dEvaluator_Curve) |
22 | |
d660a72a |
23 | Geom2dEvaluator_OffsetCurve::Geom2dEvaluator_OffsetCurve( |
24 | const Handle(Geom2d_Curve)& theBase, |
25 | const Standard_Real theOffset) |
26 | : Geom2dEvaluator_Curve(), |
27 | myBaseCurve(theBase), |
28 | myOffset(theOffset) |
29 | { |
30 | } |
31 | |
32 | Geom2dEvaluator_OffsetCurve::Geom2dEvaluator_OffsetCurve( |
33 | const Handle(Geom2dAdaptor_HCurve)& theBase, |
34 | const Standard_Real theOffset) |
35 | : Geom2dEvaluator_Curve(), |
36 | myBaseAdaptor(theBase), |
37 | myOffset(theOffset) |
38 | { |
39 | } |
40 | |
41 | void Geom2dEvaluator_OffsetCurve::D0(const Standard_Real theU, |
42 | gp_Pnt2d& theValue) const |
43 | { |
44 | gp_Vec2d aD1; |
45 | BaseD1(theU, theValue, aD1); |
68ad329c |
46 | Geom2dEvaluator::CalculateD0(theValue, aD1, myOffset); |
d660a72a |
47 | } |
48 | |
49 | void Geom2dEvaluator_OffsetCurve::D1(const Standard_Real theU, |
50 | gp_Pnt2d& theValue, |
51 | gp_Vec2d& theD1) const |
52 | { |
53 | gp_Vec2d aD2; |
54 | BaseD2(theU, theValue, theD1, aD2); |
68ad329c |
55 | Geom2dEvaluator::CalculateD1(theValue, theD1, aD2, myOffset); |
d660a72a |
56 | } |
57 | |
58 | void Geom2dEvaluator_OffsetCurve::D2(const Standard_Real theU, |
59 | gp_Pnt2d& theValue, |
60 | gp_Vec2d& theD1, |
61 | gp_Vec2d& theD2) const |
62 | { |
63 | gp_Vec2d aD3; |
64 | BaseD3(theU, theValue, theD1, theD2, aD3); |
65 | |
66 | Standard_Boolean isDirectionChange = Standard_False; |
67 | if (theD1.SquareMagnitude() <= gp::Resolution()) |
68 | { |
69 | gp_Vec2d aDummyD4; |
70 | isDirectionChange = AdjustDerivative(3, theU, theD1, theD2, aD3, aDummyD4); |
71 | } |
72 | |
68ad329c |
73 | Geom2dEvaluator::CalculateD2(theValue, theD1, theD2, aD3, isDirectionChange, myOffset); |
d660a72a |
74 | } |
75 | |
76 | void Geom2dEvaluator_OffsetCurve::D3(const Standard_Real theU, |
77 | gp_Pnt2d& theValue, |
78 | gp_Vec2d& theD1, |
79 | gp_Vec2d& theD2, |
80 | gp_Vec2d& theD3) const |
81 | { |
82 | gp_Vec2d aD4; |
83 | BaseD4(theU, theValue, theD1, theD2, theD3, aD4); |
84 | |
85 | Standard_Boolean isDirectionChange = Standard_False; |
86 | if (theD1.SquareMagnitude() <= gp::Resolution()) |
87 | isDirectionChange = AdjustDerivative(4, theU, theD1, theD2, theD3, aD4); |
88 | |
68ad329c |
89 | Geom2dEvaluator::CalculateD3(theValue, theD1, theD2, theD3, aD4, isDirectionChange, myOffset); |
d660a72a |
90 | } |
91 | |
92 | gp_Vec2d Geom2dEvaluator_OffsetCurve::DN(const Standard_Real theU, |
93 | const Standard_Integer theDeriv) const |
94 | { |
95 | Standard_RangeError_Raise_if(theDeriv < 1, "Geom2dEvaluator_OffsetCurve::DN(): theDeriv < 1"); |
96 | |
97 | gp_Pnt2d aPnt; |
98 | gp_Vec2d aDummy, aDN; |
99 | switch (theDeriv) |
100 | { |
101 | case 1: |
102 | D1(theU, aPnt, aDN); |
103 | break; |
104 | case 2: |
105 | D2(theU, aPnt, aDummy, aDN); |
106 | break; |
107 | case 3: |
108 | D3(theU, aPnt, aDummy, aDummy, aDN); |
109 | break; |
110 | default: |
111 | aDN = BaseDN(theU, theDeriv); |
112 | } |
113 | return aDN; |
114 | } |
115 | |
116 | |
117 | void Geom2dEvaluator_OffsetCurve::BaseD0(const Standard_Real theU, |
118 | gp_Pnt2d& theValue) const |
119 | { |
120 | if (!myBaseAdaptor.IsNull()) |
121 | myBaseAdaptor->D0(theU, theValue); |
122 | else |
123 | myBaseCurve->D0(theU, theValue); |
124 | } |
125 | |
126 | void Geom2dEvaluator_OffsetCurve::BaseD1(const Standard_Real theU, |
127 | gp_Pnt2d& theValue, |
128 | gp_Vec2d& theD1) const |
129 | { |
130 | if (!myBaseAdaptor.IsNull()) |
131 | myBaseAdaptor->D1(theU, theValue, theD1); |
132 | else |
133 | myBaseCurve->D1(theU, theValue, theD1); |
134 | } |
135 | |
136 | void Geom2dEvaluator_OffsetCurve::BaseD2(const Standard_Real theU, |
137 | gp_Pnt2d& theValue, |
138 | gp_Vec2d& theD1, |
139 | gp_Vec2d& theD2) const |
140 | { |
141 | if (!myBaseAdaptor.IsNull()) |
142 | myBaseAdaptor->D2(theU, theValue, theD1, theD2); |
143 | else |
144 | myBaseCurve->D2(theU, theValue, theD1, theD2); |
145 | } |
146 | |
147 | void Geom2dEvaluator_OffsetCurve::BaseD3(const Standard_Real theU, |
148 | gp_Pnt2d& theValue, |
149 | gp_Vec2d& theD1, |
150 | gp_Vec2d& theD2, |
151 | gp_Vec2d& theD3) const |
152 | { |
153 | if (!myBaseAdaptor.IsNull()) |
154 | myBaseAdaptor->D3(theU, theValue, theD1, theD2, theD3); |
155 | else |
156 | myBaseCurve->D3(theU, theValue, theD1, theD2, theD3); |
157 | } |
158 | |
159 | void Geom2dEvaluator_OffsetCurve::BaseD4(const Standard_Real theU, |
160 | gp_Pnt2d& theValue, |
161 | gp_Vec2d& theD1, |
162 | gp_Vec2d& theD2, |
163 | gp_Vec2d& theD3, |
164 | gp_Vec2d& theD4) const |
165 | { |
166 | if (!myBaseAdaptor.IsNull()) |
167 | { |
168 | myBaseAdaptor->D3(theU, theValue, theD1, theD2, theD3); |
169 | theD4 = myBaseAdaptor->DN(theU, 4); |
170 | } |
171 | else |
172 | { |
173 | myBaseCurve->D3(theU, theValue, theD1, theD2, theD3); |
174 | theD4 = myBaseCurve->DN(theU, 4); |
175 | } |
176 | } |
177 | |
178 | gp_Vec2d Geom2dEvaluator_OffsetCurve::BaseDN(const Standard_Real theU, |
179 | const Standard_Integer theDeriv) const |
180 | { |
181 | if (!myBaseAdaptor.IsNull()) |
182 | return myBaseAdaptor->DN(theU, theDeriv); |
183 | return myBaseCurve->DN(theU, theDeriv); |
184 | } |
185 | |
186 | |
d660a72a |
187 | |
188 | |
189 | Standard_Boolean Geom2dEvaluator_OffsetCurve::AdjustDerivative( |
190 | const Standard_Integer theMaxDerivative, const Standard_Real theU, |
191 | gp_Vec2d& theD1, gp_Vec2d& theD2, gp_Vec2d& theD3, gp_Vec2d& theD4) const |
192 | { |
193 | static const Standard_Real aTol = gp::Resolution(); |
194 | static const Standard_Real aMinStep = 1e-7; |
195 | static const Standard_Integer aMaxDerivOrder = 3; |
196 | |
197 | Standard_Boolean isDirectionChange = Standard_False; |
198 | Standard_Real anUinfium; |
199 | Standard_Real anUsupremum; |
200 | if (!myBaseAdaptor.IsNull()) |
201 | { |
202 | anUinfium = myBaseAdaptor->FirstParameter(); |
203 | anUsupremum = myBaseAdaptor->LastParameter(); |
204 | } |
205 | else |
206 | { |
207 | anUinfium = myBaseCurve->FirstParameter(); |
208 | anUsupremum = myBaseCurve->LastParameter(); |
209 | } |
210 | |
211 | static const Standard_Real DivisionFactor = 1.e-3; |
212 | Standard_Real du; |
213 | if ((anUsupremum >= RealLast()) || (anUinfium <= RealFirst())) |
214 | du = 0.0; |
215 | else |
216 | du = anUsupremum - anUinfium; |
217 | |
218 | const Standard_Real aDelta = Max(du * DivisionFactor, aMinStep); |
219 | |
220 | //Derivative is approximated by Taylor-series |
221 | Standard_Integer anIndex = 1; //Derivative order |
222 | gp_Vec2d V; |
223 | |
224 | do |
225 | { |
226 | V = BaseDN(theU, ++anIndex); |
227 | } while ((V.SquareMagnitude() <= aTol) && anIndex < aMaxDerivOrder); |
228 | |
229 | Standard_Real u; |
230 | |
231 | if (theU - anUinfium < aDelta) |
232 | u = theU + aDelta; |
233 | else |
234 | u = theU - aDelta; |
235 | |
236 | gp_Pnt2d P1, P2; |
237 | BaseD0(Min(theU, u), P1); |
238 | BaseD0(Max(theU, u), P2); |
239 | |
240 | gp_Vec2d V1(P1, P2); |
241 | isDirectionChange = V.Dot(V1) < 0.0; |
242 | Standard_Real aSign = isDirectionChange ? -1.0 : 1.0; |
243 | |
244 | theD1 = V * aSign; |
245 | gp_Vec2d* aDeriv[3] = { &theD2, &theD3, &theD4 }; |
246 | for (Standard_Integer i = 1; i < theMaxDerivative; i++) |
247 | *(aDeriv[i - 1]) = BaseDN(theU, anIndex + i) * aSign; |
248 | |
249 | return isDirectionChange; |
250 | } |
251 | |