0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / GeomConvert / GeomConvert_CompBezierSurfacesToBSplineSurface.cxx
CommitLineData
b311480e 1// Created on: 1996-06-07
2// Created by: Philippe MANGIN
3// Copyright (c) 1996-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
7fd59977 18#include <Geom_BezierSurface.hxx>
42cf5bc1 19#include <Geom_BSplineSurface.hxx>
7fd59977 20#include <Geom_Curve.hxx>
42cf5bc1 21#include <GeomConvert_CompBezierSurfacesToBSplineSurface.hxx>
7fd59977 22#include <gp_Pnt.hxx>
23#include <gp_Vec.hxx>
42cf5bc1 24#include <gp_XYZ.hxx>
7fd59977 25#include <Precision.hxx>
42cf5bc1 26#include <Standard_ConstructionError.hxx>
27#include <Standard_DimensionError.hxx>
28#include <Standard_NotImplemented.hxx>
29#include <TColGeom_Array2OfBezierSurface.hxx>
30#include <TColgp_HArray2OfPnt.hxx>
31#include <TColStd_HArray1OfReal.hxx>
7fd59977 32
33// ============================================================================
34GeomConvert_CompBezierSurfacesToBSplineSurface::
35GeomConvert_CompBezierSurfacesToBSplineSurface(const TColGeom_Array2OfBezierSurface& Beziers)
36// ============================================================================
37{
38 Standard_Integer ii;
39 myDone = Standard_True;
40 // Choix des noeuds
41 myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
42 for (ii=0; ii<myUKnots->Length(); ii++) { myUKnots->SetValue(ii+1, ii); }
43
44 myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
45 for (ii=0; ii<myVKnots->Length(); ii++) { myVKnots->SetValue(ii+1, ii); }
46
47 // Calcul des Poles
48 Perform(Beziers);
49}
50
51
52// ============================================================================
53GeomConvert_CompBezierSurfacesToBSplineSurface::
54GeomConvert_CompBezierSurfacesToBSplineSurface(
55 const TColGeom_Array2OfBezierSurface& Beziers,
56 const Standard_Real Tolerance,
57 const Standard_Boolean RemoveKnots)
58// ============================================================================
59{
60 Standard_Integer ii, jj, multU=0, multV, minus;
61 Standard_Boolean Ok;
62 gp_Vec vec;
63 Standard_Real V1, V2, V3, Ratio, L1, L2, Tol, val;
64 gp_Pnt P1, P2, P3;
65 Handle(Geom_Curve) FirstCurve, SecondCurve;
66
67 myDone = Standard_True;
68
69 // Choix des noeuds
70
71 myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
72 myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
73
74 // --> en U
75 myUKnots->SetValue(1, 0);
76 jj = myVKnots->Length()/2;
77 FirstCurve = Beziers(1, jj)->VIso(0.3);
78 FirstCurve->D0(0, P1);
79 FirstCurve->D0(0.5, P2);
80 FirstCurve->D1(1, P3, vec);
81
82 L1 = P1.Distance(P2) + P2.Distance(P3);
83 myUKnots->SetValue(2, L1);
84
85 V1 = vec.Magnitude();
86 // si la Parametrisation est trop bizzare on garde la pseudo-longueur
87 if ((V1 > 1000 * L1) || (V1 < L1 * 1.e-3)) V1 = L1;
88
89 for (ii=2; ii<myUKnots->Length(); ii++) {
90
91 SecondCurve = Beziers(ii, jj)->VIso(0.3);
92 SecondCurve->D1(0, P1, vec);
93 V2 = vec.Magnitude();
94 SecondCurve->D0(0.5, P2);
95 SecondCurve->D1(1, P3, vec);
96 V3 = vec.Magnitude();
97 L2 = P1.Distance(P2) + P2.Distance(P3);
98
99 // On calcul le ratio, en evitant les cas tordus...
100 if ((V2 > 1000 * L2) || (V2 < L2 * 1.e-3)) V2 = L2;
101 if ((V3 > 1000 * L2) || (V3 < L2 * 1.e-3)) V3 = L2;
102
103 Ratio = 1;
104 if ( (V1 > Precision::Confusion()) && (V2 > Precision::Confusion()) ) {
105 Ratio = V2 / V1;
106 }
107 if ( (Ratio < Precision::Confusion())
108 || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
109
110 // On en deduit un nouveau noeud
111 val = myUKnots->Value(ii);
112 myUKnots->SetValue(ii+1, val + Ratio*(val- myUKnots->Value(ii-1)) );
113
114 // Et c'est reparti, pour un tour
115 L1 = L2;
116 V1 = V3;
117 FirstCurve = SecondCurve;
118 }
119
120 // --> en V
121 myVKnots->SetValue(1, 0);
122 ii = myUKnots->Length()/2;
123 FirstCurve = Beziers(ii, 1)->UIso(0.3);
124 FirstCurve->D0(0, P1);
125 FirstCurve->D0(0.5, P2);
126 FirstCurve->D1(1, P3, vec);
127
128 L1 = P1.Distance(P2) + P2.Distance(P3);
129 myVKnots->SetValue(2, L1);
130
131 V1 = vec.Magnitude();
132 // si la Parametrisation est trop bizzare on garde la pseudo-longueur
133 if ((V1 > 1000 * L1) || (V1 < L1 * 1.e-3)) V1 = L1;
134
135 for (jj=2; jj<myVKnots->Length(); jj++) {
136
137 SecondCurve = Beziers(ii, jj)->UIso(0.3);
138 SecondCurve->D1(0, P1, vec);
139 V2 = vec.Magnitude();
140 SecondCurve->D0(0.5, P2);
141 SecondCurve->D1(1, P3, vec);
142 V3 = vec.Magnitude();
143 L2 = P1.Distance(P2) + P2.Distance(P3);
144
145 // On calcul le ratio, en evitant les cas tordus...
146 if ((V2 > 1000 * L2) || (V2 < L2 * 1.e-3)) V2 = L2;
147 if ((V3 > 1000 * L2) || (V3 < L2 * 1.e-3)) V3 = L2;
148
149 Ratio = 1;
150 if ( (V1 > Precision::Confusion()) && (V2 > Precision::Confusion()) ) {
151 Ratio = V2 / V1;
152 }
153 if ( (Ratio < Precision::Confusion())
154 || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
155
156 // On en deduit un nouveau noeud
157 val = myVKnots->Value(jj);
158 myVKnots->SetValue(jj+1, val + Ratio*(val-myVKnots->Value(jj-1)) );
159
160 // Et c'est reparti, pour un tour
161 L1 = L2;
162 V1 = V3;
163 FirstCurve = SecondCurve;
164 }
165
166 // Calcul des Poles
167 Perform(Beziers);
168
169 // Reduction de la multiplicite
170 Handle(Geom_BSplineSurface) Surface = new (Geom_BSplineSurface)
171 (myPoles->Array2(),
172 myUKnots->Array1(),
173 myVKnots->Array1(),
174 myUMults->Array1(),
175 myVMults->Array1(),
176 myUDegree,
177 myVDegree);
178
179 if (RemoveKnots) minus = 0;
180 else minus = 1;
181
182 for (ii=myUKnots->Length()-1; ii>1; ii--) {
183 Ok=Standard_True;
184 Tol = Tolerance/2;
185 multU = myUMults->Value(ii)-1;
186 for ( ; Ok && multU > minus; multU--, Tol/=2) {
187 Ok = Surface->RemoveUKnot(ii, multU, Tol);
188 }
189 }
190
191 for (ii=myVKnots->Length()-1; ii>1; ii--) {
192 Ok=Standard_True;
193 Tol = Tolerance/2;
194 multV = myVMults->Value(ii)-1;
195 for ( ; Ok && multU > minus; multV--, Tol/=2) {
196 Ok = Surface->RemoveVKnot(ii, multV, Tol);
197 }
198 }
199
200 // Les nouveaux champs sont arrivees ....
201 myPoles = new (TColgp_HArray2OfPnt) (1, Surface->NbUPoles(), 1, Surface->NbVPoles());
202 Surface->Poles( myPoles->ChangeArray2());
203
204 myUMults = new (TColStd_HArray1OfInteger) (1, Surface->NbUKnots());
205 myVMults = new (TColStd_HArray1OfInteger) (1, Surface->NbVKnots());
206 myUKnots = new (TColStd_HArray1OfReal) (1, Surface->NbUKnots());
207 myVKnots = new (TColStd_HArray1OfReal) (1, Surface->NbVKnots());
208
209
210 Surface->UMultiplicities( myUMults->ChangeArray1());
211 Surface->VMultiplicities( myVMults->ChangeArray1());
212 Surface->UKnots( myUKnots->ChangeArray1());
213 Surface->VKnots( myVKnots->ChangeArray1());
214}
215
216// ============================================================================
217GeomConvert_CompBezierSurfacesToBSplineSurface::
218GeomConvert_CompBezierSurfacesToBSplineSurface(
219 const TColGeom_Array2OfBezierSurface& Beziers,
220 const TColStd_Array1OfReal& UKnots,
221 const TColStd_Array1OfReal& VKnots,
222 const GeomAbs_Shape UContinuity,
223 const GeomAbs_Shape VContinuity,
224 const Standard_Real Tolerance)
225// ============================================================================
226{
227 Standard_Integer decu=0, decv=0;
228 Standard_Boolean Ok;
229
230 myDone = Standard_True;
231
232 // Recuperation des noeuds
233 myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
234 myUKnots->ChangeArray1() = UKnots;
235
236 myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
237 myVKnots->ChangeArray1() = VKnots;
238
239 // Calcul des Poles
240 Perform(Beziers);
241
242 // Obtention des bonne continuitee
243
244 switch ( UContinuity ) {
245 case GeomAbs_C0 :
246 decu = 0;
247 break;
248 case GeomAbs_C1 :
249 decu = 1;
250 break;
251 case GeomAbs_C2 :
252 decu = 2;
253 break;
254 case GeomAbs_C3 :
255 decu = 3;
256 break;
257 default:
9775fa61 258 throw Standard_ConstructionError(
7fd59977 259 "GeomConvert_CompBezierSurfacesToBSpl:: UContinuity error");
260 }
261
262 switch ( VContinuity ) {
263 case GeomAbs_C0 :
264 decv = 0;
265 break;
266 case GeomAbs_C1 :
267 decv = 1;
268 break;
269 case GeomAbs_C2 :
270 decv = 2;
271 break;
272 case GeomAbs_C3 :
273 decv = 3;
274 break;
275 default:
9775fa61 276 throw Standard_ConstructionError(
7fd59977 277 "GeomConvert_CompBezierSurfacesToBSpl:: VContinuity error");
278 }
279
280
281 if ( (decu>0) || (decv>0) ) {
282
283 Standard_Integer ii;
284 Standard_Integer multU = myUDegree - decu;
285 Standard_ConstructionError_Raise_if(
286 ((multU <= 0) && (myUKnots->Length()>2)) ,
287 "GeomConvert_CompBezierSurfacesToBSpl:: UContinuity or Udeg error");
288
289 Standard_Integer multV = myVDegree - decv;
290 Standard_ConstructionError_Raise_if(
291 ((multV <= 0) && (myVKnots->Length()>2)) ,
292 "GeomConvert_CompBezierSurfacesToBSpl:: VContinuity or Vdeg error");
293
294 Handle(Geom_BSplineSurface) Surface = new (Geom_BSplineSurface)
295 (myPoles->Array2(),
296 myUKnots->Array1(),
297 myVKnots->Array1(),
298 myUMults->Array1(),
299 myVMults->Array1(),
300 myUDegree,
301 myVDegree);
302
303
304 if (decu>0) {
305 for (ii=2; ii<myUKnots->Length(); ii++) {
306 Ok = Surface->RemoveUKnot(ii, multU, Tolerance);
307 if (!Ok) {myDone = Ok;}
308 }
309 }
310
311 if (decv>0) {
312 for (ii=2; ii<myVKnots->Length(); ii++) {
313 Ok = Surface->RemoveVKnot(ii, multV, Tolerance);
314 if (!Ok) {myDone = Ok;}
315 }
316 }
317
318 // Les nouveaux champs sont arrivees ....
319 myPoles = new (TColgp_HArray2OfPnt) (1, Surface->NbUPoles(), 1, Surface->NbVPoles());
320 Surface->Poles( myPoles->ChangeArray2());
321 Surface->UMultiplicities( myUMults->ChangeArray1());
322 Surface->VMultiplicities( myVMults->ChangeArray1());
323 }
324}
325
326
327// ================================================================================
328void GeomConvert_CompBezierSurfacesToBSplineSurface::Perform(
329 const TColGeom_Array2OfBezierSurface& Beziers)
330// ================================================================================
331{
332 Standard_Integer IU, IV;
333
334 // (1) Determination des degrees et si le resultat est rationnel.
335 isrational = Standard_False;
336 myUDegree = 1;
337 myVDegree = 1;
338
339 for (IU=Beziers.LowerRow(); IU <=Beziers.UpperRow(); IU++) {
340 for (IV=Beziers.LowerCol(); IV <=Beziers.UpperCol(); IV++) {
341 if ( Beziers(IU, IV)-> IsURational()
342 || Beziers(IU, IV)-> IsVRational()) { isrational = Standard_True;}
343
344 myUDegree = ( Beziers(IU, IV)->UDegree() > myUDegree ) ?
345 Beziers(IU, IV)->UDegree() : myUDegree;
346
347 myVDegree = ( Beziers(IU, IV)->VDegree() > myVDegree ) ?
348 Beziers(IU, IV)->VDegree() : myVDegree;
349 }
350 }
351
352 Standard_NotImplemented_Raise_if(isrational,
353 "CompBezierSurfacesToBSpl : rational !");
354
355
356 // (2) Boucle sur les carreaux -----------------------------
357
358 Handle(Geom_BezierSurface) Patch;
359 Standard_Integer UIndex, VIndex, uindex, vindex, udeb, vdeb;
360 Standard_Integer upol, vpol, ii;
361
362
363 myPoles = new (TColgp_HArray2OfPnt)
364 ( 1, (myUDegree+1)*Beziers.ColLength() - myUKnots->Length() + 2 ,
365 1, (myVDegree+1)*Beziers.RowLength() - myVKnots->Length() + 2 );
366
367 for (IU=Beziers.LowerRow(); IU <=Beziers.UpperRow(); IU++) {
368 UIndex = (IU-1)*myUDegree + 1;
369 for (IV=Beziers.LowerCol(); IV <=Beziers.UpperCol(); IV++) {
370
371 Patch = Beziers(IU, IV);
372 VIndex = (IV-1)*myVDegree + 1;
373
374 // (2.1) Augmentation du degree
375 Patch->Increase(myUDegree, myVDegree);
376
377 // (2.2) Poles a recopier
378 if (IU==1) {udeb = 1;}
379 else {udeb = 2;}
380 if (IV==1) {vdeb = 1;}
381 else {vdeb = 2;}
382
383 uindex = UIndex + udeb -1;
384
385 for (upol = udeb; upol <= myUDegree+1; upol++, uindex++ ) {
386 vindex = VIndex + vdeb - 1;
387 for (vpol = vdeb; vpol <= myVDegree+1; vpol++, vindex++) {
388 myPoles->ChangeValue(uindex, vindex) = Patch->Pole(upol, vpol);
389 }
390 }
391
392 // (2.3) Poles a sommer
393 if (udeb==2) {
394 vindex = VIndex + vdeb - 1;
395 for (vpol = vdeb; vpol <= myVDegree+1; vpol++, vindex++) {
396 myPoles->ChangeValue(UIndex, vindex).ChangeCoord() +=
397 Patch->Pole(1, vpol).Coord();
398 }
399 }
400
401 if (vdeb==2) {
402 uindex = UIndex + udeb - 1;
403 for (upol = udeb; upol <= myUDegree+1; upol++, uindex++) {
404 myPoles->ChangeValue(uindex, VIndex).ChangeCoord() +=
405 Patch->Pole(upol, 1).Coord();
406 }
407 }
408
409 if (udeb==2 && vdeb==2) {
410 myPoles->ChangeValue(UIndex, VIndex).ChangeCoord() +=
411 Patch->Pole(1, 1).Coord();
412 }
413 }
414 }
415
416 // (3) Elimination des redondances
417 // car dans la boucle precedente on compte :
418 // - 2 fois les poles associes aux noeuds simples
419 // - 4 fois les poles associes aux doubles noeuds (en U et V)
420
421 // (3.1) Elimination en U
422 for ( UIndex = myUDegree+1, ii=2;
423 ii< myUKnots->Length();
424 ii++, UIndex+=myUDegree) {
425 for (vpol = 1; vpol<=myPoles->UpperCol(); vpol++) {
426 myPoles->ChangeValue(UIndex, vpol).ChangeCoord() *= 0.5;
427 }
428 }
429
430 // (3.2) Elimination en V
431 for ( VIndex = myVDegree+1, ii=2;
432 ii< myVKnots->Length();
433 ii++, VIndex += myVDegree) {
434 for (upol = 1; upol<=myPoles->UpperRow(); upol++) {
435 myPoles->ChangeValue(upol, VIndex).ChangeCoord() *= 0.5;
436 }
437 }
438
439 // (4) Init des multiplicites
440 myUMults = new (TColStd_HArray1OfInteger) (1, myUKnots->Length());
441 myUMults->Init( myUDegree);
442 myUMults->SetValue(1, myUDegree+1);
443 myUMults->SetValue( myUMults->Upper(), myUDegree+1);
444
445 myVMults = new (TColStd_HArray1OfInteger) (1, myVKnots->Length());
446 myVMults->Init( myVDegree);
447 myVMults->SetValue(1, myVDegree+1);
448 myVMults->SetValue(myVMults->Upper(), myVDegree+1);
449}
450
451// ========================================================================
452Standard_Boolean GeomConvert_CompBezierSurfacesToBSplineSurface::IsDone() const
453// ========================================================================
454{
455 return myDone;
456}
457