1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
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 //-------------------------------------------------------------------------
41 #include <Adaptor2d_Curve2d.hxx>
42 #include <Adaptor3d_Curve.hxx>
43 #include <CPnts_UniformDeflection.hxx>
45 #include <gp_Pnt2d.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>
53 static inline void D03d(const Standard_Address C, const Standard_Real U,
56 ((Adaptor3d_Curve*)C)->D0(U,P);
59 static void D02d(const Standard_Address C, const Standard_Real U,
63 ((Adaptor2d_Curve2d*)C)->D0(U,P);
64 PP.SetCoord(P.X(),P.Y(),0.);
67 static inline void D23d(const Standard_Address C, const Standard_Real U,
68 gp_Pnt& P, gp_Vec& V1, gp_Vec& V2)
70 ((Adaptor3d_Curve*)C)->D2(U,P,V1,V2);
73 static void D22d(const Standard_Address C, const Standard_Real U,
74 gp_Pnt& PP, gp_Vec& VV1, gp_Vec& VV2)
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.);
84 //=======================================================================
87 //=======================================================================
89 void CPnts_UniformDeflection::Perform()
92 // gp_Vec V1, V2, VV1, VV2, VV;
95 Standard_Real NormD1, NormD2;
100 while ( (myNbPoints<2) && (!myFinish) ) {
102 myNbPoints = myNbPoints + 1;
103 myParams[myNbPoints] = myFirstParam;
106 D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
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);
116 NormD2 = V2.CrossMagnitude(V1);
117 if (NormD2 / NormD1 < myDeflection) { // collinearity of derivatives
118 myDu = Min(myDwmax, 1.5 * myDu);
121 myDu = Sqrt(8.* myDeflection * NormD1 / NormD2 );
122 myDu = Min(Max(myDu, myTolCur), myDwmax);
126 // check if the arrow is observed if WithControl
129 myDu = Min(myDu, myLastParam-myFirstParam);
132 D03d(myCurve, myFirstParam + myDu,P);
133 D03d(myCurve, myFirstParam + (myDu / 2.0),P1);
137 D02d(myCurve, myFirstParam + myDu,P);
138 D02d(myCurve, myFirstParam + (myDu / 2.0),P1);
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;
146 // passing of arrow starting from which the redivision is done is arbitrary
147 // probably it will be necessary to readjust it (differenciate the first point
148 // from the others) this test does not work on the points of inflexion
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);
157 myFirstParam = myFirstParam + myDu;
158 myFinish = (myLastParam - myFirstParam < myTolCur) || (myDu == 0.);
161 // the last point is corrected if control
162 if (myControl && (myNbPoints == 1) ) {
164 if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) {
165 myFirstParam = (myLastParam + Un1) / 2.0;
166 myParams[0]= myFirstParam;
167 myParams[1]= myLastParam;
169 D03d(myCurve, myParams[0], myPoints[0]);
170 D03d(myCurve, myParams[1], myPoints[1]);
173 D02d(myCurve, myParams[0], myPoints[0]);
174 D02d(myCurve, myParams[1], myPoints[1]);
179 D23d(myCurve, myLastParam, P1, V1, V2);
182 D22d(myCurve, myLastParam, P1, V1, V2);
186 NormD1 = VV.Magnitude();
187 if ( NormD1 < myDeflection) {
188 myParams[1]= myLastParam;
192 myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu)
193 /(myFirstParam -Un1);
195 D03d(myCurve, myFirstParam, P2);
197 D02d(myCurve, myFirstParam, P2);
199 if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) &&
200 (Un1 >= myLastParam - myDwmax) ) {
201 // point n is removed
202 myParams[1]= myLastParam;
206 myParams[1]=myFirstParam;
208 myParams[2]=myLastParam;
210 myNbPoints = myNbPoints +1;
216 myNbPoints = myNbPoints +1 ;
217 if (myNbPoints >= 3) myNbPoints = 2;
218 myParams[myNbPoints]= myLastParam;
220 D03d(myCurve, myLastParam, myPoints[myNbPoints]);
223 D02d(myCurve, myLastParam, myPoints[myNbPoints]);
229 //=======================================================================
230 //function : CPnts_UniformDeflection
232 //=======================================================================
234 CPnts_UniformDeflection::CPnts_UniformDeflection ()
236 myDone = Standard_False;
239 //=======================================================================
240 //function : CPnts_UniformDeflection
242 //=======================================================================
244 CPnts_UniformDeflection::CPnts_UniformDeflection
245 (const Adaptor3d_Curve& C,
246 const Standard_Real Deflection,
247 const Standard_Real Resolution,
248 const Standard_Boolean WithControl)
250 Initialize(C, Deflection, Resolution, WithControl);
253 //=======================================================================
254 //function : CPnts_UniformDeflection
256 //=======================================================================
258 CPnts_UniformDeflection::CPnts_UniformDeflection
259 (const Adaptor2d_Curve2d& C,
260 const Standard_Real Deflection,
261 const Standard_Real Resolution,
262 const Standard_Boolean WithControl)
264 Initialize(C, Deflection, Resolution, WithControl);
267 //=======================================================================
268 //function : Initialize
270 //=======================================================================
272 void CPnts_UniformDeflection::Initialize(const Adaptor3d_Curve& C,
273 const Standard_Real Deflection,
274 const Standard_Real Resolution,
275 const Standard_Boolean WithControl)
277 Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
278 Resolution,WithControl);
281 //=======================================================================
282 //function : Initialize
284 //=======================================================================
286 void CPnts_UniformDeflection::Initialize(const Adaptor2d_Curve2d& C,
287 const Standard_Real Deflection,
288 const Standard_Real Resolution,
289 const Standard_Boolean WithControl)
291 Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
292 Resolution,WithControl);
295 //=======================================================================
296 //function : CPnts_UniformDeflection
298 //=======================================================================
300 CPnts_UniformDeflection ::CPnts_UniformDeflection
301 (const Adaptor3d_Curve& C,
302 const Standard_Real Deflection,
303 const Standard_Real U1,
304 const Standard_Real U2,
305 const Standard_Real Resolution,
306 const Standard_Boolean WithControl)
308 Initialize(C, Deflection, U1, U2, Resolution, WithControl);
311 //=======================================================================
312 //function : CPnts_UniformDeflection
314 //=======================================================================
316 CPnts_UniformDeflection ::CPnts_UniformDeflection
317 (const Adaptor2d_Curve2d& C,
318 const Standard_Real Deflection,
319 const Standard_Real U1,
320 const Standard_Real U2,
321 const Standard_Real Resolution,
322 const Standard_Boolean WithControl)
324 Initialize(C, Deflection, U1, U2, Resolution, WithControl);
327 //=======================================================================
328 //function : Initialize
330 //=======================================================================
332 void CPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& C,
333 const Standard_Real Deflection,
334 const Standard_Real U1,
335 const Standard_Real U2,
336 const Standard_Real Resolution,
337 const Standard_Boolean WithControl)
347 my3d = Standard_True;
348 myDwmax = myLastParam-myFirstParam;
350 myDone = Standard_True;
351 myCurve = (Standard_Address) &C;
352 myFinish = Standard_False;
353 myTolCur = Resolution;
354 myDeflection = Deflection;
355 myControl = WithControl;
359 //=======================================================================
360 //function : Initialize
362 //=======================================================================
364 void CPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& C,
365 const Standard_Real Deflection,
366 const Standard_Real U1,
367 const Standard_Real U2,
368 const Standard_Real Resolution,
369 const Standard_Boolean WithControl)
379 my3d = Standard_False;
380 myDwmax = myLastParam-myFirstParam;
382 myDone = Standard_True;
383 myCurve = (Standard_Address) &C;
384 myFinish = Standard_False;
385 myTolCur = Resolution;
386 myDeflection = Deflection;
387 myControl = WithControl;
391 //=======================================================================
394 //=======================================================================
396 Standard_Boolean CPnts_UniformDeflection::More()
399 return Standard_False;
401 else if (myIPoint == myNbPoints) {
403 return Standard_False;
411 return myIPoint < myNbPoints;