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