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 ()) { |
65 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
66 | } |
67 | if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) { |
68 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
69 | } |
70 | |
71 | if (SUKnots.Length() != SUMults.Length() || |
72 | SVKnots.Length() != SVMults.Length()) { |
73 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
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)))) { |
79 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
80 | } |
81 | } |
82 | |
83 | for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) { |
84 | if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) { |
85 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
86 | } |
87 | } |
88 | |
89 | if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults)) |
90 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
91 | |
92 | if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults)) |
93 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
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()) |
240 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
241 | |
242 | if (Weights.RowLength() != Poles.RowLength()) |
243 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
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()) |
249 | Standard_ConstructionError::Raise("Geom_BSplineSurface"); |
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()) |
360 | Standard_ConstructionError::Raise(); |
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()) |
412 | Standard_ConstructionError::Raise(); |
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 | //======================================================================= |
532 | //function : Segment |
533 | //purpose : |
534 | //======================================================================= |
535 | |
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 | { |
541 | |
542 | Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1), |
543 | "Geom_BSplineCurve::Segment"); |
544 | Standard_Real deltaU = Max(Abs(U2),Abs(U1)); |
545 | Standard_Real EpsU = Epsilon(deltaU); |
546 | deltaU = U2 - U1; |
547 | |
548 | Standard_Real deltaV = Max(Abs(V2),Abs(V1)); |
549 | Standard_Real EpsV = Epsilon(deltaV); |
550 | deltaV = V2 - V1; |
551 | |
552 | Standard_Real NewU1, NewU2, NewV1, NewV2; |
553 | Standard_Real U,V; |
554 | Standard_Integer indexU, indexV; |
555 | |
556 | // inserting the UKnots |
557 | TColStd_Array1OfReal UKnots(1,2); |
558 | TColStd_Array1OfInteger UMults(1,2); |
559 | |
560 | indexU = 0; |
561 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
562 | U1,uperiodic,uknots->Lower(),uknots->Upper(), |
563 | indexU,NewU1); |
564 | indexU = 0; |
565 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
566 | U2,uperiodic,uknots->Lower(),uknots->Upper(), |
567 | indexU,NewU2); |
568 | UKnots( 1) = Min( NewU1, NewU2); |
569 | UKnots( 2) = Max( NewU1, NewU2); |
570 | UMults( 1) = UMults( 2) = udeg; |
571 | InsertUKnots( UKnots, UMults, EpsU); |
572 | |
573 | // Inserting the VKnots |
574 | TColStd_Array1OfReal VKnots(1,2); |
575 | TColStd_Array1OfInteger VMults(1,2); |
576 | |
577 | indexV = 0; |
578 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
579 | V1,vperiodic,vknots->Lower(),vknots->Upper(), |
580 | indexV,NewV1); |
581 | indexV = 0; |
582 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
583 | V2,vperiodic,vknots->Lower(),vknots->Upper(), |
584 | indexV,NewV2); |
585 | VKnots( 1) = Min( NewV1, NewV2); |
586 | VKnots( 2) = Max( NewV1, NewV2); |
587 | VMults( 1) = VMults( 2) = vdeg; |
588 | InsertVKnots( VKnots, VMults, EpsV); |
589 | |
590 | |
591 | if (uperiodic) { // set the origine at NewU1 |
592 | Standard_Integer index = 0; |
593 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
594 | U1,uperiodic,uknots->Lower(),uknots->Upper(), |
595 | index,U); |
596 | if ( Abs(uknots->Value(index+1)-U) <= EpsU) |
597 | index++; |
598 | SetUOrigin(index); |
599 | SetUNotPeriodic(); |
600 | } |
601 | |
602 | // compute index1 and index2 to set the new knots and mults |
603 | Standard_Integer index1U = 0, index2U = 0; |
604 | Standard_Integer FromU1 = uknots->Lower(); |
605 | Standard_Integer ToU2 = uknots->Upper(); |
606 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
607 | NewU1,uperiodic,FromU1,ToU2,index1U,U); |
608 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
609 | NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U); |
610 | if ( Abs(uknots->Value(index2U+1)-U) <= EpsU) |
611 | index2U++; |
612 | |
613 | Standard_Integer nbuknots = index2U - index1U + 1; |
614 | |
615 | Handle(TColStd_HArray1OfReal) |
616 | nuknots = new TColStd_HArray1OfReal(1,nbuknots); |
617 | Handle(TColStd_HArray1OfInteger) |
618 | numults = new TColStd_HArray1OfInteger(1,nbuknots); |
619 | |
620 | Standard_Integer i , k = 1; |
621 | for ( i = index1U; i<= index2U; i++) { |
622 | nuknots->SetValue(k, uknots->Value(i)); |
623 | numults->SetValue(k, umults->Value(i)); |
624 | k++; |
625 | } |
626 | numults->SetValue( 1, udeg + 1); |
627 | numults->SetValue(nbuknots, udeg + 1); |
628 | |
629 | |
630 | if (vperiodic) { // set the origine at NewV1 |
631 | Standard_Integer index = 0; |
632 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
633 | V1,vperiodic,vknots->Lower(),vknots->Upper(), |
634 | index,V); |
635 | if ( Abs(vknots->Value(index+1)-V) <= EpsV) |
636 | index++; |
637 | SetVOrigin(index); |
638 | SetVNotPeriodic(); |
639 | } |
640 | |
641 | // compute index1 and index2 to set the new knots and mults |
642 | Standard_Integer index1V = 0, index2V = 0; |
643 | Standard_Integer FromV1 = vknots->Lower(); |
644 | Standard_Integer ToV2 = vknots->Upper(); |
645 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
646 | NewV1,vperiodic,FromV1,ToV2,index1V,V); |
647 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
648 | NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V); |
649 | if ( Abs(vknots->Value(index2V+1)-V) <= EpsV) |
650 | index2V++; |
651 | |
652 | Standard_Integer nbvknots = index2V - index1V + 1; |
653 | |
654 | Handle(TColStd_HArray1OfReal) |
655 | nvknots = new TColStd_HArray1OfReal(1,nbvknots); |
656 | Handle(TColStd_HArray1OfInteger) |
657 | nvmults = new TColStd_HArray1OfInteger(1,nbvknots); |
658 | |
659 | k = 1; |
660 | for ( i = index1V; i<= index2V; i++) { |
661 | nvknots->SetValue(k, vknots->Value(i)); |
662 | nvmults->SetValue(k, vmults->Value(i)); |
663 | k++; |
664 | } |
665 | nvmults->SetValue( 1, vdeg + 1); |
666 | nvmults->SetValue(nbvknots, vdeg + 1); |
667 | |
668 | |
669 | // compute index1 and index2 to set the new poles and weights |
670 | Standard_Integer pindex1U |
671 | = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1()); |
672 | Standard_Integer pindex2U |
673 | = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1()); |
674 | |
675 | pindex1U++; |
676 | pindex2U = Min( pindex2U+1, poles->ColLength()); |
677 | |
678 | Standard_Integer nbupoles = pindex2U - pindex1U + 1; |
679 | |
680 | // compute index1 and index2 to set the new poles and weights |
681 | Standard_Integer pindex1V |
682 | = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1()); |
683 | Standard_Integer pindex2V |
684 | = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1()); |
685 | |
686 | pindex1V++; |
687 | pindex2V = Min( pindex2V+1, poles->RowLength()); |
688 | |
689 | Standard_Integer nbvpoles = pindex2V - pindex1V + 1; |
690 | |
691 | |
692 | Handle(TColStd_HArray2OfReal) nweights; |
693 | |
694 | Handle(TColgp_HArray2OfPnt) |
695 | npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles); |
696 | |
697 | k = 1; |
698 | Standard_Integer j, l; |
699 | if ( urational || vrational) { |
700 | nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles); |
701 | for ( i = pindex1U; i <= pindex2U; i++) { |
702 | l = 1; |
703 | for ( j = pindex1V; j <= pindex2V; j++) { |
704 | npoles->SetValue(k,l, poles->Value(i,j)); |
705 | nweights->SetValue(k,l, weights->Value(i,j)); |
706 | l++; |
707 | } |
708 | k++; |
709 | } |
710 | } |
711 | else { |
712 | for ( i = pindex1U; i <= pindex2U; i++) { |
713 | l = 1; |
714 | for ( j = pindex1V; j <= pindex2V; j++) { |
715 | npoles->SetValue(k,l, poles->Value(i,j)); |
716 | l++; |
717 | } |
718 | k++; |
719 | } |
720 | } |
721 | |
722 | uknots = nuknots; |
723 | umults = numults; |
724 | vknots = nvknots; |
725 | vmults = nvmults; |
726 | poles = npoles; |
727 | if ( urational || vrational) |
728 | weights = nweights; |
729 | else |
730 | weights = new TColStd_HArray2OfReal (1,poles->ColLength(), |
731 | 1,poles->RowLength(), 1.0); |
732 | |
733 | maxderivinvok = 0; |
734 | UpdateUKnots(); |
735 | UpdateVKnots(); |
736 | |
737 | } |
738 | |
739 | //======================================================================= |
740 | //function : CheckAndSegment |
741 | //purpose : |
742 | //======================================================================= |
743 | |
744 | void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, |
745 | const Standard_Real U2, |
746 | const Standard_Real V1, |
747 | const Standard_Real V2) |
748 | { |
749 | |
750 | Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1), |
751 | "Geom_BSplineCurve::Segment"); |
752 | Standard_Real deltaU = Max(Abs(U2),Abs(U1)); |
753 | Standard_Real EpsU = Epsilon(deltaU); |
754 | deltaU = U2 - U1; |
755 | |
756 | Standard_Real deltaV = Max(Abs(V2),Abs(V1)); |
757 | Standard_Real EpsV = Epsilon(deltaV); |
758 | deltaV = V2 - V1; |
759 | |
760 | Standard_Real NewU1, NewU2, NewV1, NewV2; |
761 | Standard_Real U,V; |
762 | Standard_Integer indexU, indexV; |
763 | |
764 | Standard_Boolean segment_in_U = Standard_True; |
765 | Standard_Boolean segment_in_V = Standard_True; |
766 | segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU ) |
767 | || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU ); |
768 | segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV ) |
769 | || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV ); |
770 | |
771 | indexU = 0; |
772 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
773 | U1,uperiodic,uknots->Lower(),uknots->Upper(), |
774 | indexU,NewU1); |
775 | indexU = 0; |
776 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
777 | U2,uperiodic,uknots->Lower(),uknots->Upper(), |
778 | indexU,NewU2); |
779 | if (segment_in_U) { |
780 | // inserting the UKnots |
781 | TColStd_Array1OfReal UKnots(1,2); |
782 | TColStd_Array1OfInteger UMults(1,2); |
783 | UKnots( 1) = Min( NewU1, NewU2); |
784 | UKnots( 2) = Max( NewU1, NewU2); |
785 | UMults( 1) = UMults( 2) = udeg; |
786 | |
787 | InsertUKnots( UKnots, UMults, EpsU); |
788 | } |
789 | |
790 | indexV = 0; |
791 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
792 | V1,vperiodic,vknots->Lower(),vknots->Upper(), |
793 | indexV,NewV1); |
794 | indexV = 0; |
795 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
796 | V2,vperiodic,vknots->Lower(),vknots->Upper(), |
797 | indexV,NewV2); |
798 | if (segment_in_V) { |
799 | // Inserting the VKnots |
800 | TColStd_Array1OfReal VKnots(1,2); |
801 | TColStd_Array1OfInteger VMults(1,2); |
802 | |
803 | VKnots( 1) = Min( NewV1, NewV2); |
804 | VKnots( 2) = Max( NewV1, NewV2); |
805 | VMults( 1) = VMults( 2) = vdeg; |
806 | InsertVKnots( VKnots, VMults, EpsV); |
807 | } |
808 | |
809 | if (uperiodic && segment_in_U) { // set the origine at NewU1 |
810 | Standard_Integer index = 0; |
811 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
812 | U1,uperiodic,uknots->Lower(),uknots->Upper(), |
813 | index,U); |
814 | if ( Abs(uknots->Value(index+1)-U) <= EpsU) |
815 | index++; |
816 | SetUOrigin(index); |
817 | SetUNotPeriodic(); |
818 | } |
819 | |
820 | // compute index1 and index2 to set the new knots and mults |
821 | Standard_Integer index1U = 0, index2U = 0; |
822 | Standard_Integer FromU1 = uknots->Lower(); |
823 | Standard_Integer ToU2 = uknots->Upper(); |
824 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
825 | NewU1,uperiodic,FromU1,ToU2,index1U,U); |
826 | BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(), |
827 | NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U); |
828 | if ( Abs(uknots->Value(index2U+1)-U) <= EpsU) |
829 | index2U++; |
830 | |
831 | Standard_Integer nbuknots = index2U - index1U + 1; |
832 | |
833 | Handle(TColStd_HArray1OfReal) |
834 | nuknots = new TColStd_HArray1OfReal(1,nbuknots); |
835 | Handle(TColStd_HArray1OfInteger) |
836 | numults = new TColStd_HArray1OfInteger(1,nbuknots); |
837 | |
838 | Standard_Integer i , k = 1; |
839 | for ( i = index1U; i<= index2U; i++) { |
840 | nuknots->SetValue(k, uknots->Value(i)); |
841 | numults->SetValue(k, umults->Value(i)); |
842 | k++; |
843 | } |
844 | if (segment_in_U) { |
845 | numults->SetValue( 1, udeg + 1); |
846 | numults->SetValue(nbuknots, udeg + 1); |
847 | } |
848 | |
849 | if (vperiodic&& segment_in_V) { // set the origine at NewV1 |
850 | Standard_Integer index = 0; |
851 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
852 | V1,vperiodic,vknots->Lower(),vknots->Upper(), |
853 | index,V); |
854 | if ( Abs(vknots->Value(index+1)-V) <= EpsV) |
855 | index++; |
856 | SetVOrigin(index); |
857 | SetVNotPeriodic(); |
858 | } |
859 | |
860 | // compute index1 and index2 to set the new knots and mults |
861 | Standard_Integer index1V = 0, index2V = 0; |
862 | Standard_Integer FromV1 = vknots->Lower(); |
863 | Standard_Integer ToV2 = vknots->Upper(); |
864 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
865 | NewV1,vperiodic,FromV1,ToV2,index1V,V); |
866 | BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(), |
867 | NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V); |
868 | if ( Abs(vknots->Value(index2V+1)-V) <= EpsV) |
869 | index2V++; |
870 | |
871 | Standard_Integer nbvknots = index2V - index1V + 1; |
872 | |
873 | Handle(TColStd_HArray1OfReal) |
874 | nvknots = new TColStd_HArray1OfReal(1,nbvknots); |
875 | Handle(TColStd_HArray1OfInteger) |
876 | nvmults = new TColStd_HArray1OfInteger(1,nbvknots); |
877 | |
878 | k = 1; |
879 | for ( i = index1V; i<= index2V; i++) { |
880 | nvknots->SetValue(k, vknots->Value(i)); |
881 | nvmults->SetValue(k, vmults->Value(i)); |
882 | k++; |
883 | } |
884 | if (segment_in_V) { |
885 | nvmults->SetValue( 1, vdeg + 1); |
886 | nvmults->SetValue(nbvknots, vdeg + 1); |
887 | } |
888 | |
889 | // compute index1 and index2 to set the new poles and weights |
890 | Standard_Integer pindex1U |
891 | = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1()); |
892 | Standard_Integer pindex2U |
893 | = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1()); |
894 | |
895 | pindex1U++; |
896 | pindex2U = Min( pindex2U+1, poles->ColLength()); |
897 | |
898 | Standard_Integer nbupoles = pindex2U - pindex1U + 1; |
899 | |
900 | // compute index1 and index2 to set the new poles and weights |
901 | Standard_Integer pindex1V |
902 | = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1()); |
903 | Standard_Integer pindex2V |
904 | = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1()); |
905 | |
906 | pindex1V++; |
907 | pindex2V = Min( pindex2V+1, poles->RowLength()); |
908 | |
909 | Standard_Integer nbvpoles = pindex2V - pindex1V + 1; |
910 | |
911 | |
912 | Handle(TColStd_HArray2OfReal) nweights; |
913 | |
914 | Handle(TColgp_HArray2OfPnt) |
915 | npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles); |
916 | |
917 | k = 1; |
918 | Standard_Integer j, l; |
919 | if ( urational || vrational) { |
920 | nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles); |
921 | for ( i = pindex1U; i <= pindex2U; i++) { |
922 | l = 1; |
923 | for ( j = pindex1V; j <= pindex2V; j++) { |
924 | npoles->SetValue(k,l, poles->Value(i,j)); |
925 | nweights->SetValue(k,l, weights->Value(i,j)); |
926 | l++; |
927 | } |
928 | k++; |
929 | } |
930 | } |
931 | else { |
932 | for ( i = pindex1U; i <= pindex2U; i++) { |
933 | l = 1; |
934 | for ( j = pindex1V; j <= pindex2V; j++) { |
935 | npoles->SetValue(k,l, poles->Value(i,j)); |
936 | l++; |
937 | } |
938 | k++; |
939 | } |
940 | } |
941 | |
942 | uknots = nuknots; |
943 | umults = numults; |
944 | vknots = nvknots; |
945 | vmults = nvmults; |
946 | poles = npoles; |
947 | if ( urational || vrational) |
948 | weights = nweights; |
949 | else |
950 | weights = new TColStd_HArray2OfReal (1,poles->ColLength(), |
951 | 1,poles->RowLength(), 1.0); |
952 | |
953 | maxderivinvok = 0; |
954 | UpdateUKnots(); |
955 | UpdateVKnots(); |
956 | |
957 | } |
958 | |
959 | //======================================================================= |
960 | //function : SetUKnot |
961 | //purpose : |
962 | //======================================================================= |
963 | |
964 | void Geom_BSplineSurface::SetUKnot |
965 | (const Standard_Integer UIndex, |
966 | const Standard_Real K ) |
967 | { |
968 | if (UIndex < 1 || UIndex > uknots->Length()) Standard_OutOfRange::Raise(); |
969 | |
970 | Standard_Integer NewIndex = UIndex; |
971 | Standard_Real DU = Abs(Epsilon (K)); |
972 | if (UIndex == 1) { |
973 | if (K >= uknots->Value (2) - DU) Standard_ConstructionError::Raise(); |
974 | } |
975 | else if (UIndex == uknots->Length()) { |
976 | if (K <= uknots->Value (uknots->Length()-1) + DU) { |
977 | Standard_ConstructionError::Raise(); |
978 | } |
979 | } |
980 | else { |
981 | if (K <= uknots->Value (NewIndex-1) + DU || |
982 | K >= uknots->Value (NewIndex+1) - DU ) { |
983 | Standard_ConstructionError::Raise(); |
984 | } |
985 | } |
986 | |
987 | if (K != uknots->Value (NewIndex)) { |
988 | uknots->SetValue (NewIndex, K); |
989 | maxderivinvok = 0; |
990 | UpdateUKnots(); |
991 | } |
992 | } |
993 | |
994 | //======================================================================= |
995 | //function : SetUKnots |
996 | //purpose : |
997 | //======================================================================= |
998 | |
999 | void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) { |
1000 | |
1001 | Standard_Integer Lower = UK.Lower(); |
1002 | Standard_Integer Upper = UK.Upper(); |
1003 | if (Lower < 1 || Lower > uknots->Length() || |
1004 | Upper < 1 || Upper > uknots->Length() ) { |
1005 | Standard_OutOfRange::Raise(); |
1006 | } |
7fd59977 |
1007 | if (Lower > 1) { |
7fd59977 |
1008 | if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) { |
1009 | Standard_ConstructionError::Raise(); |
1010 | } |
1011 | } |
1012 | if (Upper < uknots->Length ()) { |
7fd59977 |
1013 | if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) { |
1014 | Standard_ConstructionError::Raise(); |
1015 | } |
1016 | } |
1017 | Standard_Real K1 = UK (Lower); |
1018 | for (Standard_Integer i = Lower; i <= Upper; i++) { |
1019 | uknots->SetValue (i, UK(i)); |
1020 | if (i != Lower) { |
7fd59977 |
1021 | if (Abs (UK(i) - K1) <= gp::Resolution()) { |
1022 | Standard_ConstructionError::Raise(); |
1023 | } |
1024 | K1 = UK (i); |
1025 | } |
1026 | } |
1027 | |
1028 | maxderivinvok = 0; |
1029 | UpdateUKnots(); |
1030 | } |
1031 | |
1032 | //======================================================================= |
1033 | //function : SetUKnot |
1034 | //purpose : |
1035 | //======================================================================= |
1036 | |
1037 | void Geom_BSplineSurface::SetUKnot |
1038 | (const Standard_Integer UIndex, |
1039 | const Standard_Real K, |
1040 | const Standard_Integer M) |
1041 | { |
1042 | IncreaseUMultiplicity (UIndex, M); |
1043 | SetUKnot (UIndex, K); |
1044 | } |
1045 | |
1046 | //======================================================================= |
1047 | //function : SetVKnot |
1048 | //purpose : |
1049 | //======================================================================= |
1050 | |
1051 | void Geom_BSplineSurface::SetVKnot |
1052 | (const Standard_Integer VIndex, |
1053 | const Standard_Real K) |
1054 | { |
1055 | if (VIndex < 1 || VIndex > vknots->Length()) Standard_OutOfRange::Raise(); |
1056 | Standard_Integer NewIndex = VIndex + vknots->Lower() - 1; |
1057 | Standard_Real DV = Abs(Epsilon (K)); |
1058 | if (VIndex == 1) { |
1059 | if (K >= vknots->Value (2) - DV) { |
1060 | Standard_ConstructionError::Raise(); |
1061 | } |
1062 | } |
1063 | else if (VIndex == vknots->Length()) { |
1064 | if (K <= vknots->Value (vknots->Length()-1) + DV) { |
1065 | Standard_ConstructionError::Raise(); |
1066 | } |
1067 | } |
1068 | else { |
1069 | if (K <= vknots->Value (NewIndex-1) + DV || |
1070 | K >= vknots->Value (NewIndex+1) - DV ) { |
1071 | Standard_ConstructionError::Raise(); |
1072 | } |
1073 | } |
1074 | |
1075 | maxderivinvok = 0; |
1076 | UpdateVKnots(); |
1077 | } |
1078 | |
1079 | //======================================================================= |
1080 | //function : SetVKnots |
1081 | //purpose : |
1082 | //======================================================================= |
1083 | |
1084 | void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) { |
1085 | |
1086 | Standard_Integer Lower = VK.Lower(); |
1087 | Standard_Integer Upper = VK.Upper(); |
1088 | if (Lower < 1 || Lower > vknots->Length() || |
1089 | Upper < 1 || Upper > vknots->Length() ) { |
1090 | Standard_OutOfRange::Raise(); |
1091 | } |
7fd59977 |
1092 | if (Lower > 1) { |
7fd59977 |
1093 | if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) { |
1094 | Standard_ConstructionError::Raise(); |
1095 | } |
1096 | } |
1097 | if (Upper < vknots->Length ()) { |
7fd59977 |
1098 | if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) { |
1099 | Standard_ConstructionError::Raise(); |
1100 | } |
1101 | } |
1102 | Standard_Real K1 = VK (Lower); |
1103 | for (Standard_Integer i = Lower; i <= Upper; i++) { |
1104 | vknots->SetValue (i, VK(i)); |
1105 | if (i != Lower) { |
7fd59977 |
1106 | if (Abs (VK(i) - K1) <= gp::Resolution()) { |
1107 | Standard_ConstructionError::Raise(); |
1108 | } |
1109 | K1 = VK (i); |
1110 | } |
1111 | } |
1112 | |
1113 | maxderivinvok = 0; |
1114 | UpdateVKnots(); |
1115 | } |
1116 | |
1117 | //======================================================================= |
1118 | //function : SetVKnot |
1119 | //purpose : |
1120 | //======================================================================= |
1121 | |
1122 | void Geom_BSplineSurface::SetVKnot |
1123 | (const Standard_Integer VIndex, |
1124 | const Standard_Real K, |
1125 | const Standard_Integer M) |
1126 | { |
1127 | IncreaseVMultiplicity (VIndex, M); |
1128 | SetVKnot (VIndex, K); |
1129 | } |
1130 | |
1131 | //======================================================================= |
1132 | //function : InsertUKnot |
1133 | //purpose : |
1134 | //======================================================================= |
1135 | |
1136 | void Geom_BSplineSurface::InsertUKnot |
1137 | (const Standard_Real U, |
1138 | const Standard_Integer M, |
1139 | const Standard_Real ParametricTolerance, |
1140 | const Standard_Boolean Add) |
1141 | { |
1142 | TColStd_Array1OfReal k(1,1); |
1143 | k(1) = U; |
1144 | TColStd_Array1OfInteger m(1,1); |
1145 | m(1) = M; |
1146 | InsertUKnots(k,m,ParametricTolerance,Add); |
1147 | } |
1148 | |
1149 | //======================================================================= |
1150 | //function : InsertVKnot |
1151 | //purpose : |
1152 | //======================================================================= |
1153 | |
1154 | void Geom_BSplineSurface::InsertVKnot |
1155 | (const Standard_Real V, |
1156 | const Standard_Integer M, |
1157 | const Standard_Real ParametricTolerance, |
1158 | const Standard_Boolean Add) |
1159 | { |
1160 | TColStd_Array1OfReal k(1,1); |
1161 | k(1) = V; |
1162 | TColStd_Array1OfInteger m(1,1); |
1163 | m(1) = M; |
1164 | InsertVKnots(k,m,ParametricTolerance,Add); |
1165 | } |
1166 | |
1167 | //======================================================================= |
1168 | //function : IncrementUMultiplicity |
1169 | //purpose : |
1170 | //======================================================================= |
1171 | |
1172 | void Geom_BSplineSurface::IncrementUMultiplicity |
1173 | (const Standard_Integer FromI1, |
1174 | const Standard_Integer ToI2, |
1175 | const Standard_Integer Step) |
1176 | { |
1177 | Handle(TColStd_HArray1OfReal) tk = uknots; |
1178 | TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2); |
1179 | TColStd_Array1OfInteger m( FromI1, ToI2) ; |
1180 | m.Init(Step); |
1181 | InsertUKnots( k, m, Epsilon(1.)); |
1182 | } |
1183 | |
1184 | //======================================================================= |
1185 | //function : IncrementVMultiplicity |
1186 | //purpose : |
1187 | //======================================================================= |
1188 | |
1189 | void Geom_BSplineSurface::IncrementVMultiplicity |
1190 | (const Standard_Integer FromI1, |
1191 | const Standard_Integer ToI2, |
1192 | const Standard_Integer Step) |
1193 | { |
1194 | Handle(TColStd_HArray1OfReal) tk = vknots; |
1195 | TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2); |
1196 | |
1197 | TColStd_Array1OfInteger m( FromI1, ToI2) ; |
1198 | m.Init(Step); |
1199 | |
1200 | InsertVKnots( k, m, Epsilon(1.)); |
1201 | } |
1202 | |
1203 | //======================================================================= |
1204 | //function : UpdateUKnots |
1205 | //purpose : |
1206 | //======================================================================= |
1207 | |
1208 | void Geom_BSplineSurface::UpdateUKnots() |
1209 | { |
1210 | |
1211 | Standard_Integer MaxKnotMult = 0; |
06be28a4 |
1212 | BSplCLib::KnotAnalysis (udeg, uperiodic, |
7fd59977 |
1213 | uknots->Array1(), |
1214 | umults->Array1(), |
1215 | uknotSet, MaxKnotMult); |
1216 | |
1217 | if (uknotSet == GeomAbs_Uniform && !uperiodic) { |
1218 | ufknots = uknots; |
1219 | } |
1220 | else { |
1221 | ufknots = new TColStd_HArray1OfReal |
1222 | (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic)); |
1223 | |
1224 | BSplCLib::KnotSequence (uknots->Array1(), |
1225 | umults->Array1(), |
1226 | udeg,uperiodic, |
1227 | ufknots->ChangeArray1()); |
1228 | } |
1229 | |
1230 | if (MaxKnotMult == 0) Usmooth = GeomAbs_CN; |
1231 | else { |
1232 | switch (udeg - MaxKnotMult) { |
1233 | case 0 : Usmooth = GeomAbs_C0; break; |
1234 | case 1 : Usmooth = GeomAbs_C1; break; |
1235 | case 2 : Usmooth = GeomAbs_C2; break; |
1236 | case 3 : Usmooth = GeomAbs_C3; break; |
1237 | default : Usmooth = GeomAbs_C3; break; |
1238 | } |
1239 | } |
7fd59977 |
1240 | } |
1241 | |
1242 | //======================================================================= |
1243 | //function : UpdateVKnots |
1244 | //purpose : |
1245 | //======================================================================= |
1246 | |
1247 | void Geom_BSplineSurface::UpdateVKnots() |
1248 | { |
1249 | Standard_Integer MaxKnotMult = 0; |
06be28a4 |
1250 | BSplCLib::KnotAnalysis (vdeg, vperiodic, |
7fd59977 |
1251 | vknots->Array1(), |
1252 | vmults->Array1(), |
1253 | vknotSet, MaxKnotMult); |
1254 | |
1255 | if (vknotSet == GeomAbs_Uniform && !vperiodic) { |
1256 | vfknots = vknots; |
1257 | } |
1258 | else { |
1259 | vfknots = new TColStd_HArray1OfReal |
1260 | (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic)); |
1261 | |
1262 | BSplCLib::KnotSequence (vknots->Array1(), |
1263 | vmults->Array1(), |
1264 | vdeg,vperiodic, |
1265 | vfknots->ChangeArray1()); |
1266 | } |
1267 | |
1268 | if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN; |
1269 | else { |
1270 | switch (vdeg - MaxKnotMult) { |
1271 | case 0 : Vsmooth = GeomAbs_C0; break; |
1272 | case 1 : Vsmooth = GeomAbs_C1; break; |
1273 | case 2 : Vsmooth = GeomAbs_C2; break; |
1274 | case 3 : Vsmooth = GeomAbs_C3; break; |
1275 | default : Vsmooth = GeomAbs_C3; break; |
1276 | } |
1277 | } |
7fd59977 |
1278 | } |
1279 | |
7fd59977 |
1280 | |
1281 | //======================================================================= |
1282 | //function : Normalizes the parameters if the curve is periodic |
1283 | //purpose : that is compute the cache so that it is valid |
1284 | //======================================================================= |
1285 | |
1286 | void Geom_BSplineSurface::PeriodicNormalization |
1287 | (Standard_Real& Uparameter, |
1288 | Standard_Real& Vparameter) const |
1289 | { |
1290 | Standard_Real Period, aMaxVal, aMinVal; |
1291 | |
1292 | if (uperiodic) { |
1293 | aMaxVal = ufknots->Value(ufknots->Upper() - udeg); |
1294 | aMinVal = ufknots->Value (udeg + 1); |
1295 | Standard_Real eps = Abs(Epsilon(Uparameter)); |
1296 | Period = aMaxVal - aMinVal; |
1297 | |
1298 | if(Period <= eps) |
1299 | Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number"); |
1300 | |
9cbe6290 |
1301 | Standard_Boolean isLess, isGreater; |
1302 | isLess = aMinVal - Uparameter > 0; |
1303 | isGreater = Uparameter - aMaxVal > 0; |
1304 | if (isLess || isGreater) { |
1305 | Standard_Real aDPar, aNbPer; |
1306 | aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter); |
1307 | modf(aDPar / Period, &aNbPer); |
1308 | Uparameter += aNbPer * Period; |
7fd59977 |
1309 | } |
1310 | } |
1311 | if (vperiodic) { |
1312 | aMaxVal = vfknots->Value(vfknots->Upper() - vdeg); |
1313 | aMinVal = vfknots->Value (vdeg + 1); |
1314 | Standard_Real eps = Abs(Epsilon(Vparameter)); |
1315 | Period = aMaxVal - aMinVal; |
1316 | |
1317 | if(Period <= eps) |
1318 | Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number"); |
1319 | |
9cbe6290 |
1320 | Standard_Boolean isLess, isGreater; |
1321 | isLess = aMinVal - Vparameter > 0; |
1322 | isGreater = Vparameter - aMaxVal > 0; |
1323 | if (isLess || isGreater) { |
1324 | Standard_Real aDPar, aNbPer; |
1325 | aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter); |
1326 | modf(aDPar / Period, &aNbPer); |
1327 | Vparameter += aNbPer * Period; |
7fd59977 |
1328 | } |
1329 | } |
1330 | } |
1331 | |
7fd59977 |
1332 | //======================================================================= |
1333 | //function : SetWeight |
1334 | //purpose : |
1335 | //======================================================================= |
1336 | |
1337 | void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex, |
1338 | const Standard_Integer VIndex, |
1339 | const Standard_Real Weight) |
1340 | { |
1341 | if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise(); |
1342 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); |
1343 | if (UIndex < 1 || UIndex > Weights.ColLength() || |
1344 | VIndex < 1 || VIndex > Weights.RowLength() ) { |
1345 | Standard_OutOfRange::Raise(); |
1346 | } |
1347 | Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight; |
1348 | Rational(Weights, urational, vrational); |
7fd59977 |
1349 | } |
1350 | |
1351 | //======================================================================= |
1352 | //function : SetWeightCol |
1353 | //purpose : |
1354 | //======================================================================= |
1355 | |
1356 | void Geom_BSplineSurface::SetWeightCol |
1357 | (const Standard_Integer VIndex, |
1358 | const TColStd_Array1OfReal& CPoleWeights) |
1359 | { |
1360 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); |
1361 | if (VIndex < 1 || VIndex > Weights.RowLength()) { |
1362 | Standard_OutOfRange::Raise(); |
1363 | } |
1364 | if (CPoleWeights.Lower() < 1 || |
1365 | CPoleWeights.Lower() > Weights.ColLength() || |
1366 | CPoleWeights.Upper() < 1 || |
1367 | CPoleWeights.Upper() > Weights.ColLength() ) { |
1368 | Standard_ConstructionError::Raise(); |
1369 | } |
1370 | Standard_Integer I = CPoleWeights.Lower(); |
1371 | while (I <= CPoleWeights.Upper()) { |
1372 | if (CPoleWeights(I) <= gp::Resolution()) { |
1373 | Standard_ConstructionError::Raise(); |
1374 | } |
1375 | Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = |
1376 | CPoleWeights (I); |
1377 | I++; |
1378 | } |
1379 | // Verifie si c'est rationnel |
1380 | Rational(Weights, urational, vrational); |
7fd59977 |
1381 | } |
1382 | |
1383 | //======================================================================= |
1384 | //function : SetWeightRow |
1385 | //purpose : |
1386 | //======================================================================= |
1387 | |
1388 | void Geom_BSplineSurface::SetWeightRow |
1389 | (const Standard_Integer UIndex, |
1390 | const TColStd_Array1OfReal& CPoleWeights) |
1391 | { |
1392 | TColStd_Array2OfReal & Weights = weights->ChangeArray2(); |
1393 | if (UIndex < 1 || UIndex > Weights.ColLength()) { |
1394 | Standard_OutOfRange::Raise(); |
1395 | } |
1396 | if (CPoleWeights.Lower() < 1 || |
1397 | CPoleWeights.Lower() > Weights.RowLength() || |
1398 | CPoleWeights.Upper() < 1 || |
1399 | CPoleWeights.Upper() > Weights.RowLength() ) { |
1400 | |
1401 | Standard_ConstructionError::Raise(); |
1402 | } |
1403 | Standard_Integer I = CPoleWeights.Lower(); |
1404 | |
1405 | while (I <= CPoleWeights.Upper()) { |
1406 | if (CPoleWeights(I)<=gp::Resolution()) { |
1407 | Standard_ConstructionError::Raise(); |
1408 | } |
1409 | Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = |
1410 | CPoleWeights (I); |
1411 | I++; |
1412 | } |
1413 | // Verifie si c'est rationnel |
1414 | Rational(Weights, urational, vrational); |
7fd59977 |
1415 | } |
1416 | |