Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1993-03-25 |
2 | // Created by: JCV | |
3 | // Copyright (c) 1993-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. | |
b311480e | 13 | // |
973c2be1 | 14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. | |
7fd59977 | 16 | |
7fd59977 | 17 | //Avril 1991 : constructeurs + methodes de lecture. |
18 | //Mai 1991 : revue des specifs + debut de realisation des classes tool => | |
19 | // implementation des methodes Set et calcul du point courant. | |
20 | //Juillet 1991 : voir egalement File Geom2d_BSplineCurve_1.cxx | |
21 | //Juin 1992 : mise a plat des valeurs nodales - amelioration des | |
22 | // performances sur calcul du point courant | |
23 | ||
24 | //RLE Aug 1993 Remove Swaps, Init methods, Remove typedefs | |
25 | // 14-Mar-96 : xab implemented MovePointAndTangent | |
26 | ||
27 | //SAMTECH Jan 2002 : add text to Raise() | |
28 | ||
29 | #define No_Standard_OutOfRange | |
30 | ||
42cf5bc1 | 31 | |
7fd59977 | 32 | #include <BSplCLib.hxx> |
33 | #include <BSplCLib_KnotDistribution.hxx> | |
34 | #include <BSplCLib_MultDistribution.hxx> | |
42cf5bc1 | 35 | #include <Geom2d_BSplineCurve.hxx> |
36 | #include <Geom2d_Geometry.hxx> | |
37 | #include <Geom2d_UndefinedDerivative.hxx> | |
38 | #include <gp.hxx> | |
39 | #include <gp_Pnt2d.hxx> | |
40 | #include <gp_Trsf2d.hxx> | |
41 | #include <gp_Vec2d.hxx> | |
7b1c1b7c | 42 | #include <Precision.hxx> |
7fd59977 | 43 | #include <Standard_ConstructionError.hxx> |
42cf5bc1 | 44 | #include <Standard_DimensionError.hxx> |
45 | #include <Standard_DomainError.hxx> | |
46 | #include <Standard_NoSuchObject.hxx> | |
47 | #include <Standard_NotImplemented.hxx> | |
7fd59977 | 48 | #include <Standard_OutOfRange.hxx> |
42cf5bc1 | 49 | #include <Standard_RangeError.hxx> |
50 | #include <Standard_Type.hxx> | |
7fd59977 | 51 | |
92efcf78 | 52 | IMPLEMENT_STANDARD_RTTIEXT(Geom2d_BSplineCurve,Geom2d_BoundedCurve) |
53 | ||
7fd59977 | 54 | //======================================================================= |
55 | //function : CheckCurveData | |
56 | //purpose : Internal use only | |
57 | //======================================================================= | |
7fd59977 | 58 | static void CheckCurveData |
59 | (const TColgp_Array1OfPnt2d& CPoles, | |
60 | const TColStd_Array1OfReal& CKnots, | |
61 | const TColStd_Array1OfInteger& CMults, | |
62 | const Standard_Integer Degree, | |
63 | const Standard_Boolean Periodic) | |
64 | { | |
65 | if (Degree < 1 || Degree > Geom2d_BSplineCurve::MaxDegree()) { | |
1b827f04 | 66 | throw Standard_ConstructionError("BSpline curve: invalid degree"); |
7fd59977 | 67 | } |
68 | ||
1b827f04 BB |
69 | if (CPoles.Length() < 2) throw Standard_ConstructionError("BSpline curve: at least 2 poles required"); |
70 | if (CKnots.Length() != CMults.Length()) throw Standard_ConstructionError("BSpline curve: Knot and Mult array size mismatch"); | |
7fd59977 | 71 | |
72 | for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) { | |
73 | if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) { | |
1b827f04 | 74 | throw Standard_ConstructionError("BSpline curve: Knots interval values too close"); |
7fd59977 | 75 | } |
76 | } | |
77 | ||
78 | if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults)) | |
1b827f04 | 79 | throw Standard_ConstructionError("BSpline curve: # Poles and degree mismatch"); |
7fd59977 | 80 | } |
81 | ||
6b41f0f3 | 82 | //! Check rationality of an array of weights |
83 | static Standard_Boolean Rational (const TColStd_Array1OfReal& theWeights) | |
7fd59977 | 84 | { |
6b41f0f3 | 85 | for (Standard_Integer i = theWeights.Lower(); i < theWeights.Upper(); i++) |
86 | { | |
87 | if (Abs (theWeights[i] - theWeights[i + 1]) > gp::Resolution()) | |
88 | { | |
89 | return Standard_True; | |
90 | } | |
7fd59977 | 91 | } |
6b41f0f3 | 92 | return Standard_False; |
7fd59977 | 93 | } |
94 | ||
95 | //======================================================================= | |
96 | //function : Copy | |
97 | //purpose : | |
98 | //======================================================================= | |
99 | ||
100 | Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const | |
101 | { | |
102 | Handle(Geom2d_BSplineCurve) C; | |
103 | if (IsRational()) | |
104 | C = new Geom2d_BSplineCurve(poles->Array1(), | |
105 | weights->Array1(), | |
106 | knots->Array1(), | |
107 | mults->Array1(), | |
108 | deg,periodic); | |
109 | else | |
110 | C = new Geom2d_BSplineCurve(poles->Array1(), | |
111 | knots->Array1(), | |
112 | mults->Array1(), | |
113 | deg,periodic); | |
114 | return C; | |
115 | } | |
116 | ||
117 | //======================================================================= | |
118 | //function : Geom2d_BSplineCurve | |
119 | //purpose : | |
120 | //======================================================================= | |
121 | ||
122 | Geom2d_BSplineCurve::Geom2d_BSplineCurve | |
123 | (const TColgp_Array1OfPnt2d& Poles, | |
124 | const TColStd_Array1OfReal& Knots, | |
125 | const TColStd_Array1OfInteger& Mults, | |
126 | const Standard_Integer Degree, | |
127 | const Standard_Boolean Periodic) : | |
128 | rational(Standard_False), | |
129 | periodic(Periodic), | |
130 | deg(Degree), | |
131 | maxderivinvok(Standard_False) | |
132 | { | |
133 | // check | |
134 | ||
94f71cad | 135 | CheckCurveData(Poles, |
136 | Knots, | |
137 | Mults, | |
138 | Degree, | |
139 | Periodic); | |
7fd59977 | 140 | |
141 | // copy arrays | |
142 | ||
143 | poles = new TColgp_HArray1OfPnt2d(1,Poles.Length()); | |
144 | poles->ChangeArray1() = Poles; | |
145 | ||
146 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); | |
147 | knots->ChangeArray1() = Knots; | |
148 | ||
149 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); | |
150 | mults->ChangeArray1() = Mults; | |
151 | ||
152 | UpdateKnots(); | |
7fd59977 | 153 | } |
154 | ||
155 | //======================================================================= | |
156 | //function : Geom2d_BSplineCurve | |
157 | //purpose : | |
158 | //======================================================================= | |
159 | ||
160 | Geom2d_BSplineCurve::Geom2d_BSplineCurve | |
161 | (const TColgp_Array1OfPnt2d& Poles, | |
162 | const TColStd_Array1OfReal& Weights, | |
163 | const TColStd_Array1OfReal& Knots, | |
164 | const TColStd_Array1OfInteger& Mults, | |
165 | const Standard_Integer Degree, | |
166 | const Standard_Boolean Periodic) : | |
167 | rational(Standard_True), | |
168 | periodic(Periodic), | |
169 | deg(Degree), | |
170 | maxderivinvok(Standard_False) | |
171 | ||
172 | { | |
173 | ||
174 | // check | |
175 | ||
94f71cad | 176 | CheckCurveData(Poles, |
177 | Knots, | |
178 | Mults, | |
179 | Degree, | |
180 | Periodic); | |
7fd59977 | 181 | |
182 | if (Weights.Length() != Poles.Length()) | |
1b827f04 | 183 | throw Standard_ConstructionError("Geom2d_BSplineCurve: Weights and Poles array size mismatch"); |
7fd59977 | 184 | |
185 | Standard_Integer i; | |
186 | for (i = Weights.Lower(); i <= Weights.Upper(); i++) { | |
187 | if (Weights(i) <= gp::Resolution()) { | |
9775fa61 | 188 | throw Standard_ConstructionError("Geom2d_BSplineCurve: Weights values too small"); |
7fd59977 | 189 | } |
190 | } | |
191 | ||
192 | // check really rational | |
193 | rational = Rational(Weights); | |
194 | ||
195 | // copy arrays | |
196 | ||
197 | poles = new TColgp_HArray1OfPnt2d(1,Poles.Length()); | |
198 | poles->ChangeArray1() = Poles; | |
7fd59977 | 199 | if (rational) { |
200 | weights = new TColStd_HArray1OfReal(1,Weights.Length()); | |
201 | weights->ChangeArray1() = Weights; | |
7fd59977 | 202 | } |
203 | ||
204 | knots = new TColStd_HArray1OfReal(1,Knots.Length()); | |
205 | knots->ChangeArray1() = Knots; | |
206 | ||
207 | mults = new TColStd_HArray1OfInteger(1,Mults.Length()); | |
208 | mults->ChangeArray1() = Mults; | |
209 | ||
210 | UpdateKnots(); | |
7fd59977 | 211 | } |
212 | ||
213 | //======================================================================= | |
214 | //function : MaxDegree | |
215 | //purpose : | |
216 | //======================================================================= | |
217 | ||
218 | Standard_Integer Geom2d_BSplineCurve::MaxDegree () | |
219 | { | |
220 | return BSplCLib::MaxDegree(); | |
221 | } | |
222 | ||
223 | //======================================================================= | |
224 | //function : IncreaseDegree | |
225 | //purpose : | |
226 | //======================================================================= | |
227 | ||
228 | void Geom2d_BSplineCurve::IncreaseDegree | |
229 | (const Standard_Integer Degree) | |
230 | { | |
231 | if (Degree == deg) return; | |
232 | ||
233 | if (Degree < deg || Degree > Geom2d_BSplineCurve::MaxDegree()) { | |
1b827f04 | 234 | throw Standard_ConstructionError("BSpline curve: IncreaseDegree: bad degree value"); |
7fd59977 | 235 | } |
236 | ||
237 | Standard_Integer FromK1 = FirstUKnotIndex (); | |
238 | Standard_Integer ToK2 = LastUKnotIndex (); | |
239 | ||
240 | Standard_Integer Step = Degree - deg; | |
241 | ||
242 | Handle(TColgp_HArray1OfPnt2d) npoles = new | |
243 | TColgp_HArray1OfPnt2d(1,poles->Length() + Step * (ToK2-FromK1)); | |
244 | ||
245 | Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots | |
246 | (deg,Degree,periodic,mults->Array1()); | |
247 | ||
248 | Handle(TColStd_HArray1OfReal) nknots = | |
249 | new TColStd_HArray1OfReal(1,nbknots); | |
250 | ||
251 | Handle(TColStd_HArray1OfInteger) nmults = | |
252 | new TColStd_HArray1OfInteger(1,nbknots); | |
253 | ||
254 | Handle(TColStd_HArray1OfReal) nweights; | |
255 | ||
256 | if (IsRational()) { | |
7fd59977 | 257 | nweights = new TColStd_HArray1OfReal(1,npoles->Upper()); |
7fd59977 | 258 | } |
7fd59977 | 259 | |
aff73fd5 | 260 | BSplCLib::IncreaseDegree (deg, Degree, periodic, |
261 | poles->Array1(), !nweights.IsNull() ? &weights->Array1() : BSplCLib::NoWeights(), | |
262 | knots->Array1(), mults->Array1(), | |
263 | npoles->ChangeArray1(), !nweights.IsNull() ? &nweights->ChangeArray1() : BSplCLib::NoWeights(), | |
264 | nknots->ChangeArray1(), nmults->ChangeArray1()); | |
7fd59977 | 265 | |
266 | deg = Degree; | |
267 | poles = npoles; | |
268 | weights = nweights; | |
269 | knots = nknots; | |
270 | mults = nmults; | |
271 | UpdateKnots(); | |
272 | } | |
273 | ||
274 | //======================================================================= | |
275 | //function : IncreaseMultiplicity | |
276 | //purpose : | |
277 | //======================================================================= | |
278 | ||
279 | void Geom2d_BSplineCurve::IncreaseMultiplicity | |
280 | (const Standard_Integer Index, | |
281 | const Standard_Integer M) | |
282 | { | |
283 | TColStd_Array1OfReal k(1,1); | |
284 | k(1) = knots->Value(Index); | |
285 | TColStd_Array1OfInteger m(1,1); | |
286 | m(1) = M - mults->Value(Index); | |
287 | InsertKnots(k,m,Epsilon(1.),Standard_True); | |
288 | } | |
289 | ||
290 | //======================================================================= | |
291 | //function : IncreaseMultiplicity | |
292 | //purpose : | |
293 | //======================================================================= | |
294 | ||
295 | void Geom2d_BSplineCurve::IncreaseMultiplicity | |
296 | (const Standard_Integer I1, | |
297 | const Standard_Integer I2, | |
298 | const Standard_Integer M) | |
299 | { | |
300 | Handle(TColStd_HArray1OfReal) tk = knots; | |
301 | TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2); | |
302 | TColStd_Array1OfInteger m(I1,I2); | |
303 | Standard_Integer i; | |
304 | for (i = I1; i <= I2; i++) | |
305 | m(i) = M - mults->Value(i); | |
306 | InsertKnots(k,m,Epsilon(1.),Standard_True); | |
307 | } | |
308 | ||
309 | //======================================================================= | |
310 | //function : IncrementMultiplicity | |
311 | //purpose : | |
312 | //======================================================================= | |
313 | ||
314 | void Geom2d_BSplineCurve::IncrementMultiplicity | |
315 | (const Standard_Integer I1, | |
316 | const Standard_Integer I2, | |
317 | const Standard_Integer Step) | |
318 | { | |
319 | Handle(TColStd_HArray1OfReal) tk = knots; | |
320 | TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2); | |
321 | TColStd_Array1OfInteger m(I1,I2); | |
322 | m.Init(Step); | |
323 | InsertKnots(k,m,Epsilon(1.),Standard_True); | |
324 | } | |
325 | ||
326 | //======================================================================= | |
327 | //function : InsertKnot | |
328 | //purpose : | |
329 | //======================================================================= | |
330 | ||
331 | void Geom2d_BSplineCurve::InsertKnot | |
332 | (const Standard_Real U, | |
333 | const Standard_Integer M, | |
334 | const Standard_Real ParametricTolerance) | |
335 | { | |
336 | TColStd_Array1OfReal k(1,1); | |
337 | k(1) = U; | |
338 | TColStd_Array1OfInteger m(1,1); | |
339 | m(1) = M; | |
340 | InsertKnots(k,m,ParametricTolerance); | |
341 | } | |
342 | ||
343 | //======================================================================= | |
344 | //function : InsertKnots | |
345 | //purpose : | |
346 | //======================================================================= | |
347 | void Geom2d_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots, | |
348 | const TColStd_Array1OfInteger& Mults, | |
349 | const Standard_Real Epsilon, | |
350 | const Standard_Boolean Add) | |
351 | { | |
352 | // Check and compute new sizes | |
353 | Standard_Integer nbpoles,nbknots; | |
354 | ||
355 | if (!BSplCLib::PrepareInsertKnots(deg,periodic, | |
356 | knots->Array1(),mults->Array1(), | |
0e14656b | 357 | Knots,&Mults,nbpoles,nbknots,Epsilon,Add)) |
9775fa61 | 358 | throw Standard_ConstructionError("Geom2d_BSplineCurve::InsertKnots"); |
7fd59977 | 359 | |
360 | if (nbpoles == poles->Length()) return; | |
361 | ||
362 | Handle(TColgp_HArray1OfPnt2d) npoles = new TColgp_HArray1OfPnt2d(1,nbpoles); | |
363 | Handle(TColStd_HArray1OfReal) nknots = knots; | |
364 | Handle(TColStd_HArray1OfInteger) nmults = mults; | |
365 | ||
366 | if (nbknots != knots->Length()) { | |
367 | nknots = new TColStd_HArray1OfReal(1,nbknots); | |
368 | nmults = new TColStd_HArray1OfInteger(1,nbknots); | |
369 | } | |
370 | ||
aff73fd5 | 371 | Handle(TColStd_HArray1OfReal) nweights; |
372 | if (rational) | |
373 | { | |
374 | nweights = new TColStd_HArray1OfReal (1, nbpoles); | |
7fd59977 | 375 | } |
376 | ||
aff73fd5 | 377 | BSplCLib::InsertKnots (deg, periodic, |
378 | poles->Array1(), !nweights.IsNull() ? &weights->Array1() : BSplCLib::NoWeights(), | |
379 | knots->Array1(), mults->Array1(), | |
380 | Knots, &Mults, | |
381 | npoles->ChangeArray1(), !nweights.IsNull() ? &nweights->ChangeArray1() : BSplCLib::NoWeights(), | |
382 | nknots->ChangeArray1(), nmults->ChangeArray1(), | |
383 | Epsilon, Add); | |
384 | weights = nweights; | |
7fd59977 | 385 | poles = npoles; |
386 | knots = nknots; | |
387 | mults = nmults; | |
388 | UpdateKnots(); | |
7fd59977 | 389 | } |
390 | ||
391 | //======================================================================= | |
392 | //function : RemoveKnot | |
393 | //purpose : | |
394 | //======================================================================= | |
395 | ||
396 | Standard_Boolean Geom2d_BSplineCurve::RemoveKnot | |
397 | (const Standard_Integer Index, | |
398 | const Standard_Integer M, | |
399 | const Standard_Real Tolerance) | |
400 | { | |
401 | if (M < 0) return Standard_True; | |
402 | ||
403 | Standard_Integer I1 = FirstUKnotIndex (); | |
404 | Standard_Integer I2 = LastUKnotIndex (); | |
405 | ||
406 | if (Index < I1 || Index > I2) { | |
1b827f04 | 407 | throw Standard_OutOfRange("BSpline curve: RemoveKnot: index out of range"); |
7fd59977 | 408 | } |
409 | ||
410 | const TColgp_Array1OfPnt2d & oldpoles = poles->Array1(); | |
411 | ||
412 | Standard_Integer step = mults->Value(Index) - M; | |
413 | if (step <= 0) return Standard_True; | |
414 | ||
415 | Handle(TColgp_HArray1OfPnt2d) npoles = | |
416 | new TColgp_HArray1OfPnt2d(1,oldpoles.Length()-step); | |
417 | ||
418 | Handle(TColStd_HArray1OfReal) nknots = knots; | |
419 | Handle(TColStd_HArray1OfInteger) nmults = mults; | |
420 | ||
421 | if (M == 0) { | |
422 | nknots = new TColStd_HArray1OfReal(1,knots->Length()-1); | |
423 | nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1); | |
424 | } | |
425 | ||
aff73fd5 | 426 | Handle(TColStd_HArray1OfReal) nweights; |
427 | if (IsRational()) | |
428 | { | |
429 | nweights = new TColStd_HArray1OfReal(1,npoles->Length()); | |
7fd59977 | 430 | } |
aff73fd5 | 431 | |
432 | if (!BSplCLib::RemoveKnot (Index, M, deg, periodic, | |
433 | poles->Array1(), !nweights.IsNull() ? &weights->Array1() : BSplCLib::NoWeights(), | |
434 | knots->Array1(),mults->Array1(), | |
435 | npoles->ChangeArray1(), !nweights.IsNull() ? &nweights->ChangeArray1() : BSplCLib::NoWeights(), | |
436 | nknots->ChangeArray1(),nmults->ChangeArray1(), | |
437 | Tolerance)) | |
438 | { | |
439 | return Standard_False; | |
7fd59977 | 440 | } |
aff73fd5 | 441 | |
442 | weights = nweights; | |
7fd59977 | 443 | poles = npoles; |
444 | knots = nknots; | |
445 | mults = nmults; | |
446 | ||
447 | UpdateKnots(); | |
448 | maxderivinvok = 0; | |
449 | return Standard_True; | |
450 | } | |
451 | ||
452 | //======================================================================= | |
453 | //function : InsertPoleAfter | |
454 | //purpose : | |
455 | //======================================================================= | |
456 | ||
457 | void Geom2d_BSplineCurve::InsertPoleAfter | |
458 | (const Standard_Integer Index, | |
459 | const gp_Pnt2d& P, | |
460 | const Standard_Real Weight) | |
461 | { | |
1b827f04 | 462 | if (Index < 0 || Index > poles->Length()) throw Standard_OutOfRange("BSpline curve: InsertPoleAfter: Index and #pole mismatch"); |
7fd59977 | 463 | |
1b827f04 | 464 | if (Weight <= gp::Resolution()) throw Standard_ConstructionError("BSpline curve: InsertPoleAfter: Weight too small"); |
7fd59977 | 465 | |
466 | if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) { | |
1b827f04 | 467 | throw Standard_ConstructionError("BSpline curve: InsertPoleAfter: bad knotSet type"); |
7fd59977 | 468 | } |
469 | ||
470 | const TColStd_Array1OfReal& cknots = knots->Array1(); | |
471 | Standard_Integer nbknots = cknots.Length(); | |
472 | ||
473 | Handle(TColStd_HArray1OfReal) nknots = | |
474 | new TColStd_HArray1OfReal(1,nbknots+1); | |
475 | ||
476 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); | |
477 | ||
478 | Standard_Integer i; | |
479 | for (i = 1; i < nbknots; i++) { | |
480 | newknots (i) = cknots(i); | |
481 | } | |
482 | ||
483 | newknots (nbknots+1) = 2 * newknots (nbknots) - newknots(nbknots-1); | |
484 | ||
485 | Handle(TColStd_HArray1OfInteger) nmults = | |
486 | new TColStd_HArray1OfInteger(1,nbknots+1); | |
487 | ||
488 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); | |
489 | const TColStd_Array1OfInteger& cmults = mults->Array1(); | |
490 | ||
491 | for (i = 2; i <= nbknots; i++) newmults (i) = 1; | |
492 | newmults (1) = cmults(1); | |
493 | newmults (nbknots+1) = cmults(nbknots+1); | |
494 | ||
495 | const TColgp_Array1OfPnt2d& cpoles = poles->Array1(); | |
496 | Standard_Integer nbpoles = cpoles.Length(); | |
497 | Handle(TColgp_HArray1OfPnt2d) npoles = | |
498 | new TColgp_HArray1OfPnt2d(1, nbpoles+1); | |
499 | TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1(); | |
500 | ||
501 | // insert the pole | |
502 | ||
503 | for (i = 1; i <= Index; i++) | |
504 | newpoles(i) = cpoles(i); | |
505 | ||
506 | newpoles(Index+1) = P; | |
507 | ||
508 | for (i = Index+1; i <= nbpoles; i++) | |
509 | newpoles(i+1) = cpoles(i); | |
510 | ||
511 | // Insert the weight | |
512 | ||
513 | Handle(TColStd_HArray1OfReal) nweights; | |
514 | Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution(); | |
515 | ||
516 | if (rat) { | |
517 | nweights = new TColStd_HArray1OfReal(1,nbpoles+1); | |
518 | TColStd_Array1OfReal& newweights = nweights->ChangeArray1(); | |
519 | ||
520 | for (i = 1; i <= Index; i++) | |
521 | if (IsRational()) | |
522 | newweights(i) = weights->Value(i); | |
523 | else | |
524 | newweights(i) = 1.; | |
525 | ||
526 | newweights(Index+1) = Weight; | |
527 | ||
528 | for (i = Index+1; i <= nbpoles; i++) | |
529 | if (IsRational()) | |
530 | newweights(i+1) = weights->Value(i); | |
531 | else | |
532 | newweights(i+1) = 1.; | |
533 | } | |
534 | ||
535 | poles = npoles; | |
536 | weights = nweights; | |
537 | knots = nknots; | |
538 | mults = nmults; | |
539 | maxderivinvok = 0; | |
540 | UpdateKnots(); | |
541 | } | |
542 | ||
543 | //======================================================================= | |
544 | //function : InsertPoleBefore | |
545 | //purpose : | |
546 | //======================================================================= | |
547 | ||
548 | void Geom2d_BSplineCurve::InsertPoleBefore | |
549 | (const Standard_Integer Index, | |
550 | const gp_Pnt2d& P, | |
551 | const Standard_Real Weight) | |
552 | { | |
553 | InsertPoleAfter(Index-1,P,Weight); | |
554 | } | |
555 | ||
556 | //======================================================================= | |
557 | //function : RemovePole | |
558 | //purpose : | |
559 | //======================================================================= | |
560 | ||
561 | void Geom2d_BSplineCurve::RemovePole | |
562 | (const Standard_Integer Index) | |
563 | { | |
1b827f04 | 564 | if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange("BSpline curve: RemovePole: Index and #pole mismatch"); |
7fd59977 | 565 | |
1b827f04 | 566 | if (poles->Length() <= 2) throw Standard_ConstructionError("BSpline curve: RemovePole: #pole is already minimum"); |
7fd59977 | 567 | |
568 | if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) | |
1b827f04 | 569 | throw Standard_ConstructionError("BSpline curve: RemovePole: bad knotSet type"); |
7fd59977 | 570 | |
571 | Standard_Integer i; | |
572 | Handle(TColStd_HArray1OfReal) nknots = | |
573 | new TColStd_HArray1OfReal(1,knots->Length()-1); | |
574 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); | |
575 | ||
576 | Handle(TColStd_HArray1OfInteger) nmults = | |
577 | new TColStd_HArray1OfInteger(1,mults->Length()-1); | |
578 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); | |
579 | ||
580 | for (i = 1; i < newknots.Length(); i++) { | |
581 | newknots (i) = knots->Value (i); | |
582 | newmults (i) = 1; | |
583 | } | |
584 | newmults(1) = mults->Value(1); | |
585 | newknots(newknots.Upper()) = knots->Value (knots->Upper()); | |
586 | newmults(newmults.Upper()) = mults->Value (mults->Upper()); | |
587 | ||
588 | ||
589 | Handle(TColgp_HArray1OfPnt2d) npoles = | |
590 | new TColgp_HArray1OfPnt2d(1, poles->Upper()-1); | |
591 | TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1(); | |
592 | ||
593 | for (i = 1; i < Index; i++) | |
594 | newpoles(i) = poles->Value(i); | |
595 | for (i = Index; i < newpoles.Length(); i++) | |
596 | newpoles(i) = poles->Value(i+1); | |
597 | ||
598 | Handle(TColStd_HArray1OfReal) nweights; | |
599 | if (IsRational()) { | |
600 | nweights = new TColStd_HArray1OfReal(1,newpoles.Length()); | |
601 | TColStd_Array1OfReal& newweights = nweights->ChangeArray1(); | |
602 | for (i = 1; i < Index; i++) | |
603 | newweights(i) = weights->Value(i); | |
604 | for (i = Index; i < newweights.Length(); i++) | |
605 | newweights(i) = weights->Value(i+1); | |
606 | } | |
607 | ||
608 | poles = npoles; | |
609 | weights = nweights; | |
610 | knots = nknots; | |
611 | mults = nmults; | |
612 | UpdateKnots(); | |
613 | } | |
614 | ||
615 | //======================================================================= | |
616 | //function : Reverse | |
617 | //purpose : | |
618 | //======================================================================= | |
619 | ||
620 | void Geom2d_BSplineCurve::Reverse () | |
621 | { | |
622 | BSplCLib::Reverse(knots->ChangeArray1()); | |
623 | BSplCLib::Reverse(mults->ChangeArray1()); | |
624 | Standard_Integer last; | |
625 | if (periodic) | |
626 | last = flatknots->Upper() - deg - 1; | |
627 | else | |
628 | last = poles->Upper(); | |
629 | BSplCLib::Reverse(poles->ChangeArray1(),last); | |
630 | if (rational) | |
631 | BSplCLib::Reverse(weights->ChangeArray1(),last); | |
632 | UpdateKnots(); | |
633 | } | |
634 | ||
635 | //======================================================================= | |
636 | //function : ReversedParameter | |
637 | //purpose : | |
638 | //======================================================================= | |
639 | ||
640 | Standard_Real Geom2d_BSplineCurve::ReversedParameter( const Standard_Real U) const | |
641 | { | |
642 | return (FirstParameter() + LastParameter() - U); | |
643 | } | |
644 | ||
645 | //======================================================================= | |
646 | //function : Segment | |
647 | //purpose : | |
648 | //======================================================================= | |
649 | void Geom2d_BSplineCurve::Segment(const Standard_Real aU1, | |
6fd9bdf2 | 650 | const Standard_Real aU2, |
651 | const Standard_Real theTolerance) | |
7fd59977 | 652 | { |
369a38aa | 653 | if (aU2 < aU1) |
9775fa61 | 654 | throw Standard_DomainError("Geom2d_BSplineCurve::Segment"); |
7fd59977 | 655 | // |
656 | Standard_Real AbsUMax = Max(Abs(FirstParameter()),Abs(LastParameter())); | |
6fd9bdf2 | 657 | Standard_Real Eps = Max (Epsilon(AbsUMax), theTolerance); |
7fd59977 | 658 | Standard_Real NewU1, NewU2; |
659 | Standard_Real U, DU=0; | |
660 | Standard_Integer i, k, index; | |
661 | // | |
662 | //f | |
663 | // Checking the input bounds aUj (j=1,2). | |
664 | // For the case when aUj==knot(i), | |
665 | // in order to prevent the insertion of a new knot that will be too closed | |
666 | // to the existing knot, | |
667 | // we assign Uj=knot(i) | |
668 | Standard_Integer n1, n2; | |
669 | Standard_Real U1, U2; | |
670 | // | |
671 | U1=aU1; | |
672 | U2=aU2; | |
673 | n1=knots->Lower(); | |
674 | n2=knots->Upper(); | |
675 | for (i=n1; i<=n2; ++i) { | |
676 | U=knots->Value(i); | |
677 | if (Abs(U-aU1)<=Eps) { | |
678 | U1=U; | |
679 | } | |
680 | else if (Abs(U-aU2)<=Eps) { | |
681 | U2=U; | |
682 | } | |
683 | } | |
684 | // Henceforward we use U1, U2 as bounds of the segment | |
685 | //t | |
686 | // | |
687 | TColStd_Array1OfReal Knots(1,2); | |
688 | TColStd_Array1OfInteger Mults(1,2); | |
689 | // | |
21c7c457 | 690 | // define param distance to keep (eap, Apr 18 2002, occ311) |
7fd59977 | 691 | if (periodic) { |
692 | Standard_Real Period = LastParameter() - FirstParameter(); | |
693 | DU = U2 - U1; | |
369a38aa | 694 | if (DU - Period > Precision::PConfusion()) |
9775fa61 | 695 | throw Standard_DomainError("Geom2d_BSplineCurve::Segment"); |
369a38aa | 696 | if (DU > Period) |
7fd59977 | 697 | DU = Period; |
7fd59977 | 698 | } |
699 | // | |
700 | index = 0; | |
701 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), | |
702 | U1,periodic,knots->Lower(),knots->Upper(), | |
703 | index,NewU1); | |
704 | index = 0; | |
705 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), | |
706 | U2,periodic,knots->Lower(),knots->Upper(), | |
707 | index,NewU2); | |
708 | Knots(1) = Min( NewU1, NewU2); | |
709 | Knots(2) = Max( NewU1, NewU2); | |
710 | Mults(1) = Mults( 2) = deg; | |
711 | InsertKnots(Knots, Mults, Eps); | |
712 | ||
713 | if (periodic) { // set the origine at NewU1 | |
714 | index = 0; | |
715 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), | |
716 | U1,periodic,knots->Lower(),knots->Upper(), | |
717 | index,U); | |
718 | // Eps = Epsilon(knots->Value(index+1)); | |
719 | if ( Abs(knots->Value(index+1)-U) <= Eps) { | |
720 | index++; | |
721 | } | |
722 | SetOrigin(index); | |
723 | SetNotPeriodic(); | |
724 | NewU2 = NewU1 + DU; | |
725 | } | |
726 | ||
727 | // compute index1 and index2 to set the new knots and mults | |
728 | Standard_Integer index1 = 0, index2 = 0; | |
729 | Standard_Integer FromU1 = knots->Lower(); | |
730 | Standard_Integer ToU2 = knots->Upper(); | |
731 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), | |
732 | NewU1,periodic,FromU1,ToU2,index1,U); | |
733 | BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(), | |
734 | NewU2,periodic,FromU1,ToU2,index2,U); | |
735 | // Eps = Epsilon(knots->Value(index2+1)); | |
736 | if ( Abs(knots->Value(index2+1)-U) <= Eps){ | |
737 | index2++; | |
738 | } | |
739 | ||
740 | Standard_Integer nbknots = index2 - index1 + 1; | |
741 | ||
742 | Handle(TColStd_HArray1OfReal) | |
743 | nknots = new TColStd_HArray1OfReal(1,nbknots); | |
744 | Handle(TColStd_HArray1OfInteger) | |
745 | nmults = new TColStd_HArray1OfInteger(1,nbknots); | |
746 | ||
747 | // to restore changed U1 | |
748 | if (DU > 0) {// if was periodic | |
749 | DU = NewU1 - U1; | |
750 | } | |
751 | // | |
752 | k = 1; | |
753 | // | |
754 | for ( i = index1; i<= index2; i++) { | |
755 | nknots->SetValue(k, knots->Value(i) - DU); | |
756 | nmults->SetValue(k, mults->Value(i)); | |
757 | k++; | |
758 | } | |
759 | nmults->SetValue( 1, deg + 1); | |
760 | nmults->SetValue(nbknots, deg + 1); | |
761 | ||
762 | ||
763 | // compute index1 and index2 to set the new poles and weights | |
764 | Standard_Integer pindex1 | |
765 | = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1()); | |
766 | Standard_Integer pindex2 | |
767 | = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1()); | |
768 | ||
769 | pindex1++; | |
770 | pindex2 = Min( pindex2+1, poles->Length()); | |
771 | ||
772 | Standard_Integer nbpoles = pindex2 - pindex1 + 1; | |
773 | ||
774 | Handle(TColStd_HArray1OfReal) | |
775 | nweights = new TColStd_HArray1OfReal(1,nbpoles); | |
776 | Handle(TColgp_HArray1OfPnt2d) | |
777 | npoles = new TColgp_HArray1OfPnt2d(1,nbpoles); | |
778 | ||
779 | k = 1; | |
780 | if ( rational) { | |
781 | nweights = new TColStd_HArray1OfReal( 1, nbpoles); | |
782 | for ( i = pindex1; i <= pindex2; i++) { | |
783 | npoles->SetValue(k, poles->Value(i)); | |
784 | nweights->SetValue(k, weights->Value(i)); | |
785 | k++; | |
786 | } | |
787 | } | |
788 | else { | |
789 | for ( i = pindex1; i <= pindex2; i++) { | |
790 | npoles->SetValue(k, poles->Value(i)); | |
791 | k++; | |
792 | } | |
793 | } | |
794 | ||
795 | knots = nknots; | |
796 | mults = nmults; | |
797 | poles = npoles; | |
798 | if (rational){ | |
799 | weights = nweights; | |
800 | } | |
801 | UpdateKnots(); | |
802 | } | |
803 | ||
804 | //======================================================================= | |
805 | //function : SetKnot | |
806 | //purpose : | |
807 | //======================================================================= | |
808 | ||
809 | void Geom2d_BSplineCurve::SetKnot | |
810 | (const Standard_Integer Index, | |
811 | const Standard_Real K) | |
812 | { | |
1b827f04 | 813 | if (Index < 1 || Index > knots->Length()) throw Standard_OutOfRange("BSpline curve: SetKnot: Index and #knots mismatch"); |
7fd59977 | 814 | Standard_Real DK = Abs(Epsilon (K)); |
815 | if (Index == 1) { | |
1b827f04 | 816 | if (K >= knots->Value(2) - DK) throw Standard_ConstructionError("BSpline curve: SetKnot: K out of range"); |
7fd59977 | 817 | } |
818 | else if (Index == knots->Length()) { | |
819 | if (K <= knots->Value (knots->Length()-1) + DK) { | |
1b827f04 | 820 | throw Standard_ConstructionError("BSpline curve: SetKnot: K out of range"); |
7fd59977 | 821 | } |
822 | } | |
823 | else { | |
824 | if (K <= knots->Value(Index-1) + DK || | |
825 | K >= knots->Value(Index+1) - DK ) { | |
1b827f04 | 826 | throw Standard_ConstructionError("BSpline curve: SetKnot: K out of range"); |
7fd59977 | 827 | } |
828 | } | |
829 | if (K != knots->Value (Index)) { | |
830 | knots->SetValue (Index, K); | |
831 | maxderivinvok = 0; | |
832 | UpdateKnots(); | |
833 | } | |
834 | } | |
835 | ||
836 | //======================================================================= | |
837 | //function : SetKnots | |
838 | //purpose : | |
839 | //======================================================================= | |
840 | ||
841 | void Geom2d_BSplineCurve::SetKnots | |
842 | (const TColStd_Array1OfReal& K) | |
843 | { | |
844 | CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic); | |
845 | knots->ChangeArray1() = K; | |
846 | maxderivinvok = 0; | |
847 | UpdateKnots(); | |
848 | } | |
849 | ||
850 | //======================================================================= | |
851 | //function : SetKnot | |
852 | //purpose : | |
853 | //======================================================================= | |
854 | ||
855 | void Geom2d_BSplineCurve::SetKnot | |
856 | (const Standard_Integer Index, | |
857 | const Standard_Real K, | |
858 | const Standard_Integer M) | |
859 | { | |
860 | IncreaseMultiplicity (Index, M); | |
861 | SetKnot (Index, K); | |
862 | } | |
863 | ||
864 | //======================================================================= | |
865 | //function : SetPeriodic | |
866 | //purpose : | |
867 | //======================================================================= | |
868 | ||
869 | void Geom2d_BSplineCurve::SetPeriodic () | |
870 | { | |
871 | Standard_Integer first = FirstUKnotIndex(); | |
872 | Standard_Integer last = LastUKnotIndex(); | |
873 | ||
874 | Handle(TColStd_HArray1OfReal) tk = knots; | |
875 | TColStd_Array1OfReal cknots((knots->Array1())(first),first,last); | |
876 | knots = new TColStd_HArray1OfReal(1,cknots.Length()); | |
877 | knots->ChangeArray1() = cknots; | |
878 | ||
879 | Handle(TColStd_HArray1OfInteger) tm = mults; | |
880 | TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last); | |
881 | cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last))); | |
882 | mults = new TColStd_HArray1OfInteger(1,cmults.Length()); | |
883 | mults->ChangeArray1() = cmults; | |
884 | ||
885 | // compute new number of poles; | |
886 | Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults); | |
887 | ||
888 | Handle(TColgp_HArray1OfPnt2d) tp = poles; | |
889 | TColgp_Array1OfPnt2d cpoles((poles->Array1())(1),1,nbp); | |
890 | poles = new TColgp_HArray1OfPnt2d(1,nbp); | |
891 | poles->ChangeArray1() = cpoles; | |
892 | ||
893 | if (rational) { | |
894 | Handle(TColStd_HArray1OfReal) tw = weights; | |
895 | TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp); | |
896 | weights = new TColStd_HArray1OfReal(1,nbp); | |
897 | weights->ChangeArray1() = cweights; | |
898 | } | |
899 | ||
900 | periodic = Standard_True; | |
901 | ||
902 | maxderivinvok = 0; | |
903 | UpdateKnots(); | |
904 | } | |
905 | ||
906 | //======================================================================= | |
907 | //function : SetOrigin | |
908 | //purpose : | |
909 | //======================================================================= | |
910 | ||
911 | void Geom2d_BSplineCurve::SetOrigin(const Standard_Integer Index) | |
912 | { | |
369a38aa | 913 | if (!periodic) |
9775fa61 | 914 | throw Standard_NoSuchObject("Geom2d_BSplineCurve::SetOrigin"); |
7fd59977 | 915 | Standard_Integer i,k; |
916 | Standard_Integer first = FirstUKnotIndex(); | |
917 | Standard_Integer last = LastUKnotIndex(); | |
918 | ||
369a38aa | 919 | if ((Index < first) || (Index > last)) |
9775fa61 | 920 | throw Standard_DomainError("Geom2d_BSplineCurve::SetOrigin"); |
7fd59977 | 921 | |
922 | Standard_Integer nbknots = knots->Length(); | |
923 | Standard_Integer nbpoles = poles->Length(); | |
924 | ||
925 | Handle(TColStd_HArray1OfReal) nknots = | |
926 | new TColStd_HArray1OfReal(1,nbknots); | |
927 | TColStd_Array1OfReal& newknots = nknots->ChangeArray1(); | |
928 | ||
929 | Handle(TColStd_HArray1OfInteger) nmults = | |
930 | new TColStd_HArray1OfInteger(1,nbknots); | |
931 | TColStd_Array1OfInteger& newmults = nmults->ChangeArray1(); | |
932 | ||
933 | // set the knots and mults | |
934 | Standard_Real period = knots->Value(last) - knots->Value(first); | |
935 | k = 1; | |
936 | for ( i = Index; i <= last ; i++) { | |
937 | newknots(k) = knots->Value(i); | |
938 | newmults(k) = mults->Value(i); | |
939 | k++; | |
940 | } | |
941 | for ( i = first+1; i <= Index; i++) { | |
942 | newknots(k) = knots->Value(i) + period; | |
943 | newmults(k) = mults->Value(i); | |
944 | k++; | |
945 | } | |
946 | ||
947 | Standard_Integer index = 1; | |
948 | for (i = first+1; i <= Index; i++) | |
949 | index += mults->Value(i); | |
950 | ||
951 | // set the poles and weights | |
952 | Handle(TColgp_HArray1OfPnt2d) npoles = | |
953 | new TColgp_HArray1OfPnt2d(1,nbpoles); | |
954 | Handle(TColStd_HArray1OfReal) nweights = | |
955 | new TColStd_HArray1OfReal(1,nbpoles); | |
956 | TColgp_Array1OfPnt2d & newpoles = npoles->ChangeArray1(); | |
957 | TColStd_Array1OfReal & newweights = nweights->ChangeArray1(); | |
958 | first = poles->Lower(); | |
959 | last = poles->Upper(); | |
960 | if ( rational) { | |
961 | k = 1; | |
962 | for ( i = index; i <= last; i++) { | |
963 | newpoles(k) = poles->Value(i); | |
964 | newweights(k) = weights->Value(i); | |
965 | k++; | |
966 | } | |
967 | for ( i = first; i < index; i++) { | |
968 | newpoles(k) = poles->Value(i); | |
969 | newweights(k) = weights->Value(i); | |
970 | k++; | |
971 | } | |
972 | } | |
973 | else { | |
974 | k = 1; | |
975 | for ( i = index; i <= last; i++) { | |
976 | newpoles(k) = poles->Value(i); | |
977 | k++; | |
978 | } | |
979 | for ( i = first; i < index; i++) { | |
980 | newpoles(k) = poles->Value(i); | |
981 | k++; | |
982 | } | |
983 | } | |
984 | ||
985 | poles = npoles; | |
986 | knots = nknots; | |
987 | mults = nmults; | |
988 | if (rational) | |
989 | weights = nweights; | |
990 | maxderivinvok = 0; | |
991 | UpdateKnots(); | |
992 | } | |
993 | ||
994 | //======================================================================= | |
995 | //function : SetNotPeriodic | |
996 | //purpose : | |
997 | //======================================================================= | |
998 | ||
999 | void Geom2d_BSplineCurve::SetNotPeriodic () | |
1000 | { | |
1001 | if (periodic) { | |
1002 | Standard_Integer NbKnots, NbPoles; | |
1003 | BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles); | |
1004 | ||
1005 | Handle(TColgp_HArray1OfPnt2d) npoles | |
1006 | = new TColgp_HArray1OfPnt2d(1,NbPoles); | |
1007 | ||
1008 | Handle(TColStd_HArray1OfReal) nknots | |
1009 | = new TColStd_HArray1OfReal(1,NbKnots); | |
1010 | ||
1011 | Handle(TColStd_HArray1OfInteger) nmults | |
1012 | = new TColStd_HArray1OfInteger(1,NbKnots); | |
1013 | ||
1014 | Handle(TColStd_HArray1OfReal) nweights; | |
7fd59977 | 1015 | if (IsRational()) { |
7fd59977 | 1016 | nweights = new TColStd_HArray1OfReal(1,NbPoles); |
7fd59977 | 1017 | } |
aff73fd5 | 1018 | |
1019 | BSplCLib::Unperiodize (deg, | |
1020 | mults->Array1(), knots->Array1(), poles->Array1(), | |
1021 | !nweights.IsNull() ? &weights->Array1() : BSplCLib::NoWeights(), | |
1022 | nmults->ChangeArray1(), nknots->ChangeArray1(), npoles->ChangeArray1(), | |
1023 | !nweights.IsNull() ? &nweights->ChangeArray1() : BSplCLib::NoWeights()); | |
7fd59977 | 1024 | poles = npoles; |
1025 | weights = nweights; | |
1026 | mults = nmults; | |
1027 | knots = nknots; | |
1028 | periodic = Standard_False; | |
1029 | maxderivinvok = 0; | |
1030 | UpdateKnots(); | |
1031 | } | |
1032 | } | |
1033 | ||
1034 | //======================================================================= | |
1035 | //function : SetPole | |
1036 | //purpose : | |
1037 | //======================================================================= | |
1038 | ||
1039 | void Geom2d_BSplineCurve::SetPole | |
1040 | (const Standard_Integer Index, | |
1041 | const gp_Pnt2d& P) | |
1042 | { | |
1b827f04 | 1043 | if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange("BSpline curve: SetPole: index and #pole mismatch"); |
7fd59977 | 1044 | poles->SetValue (Index, P); |
1045 | maxderivinvok = 0; | |
7fd59977 | 1046 | } |
1047 | ||
1048 | //======================================================================= | |
1049 | //function : SetPole | |
1050 | //purpose : | |
1051 | //======================================================================= | |
1052 | ||
1053 | void Geom2d_BSplineCurve::SetPole | |
1054 | (const Standard_Integer Index, | |
1055 | const gp_Pnt2d& P, | |
1056 | const Standard_Real W) | |
1057 | { | |
1058 | SetPole(Index,P); | |
1059 | SetWeight(Index,W); | |
1060 | } | |
1061 | ||
1062 | //======================================================================= | |
1063 | //function : SetWeight | |
1064 | //purpose : | |
1065 | //======================================================================= | |
1066 | ||
1067 | void Geom2d_BSplineCurve::SetWeight | |
1068 | (const Standard_Integer Index, | |
1069 | const Standard_Real W) | |
1070 | { | |
1b827f04 | 1071 | if (Index < 1 || Index > poles->Length()) throw Standard_OutOfRange("BSpline curve: SetWeight: Index and #pole mismatch"); |
7fd59977 | 1072 | |
1b827f04 | 1073 | if (W <= gp::Resolution ()) throw Standard_ConstructionError("BSpline curve: SetWeight: Weight too small"); |
7fd59977 | 1074 | |
1075 | ||
1076 | Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution()); | |
1077 | ||
1078 | if ( rat) { | |
1079 | if (rat && !IsRational()) { | |
1080 | weights = new TColStd_HArray1OfReal(1,poles->Length()); | |
1081 | weights->Init(1.); | |
1082 | } | |
1083 | ||
1084 | weights->SetValue (Index, W); | |
1085 | ||
1086 | if (IsRational()) { | |
1087 | rat = Rational(weights->Array1()); | |
1088 | if (!rat) weights.Nullify(); | |
1089 | } | |
1090 | ||
1091 | rational = !weights.IsNull(); | |
1092 | } | |
1093 | ||
1094 | maxderivinvok = 0; | |
7fd59977 | 1095 | } |
1096 | ||
1097 | //======================================================================= | |
1098 | //function : MovePoint | |
1099 | //purpose : | |
1100 | //======================================================================= | |
1101 | ||
1102 | void Geom2d_BSplineCurve::MovePoint(const Standard_Real U, | |
94f71cad | 1103 | const gp_Pnt2d& P, |
1104 | const Standard_Integer Index1, | |
1105 | const Standard_Integer Index2, | |
1106 | Standard_Integer& FirstModifiedPole, | |
1107 | Standard_Integer& LastmodifiedPole) | |
7fd59977 | 1108 | { |
1109 | if (Index1 < 1 || Index1 > poles->Length() || | |
1110 | Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) { | |
1b827f04 | 1111 | throw Standard_OutOfRange("BSpline curve: MovePoint: Index and #pole mismatch"); |
7fd59977 | 1112 | } |
1113 | TColgp_Array1OfPnt2d npoles(1, poles->Length()); | |
1114 | gp_Pnt2d P0; | |
1115 | D0(U, P0); | |
1116 | gp_Vec2d Displ(P0, P); | |
aff73fd5 | 1117 | |
1118 | BSplCLib::MovePoint (U, Displ, Index1, Index2, deg, poles->Array1(), | |
1119 | rational ? &weights->Array1() : BSplCLib::NoWeights(), flatknots->Array1(), | |
1120 | FirstModifiedPole, LastmodifiedPole, npoles); | |
7fd59977 | 1121 | if (FirstModifiedPole) { |
1122 | poles->ChangeArray1() = npoles; | |
1123 | maxderivinvok = 0; | |
7fd59977 | 1124 | } |
1125 | } | |
1126 | ||
1127 | //======================================================================= | |
1128 | //function : MovePointAndTangent | |
1129 | //purpose : | |
1130 | //======================================================================= | |
1131 | ||
1132 | void Geom2d_BSplineCurve:: | |
1133 | MovePointAndTangent(const Standard_Real U, | |
1134 | const gp_Pnt2d& P, | |
1135 | const gp_Vec2d& Tangent, | |
1136 | const Standard_Real Tolerance, | |
1137 | const Standard_Integer StartingCondition, | |
1138 | const Standard_Integer EndingCondition, | |
1139 | Standard_Integer& ErrorStatus) | |
1140 | { | |
1141 | Standard_Integer ii ; | |
1142 | if (IsPeriodic()) { | |
1143 | // | |
1144 | // for the time being do not deal with periodic curves | |
1145 | // | |
1146 | SetNotPeriodic() ; | |
1147 | } | |
1148 | TColgp_Array1OfPnt2d new_poles(1, poles->Length()); | |
1149 | gp_Pnt2d P0; | |
1150 | ||
1151 | ||
1152 | gp_Vec2d delta_derivative; | |
1153 | D1(U, P0, | |
1154 | delta_derivative) ; | |
1155 | gp_Vec2d delta(P0, P); | |
1156 | for (ii = 1 ; ii <= 2 ; ii++) { | |
1157 | delta_derivative.SetCoord(ii, | |
1158 | Tangent.Coord(ii)- delta_derivative.Coord(ii)) ; | |
1159 | } | |
aff73fd5 | 1160 | |
1161 | BSplCLib::MovePointAndTangent (U, | |
1162 | delta, | |
1163 | delta_derivative, | |
1164 | Tolerance, | |
1165 | deg, | |
1166 | StartingCondition, | |
1167 | EndingCondition, | |
1168 | poles->Array1(), | |
1169 | rational ? &weights->Array1() : BSplCLib::NoWeights(), | |
1170 | flatknots->Array1(), | |
1171 | new_poles, | |
1172 | ErrorStatus); | |
7fd59977 | 1173 | if (!ErrorStatus) { |
1174 | poles->ChangeArray1() = new_poles; | |
1175 | maxderivinvok = 0; | |
7fd59977 | 1176 | } |
1177 | } | |
1178 | ||
1179 | //======================================================================= | |
1180 | //function : UpdateKnots | |
1181 | //purpose : | |
1182 | //======================================================================= | |
1183 | ||
1184 | void Geom2d_BSplineCurve::UpdateKnots() | |
1185 | { | |
1186 | ||
1187 | rational = !weights.IsNull(); | |
1188 | ||
1189 | Standard_Integer MaxKnotMult = 0; | |
06be28a4 | 1190 | BSplCLib::KnotAnalysis (deg, |
7fd59977 | 1191 | periodic, |
1192 | knots->Array1(), | |
1193 | mults->Array1(), | |
1194 | knotSet, MaxKnotMult); | |
1195 | ||
1196 | if (knotSet == GeomAbs_Uniform && !periodic) { | |
1197 | flatknots = knots; | |
1198 | } | |
1199 | else { | |
1200 | flatknots = new TColStd_HArray1OfReal | |
1201 | (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic)); | |
1202 | ||
1203 | BSplCLib::KnotSequence (knots->Array1(), | |
1204 | mults->Array1(), | |
1205 | deg,periodic, | |
1206 | flatknots->ChangeArray1()); | |
1207 | } | |
1208 | ||
1209 | if (MaxKnotMult == 0) smooth = GeomAbs_CN; | |
1210 | else { | |
1211 | switch (deg - MaxKnotMult) { | |
1212 | case 0 : smooth = GeomAbs_C0; break; | |
1213 | case 1 : smooth = GeomAbs_C1; break; | |
1214 | case 2 : smooth = GeomAbs_C2; break; | |
1215 | case 3 : smooth = GeomAbs_C3; break; | |
1216 | default : smooth = GeomAbs_C3; break; | |
1217 | } | |
1218 | } | |
7fd59977 | 1219 | } |
1220 | ||
1221 | //======================================================================= | |
1222 | //function : Normalizes the parameters if the curve is periodic | |
1223 | //purpose : that is compute the cache so that it is valid | |
1224 | //======================================================================= | |
1225 | ||
1226 | void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const | |
1227 | { | |
1228 | Standard_Real Period ; | |
1229 | ||
1230 | if (periodic) { | |
1231 | Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ; | |
1232 | while (Parameter > flatknots->Value(flatknots->Upper()-deg)) { | |
1233 | Parameter -= Period ; | |
1234 | } | |
1235 | while (Parameter < flatknots->Value((deg + 1))) { | |
1236 | Parameter += Period ; | |
1237 | } | |
1238 | } | |
1239 | } | |
1240 | ||
bc73b006 | 1241 | //======================================================================= |
1242 | //function : DumpJson | |
1243 | //purpose : | |
1244 | //======================================================================= | |
1245 | void Geom2d_BSplineCurve::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const | |
1246 | { | |
1247 | OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) | |
1248 | ||
1249 | OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Geom2d_BoundedCurve) | |
1250 | ||
1251 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, rational) | |
1252 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, periodic) | |
1253 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, knotSet) | |
1254 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, smooth) | |
1255 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, deg) | |
1256 | if (!poles.IsNull()) | |
1257 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, poles->Size()) | |
1258 | ||
1259 | if (!weights.IsNull()) | |
1260 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, weights->Size()) | |
1261 | if (!flatknots.IsNull()) | |
1262 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, flatknots->Size()) | |
1263 | if (!knots.IsNull()) | |
1264 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, knots->Size()) | |
1265 | if (!mults.IsNull()) | |
1266 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mults->Size()) | |
1267 | ||
1268 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinv) | |
1269 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinvok) | |
1270 | } |