0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / Convert / Convert_CompPolynomialToPoles.cxx
1 // Created on: 1995-05-30
2 // Created by: Xavier BENVENISTE
3 // Copyright (c) 1995-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 // 19-06-96 : JPI : NbPoles doit utiliser  ColLength() au lieu de RowLength()
18 // 16-09-96 : PMN : On ne doit pas se soucier de la continuite lorsqu'il n'y
19 //                  qu'un seul segment(PRO5474).
20 // 11-12-96 : PMN : Respect de l'indicage des tableaux passer en arguments 
21 //                  TrueIntervals et PolynomialIntervals (BUC40077)
22 // 15-04-97 : PMN : Constructeurs avec un seul segement ou differentes 
23 //                  continuitees. 
24
25 #define No_Standard_OutOfRange
26
27
28 #include <BSplCLib.hxx>
29 #include <Convert_CompPolynomialToPoles.hxx>
30 #include <PLib.hxx>
31 #include <Standard_ConstructionError.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <TColStd_Array1OfInteger.hxx>
34 #include <TColStd_Array1OfReal.hxx>
35 #include <TColStd_HArray1OfInteger.hxx>
36 #include <TColStd_HArray1OfReal.hxx>
37
38 //=======================================================================
39 //function : Constructor
40 //purpose  : 
41 //=======================================================================
42 Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
43     const Standard_Integer                 NumCurves,
44     const Standard_Integer                 Continuity, 
45     const Standard_Integer                 Dimension, 
46     const Standard_Integer                 MaxDegree, 
47     const Handle(TColStd_HArray1OfInteger)& NumCoeffPerCurve, 
48     const Handle(TColStd_HArray1OfReal)&    Coefficients,    
49     const Handle(TColStd_HArray2OfReal)&    PolynomialIntervals, 
50     const Handle(TColStd_HArray1OfReal)&    TrueIntervals)
51      : myDone(Standard_False) 
52 {
53  Standard_Integer ii, delta;
54  if (NumCurves <= 0               ||
55      NumCoeffPerCurve.IsNull()    ||
56      Coefficients.IsNull()        ||
57      PolynomialIntervals.IsNull() ||
58      TrueIntervals.IsNull()       || 
59      Continuity < 0               ||
60      MaxDegree  <= 0              ||
61      Dimension  <= 0              ||
62      PolynomialIntervals->RowLength() != 2) {
63    throw Standard_ConstructionError
64    ("Convert_CompPolynomialToPoles:bad arguments");
65  } 
66  myDegree = 0 ;
67
68  delta = NumCurves - 1 ;
69  for (ii =  NumCoeffPerCurve->Lower(); 
70       ii <= NumCoeffPerCurve->Lower() + delta ;
71       ii++) {
72    myDegree = Max(NumCoeffPerCurve->Value(ii)-1,myDegree) ;
73  }
74  if ((Continuity > myDegree)&& (NumCurves>1)) {
75    throw Standard_ConstructionError
76    ("Convert_CompPolynomialToPoles:Continuity is too great");
77  } 
78 //
79 //  prepare output
80 //
81  Standard_Integer Tindex, multiplicities ;
82
83  myKnots = 
84  new TColStd_HArray1OfReal(1, NumCurves + 1) ;
85  for (ii = 1, Tindex = TrueIntervals->Lower() ; 
86       ii <=  NumCurves + 1 ; ii++,Tindex++ ) {
87     myKnots->ChangeArray1().SetValue(ii,TrueIntervals->Value(Tindex)) ;
88   }
89
90  multiplicities = myDegree - Continuity ;
91  myMults =
92  new TColStd_HArray1OfInteger(1, NumCurves + 1) ;
93  for (ii = 2 ; ii < NumCurves + 1 ; ii++) {
94    myMults -> SetValue(ii,multiplicities);
95  }
96  myMults -> SetValue(1, myDegree + 1) ;
97  myMults -> SetValue(NumCurves + 1, myDegree + 1) ;
98
99  Perform(NumCurves, MaxDegree, Dimension,
100          NumCoeffPerCurve->Array1(), Coefficients->Array1(),
101          PolynomialIntervals->Array2(), TrueIntervals->Array1());
102 }
103
104 Convert_CompPolynomialToPoles::
105 Convert_CompPolynomialToPoles(const Standard_Integer NumCurves,
106                               const Standard_Integer Dimension,
107                               const Standard_Integer MaxDegree,
108                               const TColStd_Array1OfInteger& Continuity,
109                               const TColStd_Array1OfInteger& NumCoeffPerCurve,
110                               const TColStd_Array1OfReal& Coefficients,
111                               const TColStd_Array2OfReal& PolynomialIntervals,
112                               const TColStd_Array1OfReal& TrueIntervals)
113                               : myDone(Standard_False) 
114 {
115  Standard_Integer ii, delta;
116  if (NumCurves <= 0               ||
117      MaxDegree  <= 0              ||
118      Dimension  <= 0              ||
119      PolynomialIntervals.RowLength() != 2) {
120    throw Standard_ConstructionError
121    ("Convert_CompPolynomialToPoles:bad arguments");
122  } 
123  myDegree = 0 ;
124
125  delta = NumCurves - 1 ;
126  for (ii =  NumCoeffPerCurve.Lower(); 
127       ii <= NumCoeffPerCurve.Lower() + delta ;
128       ii++) {
129    myDegree = Max(NumCoeffPerCurve.Value(ii)-1,myDegree) ;
130  }
131 //
132 //  prepare output
133 //
134  Standard_Integer Tindex ;
135
136  myKnots = 
137  new TColStd_HArray1OfReal(1, NumCurves + 1) ;
138  for (ii = 1, Tindex = TrueIntervals.Lower() ; 
139       ii <=  NumCurves + 1 ; ii++,Tindex++ ) {
140     myKnots->ChangeArray1().SetValue(ii,TrueIntervals.Value(Tindex)) ;
141   }
142
143  myMults =
144  new TColStd_HArray1OfInteger(1, NumCurves + 1) ;
145  for (ii = 2 ; ii < NumCurves + 1 ; ii++) {
146    if ((Continuity(ii) > myDegree)&& (NumCurves>1)) {
147      throw Standard_ConstructionError
148      ("Convert_CompPolynomialToPoles:Continuity is too great");
149    }
150
151    myMults -> SetValue(ii, myDegree-Continuity(ii) );
152  }
153  myMults -> SetValue(1, myDegree + 1) ;
154  myMults -> SetValue(NumCurves + 1, myDegree + 1) ;
155
156 // Calculs
157  Perform(NumCurves, MaxDegree, Dimension,
158          NumCoeffPerCurve, Coefficients,
159          PolynomialIntervals, TrueIntervals);  
160 }
161
162 Convert_CompPolynomialToPoles::
163 Convert_CompPolynomialToPoles(const Standard_Integer Dimension,
164                               const Standard_Integer MaxDegree,
165                               const Standard_Integer Degree,
166                               const TColStd_Array1OfReal& Coefficients,
167                               const TColStd_Array1OfReal& PolynomialIntervals,
168                               const TColStd_Array1OfReal& TrueIntervals) :
169                               myDegree(Degree) ,
170                               myDone(Standard_False)
171   
172 {
173  if (MaxDegree  <= 0              ||
174      Dimension  <= 0              ||
175      PolynomialIntervals.Length() != 2) 
176    {
177      throw Standard_ConstructionError
178      ("Convert_CompPolynomialToPoles:bad arguments");
179    }
180
181  TColStd_Array2OfReal ThePolynomialIntervals(1,1,1,2);
182  ThePolynomialIntervals.SetValue(1,1,PolynomialIntervals(PolynomialIntervals.Lower()));
183  ThePolynomialIntervals.SetValue(1,2,PolynomialIntervals(PolynomialIntervals.Upper()));
184  
185  TColStd_Array1OfInteger NumCoeffPerCurve(1,1);
186  NumCoeffPerCurve(1) = Degree+1;
187
188  myKnots = 
189  new TColStd_HArray1OfReal(1, 2) ;
190  myKnots->ChangeArray1().SetValue(1, TrueIntervals.Value(TrueIntervals.Lower()));
191  myKnots->ChangeArray1().SetValue(2, TrueIntervals.Value(TrueIntervals.Lower()+1));
192
193  myMults =
194  new TColStd_HArray1OfInteger(1, 2) ;
195  myMults->Init( myDegree + 1);
196
197
198 // Calculs
199  Perform(1, MaxDegree, Dimension,
200          NumCoeffPerCurve, Coefficients,
201          ThePolynomialIntervals, TrueIntervals);  
202 }
203
204 void Convert_CompPolynomialToPoles::
205 Perform(const Standard_Integer NumCurves,
206         const Standard_Integer MaxDegree,
207         const Standard_Integer Dimension,
208         const TColStd_Array1OfInteger& NumCoeffPerCurve,
209         const TColStd_Array1OfReal& Coefficients, 
210         const TColStd_Array2OfReal& PolynomialIntervals,
211         const TColStd_Array1OfReal& TrueIntervals)
212 {
213  Standard_Integer ii, 
214  num_flat_knots,
215  index, Tindex, Pindex,
216  coeff_index,
217  inversion_problem,
218  poles_index,
219  num_poles ;
220  Standard_Real normalized_value,
221  *coefficient_array,
222  *poles_array ;
223  
224  num_flat_knots = 2 * myDegree + 2 ;
225  for (ii=2; ii<myMults->Length(); ii++) {
226    num_flat_knots += myMults->Value(ii);
227  }
228  num_poles = num_flat_knots - myDegree - 1 ;
229
230  myFlatKnots = new TColStd_HArray1OfReal(1,num_flat_knots) ;
231  BSplCLib::KnotSequence (myKnots->Array1(), 
232                          myMults->Array1(),
233                          myDegree,
234                          Standard_False,
235                          myFlatKnots->ChangeArray1());
236
237  TColStd_Array1OfReal parameters(1,num_poles) ;
238  BSplCLib::BuildSchoenbergPoints(myDegree,
239                                  myFlatKnots->Array1(),
240                                  parameters) ;
241  myPoles = new TColStd_HArray2OfReal(1, num_poles,
242                                      1, Dimension) ;
243  index = 2;
244  Tindex = TrueIntervals.Lower()+1;
245  Pindex = PolynomialIntervals.LowerRow();
246  poles_array =
247  (Standard_Real *) &(myPoles->ChangeArray2()).Value(1,1) ;
248
249  TColStd_Array1OfInteger contact_array(1,num_poles) ;
250
251  poles_index = 0 ;
252  for (ii = 1 ; ii <= num_poles ; ii++, poles_index += Dimension) {
253    contact_array.SetValue(ii,0) ;
254    while (parameters.Value(ii) >= TrueIntervals(Tindex) &&
255           index <= NumCurves) {
256      index++; Tindex++; Pindex++;
257    }
258 // 
259 // normalized value so that it fits the original intervals for
260 // the polynomial definition of the curves
261 //
262    normalized_value =  parameters.Value(ii) - TrueIntervals(Tindex-1) ;
263    normalized_value /=  TrueIntervals(Tindex) 
264                      -  TrueIntervals(Tindex-1)  ;
265    normalized_value = (1.0e0 -normalized_value) * 
266      PolynomialIntervals(Pindex, PolynomialIntervals.LowerCol()) 
267                     + normalized_value * 
268      PolynomialIntervals(Pindex, PolynomialIntervals.UpperCol()) ;
269    coeff_index = ((index-2) * Dimension * (Max(MaxDegree, myDegree) + 1))  
270                + Coefficients.Lower();
271    
272    coefficient_array =
273      (Standard_Real *) &(Coefficients(coeff_index)) ;
274    Standard_Integer Deg = NumCoeffPerCurve(NumCoeffPerCurve.Lower()+index-2) - 1;
275
276    PLib::NoDerivativeEvalPolynomial
277      (normalized_value,
278       Deg,
279       Dimension,
280       Deg * Dimension,
281       coefficient_array[0],
282       poles_array[poles_index]) ; 
283  }
284 //
285 // interpolation at schoenberg points should yield the desired
286 // result
287 //
288  BSplCLib::Interpolate(myDegree,
289                        myFlatKnots->Array1(),
290                        parameters,
291                        contact_array,
292                        Dimension,
293                        poles_array[0],
294                        inversion_problem) ;
295  if (inversion_problem != 0) {
296   throw Standard_ConstructionError
297   ("Convert_CompPolynomialToPoles:inversion_problem");
298  } 
299  myDone = Standard_True ;
300 }
301
302
303  
304 //=======================================================================
305 //function : NbPoles
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Integer Convert_CompPolynomialToPoles::NbPoles()  const 
310 {
311   if (myDone) {
312     return myPoles->ColLength() ;
313   }
314   else 
315     return 0 ;
316 }
317 //=======================================================================
318 //function : Poles
319 //purpose  : 
320 //=======================================================================
321
322 void Convert_CompPolynomialToPoles::Poles(
323                         Handle(TColStd_HArray2OfReal)& P) const 
324  { if (myDone) {
325    P = myPoles ; } 
326  }
327 //=======================================================================
328 //function : NbKnots
329 //purpose  : 
330 //=======================================================================
331
332 Standard_Integer Convert_CompPolynomialToPoles::NbKnots()  const 
333 {
334   if (myDone) {
335     return myKnots->Length() ;
336   }
337   else 
338     return 0 ;
339 }
340 //=======================================================================
341 //function : Knots
342 //purpose  : 
343 //=======================================================================
344
345 void Convert_CompPolynomialToPoles::Knots(
346                          Handle(TColStd_HArray1OfReal)& K) const 
347  { if (myDone) {
348    K = myKnots ; } 
349  }
350    
351 //=======================================================================
352 //function : Knots
353 //purpose  : 
354 //=======================================================================
355
356 void Convert_CompPolynomialToPoles::Multiplicities(
357                       Handle(TColStd_HArray1OfInteger)& M) const 
358  { if (myDone) {
359    M = myMults ; }
360  }
361 //=======================================================================
362 //function : IsDone
363 //purpose  : 
364 //=======================================================================
365
366 Standard_Boolean  Convert_CompPolynomialToPoles::IsDone() const 
367 { return myDone ; }
368 //=======================================================================
369 //function : IsDone
370 //purpose  : 
371 //=======================================================================
372
373 Standard_Integer Convert_CompPolynomialToPoles::Degree() const 
374
375   if (myDone) {
376     return myDegree ; 
377   }
378   return 0 ;
379 }