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