0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / CPnts / CPnts_UniformDeflection.cxx
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
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
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
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
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
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 (differenciate 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
234 CPnts_UniformDeflection::CPnts_UniformDeflection () 
235
236   myDone = Standard_False;
237
238
239 //=======================================================================
240 //function : CPnts_UniformDeflection
241 //purpose  : 
242 //=======================================================================
243
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)
249 {
250   Initialize(C, Deflection, Resolution, WithControl);
251 }
252
253 //=======================================================================
254 //function : CPnts_UniformDeflection
255 //purpose  : 
256 //=======================================================================
257
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)
263 {
264   Initialize(C, Deflection, Resolution, WithControl);
265 }
266
267 //=======================================================================
268 //function : Initialize
269 //purpose  : 
270 //=======================================================================
271
272 void CPnts_UniformDeflection::Initialize(const Adaptor3d_Curve& C, 
273                                          const Standard_Real Deflection,
274                                          const Standard_Real Resolution,
275                                          const Standard_Boolean WithControl)
276 {
277   Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
278              Resolution,WithControl);
279 }
280
281 //=======================================================================
282 //function : Initialize
283 //purpose  : 
284 //=======================================================================
285
286 void CPnts_UniformDeflection::Initialize(const Adaptor2d_Curve2d& C, 
287                                          const Standard_Real Deflection,
288                                          const Standard_Real Resolution,
289                                          const Standard_Boolean WithControl)
290 {
291   Initialize(C,Deflection,C.FirstParameter(),C.LastParameter(),
292              Resolution,WithControl);
293 }
294
295 //=======================================================================
296 //function : CPnts_UniformDeflection
297 //purpose  : 
298 //=======================================================================
299
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)
307 {
308   Initialize(C, Deflection, U1, U2, Resolution, WithControl);
309 }
310
311 //=======================================================================
312 //function : CPnts_UniformDeflection
313 //purpose  : 
314 //=======================================================================
315
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)
323 {
324   Initialize(C, Deflection, U1, U2, Resolution, WithControl);
325 }
326
327 //=======================================================================
328 //function : Initialize
329 //purpose  : 
330 //=======================================================================
331
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)
338 {
339   if (U1 > U2) {
340     myFirstParam = U2;
341     myLastParam  = U1;
342   }
343   else {
344     myFirstParam = U1;
345     myLastParam  = U2;
346   }
347   my3d         = Standard_True;
348   myDwmax      = myLastParam-myFirstParam;
349   myDu         = myDwmax/2. ;
350   myDone       = Standard_True;
351   myCurve      = (Standard_Address) &C;
352   myFinish     = Standard_False;
353   myTolCur     = Resolution;
354   myDeflection = Deflection;
355   myControl    = WithControl;
356   Perform();
357 }
358
359 //=======================================================================
360 //function : Initialize
361 //purpose  : 
362 //=======================================================================
363
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)
370 {
371   if (U1 > U2) {
372     myFirstParam = U2;
373     myLastParam  = U1;
374   }
375   else {
376     myFirstParam = U1;
377     myLastParam  = U2;
378   }
379   my3d         = Standard_False;
380   myDwmax      = myLastParam-myFirstParam;
381   myDu         = myDwmax/2. ;
382   myDone       = Standard_True;
383   myCurve      = (Standard_Address) &C;
384   myFinish     = Standard_False;
385   myTolCur     = Resolution;
386   myDeflection = Deflection;
387   myControl    = WithControl;
388   Perform();
389 }
390
391 //=======================================================================
392 //function : More
393 //purpose  : 
394 //=======================================================================
395
396 Standard_Boolean CPnts_UniformDeflection::More()
397 {
398   if(!myDone) {
399     return Standard_False;
400   }
401   else if (myIPoint == myNbPoints) {
402     if (myFinish) {
403       return Standard_False;
404     }
405     else {
406       Perform();
407       return myDone;
408     }
409   }
410   else {
411     return myIPoint < myNbPoints;
412   }
413 }
414
415
416
417
418
419
420