1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 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 //-------------------------------------------------------------------
16 // Algorithm concerns the constant arrow
17 // cases processed : parameterized curve
18 // the curve should be C2
19 // provide a max arrow
20 // algorithm of parameterized curve:
21 // calculation of the step of advancement is
22 // du = sqrt(8*fleche*||P'(u)||/||P'(u)^P''(u)||
23 // calculate each point such as u+Du
24 // check if the arrow is actually taken into account, if yes, continue
25 // otherwise correct the step
26 // si du cannot be calculated (null curvature, singularity on the curve)
27 // take a constant step to reach the last point or to go past it
28 // The last point is readjusted by the following criteria:
29 // if the last calculated parameter is <2*resolution, reframe the last point found
30 // between itself and the previous point and add the end point
31 // (avoid a concentration at the end)
32 // otherwise if the distance (last calculated point, end point)<arrow,
33 // replace the last calculated point by the end point
34 // otherwise calculate max arrow between the last but one calculated point
35 // and the end point; if this arrow is greater than the arrow
36 // replace the last point by this one and the end point
37 // CONTROLS OF ARROW AND THE LAST POINT ARE DONE ONLY IF withControl=true
38 // each iteration calculates at maximum 3 points
39 //-------------------------------------------------------------------------
40
41 #include <Adaptor2d_Curve2d.hxx>
42 #include <Adaptor3d_Curve.hxx>
43 #include <CPnts_UniformDeflection.hxx>
44 #include <gp_Pnt.hxx>
45 #include <gp_Pnt2d.hxx>
46 #include <gp_Vec.hxx>
47 #include <gp_Vec2d.hxx>
48 #include <Standard_ConstructionError.hxx>
49 #include <Standard_DomainError.hxx>
50 #include <Standard_OutOfRange.hxx>
51 #include <StdFail_NotDone.hxx>
52
D03d(const Standard_Address C,const Standard_Real U,gp_Pnt & P)53 static inline void D03d(const Standard_Address C, const Standard_Real U,
54 gp_Pnt& P)
55 {
56 ((Adaptor3d_Curve*)C)->D0(U,P);
57 }
58
D02d(const Standard_Address C,const Standard_Real U,gp_Pnt & PP)59 static void D02d(const Standard_Address C, const Standard_Real U,
60 gp_Pnt& PP)
61 {
62 gp_Pnt2d P;
63 ((Adaptor2d_Curve2d*)C)->D0(U,P);
64 PP.SetCoord(P.X(),P.Y(),0.);
65 }
66
D23d(const Standard_Address C,const Standard_Real U,gp_Pnt & P,gp_Vec & V1,gp_Vec & V2)67 static inline void D23d(const Standard_Address C, const Standard_Real U,
68 gp_Pnt& P, gp_Vec& V1, gp_Vec& V2)
69 {
70 ((Adaptor3d_Curve*)C)->D2(U,P,V1,V2);
71 }
72
D22d(const Standard_Address C,const Standard_Real U,gp_Pnt & PP,gp_Vec & VV1,gp_Vec & VV2)73 static void D22d(const Standard_Address C, const Standard_Real U,
74 gp_Pnt& PP, gp_Vec& VV1, gp_Vec& VV2)
75 {
76 gp_Pnt2d P;
77 gp_Vec2d V1,V2;
78 ((Adaptor2d_Curve2d*)C)->D2(U,P,V1,V2);
79 PP.SetCoord(P.X(),P.Y(),0.);
80 VV1.SetCoord(V1.X(),V1.Y(),0.);
81 VV2.SetCoord(V2.X(),V2.Y(),0.);
82 }
83
84 //=======================================================================
85 //function : Perform
86 //purpose :
87 //=======================================================================
88
Perform()89 void CPnts_UniformDeflection::Perform()
90 {
91 gp_Pnt P, P1, P2;
92 // gp_Vec V1, V2, VV1, VV2, VV;
93 gp_Vec V1, V2, VV;
94 Standard_Real Un1;
95 Standard_Real NormD1, NormD2;
96
97 myIPoint = -1;
98 myNbPoints = -1;
99
100 while ( (myNbPoints<2) && (!myFinish) ) {
101
102 myNbPoints = myNbPoints + 1;
103 myParams[myNbPoints] = myFirstParam;
104
105 if (my3d)
106 D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
107 else
108 D22d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
109 P = myPoints[myNbPoints] ;
110 NormD1 = V1.Magnitude();
111 if (NormD1 < myTolCur || V2.Magnitude() < myTolCur) {
112 // singularity on the tangent or null curvature
113 myDu = Min(myDwmax, 1.5 * myDu);
114 }
115 else {
116 NormD2 = V2.CrossMagnitude(V1);
117 if (NormD2 / NormD1 < myDeflection) { // collinearity of derivatives
118 myDu = Min(myDwmax, 1.5 * myDu);
119 }
120 else {
121 myDu = Sqrt(8.* myDeflection * NormD1 / NormD2 );
122 myDu = Min(Max(myDu, myTolCur), myDwmax);
123 }
124 }
125
126 // check if the arrow is observed if WithControl
127
128 if (myControl) {
129 myDu = Min(myDu, myLastParam-myFirstParam);
130 if (my3d) {
131
132 D03d(myCurve, myFirstParam + myDu,P);
133 D03d(myCurve, myFirstParam + (myDu / 2.0),P1);
134 }
135 else {
136
137 D02d(myCurve, myFirstParam + myDu,P);
138 D02d(myCurve, myFirstParam + (myDu / 2.0),P1);
139 }
140 V1= gp_Vec(myPoints[myNbPoints], P);
141 NormD1 = V1.Magnitude();
142 if (NormD1 >= myDeflection) {
143 V2 = gp_Vec(myPoints[myNbPoints], P1);
144 NormD2 = V2.CrossMagnitude(V1) / NormD1;
145
146 // passing of arrow starting from which the redivision is done is arbitrary
147 // probably it will be necessary to readjust it (differentiate the first point
148 // from the others) this test does not work on the points of inflexion
149
150 if (NormD2 > myDeflection / 5.0) {
151 NormD2 = Max(NormD2, 1.1 * myDeflection);
152 myDu = myDu * Sqrt(myDeflection / NormD2);
153 myDu = Min(Max(myDu, myTolCur), myDwmax);
154 }
155 }
156 }
157 myFirstParam = myFirstParam + myDu;
158 myFinish = (myLastParam - myFirstParam < myTolCur) || (myDu == 0.);
159 }
160 if (myFinish) {
161 // the last point is corrected if control
162 if (myControl && (myNbPoints == 1) ) {
163 Un1 = myParams[0];
164 if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) {
165 myFirstParam = (myLastParam + Un1) / 2.0;
166 myParams[0]= myFirstParam;
167 myParams[1]= myLastParam;
168 if (my3d) {
169 D03d(myCurve, myParams[0], myPoints[0]);
170 D03d(myCurve, myParams[1], myPoints[1]);
171 }
172 else {
173 D02d(myCurve, myParams[0], myPoints[0]);
174 D02d(myCurve, myParams[1], myPoints[1]);
175 }
176 }
177 else {
178 if (my3d) {
179 D23d(myCurve, myLastParam, P1, V1, V2);
180 }
181 else {
182 D22d(myCurve, myLastParam, P1, V1, V2);
183 }
184 P = myPoints[0] ;
185 VV = gp_Vec(P1, P);
186 NormD1 = VV.Magnitude();
187 if ( NormD1 < myDeflection) {
188 myParams[1]= myLastParam;
189 myPoints[1]= P1 ;
190 }
191 else {
192 myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu)
193 /(myFirstParam -Un1);
194 if (my3d)
195 D03d(myCurve, myFirstParam, P2);
196 else
197 D02d(myCurve, myFirstParam, P2);
198
199 if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) &&
200 (Un1 >= myLastParam - myDwmax) ) {
201 // point n is removed
202 myParams[1]= myLastParam;
203 myPoints[1] = P1 ;
204 }
205 else {
206 myParams[1]=myFirstParam;
207 myPoints[1] = P2 ;
208 myParams[2]=myLastParam;
209 myPoints[2] = P1 ;
210 myNbPoints = myNbPoints +1;
211 }
212 }
213 }
214 }
215 else {
216 myNbPoints = myNbPoints +1 ;
217 if (myNbPoints >= 3) myNbPoints = 2;
218 myParams[myNbPoints]= myLastParam;
219 if (my3d) {
220 D03d(myCurve, myLastParam, myPoints[myNbPoints]);
221 }
222 else {
223 D02d(myCurve, myLastParam, myPoints[myNbPoints]);
224 }
225 }
226 }
227 }
228
229 //=======================================================================
230 //function : CPnts_UniformDeflection
231 //purpose :
232 //=======================================================================
233
CPnts_UniformDeflection()234 CPnts_UniformDeflection::CPnts_UniformDeflection ()
235 : myDone(Standard_False),
236 my3d(Standard_False),
237 myFinish(Standard_False),
238 myTolCur(0.0),
239 myControl(Standard_False),
240 myIPoint(0),
241 myNbPoints(0),
242 myDwmax(0.0),
243 myDeflection(0.0),
244 myFirstParam(0.0),
245 myLastParam(0.0),
246 myDu(0.0)
247 {
248 memset (myParams, 0, sizeof (myParams));
249 }
250
251 //=======================================================================
252 //function : CPnts_UniformDeflection
253 //purpose :
254 //=======================================================================
255
CPnts_UniformDeflection(const Adaptor3d_Curve & C,const Standard_Real Deflection,const Standard_Real Resolution,const Standard_Boolean WithControl)256 CPnts_UniformDeflection::CPnts_UniformDeflection
257 (const Adaptor3d_Curve& C,
258 const Standard_Real Deflection,
259 const Standard_Real Resolution,
260 const Standard_Boolean WithControl)
261 {
262 Initialize(C, Deflection, Resolution, WithControl);
263 }
264
265 //=======================================================================
266 //function : CPnts_UniformDeflection
267 //purpose :
268 //=======================================================================
269
CPnts_UniformDeflection(const Adaptor2d_Curve2d & C,const Standard_Real Deflection,const Standard_Real Resolution,const Standard_Boolean WithControl)270 CPnts_UniformDeflection::CPnts_UniformDeflection
271 (const Adaptor2d_Curve2d& C,
272 const Standard_Real Deflection,
273 const Standard_Real Resolution,
274 const Standard_Boolean WithControl)
275 {
276 Initialize(C, Deflection, Resolution, WithControl);
277 }
278
279 //=======================================================================
280 //function : Initialize
281 //purpose :
282 //=======================================================================
283
Initialize(const Adaptor3d_Curve & C,const Standard_Real Deflection,const Standard_Real Resolution,const Standard_Boolean WithControl)284 void CPnts_UniformDeflection::Initialize(const Adaptor3d_Curve& C,
285 const Standard_Real Deflection,
286 const Standard_Real Resolution,
287 const Standard_Boolean WithControl)
288 {
289 Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
290 Resolution,WithControl);
291 }
292
293 //=======================================================================
294 //function : Initialize
295 //purpose :
296 //=======================================================================
297
Initialize(const Adaptor2d_Curve2d & C,const Standard_Real Deflection,const Standard_Real Resolution,const Standard_Boolean WithControl)298 void CPnts_UniformDeflection::Initialize(const Adaptor2d_Curve2d& C,
299 const Standard_Real Deflection,
300 const Standard_Real Resolution,
301 const Standard_Boolean WithControl)
302 {
303 Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
304 Resolution,WithControl);
305 }
306
307 //=======================================================================
308 //function : CPnts_UniformDeflection
309 //purpose :
310 //=======================================================================
311
CPnts_UniformDeflection(const Adaptor3d_Curve & C,const Standard_Real Deflection,const Standard_Real U1,const Standard_Real U2,const Standard_Real Resolution,const Standard_Boolean WithControl)312 CPnts_UniformDeflection ::CPnts_UniformDeflection
313 (const Adaptor3d_Curve& C,
314 const Standard_Real Deflection,
315 const Standard_Real U1,
316 const Standard_Real U2,
317 const Standard_Real Resolution,
318 const Standard_Boolean WithControl)
319 {
320 Initialize(C, Deflection, U1, U2, Resolution, WithControl);
321 }
322
323 //=======================================================================
324 //function : CPnts_UniformDeflection
325 //purpose :
326 //=======================================================================
327
CPnts_UniformDeflection(const Adaptor2d_Curve2d & C,const Standard_Real Deflection,const Standard_Real U1,const Standard_Real U2,const Standard_Real Resolution,const Standard_Boolean WithControl)328 CPnts_UniformDeflection ::CPnts_UniformDeflection
329 (const Adaptor2d_Curve2d& C,
330 const Standard_Real Deflection,
331 const Standard_Real U1,
332 const Standard_Real U2,
333 const Standard_Real Resolution,
334 const Standard_Boolean WithControl)
335 {
336 Initialize(C, Deflection, U1, U2, Resolution, WithControl);
337 }
338
339 //=======================================================================
340 //function : Initialize
341 //purpose :
342 //=======================================================================
343
Initialize(const Adaptor3d_Curve & C,const Standard_Real Deflection,const Standard_Real U1,const Standard_Real U2,const Standard_Real Resolution,const Standard_Boolean WithControl)344 void CPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& C,
345 const Standard_Real Deflection,
346 const Standard_Real U1,
347 const Standard_Real U2,
348 const Standard_Real Resolution,
349 const Standard_Boolean WithControl)
350 {
351 if (U1 > U2) {
352 myFirstParam = U2;
353 myLastParam = U1;
354 }
355 else {
356 myFirstParam = U1;
357 myLastParam = U2;
358 }
359 my3d = Standard_True;
360 myDwmax = myLastParam-myFirstParam;
361 myDu = myDwmax/2. ;
362 myDone = Standard_True;
363 myCurve = (Standard_Address) &C;
364 myFinish = Standard_False;
365 myTolCur = Resolution;
366 myDeflection = Deflection;
367 myControl = WithControl;
368 Perform();
369 }
370
371 //=======================================================================
372 //function : Initialize
373 //purpose :
374 //=======================================================================
375
Initialize(const Adaptor2d_Curve2d & C,const Standard_Real Deflection,const Standard_Real U1,const Standard_Real U2,const Standard_Real Resolution,const Standard_Boolean WithControl)376 void CPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& C,
377 const Standard_Real Deflection,
378 const Standard_Real U1,
379 const Standard_Real U2,
380 const Standard_Real Resolution,
381 const Standard_Boolean WithControl)
382 {
383 if (U1 > U2) {
384 myFirstParam = U2;
385 myLastParam = U1;
386 }
387 else {
388 myFirstParam = U1;
389 myLastParam = U2;
390 }
391 my3d = Standard_False;
392 myDwmax = myLastParam-myFirstParam;
393 myDu = myDwmax/2. ;
394 myDone = Standard_True;
395 myCurve = (Standard_Address) &C;
396 myFinish = Standard_False;
397 myTolCur = Resolution;
398 myDeflection = Deflection;
399 myControl = WithControl;
400 Perform();
401 }
402
403 //=======================================================================
404 //function : More
405 //purpose :
406 //=======================================================================
407
More()408 Standard_Boolean CPnts_UniformDeflection::More()
409 {
410 if(!myDone) {
411 return Standard_False;
412 }
413 else if (myIPoint == myNbPoints) {
414 if (myFinish) {
415 return Standard_False;
416 }
417 else {
418 Perform();
419 return myDone;
420 }
421 }
422 else {
423 return myIPoint < myNbPoints;
424 }
425 }
426
427
428
429
430
431
432
433