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: s1422.c,v 1.2 2001-03-19 15:58:49 afr Exp $
45  *
46  */
47 
48 
49 #define S1422
50 
51 #include "sislP.h"
52 
53 #if defined(SISLNEEDPROTOTYPES)
54 void
s1422(SISLSurf * ps1,int ider,int iside1,int iside2,double epar[],int * ilfs,int * ilft,double eder[],double enorm[],int * jstat)55    s1422(SISLSurf *ps1,int ider,int iside1,int iside2,double epar[],int *ilfs,
56        int *ilft,double eder[],double enorm[],int *jstat)
57 #else
58 void s1422(ps1,ider,iside1,iside2,epar,ilfs,ilft,eder,enorm,jstat)
59      SISLSurf   *ps1;
60      int    ider;
61      int    iside1;
62      int    iside2;
63      double epar[];
64      int    *ilfs;
65      int    *ilft;
66      double eder[];
67      double enorm[];
68      int    *jstat;
69 #endif
70 /*
71 *********************************************************************
72 *
73 *********************************************************************
74 *
75 * PURPOSE    : Evaluate the surface pointed at by ps1 at the parameter
76 *              value epar. Compute ider derivatives from the right hand
77 *	       or the left hand sides.
78 *
79 *
80 *
81 * INPUT      : ps1    - Pointer to the surface to evaluate.
82 *              ider   - Number of derivatives to calculate.
83 *                       < 0 : No derivative calculated.
84 *                       = 0 : Position calculated.
85 *                       = 1 : Position and first derivative calculated.
86 *                       etc.
87 *	       iside1 - Indicator telling if the derivatives in the first
88 *			parameter direction is to be calculated from the
89 *			left or from the right:
90 *			 <  0 calculate derivative from the left hand side
91 *			 >= 0 calculate derivative from the right hand side.
92 *	       iside2 - Indicator telling if the derivatives in the second
93 *			parameter direction is to be calculated from the
94 *			left or from the right:
95 *			 <  0 calculate derivative from the left hand side
96 *			 >= 0 calculate derivative from the right hand side.
97 *              epar   - Parameter-value at which to calculate. Dimension
98 *                       of epar is 2.
99 *
100 *
101 *
102 * INPUT/OUTPUT : ilfs  - Pointer to the interval in the knotvector
103 *                        in first parameter direction where epar[0]
104 *                        is found. The relation
105 *
106 *                          et1[ilfs] <= epar[0] < et1[ilfs+1]
107 *
108 *                        where et1 is the knotvektor should hold.
109 *                        ilfs is set equal to zero at the first call
110 *                        to the routine.
111 *                ilft  - Corresponding to ilfs in the second parameter
112 *                        direction.
113 *
114 *
115 *
116 *
117 * OUTPUT     : eder   - Array where the derivative of the curve in
118 *                       apar is placed. The sequence is position,
119 *                       first derivative in first parameter direction,
120 *                       first derivative in second parameter direction,
121 *                       (2,0) derivative, (1,1) derivative, (0,2)
122 *                       derivative, etc. Dimension of eder is
123 *                       idim*(1+2+...+(ider+1)).
124 *              enorm  - Normal of surface. Is calculated if ider >= 1.
125 *                       Dimension is idim. The normal is not normalized.
126 *              jstat  - status messages
127 *                                         = 2      : Surface is degenerate
128 *                                                    at the point, normal
129 *                                                    has zero length
130 *                                         = 1      : Surface is close to
131 *                                                    degenerate at the point
132 *                                                    Angle between tangents,
133 *                                                    less than angular tolerance
134 *                                         = 0      : ok
135 *                                         < 0      : error
136 *
137 *
138 * METHOD     :
139 *
140 * REFERENCES :
141 *
142 *-
143 * CALLS      :
144 *
145 * WRITTEN BY :
146 *
147 *********************************************************************
148 */
149 {
150   int kstat=0;        /* Local status variable.                          */
151   int kpos=0;         /* Position of error.                              */
152   int kdim;           /* Dimension of the space in which the surface lies. */
153   int keder;          /* Integer used in address calculations on eder    */
154   int ksp;            /* Integer used in address calculations on sp      */
155   int kincre;         /* Increment for address calculations              */
156   int ki,kl;          /* Control variables in for loop                   */
157   int knumb;          /* Number of elements used for storage of deriv.s  */
158   double *sp;         /* Pointer to temporary array                      */
159   double sdum[48];    /* Array used in stead of allocation               */
160 
161 
162   /* Allocate array for storage of ider*ider derivatives */
163 
164   sp = SISL_NULL;
165   kdim = ps1 -> idim;
166   knumb = kdim*(ider+1)*(ider+1);
167 
168   /* Only allocate space if sdum is too smaall */
169 
170   if (knumb>48)
171     sp = newarray(knumb,DOUBLE);
172   else
173     sp = &sdum[0];
174 
175   if (sp == SISL_NULL) goto err101;
176 
177 
178   /* Evaluate s1422surface.  */
179 
180   s1425(ps1,ider,ider,iside1,iside2,epar,ilfs,ilft,sp,&kstat);
181 
182   if (kstat < 0) goto error;
183 
184   /* Copy required derivatives into eder */
185 
186   kincre = kdim*ider;
187 
188   /*  Copy all derivatives of order 0, then of order 1, up to order ider */
189 
190   for (kl=0,keder=0;kl<=ider;kl++)
191     {
192       for (ki=0,ksp=kl*kdim ; ki<=kl ; ki++,ksp+=kincre,keder+=kdim)
193         {
194 	  memcopy(eder+keder,sp+ksp,kdim,DOUBLE);
195         }
196     }
197 
198   /* Make cross products of tangents, if idim==3 and derivative >0 */
199 
200   if (ider>0 && kdim ==3)
201     {
202       double tlen1,tlen2,tnorm,tang=(double)0.0;
203 
204       s6crss(eder+kdim,eder+2*kdim,enorm);
205 
206       /*  Make length of tangents and normal */
207 
208       tlen1 = s6length(eder+kdim,kdim,&kstat);
209       tlen2 = s6length(eder+2*kdim,kdim,&kstat);
210       tnorm = s6length(enorm,kdim,&kstat);
211 
212       /*  Calculate angle between tangents */
213 
214       if (tlen1 != DZERO && tlen2 != DZERO && tnorm != DZERO)
215         tang = tnorm/(tlen1*tlen2);
216 
217       if (tang == DZERO) *jstat = 2;
218       else if (tang <= ANGULAR_TOLERANCE) *jstat = 1;
219       else *jstat = 0;
220       goto out;
221 
222     }
223 
224   *jstat = 0;
225   goto out;
226 
227   /* Error in lower level routine.  */
228 
229   error : *jstat = kstat;
230   s6err("s1422",*jstat,kpos);
231   goto out;
232 
233  err101: *jstat = -101;
234   s6err("s1422",*jstat,kpos);
235 
236 
237  out:
238 
239   /* Free allocated space (Space only allocated if sdum is too small) */
240 
241   if (knumb>48)
242     if (sp != SISL_NULL) freearray(sp);
243 
244   return;
245 }
246 
247 
248