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 #define S1538
43 
44 #include "sislP.h"
45 
46 #if defined(SISLNEEDPROTOTYPES)
47 void
s1538(int inbcrv,SISLCurve * vpcurv[],int nctyp[],double astpar,int iopen,int iord2,int iflag,SISLSurf ** rsurf,double ** gpar,int * jstat)48    s1538(int inbcrv,SISLCurve *vpcurv[],int nctyp[],double astpar,
49 	   int iopen,int iord2,int iflag,
50 	   SISLSurf **rsurf,double **gpar,int *jstat)
51 #else
52 void s1538(inbcrv,vpcurv,nctyp,astpar,iopen,iord2,
53            iflag,rsurf,gpar,jstat)
54      int    	inbcrv;
55      SISLCurve  *vpcurv[];
56      int   	nctyp[];
57      double	astpar;
58      int    	iopen;
59      int    	iord2;
60      int    	iflag;
61      SISLSurf   **rsurf;
62      double 	**gpar;
63      int    	*jstat;
64 #endif
65 /*
66 *********************************************************************
67 *
68 * PURPOSE    : To create a spline lofted surface
69 *              from a set of input-curves.
70 *
71 * INPUT      : inbcrv - Number of curves in the curve-set.
72 *              vpcurv  - Array (length inbcrv) of pointers to the
73 *                       curves in the curve-set.
74 *              nctyp  - Array (length inbcrv) containing the types
75 *                       of curves in the curve-set.
76 *                        1 - Ordinary curve.
77 *                        2 - Knuckle curve. Treated as ordinary curve.
78 *                        3 - Tangent to next curve.
79 *                        4 - Tangent to prior curve.
80 *                       (5 - Double derivative to prior curve.)
81 *                       (6 - Double derivative to next curve.)
82 *                       13 - SISLCurve giving start of tangent to next curve.
83 *                       14 - SISLCurve giving end of tengent to prior curve.
84 *              astpar - Start-parameter for spline lofting direction.
85 *              iopen  - Flag telling if the resulting surface should
86 *                       be closed or open.
87 *                       -1 - The surface should be closed and periodic.
88 *                        0 - The surface should be closed.
89 *                        1 - The surface should be open.
90 *              iord2  - Maximal order of the B-spline basis in the
91 *                       lofting direction.
92 *              iflag  - Flag telling if the size of the tangents in the
93 *                       derivative curves should be adjusted or not.
94 *                        0 - Do not adjust tangent-sizes.
95 *                        1 - Adjust tangent-sizes.
96 *
97 * OUTPUT     : rsurf  - Pointer to the surface produced.
98 *              gpar   - The input-curves are constant parameter-lines
99 *                       in the parameter-plane of the produced surface.
100 *                       (i) - contains the (constant) value of this
101 *                             parameter of input-curve no. i.
102 *              jstat  - status messages
103 *                                         > 0      : warning
104 *                                         = 0      : ok
105 *                                         < 0      : error
106 *
107 * METHOD     : A common basis for all the B-spline curves are found.
108 *              The curves are represented using this basis.
109 *              The resulting curves are given to an interpolation
110 *              routine that calculates the B-spline vertices of the
111 *              resulting spline lofted surface.
112 *              Throughout these routines, first parameterdirection
113 *              will be the interpolating direction, second parameter-
114 *              direction will be along the input curves.
115 *-
116 * CALLS      : s1931,s1917,s1918,s1358,s6err.
117 *
118 * WRITTEN BY : A. M. Ytrehus   SI  Oslo,Norway. Sep. 1988
119 * Revised by : Tor Dokken, SI, Oslo, Norway, 26-feb-1989
120 * Revised by : Trond Vidar Stensby, SI, 91-08
121 * REVISED BY: Vibeke Skytt, 03.94. This routine corresponds to s1333,
122 *                                  but differ in the use of the parameter
123 *                                  iopen.
124 * Revised by : Paal Fugelli, 17/08-1994.  Fixed memory leak from 'gpar'
125 *              allocated in s1357().
126 *
127 *********************************************************************
128 */
129 {
130   int kind,kcopy,kdim;
131   int kn1,kord1,knbcrv;
132   int kcnsta,kcnend;         /* Interpolation condition at start or end */
133   int ki,kj,kl,km;
134   int kleng;                 /* Number of doubles describing a curve  */
135   int ktype;                 /* Kind of interpolation condition.      */
136   int kopen;                 /* Open/closed parameter in curve direction. */
137   SISLCurve *qc;             /* Pointer to curve representing surface */
138   int *lder = SISL_NULL;	     /* Derivative indicators from s1915. */
139   double *spar=SISL_NULL; 	     /* Param. values of point conditions. */
140   double *spar2=SISL_NULL; 	     /* Parameter values from s1915. */
141   double *sknot1=SISL_NULL;       /* Knot vector.                 */
142   double *scoef2=SISL_NULL;       /* Pointer to vertices expressed in same basis  */
143   double tstpar;             /* Parameter value of last curve                */
144   int kstat = 0;             /* Status variable. */
145   int kpos = 0;              /* Position of error. */
146   int knbpar;                /* Number of parameter values produced          */
147   int kdimcrv;               /* kdim multiplied with number of vertices kn1  */
148   int kcont;                 /* Continuity at end of curves */
149 
150 
151   /* Initiate variables. */
152 
153   kdim = vpcurv[0]->idim;
154 
155   if (inbcrv < 2) goto err179;
156 
157   /* Put the curves into common basis. */
158 
159   s1931 (inbcrv, vpcurv, &sknot1, &scoef2, &kn1, &kord1, &kstat);
160   if (kstat < 0)
161     goto error;
162 
163   /* Create the parameter-values for the knot-vector
164      (in lofting direction) for a lofted surface, allocate array for
165      parameter values.    */
166 
167   s1917 (inbcrv, scoef2, kn1, kdim, nctyp, astpar, iopen,
168 	 &spar2, &lder, &knbcrv, &kstat);
169 
170   if (kstat < 0)
171     goto error;
172 
173   /* Convert condition 13 and 14 to 3 and 4 */
174 
175   kleng = kn1*kdim;
176   for (ki=0 ; ki<knbcrv ; ki++)
177     {
178        ktype = nctyp[ki];
179 
180       if (ktype == 13 && ki+1<knbcrv)
181         {
182 	  /*
183 	   * Start of tangent to next curve,
184 	   * make difference of next curve and this curve
185 	   */
186 
187 	  for (kj=ki*kleng,kl=kj+kleng,km=0; km <kleng ; kj++,kl++,km++)
188 	      scoef2[kj] = scoef2[kl] - scoef2[kj];
189 	  nctyp[ki] = 3;
190         }
191       else if (ktype == 14 && ki>0)
192         {
193 	  /* End of tangent to prior curve,
194 	   * make difference of this curve
195 	   * and prior curve
196 	   */
197 
198 	  for (kj=ki*kleng,kl=kj-kleng,km=0; km <kleng ; kj++,kl++,km++)
199 	      scoef2[kj] = scoef2[kj] - scoef2[kl];
200 	  nctyp[ki] = 4;
201         }
202     }
203 
204   spar = newarray(knbcrv+1,DOUBLE);
205   if (spar==SISL_NULL) goto err101;
206 
207   /*  Only copy parameter values of point conditions */
208 
209   for (ki=0,kl=0; ki<knbcrv ; ki++)
210     {
211       if (nctyp[ki] == 1 || nctyp[ki] == 2)
212         {
213 	  spar[kl] = spar2[ki];
214 	  kl++;
215         }
216     }
217 
218   /* Add one extra parameter value if closed curve */
219 
220   if (iopen != SISL_CRV_OPEN) spar[kl] = spar2[knbcrv];
221 
222   /* Adjust tangent-lengths if wanted. */
223 
224   if (iflag)
225     {
226       s1918 (knbcrv, sknot1, scoef2, kn1, kord1, kdim, spar2, lder, &kstat);
227       if (kstat < 0) goto error;
228     }
229 
230   /* Interpolate with point interpolation method */
231 
232   kcnsta = 0;
233   kcnend = 0;
234   kdimcrv = kdim*kn1;
235 
236   s1357(scoef2,knbcrv,kdimcrv,nctyp,spar,kcnsta,kcnend,iopen,iord2,astpar,
237 	&tstpar,&qc,gpar,&knbpar,&kstat);
238   if (kstat<0) goto error;
239 
240   /* The knot vector in the lofting direction and the coefficients are
241      now contained in the curve object pointed to by qc */
242 
243   /* Create the surface */
244 
245   kind = 1;
246   kcopy = 1;
247   *rsurf = newSurf(kn1,qc->in,kord1,qc->ik,sknot1,qc->et,qc->ecoef,
248 		   kind,kdim,kcopy);
249   if (*rsurf == SISL_NULL) goto err101;
250 
251   /* Copy cuopen flag from curve */
252   (*rsurf)->cuopen_2 = qc->cuopen;
253 
254   /* Release the curve object */
255 
256   freeCurve(qc);
257 
258   /* Output parametervalues according to the input curves, but must
259      remember to free the space allocated in call to s1357() first.  */
260 
261   if ( (*gpar) != SISL_NULL ) freearray(*gpar);  /* PFU 17/08-94. */
262   *gpar = spar;
263 
264   /* Decide if the surface should have a cyclic behaviour in first
265      parameter direction i.e. the direction of the curves */
266 
267   s1333_count(inbcrv,vpcurv,&kcont,&kstat);
268   if (kstat<0) goto error;
269 
270   if (kcont>=0)
271       {
272         s1333_cyclic(*rsurf,kcont,&kstat);
273 	if (kstat<0) goto error;
274 
275 	/* Set periodic flag */
276 	(*rsurf)->cuopen_1 = SISL_SURF_PERIODIC;
277       }
278       else
279       {
280          /* Test if the surface should be closed and non-periodic.  */
281 
282          for (kopen=-2, ki=0; ki<inbcrv; ki++)
283            kopen = MAX(kopen,vpcurv[ki]->cuopen);
284          if (kopen == SISL_CRV_CLOSED) (*rsurf)->cuopen_1 = SISL_SURF_CLOSED;
285       }
286 
287   /* Task done */
288 
289   *jstat = 0;
290   goto out;
291 
292   /* Error in allocation. */
293 
294  err101:
295   *jstat = -101;
296   s6err("s1538",*jstat,kpos);
297   goto out;
298 
299 
300   /* Error in interpolation conditions. No. of curves < 2. */
301 
302  err179:
303   *jstat = -179;
304   s6err("s1538",*jstat,kpos);
305   goto out;
306 
307 
308   /* Error in lower level routine.  */
309 
310   error :
311     *jstat = kstat;
312   s6err("s1538",*jstat,kpos);
313   goto out;
314  out:
315 
316   /* Free allocated scratch  */
317 
318   if (sknot1 != SISL_NULL) freearray(sknot1);
319   if (scoef2 != SISL_NULL) freearray(scoef2);
320   if (spar2 != SISL_NULL) freearray(spar2);
321   if (lder != SISL_NULL) freearray(lder);
322 
323   return;
324 }
325