Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1993-03-09 |
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 | // 14-Mar-96 : xab portage hp |
18 | // pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625) | |
19 | // pmn : 07-Jan-97 Centralisation des verif rational (PRO6834) | |
20 | // et ajout des InvalideCache() dans les SetWeight*(PRO6833) | |
21 | // RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537). | |
22 | // jct : 19-01-99 ; permutation de urational et vrational dans Rational. | |
7fd59977 | 23 | #define No_Standard_OutOfRange |
24 | ||
7fd59977 | 25 | |
7fd59977 | 26 | #include <BSplCLib.hxx> |
27 | #include <BSplSLib.hxx> | |
42cf5bc1 | 28 | #include <Geom_BSplineSurface.hxx> |
29 | #include <Geom_Curve.hxx> | |
30 | #include <Geom_Geometry.hxx> | |
31 | #include <Geom_UndefinedDerivative.hxx> | |
32 | #include <gp.hxx> | |
33 | #include <gp_Pnt.hxx> | |
34 | #include <gp_Trsf.hxx> | |
35 | #include <gp_Vec.hxx> | |
36 | #include <Precision.hxx> | |
7fd59977 | 37 | #include <Standard_ConstructionError.hxx> |
42cf5bc1 | 38 | #include <Standard_DimensionError.hxx> |
39 | #include <Standard_DomainError.hxx> | |
40 | #include <Standard_NoSuchObject.hxx> | |
7fd59977 | 41 | #include <Standard_NotImplemented.hxx> |
42 | #include <Standard_OutOfRange.hxx> | |
42cf5bc1 | 43 | #include <Standard_RangeError.hxx> |
44 | #include <Standard_Type.hxx> | |
7fd59977 | 45 | |
92efcf78 | 46 | IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineSurface,Geom_BoundedSurface) |
47 | ||
7fd59977 | 48 | //======================================================================= |
49 | //function : CheckSurfaceData | |
50 | //purpose : Internal use only. | |
51 | //======================================================================= | |
7fd59977 | 52 | static void CheckSurfaceData |
53 | (const TColgp_Array2OfPnt& SPoles, | |
54 | const TColStd_Array1OfReal& SUKnots, | |
55 | const TColStd_Array1OfReal& SVKnots, | |
56 | const TColStd_Array1OfInteger& SUMults, | |
57 | const TColStd_Array1OfInteger& SVMults, | |
58 | const Standard_Integer UDegree, | |
59 | const Standard_Integer VDegree, | |
60 | const Standard_Boolean UPeriodic, | |
61 | const Standard_Boolean VPeriodic) | |
62 | { | |
63 | if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () || | |
64 | VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) { | |
1b827f04 | 65 | throw Standard_ConstructionError("Geom_BSplineSurface: invalid degree"); |
7fd59977 | 66 | } |
67 | if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) { | |
1b827f04 | 68 | throw Standard_ConstructionError("Geom_BSplineSurface: at least 2 poles required"); |
7fd59977 | 69 | } |
70 | ||
71 | if (SUKnots.Length() != SUMults.Length() || | |
72 | SVKnots.Length() != SVMults.Length()) { | |
1b827f04 | 73 | throw Standard_ConstructionError("Geom_BSplineSurface: Knot and Mult array size mismatch"); |
7fd59977 | 74 | } |
75 | ||
76 | Standard_Integer i; | |
77 | for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) { | |
78 | if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) { | |
1b827f04 | 79 | throw Standard_ConstructionError("Geom_BSplineSurface: UKnots interval values too close"); |
7fd59977 | 80 | } |
81 | } | |
82 | ||
83 | for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) { | |
84 | if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) { | |
1b827f04 | 85 | throw Standard_ConstructionError("Geom_BSplineSurface: VKnots interval values too close"); |
7fd59977 | 86 | } |
87 | } | |
88 | ||
89 | if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults)) | |
1b827f04 | 90 | throw Standard_ConstructionError("Geom_BSplineSurface: # U Poles and degree mismatch"); |
7fd59977 | 91 | |
92 | if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults)) | |
1b827f04 | 93 | throw Standard_ConstructionError("Geom_BSplineSurface: # V Poles and degree mismatch"); |
7fd59977 | 94 | } |
95 | ||
7fd59977 | 96 | //======================================================================= |
97 | //function : Rational | |
98 | //purpose : Internal use only. | |
99 | //======================================================================= | |
100 | ||
101 | static void Rational(const TColStd_Array2OfReal& Weights, | |
102 | Standard_Boolean& Urational, | |
103 | Standard_Boolean& Vrational) | |
104 | { | |
105 | Standard_Integer I,J; | |
106 | J = Weights.LowerCol (); | |
107 | Vrational = Standard_False; | |
108 | while (!Vrational && J <= Weights.UpperCol()) { | |
109 | I = Weights.LowerRow(); | |
110 | while (!Vrational && I <= Weights.UpperRow() - 1) { | |
111 | Vrational = (Abs(Weights (I, J) - Weights (I+1, J)) | |
112 | > Epsilon (Abs(Weights (I, J)))); | |
113 | I++; | |
114 | } | |
115 | J++; | |
116 | } | |
117 | ||
118 | I = Weights.LowerRow (); | |
119 | Urational = Standard_False; | |
120 | while (!Urational && I <= Weights.UpperRow()) { | |
121 | J = Weights.LowerCol(); | |
122 | while (!Urational && J <= Weights.UpperCol() - 1) { | |
123 | Urational = (Abs(Weights (I, J) - Weights (I, J+1)) | |
124 | > Epsilon (Abs(Weights (I, J)))); | |
125 | J++; | |
126 | } | |
127 | I++; | |
128 | } | |
129 | } | |
130 | ||
131 | //======================================================================= | |
132 | //function : Copy | |
133 | //purpose : | |
134 | //======================================================================= | |
135 | ||
136 | Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const | |
137 | { | |
138 | Handle(Geom_BSplineSurface) S; | |
139 | if (urational || vrational) | |
140 | S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(), | |
141 | uknots->Array1(), vknots->Array1(), | |
142 | umults->Array1(), vmults->Array1(), | |
143 | udeg , vdeg, | |
144 | uperiodic, vperiodic); | |
145 | else | |
146 | S = new Geom_BSplineSurface (poles->Array2(), | |
147 | uknots->Array1(), vknots->Array1(), | |
148 | umults->Array1(), vmults->Array1(), | |
149 | udeg , vdeg, | |
150 | uperiodic, vperiodic); | |
151 | return S; | |
152 | } | |
153 | ||
154 | //======================================================================= | |
155 | //function : Geom_BSplineSurface | |
156 | //purpose : | |
157 | //======================================================================= | |
158 | ||
159 | Geom_BSplineSurface::Geom_BSplineSurface | |
160 | (const TColgp_Array2OfPnt& Poles, | |
161 | const TColStd_Array1OfReal& UKnots, | |
162 | const TColStd_Array1OfReal& VKnots, | |
163 | const TColStd_Array1OfInteger& UMults, | |
164 | const TColStd_Array1OfInteger& VMults, | |
165 | const Standard_Integer UDegree, | |
166 | const Standard_Integer VDegree, | |
167 | const Standard_Boolean UPeriodic, | |
168 | const Standard_Boolean VPeriodic | |
169 | ) : | |
170 | urational(Standard_False), | |
171 | vrational(Standard_False), | |
172 | uperiodic(UPeriodic), | |
173 | vperiodic(VPeriodic), | |
174 | udeg(UDegree), | |
175 | vdeg(VDegree), | |
176 | maxderivinvok(0) | |
177 | ||
178 | { | |
7fd59977 | 179 | |
180 | // check | |
181 | ||
182 | CheckSurfaceData(Poles, | |
183 | UKnots , VKnots, | |
184 | UMults , VMults, | |
185 | UDegree , VDegree, | |
186 | UPeriodic, VPeriodic); | |
187 | ||
188 | // copy arrays | |
189 | ||
190 | poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(), | |
191 | 1,Poles.RowLength()); | |
192 | poles->ChangeArray2() = Poles; | |
193 | ||
194 | weights = new TColStd_HArray2OfReal (1,Poles.ColLength(), | |
195 | 1,Poles.RowLength(), 1.0); | |
196 | ||
197 | uknots = new TColStd_HArray1OfReal (1,UKnots.Length()); | |
198 | uknots->ChangeArray1() = UKnots; | |
199 | ||
200 | umults = new TColStd_HArray1OfInteger (1,UMults.Length()); | |
201 | umults->ChangeArray1() = UMults; | |
202 | ||
203 | vknots = new TColStd_HArray1OfReal (1,VKnots.Length()); | |
204 | vknots->ChangeArray1() = VKnots; | |
205 | ||
206 | vmults = new TColStd_HArray1OfInteger (1,VMults.Length()); | |
207 | vmults->ChangeArray1() = VMults; | |
7fd59977 | 208 | |
209 | UpdateUKnots(); | |
210 | UpdateVKnots(); | |
211 | } | |
212 | ||
213 | //======================================================================= | |
214 | //function : Geom_BSplineSurface | |
215 | //purpose : | |
216 | //======================================================================= | |
217 | ||
218 | Geom_BSplineSurface::Geom_BSplineSurface | |
219 | (const TColgp_Array2OfPnt& Poles, | |
220 | const TColStd_Array2OfReal& Weights, | |
221 | const TColStd_Array1OfReal& UKnots, | |
222 | const TColStd_Array1OfReal& VKnots, | |
223 | const TColStd_Array1OfInteger& UMults, | |
224 | const TColStd_Array1OfInteger& VMults, | |
225 | const Standard_Integer UDegree, | |
226 | const Standard_Integer VDegree, | |
227 | const Standard_Boolean UPeriodic, | |
228 | const Standard_Boolean VPeriodic) : | |
229 | urational(Standard_False), | |
230 | vrational(Standard_False), | |
231 | uperiodic(UPeriodic), | |
232 | vperiodic(VPeriodic), | |
233 | udeg(UDegree), | |
234 | vdeg(VDegree), | |
235 | maxderivinvok(0) | |
236 | { | |
7fd59977 | 237 | // check weights |
238 | ||
239 | if (Weights.ColLength() != Poles.ColLength()) | |
1b827f04 | 240 | throw Standard_ConstructionError("Geom_BSplineSurface: U Weights and Poles array size mismatch"); |
7fd59977 | 241 | |
242 | if (Weights.RowLength() != Poles.RowLength()) | |
1b827f04 | 243 | throw Standard_ConstructionError("Geom_BSplineSurface: V Weights and Poles array size mismatch"); |
7fd59977 | 244 | |
245 | Standard_Integer i,j; | |
246 | for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) { | |
247 | for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) { | |
248 | if (Weights(i,j) <= gp::Resolution()) | |
1b827f04 | 249 | throw Standard_ConstructionError("Geom_BSplineSurface: Weights values too small"); |
7fd59977 | 250 | } |
251 | } | |
252 | ||
253 | // check really rational | |
254 | ||
255 | Rational(Weights, urational, vrational); | |
256 | ||
257 | // check | |
258 | ||
259 | CheckSurfaceData(Poles, | |
260 | UKnots , VKnots, | |
261 | UMults , VMults, | |
262 | UDegree , VDegree, | |
263 | UPeriodic, VPeriodic); | |
264 | ||
265 | // copy arrays | |
266 | ||
267 | poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(), | |
268 | 1,Poles.RowLength()); | |
269 | poles->ChangeArray2() = Poles; | |
270 | ||
271 | weights = new TColStd_HArray2OfReal (1,Poles.ColLength(), | |
272 | 1,Poles.RowLength()); | |
273 | weights->ChangeArray2() = Weights; | |
274 | ||
275 | uknots = new TColStd_HArray1OfReal (1,UKnots.Length()); | |
276 | uknots->ChangeArray1() = UKnots; | |
277 | ||
278 | umults = new TColStd_HArray1OfInteger (1,UMults.Length()); | |
279 | umults->ChangeArray1() = UMults; | |
280 | ||
281 | vknots = new TColStd_HArray1OfReal (1,VKnots.Length()); | |
282 | vknots->ChangeArray1() = VKnots; | |
283 | ||
284 | vmults = new TColStd_HArray1OfInteger (1,VMults.Length()); | |
285 | vmults->ChangeArray1() = VMults; | |
7fd59977 | 286 | |
287 | UpdateUKnots(); | |
288 | UpdateVKnots(); | |
289 | } | |
290 | ||
291 | //======================================================================= | |
292 | //function : ExchangeUV | |
293 | //purpose : | |
294 | //======================================================================= | |
295 | ||
296 | void Geom_BSplineSurface::ExchangeUV () | |
297 | { | |
298 | Standard_Integer LC = poles->LowerCol(); | |
299 | Standard_Integer UC = poles->UpperCol(); | |
300 | Standard_Integer LR = poles->LowerRow(); | |
301 | Standard_Integer UR = poles->UpperRow(); | |
302 | ||
303 | Handle(TColgp_HArray2OfPnt) npoles = | |
304 | new TColgp_HArray2OfPnt (LC, UC, LR, UR); | |
305 | Handle(TColStd_HArray2OfReal) nweights = | |
306 | new TColStd_HArray2OfReal (LC, UC, LR, UR); | |
307 | ||
308 | const TColgp_Array2OfPnt & spoles = poles->Array2(); | |
309 | const TColStd_Array2OfReal & sweights = weights->Array2(); | |
310 | ||
311 | TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2(); | |
312 | TColStd_Array2OfReal& snweights = nweights->ChangeArray2(); | |
313 | ||
314 | Standard_Integer i, j; | |
315 | for (i = LC; i <= UC; i++) { | |
316 | for (j = LR; j <= UR; j++) { | |
317 | snpoles (i,j) = spoles (j,i); | |
318 | snweights (i,j) = sweights (j,i); | |
319 | } | |
320 | } | |
321 | ||
322 | poles = npoles; | |
323 | weights = nweights; | |
324 | ||
325 | Standard_Boolean temp = urational; | |
326 | urational = vrational; | |
327 | vrational = temp; | |
328 | ||
329 | temp = uperiodic; | |
330 | uperiodic = vperiodic; | |
331 | vperiodic = temp; | |
332 | ||
333 | Standard_Integer tempdeg = udeg; | |
334 | udeg = vdeg; | |
335 | vdeg = tempdeg; | |
336 | ||
337 | ||
338 | Handle(TColStd_HArray1OfReal) tempknots = uknots; | |
339 | uknots = vknots; | |
340 | vknots = tempknots; | |
341 | ||
342 | Handle(TColStd_HArray1OfInteger) tempmults = umults; | |
343 | umults = vmults; | |
344 | vmults = tempmults; | |
345 | ||
346 | UpdateUKnots(); | |
347 | UpdateVKnots(); | |
348 | } | |
349 | ||
350 | //======================================================================= | |
351 | //function : IncreaseDegree | |
352 | //purpose : | |
353 | //======================================================================= | |
354 | ||
355 | void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree, | |
356 | const Standard_Integer VDegree) | |
357 | { | |
358 | if (UDegree != udeg) { | |
359 | if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree()) | |
1b827f04 | 360 | throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad U degree value"); |
7fd59977 | 361 | |
362 | Standard_Integer FromK1 = FirstUKnotIndex(); | |
363 | Standard_Integer ToK2 = LastUKnotIndex(); | |
364 | ||
365 | Standard_Integer Step = UDegree - udeg; | |
366 | ||
367 | Handle(TColgp_HArray2OfPnt) npoles = new | |
368 | TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1), | |
369 | 1, poles->RowLength()); | |
370 | ||
371 | Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots | |
372 | (udeg,UDegree,uperiodic,umults->Array1()); | |
373 | ||
374 | Handle(TColStd_HArray1OfReal) nknots = | |
375 | new TColStd_HArray1OfReal(1,nbknots); | |
376 | ||
377 | Handle(TColStd_HArray1OfInteger) nmults = | |
378 | new TColStd_HArray1OfInteger(1,nbknots); | |
379 | ||
380 | Handle(TColStd_HArray2OfReal) nweights | |
381 | = new TColStd_HArray2OfReal(1,npoles->ColLength(), | |
382 | 1,npoles->RowLength(), 1.); | |
383 | ||
384 | if (urational || vrational) { | |
385 | ||
386 | BSplSLib::IncreaseDegree | |
387 | (Standard_True, udeg, UDegree, uperiodic, | |
0e14656b | 388 | poles->Array2(),&weights->Array2(), |
7fd59977 | 389 | uknots->Array1(),umults->Array1(), |
0e14656b | 390 | npoles->ChangeArray2(),&nweights->ChangeArray2(), |
7fd59977 | 391 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
392 | } | |
393 | else { | |
394 | ||
395 | BSplSLib::IncreaseDegree | |
396 | (Standard_True, udeg, UDegree, uperiodic, | |
397 | poles->Array2(),BSplSLib::NoWeights(), | |
398 | uknots->Array1(),umults->Array1(), | |
0e14656b | 399 | npoles->ChangeArray2(),BSplSLib::NoWeights(), |
7fd59977 | 400 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
401 | } | |
402 | udeg = UDegree; | |
403 | poles = npoles; | |
404 | weights = nweights; | |
405 | uknots = nknots; | |
406 | umults = nmults; | |
407 | UpdateUKnots(); | |
408 | } | |
409 | ||
410 | if (VDegree != vdeg) { | |
411 | if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree()) | |
1b827f04 | 412 | throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad V degree value"); |
7fd59977 | 413 | |
414 | Standard_Integer FromK1 = FirstVKnotIndex(); | |
415 | Standard_Integer ToK2 = LastVKnotIndex(); | |
416 | ||
417 | Standard_Integer Step = VDegree - vdeg; | |
418 | ||
419 | Handle(TColgp_HArray2OfPnt) npoles = new | |
420 | TColgp_HArray2OfPnt( 1, poles->ColLength(), | |
421 | 1, poles->RowLength() + Step * (ToK2 - FromK1)); | |
422 | ||
423 | Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots | |
424 | (vdeg,VDegree,vperiodic,vmults->Array1()); | |
425 | ||
426 | Handle(TColStd_HArray1OfReal) nknots = | |
427 | new TColStd_HArray1OfReal(1,nbknots); | |
428 | ||
429 | Handle(TColStd_HArray1OfInteger) nmults = | |
430 | new TColStd_HArray1OfInteger(1,nbknots); | |
431 | ||
432 | Handle(TColStd_HArray2OfReal) nweights | |
433 | = new TColStd_HArray2OfReal(1,npoles->ColLength(), | |
434 | 1,npoles->RowLength(), 1.); | |
435 | ||
436 | if (urational || vrational) { | |
437 | ||
438 | BSplSLib::IncreaseDegree | |
439 | (Standard_False, vdeg, VDegree, vperiodic, | |
0e14656b | 440 | poles->Array2(),&weights->Array2(), |
7fd59977 | 441 | vknots->Array1(),vmults->Array1(), |
0e14656b | 442 | npoles->ChangeArray2(),&nweights->ChangeArray2(), |
7fd59977 | 443 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
444 | } | |
445 | else { | |
446 | ||
447 | BSplSLib::IncreaseDegree | |
448 | (Standard_False, vdeg, VDegree, vperiodic, | |
449 | poles->Array2(),BSplSLib::NoWeights(), | |
450 | vknots->Array1(),vmults->Array1(), | |
0e14656b | 451 | npoles->ChangeArray2(),BSplSLib::NoWeights(), |
7fd59977 | 452 | nknots->ChangeArray1(),nmults->ChangeArray1()); |
453 | } | |
454 | vdeg = VDegree; | |
455 | poles = npoles; | |
456 | weights = nweights; | |
457 | vknots = nknots; | |
458 | vmults = nmults; | |
459 | UpdateVKnots(); | |
460 | } | |
461 | } | |
462 | ||
463 | //======================================================================= | |
464 | //function : IncreaseUMultiplicity | |
465 | //purpose : | |
466 | //======================================================================= | |
467 | ||
468 | void Geom_BSplineSurface::IncreaseUMultiplicity | |
469 | (const Standard_Integer UIndex, | |
470 | const Standard_Integer M) | |
471 | { | |
472 | TColStd_Array1OfReal k(1,1); | |
473 | k(1) = uknots->Value(UIndex); | |
474 | TColStd_Array1OfInteger m(1,1); | |
475 | m(1) = M - umults->Value(UIndex); | |
476 | InsertUKnots(k,m,Epsilon(1.),Standard_True); | |
477 | } | |
478 | ||
479 | //======================================================================= | |
480 | //function : IncreaseUMultiplicity | |
481 | //purpose : | |
482 | //======================================================================= | |
483 | ||
484 | void Geom_BSplineSurface::IncreaseUMultiplicity | |
485 | (const Standard_Integer FromI1, | |
486 | const Standard_Integer ToI2, | |
487 | const Standard_Integer M) | |
488 | { | |
489 | Handle(TColStd_HArray1OfReal) tk = uknots; | |
490 | TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2); | |
491 | TColStd_Array1OfInteger m(FromI1, ToI2); | |
492 | for (Standard_Integer i = FromI1; i <= ToI2; i++) | |
493 | m(i) = M - umults->Value(i); | |
494 | InsertUKnots(k,m,Epsilon(1.),Standard_True); | |
495 | } | |
496 | ||
497 | //======================================================================= | |
498 | //function : IncreaseVMultiplicity | |
499 | //purpose : | |
500 | //======================================================================= | |
501 | ||
502 | void Geom_BSplineSurface::IncreaseVMultiplicity | |
503 | (const Standard_Integer VIndex, | |
504 | const Standard_Integer M) | |
505 | { | |
506 | TColStd_Array1OfReal k(1,1); | |
507 | k(1) = vknots->Value(VIndex); | |
508 | TColStd_Array1OfInteger m(1,1); | |
509 | m(1) = M - vmults->Value(VIndex); | |
510 | InsertVKnots(k,m,Epsilon(1.),Standard_True); | |
511 | } | |
512 | ||
513 | //======================================================================= | |
514 | //function : IncreaseVMultiplicity | |
515 | //purpose : | |
516 | //======================================================================= | |
517 | ||
518 | void Geom_BSplineSurface::IncreaseVMultiplicity | |
519 | (const Standard_Integer FromI1, | |
520 | const Standard_Integer ToI2, | |
521 | const Standard_Integer M) | |
522 | { | |
523 | Handle(TColStd_HArray1OfReal) tk = vknots; | |
524 | TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2); | |
525 | TColStd_Array1OfInteger m(FromI1,ToI2); | |
526 | for (Standard_Integer i = FromI1; i <= ToI2; i++) | |
527 | m(i) = M - vmults->Value(i); | |
528 | InsertVKnots(k,m,Epsilon(1.),Standard_True); | |
529 | } | |
530 | ||
531 | //======================================================================= | |
6fd9bdf2 | 532 | //function : segment |
7fd59977 | 533 | //purpose : |
534 | //======================================================================= | |
535 | ||
6fd9bdf2 | 536 | void Geom_BSplineSurface::segment(const Standard_Real U1, |
537 | const Standard_Real U2, | |
538 | const Standard_Real V1, | |
539 | const Standard_Real V2, | |
540 | const Standard_Real EpsU, | |
541 | const Standard_Real EpsV, | |
542 | const Standard_Boolean SegmentInU, | |
543 | const Standard_Boolean SegmentInV) | |
7fd59977 | 544 | { |
6fd9bdf2 | 545 | Standard_Real deltaU = U2 - U1; |
369a38aa | 546 | if (uperiodic) { |
547 | Standard_Real aUPeriod = uknots->Last() - uknots->First(); | |
548 | if (deltaU - aUPeriod > Precision::PConfusion()) | |
9775fa61 | 549 | throw Standard_DomainError("Geom_BSplineSurface::Segment"); |
369a38aa | 550 | if (deltaU > aUPeriod) |
551 | deltaU = aUPeriod; | |
552 | } | |
6fd9bdf2 | 553 | |
554 | Standard_Real deltaV = V2 - V1; | |
369a38aa | 555 | if (vperiodic) { |
556 | Standard_Real aVPeriod = vknots->Last() - vknots->First(); | |
557 | if (deltaV - aVPeriod > Precision::PConfusion()) | |
9775fa61 | 558 | throw Standard_DomainError("Geom_BSplineSurface::Segment"); |
369a38aa | 559 | if (deltaV > aVPeriod) |
560 | deltaV = aVPeriod; | |
561 | } | |
7fd59977 | 562 | |
563 | Standard_Real NewU1, NewU2, NewV1, NewV2; | |
6fd9bdf2 | 564 | Standard_Real U, V; |
7fd59977 | 565 | Standard_Integer indexU, indexV; |
566 | ||
7fd59977 | 567 | indexU = 0; |
6fd9bdf2 | 568 | BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(), |
569 | U1, uperiodic, uknots->Lower(), uknots->Upper(), | |
570 | indexU, NewU1); | |
7fd59977 | 571 | indexU = 0; |
6fd9bdf2 | 572 | BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(), |
573 | U2, uperiodic, uknots->Lower(), uknots->Upper(), | |
574 | indexU, NewU2); | |
575 | if (SegmentInU) { | |
576 | // inserting the UKnots | |
577 | TColStd_Array1OfReal UKnots(1, 2); | |
578 | TColStd_Array1OfInteger UMults(1, 2); | |
579 | UKnots(1) = Min(NewU1, NewU2); | |
580 | UKnots(2) = Max(NewU1, NewU2); | |
581 | UMults(1) = UMults(2) = udeg; | |
582 | ||
583 | InsertUKnots(UKnots, UMults, EpsU); | |
584 | } | |
7fd59977 | 585 | |
586 | indexV = 0; | |
6fd9bdf2 | 587 | BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(), |
588 | V1, vperiodic, vknots->Lower(), vknots->Upper(), | |
589 | indexV, NewV1); | |
7fd59977 | 590 | indexV = 0; |
6fd9bdf2 | 591 | BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(), |
592 | V2, vperiodic, vknots->Lower(), vknots->Upper(), | |
593 | indexV, NewV2); | |
594 | if (SegmentInV) { | |
595 | // Inserting the VKnots | |
596 | TColStd_Array1OfReal VKnots(1, 2); | |
597 | TColStd_Array1OfInteger VMults(1, 2); | |
7fd59977 | 598 | |
6fd9bdf2 | 599 | VKnots(1) = Min(NewV1, NewV2); |
600 | VKnots(2) = Max(NewV1, NewV2); | |
601 | VMults(1) = VMults(2) = vdeg; | |
602 | InsertVKnots(VKnots, VMults, EpsV); | |
603 | } | |
7fd59977 | 604 | |
6fd9bdf2 | 605 | if (uperiodic && SegmentInU) { // set the origine at NewU1 |
7fd59977 | 606 | Standard_Integer index = 0; |
6fd9bdf2 | 607 | BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(), |
608 | U1, uperiodic, uknots->Lower(), uknots->Upper(), | |
609 | index, U); | |
610 | if (Abs(uknots->Value(index + 1) - U) <= EpsU) | |
7fd59977 | 611 | index++; |
612 | SetUOrigin(index); | |
613 | SetUNotPeriodic(); | |
614 | } | |
615 | ||
616 | // compute index1 and index2 to set the new knots and mults | |
617 | Standard_Integer index1U = 0, index2U = 0; | |
618 | Standard_Integer FromU1 = uknots->Lower(); | |
6fd9bdf2 | 619 | Standard_Integer ToU2 = uknots->Upper(); |
620 | BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(), | |
621 | NewU1, uperiodic, FromU1, ToU2, index1U, U); | |
622 | BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(), | |
623 | NewU1 + deltaU, uperiodic, FromU1, ToU2, index2U, U); | |
624 | if (Abs(uknots->Value(index2U + 1) - U) <= EpsU) | |
7fd59977 | 625 | index2U++; |
6fd9bdf2 | 626 | |
7fd59977 | 627 | Standard_Integer nbuknots = index2U - index1U + 1; |
628 | ||
6fd9bdf2 | 629 | Handle(TColStd_HArray1OfReal) |
630 | nuknots = new TColStd_HArray1OfReal(1, nbuknots); | |
631 | Handle(TColStd_HArray1OfInteger) | |
632 | numults = new TColStd_HArray1OfInteger(1, nbuknots); | |
7fd59977 | 633 | |
6fd9bdf2 | 634 | Standard_Integer i, k = 1; |
635 | for (i = index1U; i <= index2U; i++) { | |
7fd59977 | 636 | nuknots->SetValue(k, uknots->Value(i)); |
637 | numults->SetValue(k, umults->Value(i)); | |
638 | k++; | |
639 | } | |
6fd9bdf2 | 640 | if (SegmentInU) { |
641 | numults->SetValue(1, udeg + 1); | |
642 | numults->SetValue(nbuknots, udeg + 1); | |
643 | } | |
7fd59977 | 644 | |
6fd9bdf2 | 645 | if (vperiodic&& SegmentInV) { // set the origine at NewV1 |
7fd59977 | 646 | Standard_Integer index = 0; |
6fd9bdf2 | 647 | BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(), |
648 | V1, vperiodic, vknots->Lower(), vknots->Upper(), | |
649 | index, V); | |
650 | if (Abs(vknots->Value(index + 1) - V) <= EpsV) | |
7fd59977 | 651 | index++; |
652 | SetVOrigin(index); | |
653 | SetVNotPeriodic(); | |
654 | } | |
655 | ||
656 | // compute index1 and index2 to set the new knots and mults | |
657 | Standard_Integer index1V = 0, index2V = 0; | |
658 | Standard_Integer FromV1 = vknots->Lower(); | |
6fd9bdf2 | 659 | Standard_Integer ToV2 = vknots->Upper(); |
660 | BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(), | |
661 | NewV1, vperiodic, FromV1, ToV2, index1V, V); | |
662 | BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(), | |
663 | NewV1 + deltaV, vperiodic, FromV1, ToV2, index2V, V); | |
664 | if (Abs(vknots->Value(index2V + 1) - V) <= EpsV) | |
7fd59977 | 665 | index2V++; |
6fd9bdf2 | 666 | |
7fd59977 | 667 | Standard_Integer nbvknots = index2V - index1V + 1; |
668 | ||
6fd9bdf2 | 669 | Handle(TColStd_HArray1OfReal) |
670 | nvknots = new TColStd_HArray1OfReal(1, nbvknots); | |
671 | Handle(TColStd_HArray1OfInteger) | |
672 | nvmults = new TColStd_HArray1OfInteger(1, nbvknots); | |
7fd59977 | 673 | |
674 | k = 1; | |
6fd9bdf2 | 675 | for (i = index1V; i <= index2V; i++) { |
7fd59977 | 676 | nvknots->SetValue(k, vknots->Value(i)); |
677 | nvmults->SetValue(k, vmults->Value(i)); | |
678 | k++; | |
679 | } | |
6fd9bdf2 | 680 | if (SegmentInV) { |
681 | nvmults->SetValue(1, vdeg + 1); | |
682 | nvmults->SetValue(nbvknots, vdeg + 1); | |
683 | } | |
7fd59977 | 684 | |
685 | ||
686 | // compute index1 and index2 to set the new poles and weights | |
6fd9bdf2 | 687 | Standard_Integer pindex1U |
688 | = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1()); | |
689 | Standard_Integer pindex2U | |
690 | = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1()); | |
7fd59977 | 691 | |
692 | pindex1U++; | |
6fd9bdf2 | 693 | pindex2U = Min(pindex2U + 1, poles->ColLength()); |
7fd59977 | 694 | |
6fd9bdf2 | 695 | Standard_Integer nbupoles = pindex2U - pindex1U + 1; |
7fd59977 | 696 | |
697 | // compute index1 and index2 to set the new poles and weights | |
6fd9bdf2 | 698 | Standard_Integer pindex1V |
699 | = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1()); | |
700 | Standard_Integer pindex2V | |
701 | = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1()); | |
7fd59977 | 702 | |
703 | pindex1V++; | |
6fd9bdf2 | 704 | pindex2V = Min(pindex2V + 1, poles->RowLength()); |
7fd59977 | 705 | |
6fd9bdf2 | 706 | Standard_Integer nbvpoles = pindex2V - pindex1V + 1; |
7fd59977 | 707 | |
708 | ||
6fd9bdf2 | 709 | Handle(TColStd_HArray2OfReal) nweights; |
7fd59977 | 710 | |
711 | Handle(TColgp_HArray2OfPnt) | |
6fd9bdf2 | 712 | npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles); |
7fd59977 | 713 | k = 1; |
714 | Standard_Integer j, l; | |
6fd9bdf2 | 715 | if (urational || vrational) { |
716 | nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles); | |
717 | for (i = pindex1U; i <= pindex2U; i++) { | |
7fd59977 | 718 | l = 1; |
6fd9bdf2 | 719 | for (j = pindex1V; j <= pindex2V; j++) { |
720 | npoles->SetValue(k, l, poles->Value(i, j)); | |
721 | nweights->SetValue(k, l, weights->Value(i, j)); | |
722 | l++; | |
7fd59977 | 723 | } |
724 | k++; | |
725 | } | |
726 | } | |
727 | else { | |
6fd9bdf2 | 728 | for (i = pindex1U; i <= pindex2U; i++) { |
7fd59977 | 729 | l = 1; |
6fd9bdf2 | 730 | for (j = pindex1V; j <= pindex2V; j++) { |
731 | npoles->SetValue(k, l, poles->Value(i, j)); | |
732 | l++; | |
7fd59977 | 733 | } |
734 | k++; | |
735 | } | |
736 | } | |
737 | ||
738 | uknots = nuknots; | |
739 | umults = numults; | |
740 | vknots = nvknots; | |
741 | vmults = nvmults; | |
742 | poles = npoles; | |
6fd9bdf2 | 743 | if (urational || vrational) |
7fd59977 | 744 | weights = nweights; |
6fd9bdf2 | 745 | else |
746 | weights = new TColStd_HArray2OfReal(1, poles->ColLength(), | |
747 | 1, poles->RowLength(), 1.0); | |
7fd59977 | 748 | |
749 | maxderivinvok = 0; | |
750 | UpdateUKnots(); | |
751 | UpdateVKnots(); | |
6fd9bdf2 | 752 | } |
753 | ||
754 | //======================================================================= | |
755 | //function : Segment | |
756 | //purpose : | |
757 | //======================================================================= | |
7fd59977 | 758 | |
6fd9bdf2 | 759 | void Geom_BSplineSurface::Segment(const Standard_Real U1, |
760 | const Standard_Real U2, | |
761 | const Standard_Real V1, | |
762 | const Standard_Real V2, | |
763 | const Standard_Real theUTolerance, | |
764 | const Standard_Real theVTolerance) | |
765 | { | |
766 | if ((U2 < U1) || (V2 < V1)) | |
767 | throw Standard_DomainError("Geom_BSplineSurface::Segment"); | |
768 | ||
769 | Standard_Real aMaxU = Max(Abs(U2), Abs(U1)); | |
770 | Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance); | |
771 | ||
772 | Standard_Real aMaxV = Max(Abs(V2), Abs(V1)); | |
773 | Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance); | |
774 | ||
775 | segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True); | |
7fd59977 | 776 | } |
777 | ||
778 | //======================================================================= | |
779 | //function : CheckAndSegment | |
780 | //purpose : | |
781 | //======================================================================= | |
782 | ||
783 | void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, | |
6fd9bdf2 | 784 | const Standard_Real U2, |
785 | const Standard_Real V1, | |
786 | const Standard_Real V2, | |
787 | const Standard_Real theUTolerance, | |
788 | const Standard_Real theVTolerance) | |
7fd59977 | 789 | { |
790 | ||
369a38aa | 791 | if ((U2 < U1) || (V2 < V1)) |
9775fa61 | 792 | throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment"); |
7fd59977 | 793 | |
6fd9bdf2 | 794 | Standard_Real aMaxU = Max(Abs(U2), Abs(U1)); |
795 | Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance); | |
796 | ||
797 | Standard_Real aMaxV = Max(Abs(V2), Abs(V1)); | |
798 | Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance); | |
7fd59977 | 799 | |
800 | Standard_Boolean segment_in_U = Standard_True; | |
801 | Standard_Boolean segment_in_V = Standard_True; | |
802 | segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU ) | |
803 | || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU ); | |
804 | segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV ) | |
805 | || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV ); | |
806 | ||
6fd9bdf2 | 807 | segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V); |
7fd59977 | 808 | } |
809 | ||
810 | //======================================================================= | |
811 | //function : SetUKnot | |
812 | //purpose : | |
813 | //======================================================================= | |
814 | ||
815 | void Geom_BSplineSurface::SetUKnot | |
816 | (const Standard_Integer UIndex, | |
817 | const Standard_Real K ) | |
818 | { | |
1b827f04 BB |
819 | if (UIndex < 1 || UIndex > uknots->Length()) |
820 | throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch"); | |
7fd59977 | 821 | |
822 | Standard_Integer NewIndex = UIndex; | |
823 | Standard_Real DU = Abs(Epsilon (K)); | |
824 | if (UIndex == 1) { | |
1b827f04 BB |
825 | if (K >= uknots->Value (2) - DU) |
826 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range"); | |
7fd59977 | 827 | } |
828 | else if (UIndex == uknots->Length()) { | |
829 | if (K <= uknots->Value (uknots->Length()-1) + DU) { | |
1b827f04 | 830 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range"); |
7fd59977 | 831 | } |
832 | } | |
833 | else { | |
834 | if (K <= uknots->Value (NewIndex-1) + DU || | |
835 | K >= uknots->Value (NewIndex+1) - DU ) { | |
1b827f04 | 836 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range"); |
7fd59977 | 837 | } |
838 | } | |
839 | ||
840 | if (K != uknots->Value (NewIndex)) { | |
841 | uknots->SetValue (NewIndex, K); | |
842 | maxderivinvok = 0; | |
843 | UpdateUKnots(); | |
844 | } | |
845 | } | |
846 | ||
847 | //======================================================================= | |
848 | //function : SetUKnots | |
849 | //purpose : | |
850 | //======================================================================= | |
851 | ||
852 | void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) { | |
853 | ||
854 | Standard_Integer Lower = UK.Lower(); | |
855 | Standard_Integer Upper = UK.Upper(); | |
856 | if (Lower < 1 || Lower > uknots->Length() || | |
857 | Upper < 1 || Upper > uknots->Length() ) { | |
1b827f04 | 858 | throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension"); |
7fd59977 | 859 | } |
7fd59977 | 860 | if (Lower > 1) { |
7fd59977 | 861 | if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) { |
1b827f04 | 862 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value"); |
7fd59977 | 863 | } |
864 | } | |
865 | if (Upper < uknots->Length ()) { | |
7fd59977 | 866 | if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) { |
1b827f04 | 867 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value"); |
7fd59977 | 868 | } |
869 | } | |
870 | Standard_Real K1 = UK (Lower); | |
871 | for (Standard_Integer i = Lower; i <= Upper; i++) { | |
872 | uknots->SetValue (i, UK(i)); | |
873 | if (i != Lower) { | |
7fd59977 | 874 | if (Abs (UK(i) - K1) <= gp::Resolution()) { |
1b827f04 | 875 | throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value"); |
7fd59977 | 876 | } |
877 | K1 = UK (i); | |
878 | } | |
879 | } | |
880 | ||
881 | maxderivinvok = 0; | |
882 | UpdateUKnots(); | |
883 | } | |
884 | ||
885 | //======================================================================= | |
886 | //function : SetUKnot | |
887 | //purpose : | |
888 | //======================================================================= | |
889 | ||
890 | void Geom_BSplineSurface::SetUKnot | |
891 | (const Standard_Integer UIndex, | |
892 | const Standard_Real K, | |
893 | const Standard_Integer M) | |
894 | { | |
895 | IncreaseUMultiplicity (UIndex, M); | |
896 | SetUKnot (UIndex, K); | |
897 | } | |
898 | ||
899 | //======================================================================= | |
900 | //function : SetVKnot | |
901 | //purpose : | |
902 | //======================================================================= | |
903 | ||
904 | void Geom_BSplineSurface::SetVKnot | |
905 | (const Standard_Integer VIndex, | |
906 | const Standard_Real K) | |
907 | { | |
1b827f04 BB |
908 | if (VIndex < 1 || VIndex > vknots->Length()) |
909 | throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch"); | |
7fd59977 | 910 | Standard_Integer NewIndex = VIndex + vknots->Lower() - 1; |
911 | Standard_Real DV = Abs(Epsilon (K)); | |
912 | if (VIndex == 1) { | |
913 | if (K >= vknots->Value (2) - DV) { | |
1b827f04 | 914 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range"); |
7fd59977 | 915 | } |
916 | } | |
917 | else if (VIndex == vknots->Length()) { | |
918 | if (K <= vknots->Value (vknots->Length()-1) + DV) { | |
1b827f04 | 919 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range"); |
7fd59977 | 920 | } |
921 | } | |
922 | else { | |
923 | if (K <= vknots->Value (NewIndex-1) + DV || | |
924 | K >= vknots->Value (NewIndex+1) - DV ) { | |
1b827f04 | 925 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range"); |
7fd59977 | 926 | } |
927 | } | |
928 | ||
a165f002 | 929 | if (K != vknots->Value (NewIndex)) { |
930 | vknots->SetValue (NewIndex, K); | |
931 | maxderivinvok = 0; | |
932 | UpdateVKnots(); | |
933 | } | |
7fd59977 | 934 | } |
935 | ||
936 | //======================================================================= | |
937 | //function : SetVKnots | |
938 | //purpose : | |
939 | //======================================================================= | |
940 | ||
941 | void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) { | |
942 | ||
943 | Standard_Integer Lower = VK.Lower(); | |
944 | Standard_Integer Upper = VK.Upper(); | |
945 | if (Lower < 1 || Lower > vknots->Length() || | |
946 | Upper < 1 || Upper > vknots->Length() ) { | |
1b827f04 | 947 | throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension"); |
7fd59977 | 948 | } |
7fd59977 | 949 | if (Lower > 1) { |
7fd59977 | 950 | if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) { |
1b827f04 | 951 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value"); |
7fd59977 | 952 | } |
953 | } | |
954 | if (Upper < vknots->Length ()) { | |
7fd59977 | 955 | if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) { |
1b827f04 | 956 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value"); |
7fd59977 | 957 | } |
958 | } | |
959 | Standard_Real K1 = VK (Lower); | |
960 | for (Standard_Integer i = Lower; i <= Upper; i++) { | |
961 | vknots->SetValue (i, VK(i)); | |
962 | if (i != Lower) { | |
7fd59977 | 963 | if (Abs (VK(i) - K1) <= gp::Resolution()) { |
1b827f04 | 964 | throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value"); |
7fd59977 | 965 | } |
966 | K1 = VK (i); | |
967 | } | |
968 | } | |
969 | ||
970 | maxderivinvok = 0; | |
971 | UpdateVKnots(); | |
972 | } | |
973 | ||
974 | //======================================================================= | |
975 | //function : SetVKnot | |
976 | //purpose : | |
977 | //======================================================================= | |
978 | ||
979 | void Geom_BSplineSurface::SetVKnot | |
980 | (const Standard_Integer VIndex, | |
981 | const Standard_Real K, | |
982 | const Standard_Integer M) | |
983 | { | |
984 | IncreaseVMultiplicity (VIndex, M); | |
985 | SetVKnot (VIndex, K); | |
986 | } | |
987 | ||
988 | //======================================================================= | |
989 | //function : InsertUKnot | |
990 | //purpose : | |
991 | //======================================================================= | |
992 | ||
993 | void Geom_BSplineSurface::InsertUKnot | |
994 | (const Standard_Real U, | |
995 | const Standard_Integer M, | |
996 | const Standard_Real ParametricTolerance, | |
997 | const Standard_Boolean Add) | |
998 | { | |
999 | TColStd_Array1OfReal k(1,1); | |
1000 | k(1) = U; | |
1001 | TColStd_Array1OfInteger m(1,1); | |
1002 | m(1) = M; | |
1003 | InsertUKnots(k,m,ParametricTolerance,Add); | |
1004 | } | |
1005 | ||
1006 | //======================================================================= | |
1007 | //function : InsertVKnot | |
1008 | //purpose : | |
1009 | //======================================================================= | |
1010 | ||
1011 | void Geom_BSplineSurface::InsertVKnot | |
1012 | (const Standard_Real V, | |
1013 | const Standard_Integer M, | |
1014 | const Standard_Real ParametricTolerance, | |
1015 | const Standard_Boolean Add) | |
1016 | { | |
1017 | TColStd_Array1OfReal k(1,1); | |
1018 | k(1) = V; | |
1019 | TColStd_Array1OfInteger m(1,1); | |
1020 | m(1) = M; | |
1021 | InsertVKnots(k,m,ParametricTolerance,Add); | |
1022 | } | |
1023 | ||
1024 | //======================================================================= | |
1025 | //function : IncrementUMultiplicity | |
1026 | //purpose : | |
1027 | //======================================================================= | |
1028 | ||
1029 | void Geom_BSplineSurface::IncrementUMultiplicity | |
1030 | (const Standard_Integer FromI1, | |
1031 | const Standard_Integer ToI2, | |
1032 | const Standard_Integer Step) | |
1033 | { | |
1034 | Handle(TColStd_HArray1OfReal) tk = uknots; | |
1035 | TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2); | |
1036 | TColStd_Array1OfInteger m( FromI1, ToI2) ; | |
1037 | m.Init(Step); | |
1038 | InsertUKnots( k, m, Epsilon(1.)); | |
1039 | } | |
1040 | ||
1041 | //======================================================================= | |
1042 | //function : IncrementVMultiplicity | |
1043 | //purpose : | |
1044 | //======================================================================= | |
1045 | ||
1046 | void Geom_BSplineSurface::IncrementVMultiplicity | |
1047 | (const Standard_Integer FromI1, | |
1048 | const Standard_Integer ToI2, | |
1049 | const Standard_Integer Step) | |
1050 | { | |
1051 | Handle(TColStd_HArray1OfReal) tk = vknots; | |
1052 | TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2); | |
1053 | ||
1054 | TColStd_Array1OfInteger m( FromI1, ToI2) ; | |
1055 | m.Init(Step); | |
1056 | ||
1057 | InsertVKnots( k, m, Epsilon(1.)); | |
1058 | } | |
1059 | ||
1060 | //======================================================================= | |
1061 | //function : UpdateUKnots | |
1062 | //purpose : | |
1063 | //======================================================================= | |
1064 | ||
1065 | void Geom_BSplineSurface::UpdateUKnots() | |
1066 | { | |
1067 | ||
1068 | Standard_Integer MaxKnotMult = 0; | |
06be28a4 | 1069 | BSplCLib::KnotAnalysis (udeg, uperiodic, |
7fd59977 | 1070 | uknots->Array1(), |
1071 | umults->Array1(), | |
1072 | uknotSet, MaxKnotMult); | |
1073 | ||
1074 | if (uknotSet == GeomAbs_Uniform && !uperiodic) { | |
1075 | ufknots = uknots; | |
1076 | } | |
1077 | else { | |
1078 | ufknots = new TColStd_HArray1OfReal | |
1079 | (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic)); | |
1080 | ||
1081 | BSplCLib::KnotSequence (uknots->Array1(), | |
1082 | umults->Array1(), | |
1083 | udeg,uperiodic, | |
1084 | ufknots->ChangeArray1()); | |
1085 | } | |
1086 | ||
1087 | if (MaxKnotMult == 0) Usmooth = GeomAbs_CN; | |
1088 | else { | |
1089 | switch (udeg - MaxKnotMult) { | |
1090 | case 0 : Usmooth = GeomAbs_C0; break; | |
1091 | case 1 : Usmooth = GeomAbs_C1; break; | |
1092 | case 2 : Usmooth = GeomAbs_C2; break; | |
1093 | case 3 : Usmooth = GeomAbs_C3; break; | |
1094 | default : Usmooth = GeomAbs_C3; break; | |
1095 | } | |
1096 | } | |
7fd59977 | 1097 | } |
1098 | ||
1099 | //======================================================================= | |
1100 | //function : UpdateVKnots | |
1101 | //purpose : | |
1102 | //======================================================================= | |
1103 | ||
1104 | void Geom_BSplineSurface::UpdateVKnots() | |
1105 | { | |
1106 | Standard_Integer MaxKnotMult = 0; | |
06be28a4 | 1107 | BSplCLib::KnotAnalysis (vdeg, vperiodic, |
7fd59977 | 1108 | vknots->Array1(), |
1109 | vmults->Array1(), | |
1110 | vknotSet, MaxKnotMult); | |
1111 | ||
1112 | if (vknotSet == GeomAbs_Uniform && !vperiodic) { | |
1113 | vfknots = vknots; | |
1114 | } | |
1115 | else { | |
1116 | vfknots = new TColStd_HArray1OfReal | |
1117 | (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic)); | |
1118 | ||
1119 | BSplCLib::KnotSequence (vknots->Array1(), | |
1120 | vmults->Array1(), | |
1121 | vdeg,vperiodic, | |
1122 | vfknots->ChangeArray1()); | |
1123 | } | |
1124 | ||
1125 | if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN; | |
1126 | else { | |
1127 | switch (vdeg - MaxKnotMult) { | |
1128 | case 0 : Vsmooth = GeomAbs_C0; break; | |
1129 | case 1 : Vsmooth = GeomAbs_C1; break; | |
1130 | case 2 : Vsmooth = GeomAbs_C2; break; | |
1131 | case 3 : Vsmooth = GeomAbs_C3; break; | |
1132 | default : Vsmooth = GeomAbs_C3; break; | |
1133 | } | |
1134 | } | |
7fd59977 | 1135 | } |
1136 | ||
7fd59977 | 1137 | |
1138 | //======================================================================= | |
1139 | //function : Normalizes the parameters if the curve is periodic | |
1140 | //purpose : that is compute the cache so that it is valid | |
1141 | //======================================================================= | |
1142 | ||
1143 | void Geom_BSplineSurface::PeriodicNormalization | |
1144 | (Standard_Real& Uparameter, | |
1145 | Standard_Real& Vparameter) const | |
1146 | { | |
1147 | Standard_Real Period, aMaxVal, aMinVal; | |
1148 | ||
1149 | if (uperiodic) { | |
1150 | aMaxVal = ufknots->Value(ufknots->Upper() - udeg); | |
1151 | aMinVal = ufknots->Value (udeg + 1); | |
1152 | Standard_Real eps = Abs(Epsilon(Uparameter)); | |
1153 | Period = aMaxVal - aMinVal; | |
1154 | ||
1155 | if(Period <= eps) | |
9775fa61 | 1156 | throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number"); |
7fd59977 | 1157 | |
9cbe6290 | 1158 | Standard_Boolean isLess, isGreater; |
1159 | isLess = aMinVal - Uparameter > 0; | |
1160 | isGreater = Uparameter - aMaxVal > 0; | |
1161 | if (isLess || isGreater) { | |
1162 | Standard_Real aDPar, aNbPer; | |
1163 | aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter); | |
1164 | modf(aDPar / Period, &aNbPer); | |
1165 | Uparameter += aNbPer * Period; | |
7fd59977 | 1166 | } |
1167 | } | |
1168 | if (vperiodic) { | |
1169 | aMaxVal = vfknots->Value(vfknots->Upper() - vdeg); | |
1170 | aMinVal = vfknots->Value (vdeg + 1); | |
1171 | Standard_Real eps = Abs(Epsilon(Vparameter)); | |
1172 | Period = aMaxVal - aMinVal; | |
1173 | ||
1174 | if(Period <= eps) | |
9775fa61 | 1175 | throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number"); |
7fd59977 | 1176 | |
9cbe6290 | 1177 | Standard_Boolean isLess, isGreater; |
1178 | isLess = aMinVal - Vparameter > 0; | |
1179 | isGreater = Vparameter - aMaxVal > 0; | |
1180 | if (isLess || isGreater) { | |
1181 | Standard_Real aDPar, aNbPer; | |
1182 | aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter); | |
1183 | modf(aDPar / Period, &aNbPer); | |
1184 | Vparameter += aNbPer * Period; | |
7fd59977 | 1185 | } |
1186 | } | |
1187 | } | |
1188 | ||
7fd59977 | 1189 | //======================================================================= |
1190 | //function : SetWeight | |
1191 | //purpose : | |
1192 | //======================================================================= | |
1193 | ||
1194 | void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex, | |
1195 | const Standard_Integer VIndex, | |
1196 | const Standard_Real Weight) | |
1197 | { | |
1b827f04 BB |
1198 | if (Weight <= gp::Resolution()) |
1199 | throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small"); | |
7fd59977 | 1200 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); |
1201 | if (UIndex < 1 || UIndex > Weights.ColLength() || | |
1202 | VIndex < 1 || VIndex > Weights.RowLength() ) { | |
1b827f04 | 1203 | throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch"); |
7fd59977 | 1204 | } |
1205 | Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight; | |
1206 | Rational(Weights, urational, vrational); | |
7fd59977 | 1207 | } |
1208 | ||
1209 | //======================================================================= | |
1210 | //function : SetWeightCol | |
1211 | //purpose : | |
1212 | //======================================================================= | |
1213 | ||
1214 | void Geom_BSplineSurface::SetWeightCol | |
1215 | (const Standard_Integer VIndex, | |
1216 | const TColStd_Array1OfReal& CPoleWeights) | |
1217 | { | |
1218 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); | |
1219 | if (VIndex < 1 || VIndex > Weights.RowLength()) { | |
1b827f04 | 1220 | throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch"); |
7fd59977 | 1221 | } |
1222 | if (CPoleWeights.Lower() < 1 || | |
1223 | CPoleWeights.Lower() > Weights.ColLength() || | |
1224 | CPoleWeights.Upper() < 1 || | |
1225 | CPoleWeights.Upper() > Weights.ColLength() ) { | |
1b827f04 | 1226 | throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension"); |
7fd59977 | 1227 | } |
1228 | Standard_Integer I = CPoleWeights.Lower(); | |
1229 | while (I <= CPoleWeights.Upper()) { | |
1230 | if (CPoleWeights(I) <= gp::Resolution()) { | |
1b827f04 | 1231 | throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small"); |
7fd59977 | 1232 | } |
1233 | Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = | |
1234 | CPoleWeights (I); | |
1235 | I++; | |
1236 | } | |
1237 | // Verifie si c'est rationnel | |
1238 | Rational(Weights, urational, vrational); | |
7fd59977 | 1239 | } |
1240 | ||
1241 | //======================================================================= | |
1242 | //function : SetWeightRow | |
1243 | //purpose : | |
1244 | //======================================================================= | |
1245 | ||
1246 | void Geom_BSplineSurface::SetWeightRow | |
1247 | (const Standard_Integer UIndex, | |
1248 | const TColStd_Array1OfReal& CPoleWeights) | |
1249 | { | |
1250 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); | |
1251 | if (UIndex < 1 || UIndex > Weights.ColLength()) { | |
1b827f04 | 1252 | throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch"); |
7fd59977 | 1253 | } |
1254 | if (CPoleWeights.Lower() < 1 || | |
1255 | CPoleWeights.Lower() > Weights.RowLength() || | |
1256 | CPoleWeights.Upper() < 1 || | |
1257 | CPoleWeights.Upper() > Weights.RowLength() ) { | |
1258 | ||
1b827f04 | 1259 | throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension"); |
7fd59977 | 1260 | } |
1261 | Standard_Integer I = CPoleWeights.Lower(); | |
1262 | ||
1263 | while (I <= CPoleWeights.Upper()) { | |
1264 | if (CPoleWeights(I)<=gp::Resolution()) { | |
1b827f04 | 1265 | throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small"); |
7fd59977 | 1266 | } |
1267 | Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = | |
1268 | CPoleWeights (I); | |
1269 | I++; | |
1270 | } | |
1271 | // Verifie si c'est rationnel | |
1272 | Rational(Weights, urational, vrational); | |
7fd59977 | 1273 | } |
1274 |