0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / Convert / Convert_GridPolynomialToPoles.cxx
1 // Created on: 1996-07-08
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified:    Fri Oct  3 14:58:05 1997
18 //    by:       Joelle CHAUVET
19 //              Condition d'extraction corrigee
20 //              + positionnement par EvalPoly2Var
21
22 #include <BSplCLib.hxx>
23 #include <BSplSLib.hxx>
24 #include <Convert_GridPolynomialToPoles.hxx>
25 #include <PLib.hxx>
26 #include <Standard_DomainError.hxx>
27 #include <StdFail_NotDone.hxx>
28
29 Convert_GridPolynomialToPoles::
30 Convert_GridPolynomialToPoles(
31                               const Standard_Integer MaxUDegree, 
32                               const Standard_Integer MaxVDegree, 
33                               const Handle(TColStd_HArray1OfInteger)& NumCoeffPerSurface,
34                               const Handle(TColStd_HArray1OfReal)& Coefficients, 
35                               const Handle(TColStd_HArray1OfReal)& PolynomialUIntervals, 
36                               const Handle(TColStd_HArray1OfReal)& PolynomialVIntervals) :
37                               myDone(Standard_False)                          
38 {
39   // Les Controles
40   if ((NumCoeffPerSurface->Lower()!=1 ) || 
41       (NumCoeffPerSurface->Upper()!= 2) )
42     {
43       throw Standard_DomainError("Convert : Wrong Coefficients");
44     } 
45   if ((Coefficients->Lower()!=1 ) || 
46       (Coefficients->Upper()!= 3*(MaxUDegree+1)*(MaxVDegree+1)))
47     {
48       throw Standard_DomainError("Convert : Wrong Coefficients");
49     }  
50
51   // Les Degres
52   myUDegree = NumCoeffPerSurface->Value(1)-1;
53   myVDegree = NumCoeffPerSurface->Value(2)-1;
54
55   if (myUDegree > MaxUDegree) 
56      throw Standard_DomainError("Convert : Incoherence beetween NumCoeffPerSurface and MaxUDegree");
57   if (myVDegree > MaxVDegree) 
58      throw Standard_DomainError("Convert : Incoherence beetween NumCoeffPerSurface and MaxVDegree");
59
60   Handle(TColStd_HArray2OfInteger) NumCoeff = 
61     new (TColStd_HArray2OfInteger)(1, 1, 1, 2);
62   NumCoeff->SetValue(1, 1, NumCoeffPerSurface->Value(1));
63   NumCoeff->SetValue(1, 2, NumCoeffPerSurface->Value(2));
64   
65   Perform (0, 0, 
66            MaxUDegree, MaxVDegree,  
67            NumCoeff,
68            Coefficients,
69            PolynomialUIntervals,
70            PolynomialVIntervals,
71            PolynomialUIntervals,
72            PolynomialVIntervals);
73 }
74
75 Convert_GridPolynomialToPoles::
76 Convert_GridPolynomialToPoles(
77                               const Standard_Integer NbUSurfaces,
78                               const Standard_Integer NbVSurfaces, 
79                               const Standard_Integer UContinuity, 
80                               const Standard_Integer VContinuity,
81                               const Standard_Integer MaxUDegree,
82                               const Standard_Integer MaxVDegree,
83                               const Handle(TColStd_HArray2OfInteger)& NumCoeffPerSurface,
84                               const Handle(TColStd_HArray1OfReal)& Coefficients,
85                               const Handle(TColStd_HArray1OfReal)& PolynomialUIntervals,
86                               const Handle(TColStd_HArray1OfReal)& PolynomialVIntervals,
87                               const Handle(TColStd_HArray1OfReal)& TrueUIntervals,
88                               const Handle(TColStd_HArray1OfReal)& TrueVIntervals) :
89                               myDone(Standard_False)
90 {
91   Standard_Integer ii;
92   Standard_Integer RealUDegree = Max(MaxUDegree, 2*UContinuity + 1);
93   Standard_Integer RealVDegree = Max(MaxVDegree, 2*VContinuity + 1);
94   myUDegree = 0;
95   myVDegree = 0;
96   
97   // Les controles
98   if((NumCoeffPerSurface->LowerRow()!=1) || 
99      (NumCoeffPerSurface->UpperRow()!=NbUSurfaces*NbVSurfaces) ||
100      (NumCoeffPerSurface->LowerCol()!=1) || 
101      (NumCoeffPerSurface->UpperCol()!=2) )
102     {
103       throw Standard_DomainError("Convert : Wrong NumCoeffPerSurface");
104     }
105
106   if ((Coefficients->Lower()!=1 ) || 
107       (Coefficients->Upper()!= 3*NbUSurfaces*NbVSurfaces*
108        (RealUDegree + 1) * (RealVDegree + 1)) )
109     {
110       throw Standard_DomainError("Convert : Wrong Coefficients");
111     }
112      
113   // Calcul des degree
114   for (ii=1; ii<=NbUSurfaces*NbVSurfaces; ii++) {
115     if (NumCoeffPerSurface->Value(ii,1) > myUDegree+1) 
116       myUDegree = NumCoeffPerSurface->Value(ii,1)-1;
117     if (NumCoeffPerSurface->Value(ii,2) > myVDegree+1) 
118       myVDegree = NumCoeffPerSurface->Value(ii,2)-1;
119   }
120
121   if (myUDegree > RealUDegree) 
122      throw Standard_DomainError("Convert : Incoherence beetween NumCoeffPerSurface and MaxUDegree");
123   if (myVDegree > RealVDegree) 
124      throw Standard_DomainError("Convert : Incoherence beetween NumCoeffPerSurface and MaxVDegree");
125
126   Perform (UContinuity, VContinuity, 
127            RealUDegree, RealVDegree,
128            NumCoeffPerSurface,
129            Coefficients,
130            PolynomialUIntervals,
131            PolynomialVIntervals,
132            TrueUIntervals,
133            TrueVIntervals);
134 }
135
136 void Convert_GridPolynomialToPoles::Perform(const Standard_Integer UContinuity,
137                                             const Standard_Integer VContinuity,
138                                             const Standard_Integer MaxUDegree, 
139                                             const Standard_Integer MaxVDegree,
140                                             const Handle(TColStd_HArray2OfInteger)& NumCoeffPerSurface,
141                                             const Handle(TColStd_HArray1OfReal)& Coefficients,
142                                             const Handle(TColStd_HArray1OfReal)& PolynomialUIntervals,
143                                             const Handle(TColStd_HArray1OfReal)& PolynomialVIntervals,
144                                             const Handle(TColStd_HArray1OfReal)& TrueUIntervals,
145                                             const Handle(TColStd_HArray1OfReal)& TrueVIntervals)
146 {
147  // (1) Construction des Tables monodimensionnelles ----------------------------
148     Handle(TColStd_HArray1OfReal) UParameters, VParameters;
149     myUKnots = new (TColStd_HArray1OfReal) (1,  TrueUIntervals->Length());
150     myUKnots->ChangeArray1() =  TrueUIntervals->Array1();
151     myVKnots = new (TColStd_HArray1OfReal) (1,  TrueVIntervals->Length());
152     myVKnots->ChangeArray1() = TrueVIntervals->Array1();
153
154     BuildArray( myUDegree,
155                 myUKnots,
156                 UContinuity,
157                 myUFlatKnots,
158                 myUMults, 
159                 UParameters);
160
161     BuildArray( myVDegree,
162                 myVKnots,
163                 VContinuity,
164                 myVFlatKnots,
165                 myVMults, 
166                 VParameters);
167
168  // (2) Digitalisation -------------------------------------------------------
169
170    Standard_Integer ii, jj, Uindex=0, Vindex=0;
171    Standard_Integer Patch_Indice=0;
172    Standard_Real NValue, UValue, VValue;
173    Standard_Integer dimension = 3*( myVDegree+1);
174    Standard_Integer SizPatch = 3 * (MaxUDegree+1) * (MaxVDegree+1);
175    myPoles = new (TColgp_HArray2OfPnt) (1, UParameters->Length(), 
176                                         1, VParameters->Length());
177
178    TColStd_Array1OfReal Patch(1, (myUDegree+1)*dimension);
179    TColStd_Array1OfReal Point(1, 3); 
180    Standard_Real * Coeffs =  (Standard_Real *) &Patch.ChangeValue(1);
181    Standard_Real * Digit  =  (Standard_Real *) &Point.ChangeValue(1);
182
183    for (ii=1, Uindex=1; ii<=UParameters->Length(); ii++) {
184
185      while (UParameters->Value(ii) > TrueUIntervals->Value(Uindex+1) 
186             &&  Uindex < myUKnots->Length()-1) { Uindex++; }
187
188      NValue = (UParameters->Value(ii) - TrueUIntervals->Value(Uindex) )
189             / (TrueUIntervals->Value(Uindex+1) - TrueUIntervals->Value(Uindex));
190      UValue = (1-NValue) *  PolynomialUIntervals->Value(1) 
191             + NValue * PolynomialUIntervals->Value(2) ;
192     
193     for (jj=1, Vindex=1; jj<=VParameters->Length(); jj++) {
194       
195       while (VParameters->Value(jj) > TrueVIntervals->Value(Vindex+1) 
196              && Vindex < myVKnots->Length()-1) { Vindex++; }
197
198       NValue = (VParameters->Value(jj) - TrueVIntervals->Value(Vindex) )
199              / (TrueVIntervals->Value(Vindex+1) - TrueVIntervals->Value(Vindex));
200       VValue = (1-NValue) *  PolynomialVIntervals->Value(1) 
201              + NValue * PolynomialVIntervals->Value(2) ;
202
203       // (2.1) Extraction du bon Patch
204       if (Patch_Indice != Uindex + (myUKnots->Length()-1)*(Vindex-1)) {
205         Standard_Integer k1, k2, pos, ll=1;
206         Patch_Indice = Uindex + (myUKnots->Length()-1)*(Vindex-1);
207         for (k1 = 1; k1 <= NumCoeffPerSurface->Value(Patch_Indice, 1); k1++) {
208           pos = SizPatch*(Patch_Indice-1)+3*(MaxVDegree+1)*(k1-1)+1;
209           for (k2 = 1; 
210                k2 <= NumCoeffPerSurface->Value(Patch_Indice, 2); 
211                k2++, pos+=3 ) {
212             Patch(ll)   =  Coefficients->Value(pos);
213             Patch(ll+1) =  Coefficients->Value(pos+1);
214             Patch(ll+2) =  Coefficients->Value(pos+2);
215             ll += 3;
216           }
217         }
218       }
219
220       // (2.2) Positionnement en UValue,VValue
221       PLib::EvalPoly2Var(UValue,VValue,0,0,
222                          NumCoeffPerSurface->Value(Patch_Indice,1)-1,
223                          NumCoeffPerSurface->Value(Patch_Indice,2)-1,  
224                          3,
225                          Coeffs[0],
226                          Digit[0]);
227
228       myPoles->SetValue(ii, jj, gp_Pnt (Digit[0], Digit[1], Digit[2]));
229     }
230    }
231
232
233  // (3)Interpolation --------------------------------------------------------------
234
235   Standard_Integer InversionProblem;
236   BSplSLib::Interpolate(myUDegree, myVDegree, 
237                         myUFlatKnots->Array1(),
238                         myVFlatKnots->Array1(),
239                         UParameters->Array1(), 
240                         VParameters->Array1(),
241                         myPoles->ChangeArray2(),
242                         InversionProblem);
243   myDone = (InversionProblem == 0);  
244 }
245
246
247 void  Convert_GridPolynomialToPoles::BuildArray(const Standard_Integer Degree,
248                                                 const Handle(TColStd_HArray1OfReal)& Knots,
249                                                 const Standard_Integer Continuity,
250                                                 Handle(TColStd_HArray1OfReal)& FlatKnots,
251                                                 Handle(TColStd_HArray1OfInteger)& Mults, 
252                                                 Handle(TColStd_HArray1OfReal)& Parameters) const
253 {
254  Standard_Integer NumCurves =  Knots->Length()-1;
255
256  // Calcul des Multiplicites
257  Standard_Integer ii;
258  Standard_Integer multiplicities = Degree - Continuity;
259  Mults = new (TColStd_HArray1OfInteger)(1, Knots->Length());
260
261  for (ii = 2 ; ii < Knots->Length() ; ii++) {
262    Mults ->SetValue(ii,multiplicities) ;
263  }
264  Mults ->SetValue(1, Degree + 1) ;
265  Mults ->SetValue(NumCurves + 1, Degree + 1) ;
266
267  // Calcul des Noeuds Plats
268  Standard_Integer num_flat_knots = multiplicities * (NumCurves - 1) 
269                                  +  2 * Degree + 2;
270  FlatKnots =
271  new TColStd_HArray1OfReal(1,num_flat_knots) ;
272
273  BSplCLib::KnotSequence (Knots->Array1(), 
274                          Mults->Array1(),
275                          Degree,
276                          Standard_False,
277                          FlatKnots->ChangeArray1());
278
279  // Calcul du nombre de Poles
280  Standard_Integer num_poles = num_flat_knots - Degree - 1;
281
282  // Cacul des parametres d'interpolation
283  Parameters = new (TColStd_HArray1OfReal) (1,num_poles);
284  BSplCLib::BuildSchoenbergPoints(Degree,
285                                  FlatKnots->Array1(),
286                                  Parameters->ChangeArray1());  
287 }
288
289 Standard_Integer Convert_GridPolynomialToPoles::NbUPoles() const 
290 {
291  StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
292  return  myPoles->ColLength(); 
293 }
294
295 Standard_Integer Convert_GridPolynomialToPoles::NbVPoles() const 
296 {
297  StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
298  return  myPoles->RowLength(); 
299 }
300
301
302 const Handle(TColgp_HArray2OfPnt)& 
303 Convert_GridPolynomialToPoles::Poles() const 
304 {
305  StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
306  return myPoles; 
307 }
308
309 Standard_Integer Convert_GridPolynomialToPoles::UDegree() const 
310 {
311  StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
312  return  myUDegree;
313 }
314
315 Standard_Integer Convert_GridPolynomialToPoles::VDegree() const 
316 {
317   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
318   return  myVDegree;
319 }
320
321 Standard_Integer Convert_GridPolynomialToPoles::NbUKnots() const 
322 {
323  StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
324  return myUKnots->Length();
325 }
326
327 Standard_Integer Convert_GridPolynomialToPoles::NbVKnots() const 
328 {
329   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
330   return myVKnots->Length();
331 }
332
333 const Handle(TColStd_HArray1OfReal)&  
334 Convert_GridPolynomialToPoles::UKnots() const 
335 {
336   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
337   return myUKnots;
338 }
339
340 const Handle(TColStd_HArray1OfReal)& 
341 Convert_GridPolynomialToPoles::VKnots() const 
342 {
343   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
344   return myVKnots;
345 }
346
347 const Handle(TColStd_HArray1OfInteger)& 
348 Convert_GridPolynomialToPoles::UMultiplicities() const 
349 {
350   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
351   return myUMults;
352 }
353
354 const Handle(TColStd_HArray1OfInteger)& 
355 Convert_GridPolynomialToPoles::VMultiplicities() const 
356 {
357   StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
358   return myVMults;
359 }
360
361 Standard_Boolean Convert_GridPolynomialToPoles::IsDone() const 
362 {
363   return myDone;
364 }