Warnings on vc14 were eliminated
[occt.git] / src / GeomAPI / GeomAPI_Interpolate.cxx
CommitLineData
b311480e 1// Created on: 1994-08-18
2// Created by: Laurent PAINNOT
3// Copyright (c) 1994-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
7fd59977 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
17// 08-Aug-95 : xab : interpolation uses BSplCLib::Interpolate
7fd59977 18
7fd59977 19#include <BSplCLib.hxx>
42cf5bc1 20#include <Geom_BSplineCurve.hxx>
21#include <GeomAPI_Interpolate.hxx>
7fd59977 22#include <gp_Vec.hxx>
42cf5bc1 23#include <PLib.hxx>
24#include <Standard_ConstructionError.hxx>
25#include <StdFail_NotDone.hxx>
7fd59977 26#include <TColgp_Array1OfPnt.hxx>
27#include <TColgp_Array1OfVec.hxx>
42cf5bc1 28#include <TColStd_Array1OfBoolean.hxx>
7fd59977 29#include <TColStd_Array1OfInteger.hxx>
30#include <TColStd_HArray1OfReal.hxx>
cb389a77 31
7fd59977 32//=======================================================================
33//function : CheckPoints
34//purpose :
35//=======================================================================
7fd59977 36static Standard_Boolean CheckPoints(const TColgp_Array1OfPnt& PointArray,
37 const Standard_Real Tolerance)
38{
39 Standard_Integer ii ;
40 Standard_Real tolerance_squared = Tolerance * Tolerance,
41 distance_squared ;
42 Standard_Boolean result = Standard_True ;
43 for (ii = PointArray.Lower() ; result && ii < PointArray.Upper() ; ii++) {
44 distance_squared =
45 PointArray.Value(ii).SquareDistance(PointArray.Value(ii+1)) ;
46 result = (distance_squared >= tolerance_squared) ;
47 }
48 return result ;
49
50}
51//=======================================================================
52//function : CheckTangents
53//purpose :
54//=======================================================================
55static Standard_Boolean CheckTangents(
56 const TColgp_Array1OfVec& Tangents,
57 const TColStd_Array1OfBoolean& TangentFlags,
58 const Standard_Real Tolerance)
59{
60 Standard_Integer ii,
61 index ;
62 Standard_Real tolerance_squared = Tolerance * Tolerance,
63 distance_squared ;
64 Standard_Boolean result = Standard_True ;
65 index = TangentFlags.Lower() ;
66 for (ii = Tangents.Lower(); result && ii <= Tangents.Upper() ; ii++) {
67 if(TangentFlags.Value(index)) {
68 distance_squared =
69 Tangents.Value(ii).SquareMagnitude() ;
70 result = (distance_squared >= tolerance_squared) ;
71 }
72 index += 1 ;
73 }
74 return result ;
75
76}
77//=======================================================================
78//function : CheckParameters
79//purpose :
80//=======================================================================
81static Standard_Boolean CheckParameters(const
82 TColStd_Array1OfReal& Parameters)
83{
84 Standard_Integer ii ;
85 Standard_Real distance ;
86 Standard_Boolean result = Standard_True ;
87 for (ii = Parameters.Lower() ; result && ii < Parameters.Upper() ; ii++) {
88 distance =
89 Parameters.Value(ii+1) - Parameters.Value(ii) ;
90 result = (distance >= RealSmall()) ;
91 }
92 return result ;
93}
94//=======================================================================
95//function : BuildParameters
96//purpose :
97//=======================================================================
98static void BuildParameters(const Standard_Boolean PeriodicFlag,
99 const TColgp_Array1OfPnt& PointsArray,
857ffd5e 100 Handle(TColStd_HArray1OfReal)& ParametersPtr)
7fd59977 101{
102 Standard_Integer ii,
103 index ;
104 Standard_Real distance ;
105 Standard_Integer
106 num_parameters = PointsArray.Length() ;
107 if (PeriodicFlag) {
108 num_parameters += 1 ;
109 }
110 ParametersPtr =
111 new TColStd_HArray1OfReal(1,
112 num_parameters) ;
113 ParametersPtr->SetValue(1,0.0e0) ;
114 index = 2 ;
115 for (ii = PointsArray.Lower() ; ii < PointsArray.Upper() ; ii++) {
116 distance =
117 PointsArray.Value(ii).Distance(PointsArray.Value(ii+1)) ;
118 ParametersPtr->SetValue(index,
119 ParametersPtr->Value(ii) + distance) ;
120 index += 1 ;
121 }
122 if (PeriodicFlag) {
123 distance =
124 PointsArray.Value(PointsArray.Upper()).
125 Distance(PointsArray.Value(PointsArray.Lower())) ;
126 ParametersPtr->SetValue(index,
127 ParametersPtr->Value(ii) + distance) ;
128 }
129}
130//=======================================================================
131//function : BuildPeriodicTangents
132//purpose :
133//=======================================================================
134
135static void BuildPeriodicTangent(
136 const TColgp_Array1OfPnt& PointsArray,
137 TColgp_Array1OfVec& TangentsArray,
138 TColStd_Array1OfBoolean& TangentFlags,
139 const TColStd_Array1OfReal& ParametersArray)
140{
141 Standard_Integer
142 ii,
143 degree ;
144 Standard_Real *point_array,
145 *parameter_array,
146 eval_result[2][3] ;
147
148 gp_Vec a_vector ;
149
150 if (PointsArray.Length() < 3) {
9775fa61 151 throw Standard_ConstructionError();
7fd59977 152 }
153
154 if (!TangentFlags.Value(1)) {
155 degree = 3 ;
156 if (PointsArray.Length() == 3) {
157 degree = 2 ;
158 }
159 point_array = (Standard_Real *) &PointsArray.Value(PointsArray.Lower()) ;
160 parameter_array =
161 (Standard_Real *) &ParametersArray.Value(1) ;
162 TangentFlags.SetValue(1,Standard_True) ;
163 PLib::EvalLagrange(ParametersArray.Value(1),
164 1,
165 degree,
166 3,
167 point_array[0],
168 parameter_array[0],
169 eval_result[0][0]) ;
170 for (ii = 1 ; ii <= 3 ; ii++) {
171 a_vector.SetCoord(ii,eval_result[1][ii-1]) ;
172 }
173 TangentsArray.SetValue(1,a_vector) ;
174 }
175 }
176//=======================================================================
177//function : BuildTangents
178//purpose :
179//=======================================================================
180
181static void BuildTangents(const TColgp_Array1OfPnt& PointsArray,
182 TColgp_Array1OfVec& TangentsArray,
183 TColStd_Array1OfBoolean& TangentFlags,
184 const TColStd_Array1OfReal& ParametersArray)
185{
186 Standard_Integer ii,
187 degree ;
188 Standard_Real *point_array,
189 *parameter_array,
190
191 eval_result[2][3] ;
192 gp_Vec a_vector ;
193
194 degree = 3 ;
195
196 if ( PointsArray.Length() < 3) {
9775fa61 197 throw Standard_ConstructionError();
7fd59977 198 }
199 if (PointsArray.Length() == 3) {
200 degree = 2 ;
201 }
202 if (!TangentFlags.Value(1)) {
203 point_array = (Standard_Real *) &PointsArray.Value(PointsArray.Lower()) ;
204 parameter_array =
205 (Standard_Real *) &ParametersArray.Value(1) ;
206 TangentFlags.SetValue(1,Standard_True) ;
207 PLib::EvalLagrange(ParametersArray.Value(1),
208 1,
209 degree,
210 3,
211 point_array[0],
212 parameter_array[0],
213 eval_result[0][0]) ;
214 for (ii = 1 ; ii <= 3 ; ii++) {
215 a_vector.SetCoord(ii,eval_result[1][ii-1]) ;
216 }
217 TangentsArray.SetValue(1,a_vector) ;
218 }
219 if (! TangentFlags.Value(TangentFlags.Upper())) {
220 point_array =
221 (Standard_Real *) &PointsArray.Value(PointsArray.Upper() - degree) ;
222 TangentFlags.SetValue(TangentFlags.Upper(),Standard_True) ;
223 parameter_array =
224 (Standard_Real *) &ParametersArray.Value(ParametersArray.Upper() - degree) ;
225 PLib::EvalLagrange(ParametersArray.Value(ParametersArray.Upper()),
226 1,
227 degree,
228 3,
229 point_array[0],
230 parameter_array[0],
231 eval_result[0][0]) ;
232 for (ii = 1 ; ii <= 3 ; ii++) {
233 a_vector.SetCoord(ii,eval_result[1][ii-1]) ;
234 }
235 TangentsArray.SetValue(TangentsArray.Upper(),a_vector) ;
236 }
237}
238//=======================================================================
239//function : BuildTangents
240//purpose : scale the given tangent so that they have the length of
241// the size of the derivative of the lagrange interpolation
242//
243//=======================================================================
244static void ScaleTangents(const TColgp_Array1OfPnt& PointsArray,
245 TColgp_Array1OfVec& TangentsArray,
246 const TColStd_Array1OfBoolean& TangentFlags,
247 const TColStd_Array1OfReal& ParametersArray)
248{
249 Standard_Integer ii,
250 jj,
251 degree=0,
252 index,
253 num_points ;
254
255 Standard_Real *point_array,
256 *parameter_array,
257 value[2],
258 ratio,
259 eval_result[2][3] ;
260
261 gp_Vec a_vector ;
262
263 num_points = PointsArray.Length() ;
264 if (num_points == 2) {
265 degree = 1 ;
266 }
267 else if (num_points >= 3) {
268 degree = 2 ;
269 }
270
271 index = PointsArray.Lower() ;
272 for (ii = TangentFlags.Lower() ; ii <= TangentFlags.Upper() ; ii++) {
273 if (TangentFlags.Value(ii)) {
274 point_array =
275 (Standard_Real *) &PointsArray.Value(index) ;
276 parameter_array =
277 (Standard_Real *) &ParametersArray.Value(index) ;
278 PLib::EvalLagrange(ParametersArray.Value(ii),
279 1,
280 degree,
281 3,
282 point_array[0],
283 parameter_array[0],
284 eval_result[0][0]) ;
285 value[0] =
286 value[1] = 0.0e0 ;
287 for (jj = 1 ; jj <= 3 ; jj++) {
288 value[0] += Abs(TangentsArray.Value(ii).Coord(jj)) ;
289 value[1] += Abs(eval_result[1][jj-1]) ;
290 }
291 ratio = value[1] / value[0] ;
292 for (jj = 1 ; jj <= 3 ; jj++) {
293 a_vector.SetCoord(jj, ratio *
294 TangentsArray.Value(ii).Coord(jj)) ;
295 }
296 TangentsArray.SetValue(ii, a_vector) ;
297 if (ii != TangentFlags.Lower()) {
298 index += 1 ;
299 }
300 if (index > PointsArray.Upper() - degree) {
301 index = PointsArray.Upper() - degree ;
302 }
303
304 }
305 }
306}
307
308//=======================================================================
309//function : GeomAPI_Interpolate
310//purpose :
311//=======================================================================
312
313GeomAPI_Interpolate::GeomAPI_Interpolate
857ffd5e 314 (const Handle(TColgp_HArray1OfPnt)& PointsPtr,
7fd59977 315 const Standard_Boolean PeriodicFlag,
316 const Standard_Real Tolerance) :
317myTolerance(Tolerance),
318myPoints(PointsPtr),
319myIsDone(Standard_False),
320myPeriodic(PeriodicFlag),
321myTangentRequest(Standard_False)
322{
323 Standard_Integer ii ;
324 Standard_Boolean result =
325 CheckPoints(PointsPtr->Array1(),
326 Tolerance) ;
327 myTangents =
328 new TColgp_HArray1OfVec(myPoints->Lower(),
329 myPoints->Upper()) ;
330 myTangentFlags =
331 new TColStd_HArray1OfBoolean(myPoints->Lower(),
332 myPoints->Upper()) ;
333
334 if (!result) {
9775fa61 335 throw Standard_ConstructionError();
7fd59977 336 }
337 BuildParameters(PeriodicFlag,
338 PointsPtr->Array1(),
339 myParameters) ;
340
341 for (ii = myPoints->Lower() ; ii <= myPoints->Upper() ; ii++) {
342 myTangentFlags->SetValue(ii,Standard_False) ;
343 }
344
345
346
347}
348
349//=======================================================================
350//function : GeomAPI_Interpolate
351//purpose :
352//=======================================================================
353
354GeomAPI_Interpolate::GeomAPI_Interpolate
857ffd5e 355 (const Handle(TColgp_HArray1OfPnt)& PointsPtr,
356 const Handle(TColStd_HArray1OfReal)& ParametersPtr,
7fd59977 357 const Standard_Boolean PeriodicFlag,
358 const Standard_Real Tolerance) :
359myTolerance(Tolerance),
360myPoints(PointsPtr),
361myIsDone(Standard_False),
362myParameters(ParametersPtr),
363myPeriodic(PeriodicFlag),
364myTangentRequest(Standard_False)
365{
366 Standard_Integer ii ;
367
368
369 Standard_Boolean result =
370 CheckPoints(PointsPtr->Array1(),
371 Tolerance) ;
372
373 if (PeriodicFlag) {
374 if ((PointsPtr->Length()) + 1 != ParametersPtr->Length()) {
9775fa61 375 throw Standard_ConstructionError();
7fd59977 376 }
377 }
378 myTangents =
379 new TColgp_HArray1OfVec(myPoints->Lower(),
380 myPoints->Upper()) ;
381 myTangentFlags =
382 new TColStd_HArray1OfBoolean(myPoints->Lower(),
383 myPoints->Upper()) ;
384
385 if (!result) {
9775fa61 386 throw Standard_ConstructionError();
7fd59977 387 }
388
389 result =
390 CheckParameters(ParametersPtr->Array1()) ;
391 if (!result) {
9775fa61 392 throw Standard_ConstructionError();
7fd59977 393 }
394
395 for (ii = myPoints->Lower() ; ii <= myPoints->Upper() ; ii++) {
396 myTangentFlags->SetValue(ii,Standard_False) ;
397 }
398
399}
400//=======================================================================
401//function : Load
402//purpose :
403//=======================================================================
404
405void GeomAPI_Interpolate::Load(
406 const TColgp_Array1OfVec& Tangents,
857ffd5e 407 const Handle(TColStd_HArray1OfBoolean)& TangentFlagsPtr,
7fd59977 408 const Standard_Boolean Scale )
409
410{
411 Standard_Boolean result ;
412 Standard_Integer ii ;
413 myTangentRequest = Standard_True ;
414 myTangentFlags = TangentFlagsPtr ;
415 if (Tangents.Length() != myPoints->Length() ||
416 TangentFlagsPtr->Length() != myPoints->Length()) {
9775fa61 417 throw Standard_ConstructionError();
7fd59977 418 }
419 result =
420 CheckTangents(Tangents,
421 TangentFlagsPtr->Array1(),
422 myTolerance) ;
423 if (result) {
424 myTangents =
425 new TColgp_HArray1OfVec(Tangents.Lower(),Tangents.Upper()) ;
426 for (ii = Tangents.Lower() ; ii <= Tangents.Upper() ; ii++ ) {
427 myTangents->SetValue(ii,Tangents.Value(ii)) ;
428 }
429
430 if(Scale) {
431 ScaleTangents(myPoints->Array1(),
432 myTangents->ChangeArray1(),
433 TangentFlagsPtr->Array1(),
434 myParameters->Array1()) ;
435 }
436 }
437 else {
9775fa61 438 throw Standard_ConstructionError();
7fd59977 439 }
440
441
442}
443
444//=======================================================================
445//function : Load
446//purpose :
447//=======================================================================
448
449void GeomAPI_Interpolate::Load(const gp_Vec& InitialTangent,
450 const gp_Vec& FinalTangent,
451 const Standard_Boolean Scale )
452{
453 Standard_Boolean result ;
454 myTangentRequest = Standard_True ;
455 myTangentFlags->SetValue(1,Standard_True) ;
456 myTangentFlags->SetValue(myPoints->Length(),Standard_True) ;
457 myTangents->SetValue(1,InitialTangent) ;
458 myTangents->SetValue(myPoints->Length(),FinalTangent) ;
459 result =
460 CheckTangents(myTangents->Array1(),
461 myTangentFlags->Array1(),
462 myTolerance) ;
463 if (!result) {
9775fa61 464 throw Standard_ConstructionError();
7fd59977 465 }
466
467 if(Scale) {
468 ScaleTangents(myPoints->Array1(),
469 myTangents->ChangeArray1(),
470 myTangentFlags->Array1(),
471 myParameters->Array1()) ;
472 }
473
474}
475//=======================================================================
476//function : Perform
477//purpose :
478//=======================================================================
479
480void GeomAPI_Interpolate::Perform()
481{
482 if (myPeriodic) {
483 PerformPeriodic() ;
484 }
485 else {
486 PerformNonPeriodic() ;
487 }
488}
489//=======================================================================
490//function : PerformPeriodic
491//purpose :
492//=======================================================================
493
494void GeomAPI_Interpolate::PerformPeriodic()
495{
496 Standard_Integer degree,
497 ii,
498 jj,
499 index,
500 index1,
501// index2,
502 mult_index,
503 half_order,
504 inversion_problem,
505 num_points,
506 num_distinct_knots,
507 num_poles ;
508
509 Standard_Real period ;
510
511 gp_Pnt a_point ;
512
513 num_points = myPoints->Length() ;
514 period = myParameters->Value(myParameters->Upper()) -
515 myParameters->Value(myParameters->Lower()) ;
516 num_poles = num_points + 1 ;
517 if (num_points == 2 && !myTangentRequest) {
518//
519// build a periodic curve of degree 1
520//
521
522 degree = 1 ;
523 TColStd_Array1OfInteger deg1_mults(1,num_poles) ;
524 for (ii = 1 ; ii <= num_poles ; ii++) {
525 deg1_mults.SetValue(ii,1) ;
526 }
527
528 myCurve =
529 new Geom_BSplineCurve(myPoints->Array1(),
530 myParameters->Array1(),
531 deg1_mults,
532 degree,
533 myPeriodic) ;
534 myIsDone = Standard_True ;
535
536 }
537 else {
538 num_distinct_knots = num_points + 1 ;
539 half_order = 2 ;
540 degree = 3 ;
541 num_poles += 2 ;
542 if (myTangentRequest)
543 for (ii = myTangentFlags->Lower() + 1 ;
544 ii <= myTangentFlags->Upper() ; ii++) {
545 if (myTangentFlags->Value(ii)) {
546 num_poles += 1 ;
547 }
548 }
549
550 TColStd_Array1OfReal parameters(1,num_poles) ;
551 TColStd_Array1OfReal flatknots(1,num_poles + degree + 1) ;
552 TColStd_Array1OfInteger mults(1,num_distinct_knots) ;
553 TColStd_Array1OfInteger contact_order_array(1, num_poles) ;
554 TColgp_Array1OfPnt poles(1,num_poles) ;
555
556 for (ii = 1 ; ii <= half_order ; ii++) {
557 flatknots.SetValue(ii,myParameters->Value(myParameters->Upper() -1) -
558 period) ;
559 flatknots.SetValue(ii + half_order,myParameters->
560 Value(myParameters->Lower())) ;
561 flatknots.SetValue(num_poles + ii,
562 myParameters->Value(myParameters->Upper())) ;
563 flatknots.SetValue(num_poles + half_order + ii,
564 myParameters->Value(half_order) + period) ;
565 }
566 for (ii = 1 ; ii <= num_poles ; ii++) {
567 contact_order_array.SetValue(ii,0) ;
568 }
569 for (ii = 2 ; ii < num_distinct_knots ; ii++) {
570 mults.SetValue(ii,1) ;
571 }
572 mults.SetValue(1,half_order) ;
573 mults.SetValue(num_distinct_knots ,half_order) ;
574 if (num_points >= 3) {
575
576//
577// only enter here if there are more than 3 points otherwise
578// it means we have already the tangent
579//
580 BuildPeriodicTangent(myPoints->Array1(),
581 myTangents->ChangeArray1(),
582 myTangentFlags->ChangeArray1(),
583 myParameters->Array1()) ;
584 }
585 contact_order_array.SetValue(2,1) ;
586 parameters.SetValue(1,myParameters->Value(1)) ;
587 parameters.SetValue(2,myParameters->Value(1)) ;
588 poles.SetValue(1,myPoints->Value(1)) ;
589 for (jj = 1 ; jj <= 3 ; jj++) {
590 a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
591 }
592 poles.SetValue(2,a_point) ;
593
594 mult_index = 2 ;
595 index = 3 ;
596 index1 = degree + 2 ;
597 if (myTangentRequest) {
598 for (ii = myTangentFlags->Lower() + 1 ;
599 ii <= myTangentFlags->Upper() ; ii++) {
600 parameters.SetValue(index,myParameters->Value(ii)) ;
601 flatknots.SetValue(index1,myParameters->Value(ii)) ;
602 poles.SetValue(index,myPoints->Value(ii)) ;
603 index += 1 ;
604 index1 += 1 ;
605 if (myTangentFlags->Value(ii)) {
606 mults.SetValue(mult_index,mults.Value(mult_index) + 1) ;
607 contact_order_array(index) = 1 ;
608
609 parameters.SetValue(index,
610 myParameters->Value(ii)) ;
611 flatknots.SetValue(index1,myParameters->Value(ii)) ;
612 for (jj = 1 ; jj <= 3 ; jj++) {
613 a_point.SetCoord(jj,myTangents->Value(ii).Coord(jj)) ;
614 }
615 poles.SetValue(index,a_point) ;
616 index += 1 ;
617 index1 += 1 ;
618 }
619 mult_index += 1 ;
620 }
621 }
622 else {
623 index = degree + 1 ;
624 index1 = 2 ;
625 for(ii = myParameters->Lower() ; ii <= myParameters->Upper() ; ii++) {
626 parameters.SetValue(index1,
627 myParameters->Value(ii)) ;
628 flatknots.SetValue(index,
629 myParameters->Value(ii)) ;
630 index += 1 ;
631 index1 += 1 ;
632 }
633 index = 3 ;
634 for (ii = myPoints->Lower() + 1 ; ii <= myPoints->Upper() ; ii++) {
635//
636// copy all the given points since the last one will be initialized
637// below by the first point in the array myPoints
638//
639 poles.SetValue(index,
640 myPoints->Value(ii)) ;
641 index += 1 ;
642 }
643
644 }
645 contact_order_array.SetValue(num_poles - 1, 1) ;
646 parameters.SetValue(num_poles-1,
647 myParameters->Value(myParameters->Upper())) ;
648//
649// for the periodic curve ONLY the tangent of the first point
650// will be used since the curve should close itself at the first
651// point See BuildPeriodicTangent
652//
653 for (jj = 1 ; jj <= 3 ; jj++) {
654 a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
655 }
656 poles.SetValue(num_poles-1,a_point) ;
657
658 parameters.SetValue(num_poles,
659 myParameters->Value(myParameters->Upper())) ;
660
661 poles.SetValue(num_poles,
662 myPoints->Value(1)) ;
663
664
665 BSplCLib::Interpolate(degree,
666 flatknots,
667 parameters,
668 contact_order_array,
669 poles,
670 inversion_problem) ;
671 if (!inversion_problem) {
672 TColgp_Array1OfPnt newpoles(poles.Value(1),
673 1,
674 num_poles - 2) ;
675 myCurve =
676 new Geom_BSplineCurve(newpoles,
677 myParameters->Array1(),
678 mults,
679 degree,
680 myPeriodic) ;
681 myIsDone = Standard_True ;
682 }
683 }
684}
685
686
687//=======================================================================
688//function : PerformNonPeriodic
689//purpose :
690//=======================================================================
691
692void GeomAPI_Interpolate::PerformNonPeriodic()
693{
694 Standard_Integer degree,
695 ii,
696 jj,
697 index,
698 index1,
699 index2,
700 index3,
701 mult_index,
702 inversion_problem,
703 num_points,
704 num_distinct_knots,
705 num_poles ;
706
707 gp_Pnt a_point ;
708
709 num_points =
710 num_distinct_knots =
711 num_poles = myPoints->Length() ;
712 if (num_poles == 2 && !myTangentRequest) {
713 degree = 1 ;
714 }
715 else if (num_poles == 3 && !myTangentRequest) {
716 degree = 2 ;
717 num_distinct_knots = 2 ;
718 }
719 else {
720 degree = 3 ;
721 num_poles += 2 ;
722 if (myTangentRequest)
723 for (ii = myTangentFlags->Lower() + 1 ;
724 ii < myTangentFlags->Upper() ; ii++) {
725 if (myTangentFlags->Value(ii)) {
726 num_poles += 1 ;
727 }
728 }
729 }
730
731
732 TColStd_Array1OfReal parameters(1,num_poles) ;
733 TColStd_Array1OfReal flatknots(1,num_poles + degree + 1) ;
734 TColStd_Array1OfInteger mults(1,num_distinct_knots) ;
735 TColStd_Array1OfReal knots(1,num_distinct_knots) ;
736 TColStd_Array1OfInteger contact_order_array(1, num_poles) ;
737 TColgp_Array1OfPnt poles(1,num_poles) ;
738
739 for (ii = 1 ; ii <= degree + 1 ; ii++) {
740 flatknots.SetValue(ii,myParameters->Value(1)) ;
741 flatknots.SetValue(ii + num_poles,
742 myParameters->Value(num_points)) ;
743 }
744 for (ii = 1 ; ii <= num_poles ; ii++) {
745 contact_order_array.SetValue(ii,0) ;
746 }
747 for (ii = 2 ; ii < num_distinct_knots ; ii++) {
748 mults.SetValue(ii,1) ;
749 }
750 mults.SetValue(1,degree + 1) ;
751 mults.SetValue(num_distinct_knots ,degree + 1) ;
752
753 switch (degree) {
754 case 1:
755 for (ii = 1 ; ii <= num_poles ; ii++) {
756 poles.SetValue(ii ,myPoints->Value(ii)) ;
757 }
758 myCurve =
759 new Geom_BSplineCurve(poles,
760 myParameters->Array1(),
761 mults,
762 degree) ;
763 myIsDone = Standard_True ;
764 break ;
765 case 2:
766 knots.SetValue(1,myParameters->Value(1)) ;
767 knots.SetValue(2,myParameters->Value(3)) ;
768 for (ii = 1 ; ii <= num_poles ; ii++) {
769 poles.SetValue(ii,myPoints->Value(ii)) ;
770
771 }
772 BSplCLib::Interpolate(degree,
773 flatknots,
774 myParameters->Array1(),
775 contact_order_array,
776 poles,
777 inversion_problem) ;
778 if (!inversion_problem) {
779 myCurve =
780 new Geom_BSplineCurve(poles,
781 knots,
782 mults,
783 degree) ;
784 myIsDone = Standard_True ;
785 }
786 break ;
787 case 3:
788//
789// check if the boundary conditions are set
790//
791 if (num_points >= 3) {
792//
793// cannot build the tangents with degree 3 with only 2 points
794// if those where not given in advance
795//
796 BuildTangents(myPoints->Array1(),
797 myTangents->ChangeArray1(),
798 myTangentFlags->ChangeArray1(),
799 myParameters->Array1()) ;
800 }
801 contact_order_array.SetValue(2,1) ;
802 parameters.SetValue(1,myParameters->Value(1)) ;
803 parameters.SetValue(2,myParameters->Value(1)) ;
804 poles.SetValue(1,myPoints->Value(1)) ;
805 for (jj = 1 ; jj <= 3 ; jj++) {
806 a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
807
808 }
809 poles.SetValue(2,a_point) ;
810 mult_index = 2 ;
811 index = 3 ;
812 index1 = 2 ;
813 index2 = myPoints->Lower() + 1 ;
814 index3 = degree + 2 ;
815 if (myTangentRequest) {
816 for (ii = myParameters->Lower() + 1 ;
817 ii < myParameters->Upper() ; ii++) {
818 parameters.SetValue(index,myParameters->Value(ii)) ;
819 poles.SetValue(index,myPoints->Value(index2)) ;
820 flatknots.SetValue(index3,myParameters->Value(ii)) ;
821 index += 1 ;
822 index3 += 1 ;
823 if (myTangentFlags->Value(index1)) {
824//
825// set the multiplicities, the order of the contact, the
826// the flatknots,
827//
828 mults.SetValue(mult_index,mults.Value(mult_index) + 1) ;
829 contact_order_array(index) = 1 ;
830 flatknots.SetValue(index3, myParameters->Value(ii)) ;
831 parameters.SetValue(index,
832 myParameters->Value(ii)) ;
833 for (jj = 1 ; jj <= 3 ; jj++) {
834 a_point.SetCoord(jj,myTangents->Value(ii).Coord(jj)) ;
835 }
836 poles.SetValue(index,a_point) ;
837 index += 1 ;
838 index3 += 1 ;
839 }
840 mult_index += 1 ;
841 index1 += 1 ;
842 index2 += 1 ;
843
844 }
845 }
846 else {
847 index1 = 2 ;
848 for(ii = myParameters->Lower() ; ii <= myParameters->Upper() ; ii++) {
849 parameters.SetValue(index1,
850 myParameters->Value(ii)) ;
851 index1 += 1 ;
852 }
853 index = 3 ;
854 for (ii = myPoints->Lower() + 1 ; ii <= myPoints->Upper() - 1 ; ii++) {
855 poles.SetValue(index,
856 myPoints->Value(ii)) ;
857 index += 1 ;
858 }
859
860
861 index = degree + 1 ;
862 for(ii = myParameters->Lower() ; ii <= myParameters->Upper() ; ii++) {
863 flatknots.SetValue(index,
864 myParameters->Value(ii)) ;
865 index += 1 ;
866 }
867 }
868 for (jj = 1 ; jj <= 3 ; jj++) {
869 a_point.SetCoord(jj,
870 myTangents->Value(num_points).Coord(jj)) ;
871 }
872 poles.SetValue(num_poles-1 ,a_point) ;
873
874 contact_order_array.SetValue(num_poles - 1,1) ;
875 parameters.SetValue(num_poles,
876 myParameters->Value(myParameters->Upper())) ;
877 parameters.SetValue(num_poles -1,
878 myParameters->Value(myParameters->Upper())) ;
879
880 poles.SetValue(num_poles,
881 myPoints->Value(num_points)) ;
882
883 BSplCLib::Interpolate(degree,
884 flatknots,
885 parameters,
886 contact_order_array,
887 poles,
888 inversion_problem) ;
889 if (!inversion_problem) {
890 myCurve =
891 new Geom_BSplineCurve(poles,
892 myParameters->Array1(),
893 mults,
894 degree) ;
895 myIsDone = Standard_True ;
896 }
897 break ;
898
899 }
900}
901//=======================================================================
857ffd5e 902//function : Handle(Geom_BSplineCurve)&
7fd59977 903//purpose :
904//=======================================================================
905
906const Handle(Geom_BSplineCurve)& GeomAPI_Interpolate::Curve() const
907{
908 if ( !myIsDone)
9775fa61 909 throw StdFail_NotDone(" ");
7fd59977 910 return myCurve;
911}
912
913
914
915//=======================================================================
916//function : Geom_BSplineCurve
917//purpose :
918//=======================================================================
919
920GeomAPI_Interpolate::operator Handle(Geom_BSplineCurve)() const
921{
922 return myCurve;
923}
924
925
926//=======================================================================
927//function : IsDone
928//purpose :
929//=======================================================================
930
931Standard_Boolean GeomAPI_Interpolate::IsDone() const
932{
933 return myIsDone;
934}
935