1 // File: Law_Interpolate.cxx
2 // Created: Thu Nov 16 09:40:28 1995
3 // Author: Laurent BOURESCHE
7 #include <Law_Interpolate.ixx>
8 #include <Standard_ConstructionError.hxx>
10 #include <BSplCLib.hxx>
11 #include <TColStd_Array1OfBoolean.hxx>
12 #include <TColStd_Array1OfInteger.hxx>
15 //=======================================================================
16 //function : CheckParameters
18 //=======================================================================
20 static Standard_Boolean CheckParameters
21 (const TColStd_Array1OfReal& Parameters)
24 Standard_Real distance;
25 Standard_Boolean result = Standard_True;
26 for (ii = Parameters.Lower() ; result && ii < Parameters.Upper() ; ii++) {
27 distance = Parameters.Value(ii+1) - Parameters.Value(ii);
28 result = (distance >= RealSmall());
33 //=======================================================================
34 //function : BuildParameters
36 //=======================================================================
37 static void BuildParameters(const Standard_Boolean PeriodicFlag,
38 const TColStd_Array1OfReal& PointsArray,
39 Handle(TColStd_HArray1OfReal)& ParametersPtr)
41 Standard_Integer ii, index = 2;
42 Standard_Real distance;
43 Standard_Integer num_parameters = PointsArray.Length();
47 ParametersPtr = new TColStd_HArray1OfReal(1, num_parameters);
48 ParametersPtr->SetValue(1,0.);
49 for (ii = PointsArray.Lower(); ii < PointsArray.Upper(); ii++) {
50 distance = Abs(PointsArray.Value(ii) - PointsArray.Value(ii+1));
51 ParametersPtr->SetValue(index, ParametersPtr->Value(ii) + distance);
55 distance = Abs(PointsArray.Value(PointsArray.Upper()) -
56 PointsArray.Value(PointsArray.Lower()));
57 ParametersPtr->SetValue(index, ParametersPtr->Value(ii) + distance);
61 //=======================================================================
62 //function : BuildPeriodicTangents
64 //=======================================================================
66 static void BuildPeriodicTangent
67 (const TColStd_Array1OfReal& PointsArray,
68 TColStd_Array1OfReal& TangentsArray,
69 TColStd_Array1OfBoolean& TangentFlags,
70 const TColStd_Array1OfReal& ParametersArray)
72 Standard_Real point_array[3], parameter_array[3], eval_result[2];
74 if (PointsArray.Length() < 2) {
75 TangentFlags.SetValue(1,Standard_True);
76 TangentsArray.SetValue(1,0.);
78 else if (!TangentFlags.Value(1)){
79 //Pour les periodiques on evalue la tangente du point de fermeture
80 //par une interpolation de degre 2 entre le dernier point, le point
81 //de fermeture et le deuxieme point.
82 Standard_Integer degree = 2;
83 Standard_Real period = (ParametersArray.Value(ParametersArray.Upper()) -
84 ParametersArray.Value(ParametersArray.Lower()));
85 point_array [0] = PointsArray.Value(PointsArray.Upper());
86 point_array [1] = PointsArray.Value(PointsArray.Lower());
87 point_array [2] = PointsArray.Value(PointsArray.Lower()+1);
88 parameter_array[0] = ParametersArray.Value(ParametersArray.Upper() - 1) - period;
89 parameter_array[1] = ParametersArray.Value(ParametersArray.Lower());
90 parameter_array[2] = ParametersArray.Value(ParametersArray.Lower() + 1);
91 TangentFlags.SetValue(1,Standard_True);
92 PLib::EvalLagrange(parameter_array[1],
99 TangentsArray.SetValue(1,eval_result[1]);
103 //=======================================================================
104 //function : BuildTangents
106 //=======================================================================
108 static void BuildTangents(const TColStd_Array1OfReal& PointsArray,
109 TColStd_Array1OfReal& TangentsArray,
110 TColStd_Array1OfBoolean& TangentFlags,
111 const TColStd_Array1OfReal& ParametersArray)
113 Standard_Integer degree = 3;//,ii;
114 Standard_Real *point_array, *parameter_array, eval_result[2];
116 if ( PointsArray.Length() < 3) {
117 Standard_ConstructionError::Raise();
119 if (PointsArray.Length() == 3) {
122 if (!TangentFlags.Value(1)) {
123 point_array = (Standard_Real *) &PointsArray.Value(PointsArray.Lower());
124 parameter_array = (Standard_Real *) &ParametersArray.Value(1);
125 TangentFlags.SetValue(1,Standard_True);
126 PLib::EvalLagrange(ParametersArray.Value(1),
133 TangentsArray.SetValue(1,eval_result[1]);
135 if (! TangentFlags.Value(TangentFlags.Upper())) {
137 (Standard_Real *) &PointsArray.Value(PointsArray.Upper() - degree);
138 TangentFlags.SetValue(TangentFlags.Upper(),Standard_True);
139 Standard_Integer iup = ParametersArray.Upper() - degree;
140 parameter_array = (Standard_Real *) &ParametersArray.Value(iup);
141 PLib::EvalLagrange(ParametersArray.Value(ParametersArray.Upper()),
148 TangentsArray.SetValue(TangentsArray.Upper(),eval_result[1]);
152 //=======================================================================
153 //function : Law_Interpolate
155 //=======================================================================
157 Law_Interpolate::Law_Interpolate
158 (const Handle(TColStd_HArray1OfReal)& PointsPtr,
159 const Standard_Boolean PeriodicFlag,
160 const Standard_Real Tolerance) :
161 myTolerance(Tolerance),
163 myIsDone(Standard_False),
164 myPeriodic(PeriodicFlag),
165 myTangentRequest(Standard_False)
168 //Standard_Integer ii;
169 myTangents = new TColStd_HArray1OfReal (myPoints->Lower(),
171 myTangentFlags = new TColStd_HArray1OfBoolean(myPoints->Lower(),
174 BuildParameters(PeriodicFlag,
177 myTangentFlags->Init(Standard_False);
180 //=======================================================================
181 //function : Law_Interpolate
183 //=======================================================================
185 Law_Interpolate::Law_Interpolate
186 (const Handle(TColStd_HArray1OfReal)& PointsPtr,
187 const Handle(TColStd_HArray1OfReal)& ParametersPtr,
188 const Standard_Boolean PeriodicFlag,
189 const Standard_Real Tolerance) :
190 myTolerance(Tolerance),
192 myIsDone(Standard_False),
193 myParameters(ParametersPtr),
194 myPeriodic(PeriodicFlag),
195 myTangentRequest(Standard_False)
197 //Standard_Integer ii;
199 if ((PointsPtr->Length()) + 1 != ParametersPtr->Length()) {
200 Standard_ConstructionError::Raise();
203 myTangents = new TColStd_HArray1OfReal(myPoints->Lower(),
205 myTangentFlags = new TColStd_HArray1OfBoolean(myPoints->Lower(),
207 Standard_Boolean result = CheckParameters(ParametersPtr->Array1());
209 Standard_ConstructionError::Raise();
211 myTangentFlags->Init(Standard_False);
214 //=======================================================================
217 //=======================================================================
219 void Law_Interpolate::Load
220 (const TColStd_Array1OfReal& Tangents,
221 const Handle(TColStd_HArray1OfBoolean)& TangentFlagsPtr)
223 //Standard_Boolean result;
225 myTangentRequest = Standard_True;
226 myTangentFlags = TangentFlagsPtr;
227 if (Tangents.Length() != myPoints->Length() ||
228 TangentFlagsPtr->Length() != myPoints->Length()) {
229 Standard_ConstructionError::Raise();
231 myTangents = new TColStd_HArray1OfReal(Tangents.Lower(),Tangents.Upper());
232 for (ii = Tangents.Lower() ; ii <= Tangents.Upper() ; ii++ ) {
233 myTangents->SetValue(ii,Tangents.Value(ii));
237 //=======================================================================
240 //=======================================================================
242 void Law_Interpolate::Load(const Standard_Real InitialTangent,
243 const Standard_Real FinalTangent)
245 //Standard_Boolean result;
246 myTangentRequest = Standard_True;
247 myTangentFlags->SetValue(1,Standard_True);
248 myTangents->SetValue(1,InitialTangent);
249 myTangentFlags->SetValue(myPoints->Length(),Standard_True);
250 myTangents->SetValue(myPoints->Length(),FinalTangent) ;
253 //=======================================================================
256 //=======================================================================
258 void Law_Interpolate::Perform()
264 PerformNonPeriodic();
268 //=======================================================================
269 //function : PerformPeriodic
271 //=======================================================================
273 void Law_Interpolate::PerformPeriodic()
275 Standard_Integer degree,
288 Standard_Real period;
292 num_points = myPoints->Length();
293 period = myParameters->Value(myParameters->Upper()) -
294 myParameters->Value(myParameters->Lower()) ;
295 num_poles = num_points + 1 ;
296 num_distinct_knots = num_points + 1;
300 if (myTangentRequest) {
301 for (ii = myTangentFlags->Lower() + 1;
302 ii <= myTangentFlags->Upper(); ii++) {
303 if (myTangentFlags->Value(ii)) {
308 TColStd_Array1OfReal parameters(1,num_poles);
309 TColStd_Array1OfReal flatknots(1,num_poles + degree + 1);
310 TColStd_Array1OfInteger mults(1,num_distinct_knots);
311 TColStd_Array1OfInteger contact_order_array(1, num_poles);
312 TColStd_Array1OfReal poles(1,num_poles);
314 for (ii = 1 ; ii <= half_order ; ii++) {
315 flatknots.SetValue(ii,myParameters->Value(myParameters->Upper() -1) -
317 flatknots.SetValue(ii + half_order,myParameters->
318 Value(myParameters->Lower()));
319 flatknots.SetValue(num_poles + ii,
320 myParameters->Value(myParameters->Upper()));
321 flatknots.SetValue(num_poles + half_order + ii,
322 myParameters->Value(half_order) + period);
324 for (ii = 1 ; ii <= num_poles ; ii++) {
325 contact_order_array.SetValue(ii,0) ;
327 for (ii = 2; ii < num_distinct_knots; ii++) {
328 mults.SetValue(ii,1);
330 mults.SetValue(1,half_order);
331 mults.SetValue(num_distinct_knots ,half_order);
333 BuildPeriodicTangent(myPoints->Array1(),
334 myTangents->ChangeArray1(),
335 myTangentFlags->ChangeArray1(),
336 myParameters->Array1());
338 contact_order_array.SetValue(2,1);
339 parameters.SetValue(1,myParameters->Value(1));
340 parameters.SetValue(2,myParameters->Value(1));
341 poles.SetValue(1,myPoints->Value(1));
342 poles.SetValue(2,myTangents->Value(1));
346 if (myTangentRequest) {
347 for (ii = myTangentFlags->Lower() + 1;
348 ii <= myTangentFlags->Upper(); ii++) {
349 parameters.SetValue(index,myParameters->Value(ii));
350 flatknots.SetValue(index1,myParameters->Value(ii));
351 poles.SetValue(index,myPoints->Value(ii));
354 if (myTangentFlags->Value(ii)) {
355 mults.SetValue(mult_index,mults.Value(mult_index) + 1);
356 contact_order_array(index) = 1;
358 parameters.SetValue(index,
359 myParameters->Value(ii));
360 flatknots.SetValue(index1,myParameters->Value(ii));
361 poles.SetValue(index,myTangents->Value(ii));
371 for(ii = myParameters->Lower(); ii <= myParameters->Upper(); ii++) {
372 parameters.SetValue(index1, myParameters->Value(ii));
373 flatknots.SetValue(index, myParameters->Value(ii));
378 for (ii = myPoints->Lower() + 1; ii <= myPoints->Upper(); ii++) {
380 // copy all the given points since the last one will be initialized
381 // below by the first point in the array myPoints
383 poles.SetValue(index, myPoints->Value(ii));
387 contact_order_array.SetValue(num_poles - 1, 1);
388 parameters.SetValue(num_poles-1,
389 myParameters->Value(myParameters->Upper()));
391 // for the periodic curve ONLY the tangent of the first point
392 // will be used since the curve should close itself at the first
393 // point See BuildPeriodicTangent
395 poles.SetValue(num_poles-1,myTangents->Value(1));
396 parameters.SetValue(num_poles,
397 myParameters->Value(myParameters->Upper()));
398 poles.SetValue(num_poles,
401 BSplCLib::Interpolate(degree,
408 if (!inversion_problem) {
409 TColStd_Array1OfReal newpoles(poles.Value(1),
412 myCurve = new Law_BSpline(newpoles,
413 myParameters->Array1(),
417 myIsDone = Standard_True;
422 //=======================================================================
423 //function : PerformNonPeriodic
425 //=======================================================================
427 void Law_Interpolate::PerformNonPeriodic()
429 Standard_Integer degree,
444 num_poles = myPoints->Length();
445 if (num_poles == 2 && !myTangentRequest) {
448 else if (num_poles == 3 && !myTangentRequest) {
450 num_distinct_knots = 2;
455 if (myTangentRequest) {
456 for (ii = myTangentFlags->Lower() + 1;
457 ii < myTangentFlags->Upper(); ii++) {
458 if (myTangentFlags->Value(ii)) {
464 TColStd_Array1OfReal parameters(1,num_poles) ;
465 TColStd_Array1OfReal flatknots(1,num_poles + degree + 1) ;
466 TColStd_Array1OfInteger mults(1,num_distinct_knots) ;
467 TColStd_Array1OfReal knots(1,num_distinct_knots) ;
468 TColStd_Array1OfInteger contact_order_array(1, num_poles) ;
469 TColStd_Array1OfReal poles(1,num_poles) ;
471 for (ii = 1 ; ii <= degree + 1 ; ii++) {
472 flatknots.SetValue(ii,myParameters->Value(1));
473 flatknots.SetValue(ii + num_poles,
474 myParameters->Value(num_points));
476 for (ii = 1 ; ii <= num_poles ; ii++) {
477 contact_order_array.SetValue(ii,0);
479 for (ii = 2 ; ii < num_distinct_knots ; ii++) {
480 mults.SetValue(ii,1);
482 mults.SetValue(1,degree + 1);
483 mults.SetValue(num_distinct_knots ,degree + 1);
487 for (ii = 1 ; ii <= num_poles ; ii++) {
488 poles.SetValue(ii ,myPoints->Value(ii));
491 new Law_BSpline(poles,
492 myParameters->Array1(),
495 myIsDone = Standard_True ;
498 knots.SetValue(1,myParameters->Value(1)) ;
499 knots.SetValue(2,myParameters->Value(num_poles)) ;
500 for (ii = 1 ; ii <= num_poles ; ii++) {
501 poles.SetValue(ii,myPoints->Value(ii)) ;
504 BSplCLib::Interpolate(degree,
506 myParameters->Array1(),
511 if (!inversion_problem) {
512 myCurve = new Law_BSpline(poles,
516 myIsDone = Standard_True;
521 // check if the boundary conditions are set
523 if (num_points >= 3) {
525 // cannot build the tangents with degree 3 with only 2 points
526 // if those where not given in advance
528 BuildTangents(myPoints->Array1(),
529 myTangents->ChangeArray1(),
530 myTangentFlags->ChangeArray1(),
531 myParameters->Array1()) ;
533 contact_order_array.SetValue(2,1);
534 parameters.SetValue(1,myParameters->Value(1));
535 parameters.SetValue(2,myParameters->Value(1));
536 poles.SetValue(1,myPoints->Value(1));
537 poles.SetValue(2,myTangents->Value(1));
541 index2 = myPoints->Lower() + 1 ;
542 index3 = degree + 2 ;
543 if (myTangentRequest) {
544 for (ii = myParameters->Lower() + 1 ;
545 ii < myParameters->Upper() ; ii++) {
546 parameters.SetValue(index,myParameters->Value(ii)) ;
547 poles.SetValue(index,myPoints->Value(index2)) ;
548 flatknots.SetValue(index3,myParameters->Value(ii)) ;
551 if (myTangentFlags->Value(index1)) {
553 // set the multiplicities, the order of the contact, the
556 mults.SetValue(mult_index,mults.Value(mult_index) + 1) ;
557 contact_order_array(index) = 1 ;
558 flatknots.SetValue(index3, myParameters->Value(ii)) ;
559 parameters.SetValue(index,
560 myParameters->Value(ii));
561 poles.SetValue(index,myTangents->Value(ii));
572 for(ii = myParameters->Lower(); ii <= myParameters->Upper(); ii++) {
573 parameters.SetValue(index1, myParameters->Value(ii));
577 for (ii = myPoints->Lower() + 1; ii <= myPoints->Upper() - 1; ii++){
578 poles.SetValue(index, myPoints->Value(ii));
582 for(ii = myParameters->Lower(); ii <= myParameters->Upper(); ii++){
583 flatknots.SetValue(index, myParameters->Value(ii));
587 poles.SetValue(num_poles-1, myTangents->Value(num_points));
589 contact_order_array.SetValue(num_poles - 1, 1);
590 parameters.SetValue(num_poles,
591 myParameters->Value(myParameters->Upper())) ;
592 parameters.SetValue(num_poles -1,
593 myParameters->Value(myParameters->Upper())) ;
595 poles.SetValue(num_poles,
596 myPoints->Value(num_points)) ;
598 BSplCLib::Interpolate(degree,
605 if (!inversion_problem) {
606 myCurve = new Law_BSpline(poles,
607 myParameters->Array1(),
610 myIsDone = Standard_True;
616 //=======================================================================
617 //function : Handle_Geom_BSplineCurve&
619 //=======================================================================
621 const Handle(Law_BSpline)& Law_Interpolate::Curve() const
624 StdFail_NotDone::Raise(" ");
628 //=======================================================================
631 //=======================================================================
633 Standard_Boolean Law_Interpolate::IsDone() const