1 /*
2  * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
3  * Applied Mathematics, Norway.
4  *
5  * Contact information: E-mail: tor.dokken@sintef.no
6  * SINTEF ICT, Department of Applied Mathematics,
7  * P.O. Box 124 Blindern,
8  * 0314 Oslo, Norway.
9  *
10  * This file is part of SISL.
11  *
12  * SISL is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * SISL is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public
23  * License along with SISL. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  * In accordance with Section 7(b) of the GNU Affero General Public
27  * License, a covered work must retain the producer line in every data
28  * file that is created or manipulated using SISL.
29  *
30  * Other Usage
31  * You can be released from the requirements of the license by purchasing
32  * a commercial license. Buying such a license is mandatory as soon as you
33  * develop commercial activities involving the SISL library without
34  * disclosing the source code of your own applications.
35  *
36  * This file may be used in accordance with the terms contained in a
37  * written agreement between you and SINTEF ICT.
38  */
39 
40 #include "sisl-copyright.h"
41 
42 /*
43  *
44  * $Id: s1389.c,v 1.2 2001-03-19 15:58:48 afr Exp $
45  *
46  */
47 
48 
49 #define S1389
50 
51 #include "sislP.h"
52 
53 #if defined(SISLNEEDPROTOTYPES)
54 void
s1389(SISLCurve * pc1,double * gcubic[],int * jnumb,int * jdim,int * jstat)55 s1389(SISLCurve *pc1,double *gcubic[],int *jnumb,int *jdim,int *jstat)
56 #else
57 void s1389(pc1,gcubic,jnumb,jdim,jstat)
58      SISLCurve  *pc1;
59      double *gcubic[];
60      int    *jnumb;
61      int    *jdim;
62      int    *jstat;
63 #endif
64 /*
65 *********************************************************************
66 *
67 *********************************************************************
68 *
69 * PURPOSE    : Convert a B-spline curve of order up to 4 to a sequence
70 *              of cubic segment with uniform parametrization
71 *
72 *
73 * INPUT      : pc1    - Pointer to the curve to be converted
74 *
75 *
76 * OUTPUT     : gcubic - Array containing the sequence of cubic segments.
77 *                       Each segment is represented by the start point,
78 *                       followed by the start tangent, end point and end
79 *                       tangent. Each segment takes 4*jdim doubles.
80 *                       This array is allocated inside the function and must
81 *                       be released by the calling function.
82 *
83 *              jstat  - status messages
84 *                                         = 1      : Order too high, curve
85 *                                                    interpolated
86 *                                         = 0      : ok
87 *                                         < 0      : error
88 *
89 *
90 * METHOD     : For each polynomial segment end, the position and first
91 *              derivative is calculated.
92 *
93 * USE:         int knumb,kdim,kstat;
94 *              double *scubic;
95 *              SISLSurf *qc1;
96 *               .
97 *               .
98 *              s1389(qc1,&scubic,&knumb,&kdim,&kstat);
99 *               .
100 *              If one of the order of the curve is greater than four
101 *              (*jstat==1) then degree reduction (order reduction) should
102 *              be applied before using this routine to get a satisfactory
103 *              representation of the curve by Coons patches.
104 *              The degree reduction routine is s1343.
105 *
106 *
107 *
108 * REFERENCES :
109 *
110 *-
111 * CALLS      : s1221, s1227, s6err
112 *
113 * WRITTEN BY : Tor Dokken, SI, Norway, 1988-11
114 *
115 *********************************************************************
116 */
117 {
118   int kstat=0;        /* Local status variable.                          */
119   int kpos=0;         /* Position of error.                              */
120   int kdim;           /* Dimension of the space in which the surface lies. */
121   int kder=1;         /* Calculate all first derivatives                 */
122   int kleft=0;        /* Pointer into knot vector                        */
123   int kdumlft;        /* Temporary pointer into knot vector              */
124   int ksize;          /* Number of doubles to store a cubic segment      */
125 
126   int ki;             /* Control variables in for loop                   */
127   int kn;             /* Number of vertices                              */
128   int kk;             /* Polynomial order                                */
129   double *st;         /* Knots                                           */
130   double tpar;        /* Current parameter value                         */
131   double tparx;       /* Temporary parameter value                       */
132   double tdiff1;      /* Length of parameter interval                    */
133   double *scorn1;     /* Pointer to first end of segment                 */
134   double *scorn2;     /* Pointer to second end of segment                */
135 
136   kn  = pc1->in;
137   kk  = pc1->ik;
138   kdim = pc1 -> idim;
139   st  = pc1 -> et;
140 
141 
142   /* Calculate number of doubles to store a cubic segment*/
143 
144   ksize = kdim*4;
145 
146 
147   /* Allocate array for storage of the coefficients */
148 
149   *gcubic = newarray((kn*4*kdim),DOUBLE);
150   if (*gcubic == SISL_NULL) goto err101;
151 
152   kleft = kk - 1;
153 
154   *jnumb = 0;
155 
156   scorn1 = *gcubic;
157 
158   while (kleft < kn)
159     {
160 
161       /* Set pointers to the end of the segment */
162 
163       scorn2 = scorn1 + 2*kdim;
164 
165       tpar = st[kleft];
166 
167       /* The parameter describes the left corner of the segment. By
168 	 evaluating at tpar we get the kleft to point to the parameter
169 	 interval. The other end is at st[kleft+1].
170 	 */
171 
172       /* Calulate start of segement */
173 
174       s1221(pc1,kder,tpar,&kleft,scorn1,&kstat);
175       if (kstat<0) goto error;
176 
177       /* Find length of aprameter intervals */
178 
179       tdiff1 = st[kleft+1] - st[kleft];
180 
181       /* Calculate end of segment, us left derivative */
182 
183       tparx = st[kleft+1];
184       kdumlft = kleft;
185 
186       s1227(pc1,kder,tparx,&kdumlft,scorn2,&kstat);
187       if (kstat<0) goto error;
188 
189       /* Scale derivatives to match uniform parametrization */
190 
191       for (ki=kdim;ki<2*kdim;ki++)
192         {
193 	  scorn1[ki] *= tdiff1;
194 	  scorn2[ki] *= tdiff1;
195         }
196 
197       kleft += 1;
198       *jnumb +=1;
199       scorn1 += kdim*4;
200     }
201 
202   /* The array is probably too big for the Coons patches, decrease the
203      array size */
204 
205 
206   /* Allocate array for storage of the coefficients */
207 
208   *gcubic = increasearray(*gcubic,((*jnumb)*4*kdim),DOUBLE);
209   if (*gcubic == SISL_NULL) goto err101;
210 
211 
212   /* Test if order to high */
213 
214   *jdim = kdim;
215 
216   if (kk>4) goto war01;
217 
218   *jstat = 0;
219 
220   goto out;
221 
222   /* Orders too high */
223 
224   war01:*jstat=1;
225     goto out;
226 
227   /* Error in scratch allocation */
228 
229   err101:
230     *jstat = -101;
231     s6err("s1389",*jstat,kpos);
232     goto freeout;
233 
234   /* Error in lower level function.  */
235 
236   error : *jstat = kstat;
237     s6err("s1389",*jstat,kpos);
238     goto freeout;
239 
240   /* Some error has occured free allocated space */
241 
242   freeout:
243     if (*gcubic != SISL_NULL) freearray(*gcubic);
244     goto out;
245 
246   out:
247     return;
248 }
249 
250