0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / Geom2dAPI / Geom2dAPI_PointsToBSpline.cxx
1 // Created on: 1994-03-23
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <AppDef_BSplineCompute.hxx>
19 #include <AppDef_MultiLine.hxx>
20 #include <AppDef_MultiPointConstraint.hxx>
21 #include <AppDef_Variational.hxx>
22 #include <AppParCurves_HArray1OfConstraintCouple.hxx>
23 #include <AppParCurves_MultiBSpCurve.hxx>
24 #include <BSplCLib.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom2dAPI_PointsToBSpline.hxx>
27 #include <math_Vector.hxx>
28 #include <Standard_OutOfRange.hxx>
29 #include <StdFail_NotDone.hxx>
30 #include <TColgp_Array1OfPnt2d.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33
34 //=======================================================================
35 //function : Geom2dAPI_PointsToBSpline
36 //purpose  : 
37 //=======================================================================
38 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline()
39 {
40   myIsDone = Standard_False;
41 }
42
43
44 //=======================================================================
45 //function : Geom2dAPI_PointsToBSpline
46 //purpose  : 
47 //=======================================================================
48
49 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline
50   (const TColgp_Array1OfPnt2d& Points,
51    const Standard_Integer      DegMin, 
52    const Standard_Integer      DegMax,
53    const GeomAbs_Shape         Continuity,
54    const Standard_Real         Tol2D)
55 {
56   Init(Points,DegMin,DegMax,Continuity,Tol2D);
57 }
58
59
60 //=======================================================================
61 //function : Geom2dAPI_PointsToBSpline
62 //purpose  : 
63 //=======================================================================
64
65 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline
66   (const TColStd_Array1OfReal& YValues,
67    const Standard_Real         X0,
68    const Standard_Real         DX,
69    const Standard_Integer      DegMin, 
70    const Standard_Integer      DegMax,
71    const GeomAbs_Shape         Continuity,
72    const Standard_Real         Tol2D)
73 {
74   Init(YValues,X0,DX,DegMin,DegMax,Continuity,Tol2D);
75 }
76
77 //=======================================================================
78 //function : Geom2dAPI_PointsToBSpline
79 //purpose  : 
80 //=======================================================================
81
82 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline
83   (const TColgp_Array1OfPnt2d& Points,
84    const Approx_ParametrizationType ParType,
85    const Standard_Integer    DegMin, 
86    const Standard_Integer    DegMax,
87    const GeomAbs_Shape       Continuity,
88    const Standard_Real       Tol2D)
89 {
90   myIsDone = Standard_False;
91   Init(Points,ParType,DegMin,DegMax,Continuity,Tol2D);
92 }
93
94 //=======================================================================
95 //function : Geom2dAPI_PointsToBSpline
96 //purpose  : 
97 //=======================================================================
98
99 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline
100   (const TColgp_Array1OfPnt2d&   Points,
101    const TColStd_Array1OfReal& Params,
102    const Standard_Integer      DegMin, 
103    const Standard_Integer      DegMax,
104    const GeomAbs_Shape         Continuity,
105    const Standard_Real         Tol2D)
106 {
107   myIsDone = Standard_False;
108   Init(Points,Params,DegMin,DegMax,Continuity,Tol2D);
109 }
110
111
112 //=======================================================================
113 //function : Geom2dAPI_PointsToBSpline
114 //purpose  : 
115 //=======================================================================
116
117 Geom2dAPI_PointsToBSpline::Geom2dAPI_PointsToBSpline
118   (const TColgp_Array1OfPnt2d&   Points,
119    const Standard_Real         W1,
120    const Standard_Real         W2,
121    const Standard_Real         W3,
122    const Standard_Integer      DegMax,
123    const GeomAbs_Shape         Continuity,
124    const Standard_Real         Tol2D)
125 {
126   myIsDone = Standard_False;
127   Init(Points,W1,W2,W3,DegMax,Continuity,Tol2D);
128 }
129
130
131 //=======================================================================
132 //function : Init
133 //purpose  : 
134 //=======================================================================
135
136 void Geom2dAPI_PointsToBSpline::Init
137   (const TColgp_Array1OfPnt2d& Points,
138    const Approx_ParametrizationType ParType,
139    const Standard_Integer      DegMin,
140    const Standard_Integer      DegMax,
141    const GeomAbs_Shape         Continuity,
142    const Standard_Real         Tol2D)
143 {
144   Standard_Real Tol3D = 0.; // dummy argument for BSplineCompute.
145
146
147   Standard_Integer nbit = 2;
148   Standard_Boolean UseSquares = Standard_False;
149   if(Tol2D <= 1.e-3) UseSquares = Standard_True;
150
151   AppDef_BSplineCompute TheComputer
152     (DegMin,DegMax,Tol3D,Tol2D,nbit,Standard_True,ParType,UseSquares);
153
154   switch( Continuity) {
155   case GeomAbs_C0:
156     TheComputer.SetContinuity(0); break;
157
158   case GeomAbs_G1: 
159   case GeomAbs_C1: 
160     TheComputer.SetContinuity(1); break;
161
162   case GeomAbs_G2:
163   case GeomAbs_C2:
164     TheComputer.SetContinuity(2); break;
165
166   default: 
167     TheComputer.SetContinuity(3);
168   }
169   
170   TheComputer.Perform(Points);
171
172   AppParCurves_MultiBSpCurve TheCurve = TheComputer.Value();
173   
174   TColgp_Array1OfPnt2d Poles(1,TheCurve.NbPoles());
175
176   TheCurve.Curve(1, Poles);
177   
178   myCurve = new Geom2d_BSplineCurve(Poles, 
179                                     TheCurve.Knots(),
180                                     TheCurve.Multiplicities(),
181                                     TheCurve.Degree());
182   myIsDone = Standard_True;
183 }
184
185 //=======================================================================
186 //function : Init
187 //purpose  : 
188 //=======================================================================
189
190 void Geom2dAPI_PointsToBSpline::Init
191   (const TColStd_Array1OfReal& YValues,
192    const Standard_Real         X0,
193    const Standard_Real         DX,
194    const Standard_Integer      DegMin, 
195    const Standard_Integer      DegMax,
196    const GeomAbs_Shape         Continuity,
197    const Standard_Real         Tol2D)
198 {
199   // first approximate the Y values (with dummy 0 as X values)
200
201   Standard_Real Tol3D = 0.; // dummy argument for BSplineCompute.
202   TColgp_Array1OfPnt2d Points(YValues.Lower(),YValues.Upper());
203   math_Vector Param(YValues.Lower(),YValues.Upper());
204   Standard_Real length = DX * (YValues.Upper() - YValues.Lower());
205   Standard_Integer i;
206   
207   for (i = YValues.Lower(); i <= YValues.Upper(); i++) {
208     Param(i) = (X0+(i-1)*DX)/(X0+length);
209     Points(i).SetCoord(0.0, YValues(i));
210   }
211
212   AppDef_BSplineCompute TheComputer
213     (Param, DegMin,DegMax,Tol3D,Tol2D,0, Standard_True, Standard_True);
214
215   switch( Continuity) {
216   case GeomAbs_C0:
217     TheComputer.SetContinuity(0); break;
218
219   case GeomAbs_G1: 
220   case GeomAbs_C1: 
221     TheComputer.SetContinuity(1); break;
222
223   case GeomAbs_G2:
224   case GeomAbs_C2:
225     TheComputer.SetContinuity(2); break;
226
227   default: 
228     TheComputer.SetContinuity(3);
229   }
230   
231   TheComputer.Perform(Points);
232
233   const AppParCurves_MultiBSpCurve& TheCurve = TheComputer.Value();
234   
235   Standard_Integer Degree = TheCurve.Degree();
236   TColgp_Array1OfPnt2d Poles(1,TheCurve.NbPoles());
237   Standard_Integer nk = TheCurve.Knots().Length();
238   TColStd_Array1OfReal Knots(1,nk);
239   TColStd_Array1OfInteger Mults(1,nk);
240
241   TheCurve.Curve(1, Poles);
242
243
244
245   // compute X values for the poles
246   TColStd_Array1OfReal XPoles(1,Poles.Upper());
247
248   // start with a line
249   TColStd_Array1OfReal    TempPoles(1,2);
250   TColStd_Array1OfReal    TempKnots(1,2);
251   TColStd_Array1OfInteger TempMults(1,2);
252   TempMults.Init(2);
253   TempPoles(1) = X0;
254   TempPoles(2) = X0 + length;
255   TempKnots(1) = 0.;
256   TempKnots(2) = 1.;
257
258   // increase the Degree
259   TColStd_Array1OfReal    NewTempPoles(1,Degree+1);
260   TColStd_Array1OfReal    NewTempKnots(1,2);
261   TColStd_Array1OfInteger NewTempMults(1,2);
262   BSplCLib::IncreaseDegree(1,Degree,Standard_False,1,
263                            TempPoles,TempKnots,TempMults,
264                            NewTempPoles,NewTempKnots,NewTempMults);
265
266
267   // insert the Knots
268   BSplCLib::InsertKnots(Degree,Standard_False,1,
269                         NewTempPoles,NewTempKnots,NewTempMults,
270                         TheCurve.Knots(),&TheCurve.Multiplicities(),
271                         XPoles,Knots,Mults,
272                         Epsilon(1));
273   
274   // scale the knots
275   for (i = 1; i <= nk; i++) {
276     Knots(i) = X0 + length * Knots(i);
277   }
278
279   // set the Poles
280   for (i = 1; i <= Poles.Upper(); i++) {
281     Poles(i).SetX(XPoles(i));
282   }
283
284
285
286   myCurve = new Geom2d_BSplineCurve(Poles, Knots, Mults, Degree);
287   myIsDone = Standard_True;
288 }
289
290 //=======================================================================
291 //function : Init
292 //purpose  : 
293 //=======================================================================
294
295 void Geom2dAPI_PointsToBSpline::Init
296   (const TColgp_Array1OfPnt2d& Points,
297    const Standard_Integer    DegMin,
298    const Standard_Integer    DegMax,
299    const GeomAbs_Shape       Continuity,
300    const Standard_Real       Tol2D)
301 {
302   myIsDone = Standard_False;
303   Init(Points,Approx_ChordLength,DegMin,DegMax,Continuity,Tol2D);
304 }
305
306
307 //=======================================================================
308 //function : Init
309 //purpose  : 
310 //=======================================================================
311
312 void Geom2dAPI_PointsToBSpline::Init
313   (const TColgp_Array1OfPnt2d&   Points,
314    const TColStd_Array1OfReal& Params,
315    const Standard_Integer      DegMin,
316    const Standard_Integer      DegMax,
317    const GeomAbs_Shape         Continuity,
318    const Standard_Real         Tol2D)
319 {
320   if (Params.Length() != Points.Length()) throw Standard_OutOfRange ("Geom2dAPI_PointsToBSpline::Init() - invalid input");
321
322   Standard_Real Tol3D = 0.; // dummy argument for BSplineCompute.
323   Standard_Integer Nbp = Params.Length();
324   math_Vector theParams(1,Nbp);
325   theParams(1) = 0.;
326   theParams(Nbp) = 1.;
327
328   Standard_Real Uf = Params(Params.Lower());
329   Standard_Real Ul = Params(Params.Upper()) - Uf;
330   for (Standard_Integer i=2; i<Nbp; i++) {
331     theParams(i) = (Params(i)-Uf)/Ul;
332   }
333   
334   AppDef_BSplineCompute TheComputer
335     (DegMin,DegMax,Tol3D,Tol2D,0,
336      Standard_True,Approx_IsoParametric,Standard_True);
337
338   TheComputer.SetParameters(theParams);
339
340   switch( Continuity) {
341   case GeomAbs_C0:
342     TheComputer.SetContinuity(0); break;
343
344   case GeomAbs_G1: 
345   case GeomAbs_C1: 
346     TheComputer.SetContinuity(1); break;
347
348   case GeomAbs_G2:
349   case GeomAbs_C2:
350     TheComputer.SetContinuity(2); break;
351
352   default: 
353     TheComputer.SetContinuity(3);
354   }
355
356   TheComputer.Perform(Points);
357
358   AppParCurves_MultiBSpCurve TheCurve = TheComputer.Value();
359   
360   TColgp_Array1OfPnt2d Poles(1,TheCurve.NbPoles());
361
362   TheCurve.Curve(1, Poles);
363   
364   myCurve = new Geom2d_BSplineCurve(Poles, 
365                                     TheCurve.Knots(),
366                                     TheCurve.Multiplicities(),
367                                     TheCurve.Degree());
368   myIsDone = Standard_True;  
369
370 }
371
372
373 //=======================================================================
374 //function : Init
375 //purpose  : 
376 //=======================================================================
377
378 void Geom2dAPI_PointsToBSpline::Init
379   (const TColgp_Array1OfPnt2d&   Points,
380    const Standard_Real         W1,
381    const Standard_Real         W2,
382    const Standard_Real         W3,
383    const Standard_Integer      DegMax,
384    const GeomAbs_Shape         Continuity,
385    const Standard_Real         Tol2D)
386 {
387   Standard_Integer NbPoint = Points.Length(), i;
388
389  
390   Standard_Integer nbit = 2;
391   if(Tol2D <= 1.e-3) nbit = 0;
392
393  //Variational algo
394
395   AppDef_MultiLine multL(NbPoint);
396   for(i = 1; i <= NbPoint; ++i) {
397     AppDef_MultiPointConstraint mpc(0, 1);
398     mpc.SetPoint2d(1, Points.Value(Points.Lower() + i - 1));
399     multL.SetValue(i, mpc);
400   }
401
402   Handle(AppParCurves_HArray1OfConstraintCouple) TABofCC = 
403     new AppParCurves_HArray1OfConstraintCouple(1, NbPoint);
404   AppParCurves_Constraint  Constraint=AppParCurves_NoConstraint;
405   
406   for(i = 1; i <= NbPoint; ++i) {
407     AppParCurves_ConstraintCouple ACC(i,Constraint);
408     TABofCC->SetValue(i,ACC);
409   }
410   
411
412   AppDef_Variational Variation(multL, 1, NbPoint, TABofCC);
413
414 //===================================
415   Standard_Integer theMaxSegments = 1000;
416   Standard_Boolean theWithMinMax = Standard_False;
417 //===================================      
418
419   Variation.SetMaxDegree(DegMax);
420   Variation.SetContinuity(Continuity);
421   Variation.SetMaxSegment(theMaxSegments);
422
423   Variation.SetTolerance(Tol2D);
424   Variation.SetWithMinMax(theWithMinMax);
425   Variation.SetNbIterations(nbit);
426
427   Variation.SetCriteriumWeight(W1, W2, W3);
428
429   if(!Variation.IsCreated()) {
430     return;
431   }
432   
433   if(Variation.IsOverConstrained()) {
434     return;
435   }
436
437   try {
438     Variation.Approximate();
439   }
440   catch (Standard_Failure const&) {
441     return;
442   }
443
444   if(!Variation.IsDone()) {
445     return;
446   }
447
448   AppParCurves_MultiBSpCurve TheCurve = Variation.Value();
449
450   TColgp_Array1OfPnt2d Poles(1,TheCurve.NbPoles());
451
452   TheCurve.Curve(1, Poles);
453   
454   myCurve = new Geom2d_BSplineCurve(Poles, 
455                                     TheCurve.Knots(),
456                                     TheCurve.Multiplicities(),
457                                     TheCurve.Degree());
458
459   myIsDone = Standard_True;
460
461 }
462
463 //=======================================================================
464 //function : Handle(Geom2d_BSplineCurve)&
465 //purpose  : 
466 //=======================================================================
467
468 const Handle(Geom2d_BSplineCurve)& Geom2dAPI_PointsToBSpline::Curve() const 
469 {
470   if ( !myIsDone) 
471     throw StdFail_NotDone(" ");
472   return myCurve;
473 }
474
475
476
477 //=======================================================================
478 //function : Geom2d_BSplineCurve
479 //purpose  : 
480 //=======================================================================
481
482 Geom2dAPI_PointsToBSpline::operator Handle(Geom2d_BSplineCurve)() const
483 {
484   return myCurve;
485 }
486
487 //=======================================================================
488 //function : Geom2d_BSplineCurve
489 //purpose  : 
490 //=======================================================================
491
492 Standard_Boolean Geom2dAPI_PointsToBSpline::IsDone() const
493 {
494   return myIsDone;
495 }
496
497