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: s1772.c,v 1.3 2005-02-28 09:04:49 afr Exp $
45  *
46  */
47 #define S1772
48 
49 #include "sislP.h"
50 
51 #define SINGULAR 1.0e-16
52 #define copy2(a,b,c) for (ki=0;ki<(c);ki++) (a)[ki]=(b)[ki]
53 #define copy3(a,b,c,d) for (ki=0;ki<(d);ki++) (a)[ki]=(b)[ki]=(c)[ki]
54 #define incr2(a,b,c) for (ki=0;ki<(c);ki++) (a)[ki]+=(b)[ki]
55 #define decr2(a,b,c) for (ki=0;ki<(c);ki++) (a)[ki]-=(b)[ki]
56 #define set_order(a) if((a)==1) {s_v=s_uu;order=0;} else {s_v=s_v1;order=1;}
57 /* extern int debug_flag; */
58 /*
59 * Forward declarations.
60 * ---------------------
61 */
62 
63 #if defined(SISLNEEDPROTOTYPES)
64 static
65 void
66 s1772_s9corr(double[],double[],double,double,double[],double[],int*);
67 static
68 void
69 s1772_s9dir(double*,double[],double[],double[],double[],double[],double[],
70 	    double[],double[],double[],double[],double[],int,int,int*);
71 static
72 void
73 s1772_s6sekant1(SISLCurve *,SISLSurf *,double[],double,double *,double,double,
74 		double[],double,double[],double[],double[],double[],int *);
75 static
76 int
77 s1772_s6local_pretop(double,double[],double[],double[],double[],double[],
78 		     double[],double[],double[],double[],double[],double[],
79 		     int,int*);
80 #else
81 static void s1772_s9corr();
82 static void s1772_s9dir();
83 static void s1772_s6sekant1();
84 static int s1772_s6local_pretop();
85 #endif
86 
87 #if defined(SISLNEEDPROTOTYPES)
88 void
s1772(SISLCurve * pcurve,SISLSurf * psurf,double aepsge,double astart1,double estart2[],double aend1,double eend2[],double anext1,double enext2[],double * cpos1,double gpos2[],int * jstat)89 s1772(SISLCurve *pcurve,SISLSurf *psurf,double aepsge,
90 	   double astart1,double estart2[],double aend1,double eend2[],
91 	   double anext1,double enext2[],double *cpos1,double gpos2[],
92 	   int *jstat)
93 #else
94 void s1772(pcurve,psurf,aepsge,astart1,estart2,aend1,eend2,
95 	   anext1,enext2,cpos1,gpos2,jstat)
96      SISLCurve  *pcurve;
97      SISLSurf   *psurf;
98      double aepsge;
99      double astart1;
100      double estart2[];
101      double aend1;
102      double eend2[];
103      double anext1;
104      double enext2[];
105      double *cpos1;
106      double gpos2[];
107      int    *jstat;
108 #endif
109 /*
110 *********************************************************************
111 *
112 *********************************************************************
113 *
114 * PURPOSE    : Newton iteration on the distance function between
115 *              a curve and a surface to find a closest point
116 *              or an intersection point.
117 *
118 *
119 * INPUT      : pcurve    - Pointer to the curve in the intersection.
120 *              psurf     - Pointer to the surface in the intersection.
121 *              aepsge    - Geometry resolution.
122 *              astart1   - Start parameter value of the curve.
123 *              estart2[] - Start parameter value of surface.
124 *              aend1     - End parameter value of the curve.
125 *              eend2[]   - End 1.st parameter value of the surface.
126 *              anext1    - Start parameter value of the iteration on
127 *                          the curve.
128 *              enext2[]  - Start parameter value of the iteration on
129 *                          the surface.
130 *              jstat     -	=1   : A quick version is to be used.
131 *				else : Importent to find a solution.
132 *
133 *
134 * OUTPUT     : cpos1   - Parameter value of the curve in intersection
135 *                        point.
136 *              gpos2[] - Parameter value of the surface in
137 *                        intersection point.
138 *              jstat   - status messages
139 *                                = 3   : A minimum distanse found.
140 *                                = 2   : Nothing found.
141 *                                = 1   : Intersection found.
142 *                                < 0   : error.
143 *
144 *
145 * METHOD     : Newton iteration in tree parameter directions.
146 *
147 *
148 * REFERENCES :
149 *
150 *
151 * WRITTEN BY : Arne Laksaa, SI, Nov 1992
152 *
153 *********************************************************************
154 */
155 {
156   int ki;		    /* Counter.					   */
157   int kstat = 0;            /* Local status variable.                      */
158   int kpos = 0;             /* Position of error.                          */
159   int left[3];              /* Variables used in the evaluator.            */
160   int dim;                  /* Dimension of space the curves lie in        */
161   int knbit;                /* Number of iterations                        */
162   int p_dir;                /* Changing direction in par-space.            */
163   int g_up,ng_up,g_dir;     /* Changing direction in geometric space.      */
164   int order;		    /* Order of methode.			   */
165   int sing = 0;		    /* Mark that singularity has ocured.	   */
166   double *c0=SISL_NULL;          /* Value  of curve.				   */
167   double *c_t;		    /* First derivatiev of curve.		   */
168   double *c_tt;		    /* Second derivatiev of curve.		   */
169   double *s0;               /* Value of surf. 				   */
170   double *s_u;		    /* First derivatiev in first dir of surf. 	   */
171   double *s_v;		    /* First derivatiev in second dir of surf.	   */
172   double *s_uu;		    /* Second derivatiev in first dir of surf. 	   */
173   double *s_vv;		    /* Second derivatiev in second dir of surf.	   */
174   double *s_uv;		    /* Cross derivatiev of surf.	   	   */
175   double *s_v1;		    /* First derivatiev in second dir of surf.	   */
176   double *norm;		    /* Normal to the surface.			   */
177   double *diff;             /* Difference between the curve and the surf.  */
178   double *prev_diff;        /* Previous difference.			   */
179   double delta[3];          /* Parameter interval of the curve and surface.*/
180   double d[3];		    /* Clipped distances between old and new par.
181 			       value in the tree parameter directions.     */
182   double c_d[3];	    /* Computed distances ....			   */
183   double nc_d[3];	    /* New computed distances ....		   */
184   double dist;              /* Distance between position and origo.        */
185   double prev_dist;         /* Previous difference between the curves.     */
186   double par_val[3];        /* Parameter values                            */
187   double local[45];
188   int corr = 0, div2 = 0;
189 
190 
191 
192 
193   /* Test input.  */
194 
195   if (pcurve->idim != psurf->idim) goto err106;
196   dim = pcurve->idim;
197 
198   /* Fetch endpoints and the intervals of parameter interval of curves.  */
199 
200   delta[0] = psurf->et1[psurf->in1] - psurf->et1[psurf->ik1 - 1];
201   delta[1] = psurf->et2[psurf->in2] - psurf->et2[psurf->ik2 - 1];
202   delta[2] = pcurve->et[pcurve->in] - pcurve->et[pcurve->ik - 1];
203 
204   /* Allocate local used memory and set value pointers.*/
205 
206   if (dim > 3)
207   {
208      c0 = newarray((15)*dim,double);
209      if (c0 == SISL_NULL) goto err101;
210   }
211   else
212      c0 = local;
213 
214   s0 = c0 + 3*dim;
215   diff = s0 + 10*dim;
216   prev_diff = diff+dim;
217   c_t = c0+dim;
218   c_tt = c_t+dim;
219   s_u = s0+dim;
220   s_uu = s_u+dim;
221   s_v1 = s_uu+dim;
222   s_uv  = s_v1+dim;
223   s_vv = s_uv+dim+dim;
224   norm = s_vv+dim;
225 
226   /* Initiate variables.  */
227 
228   copy2(par_val,enext2,2);
229   par_val[2] = anext1;
230   left[0]=left[1]=left[2]=0;
231 
232   for (ki=1; ki<3; ki++)
233   {
234      set_order(ki);
235 
236      /* Evaluate 0-2.st derivatives of curve */
237 
238      if (par_val[2] == aend1)
239 	s1227(pcurve,1+order,par_val[2],left+2,c0,&kstat);
240      else
241 	s1221(pcurve,1+order,par_val[2],left+2,c0,&kstat);
242      if (kstat < 0) goto error;
243 
244      /* Evaluate 0-2.st derivatives of surface */
245 
246      s1424(psurf,1+order,1+order,par_val,left,left+1,s0,&kstat);
247      if (kstat < 0) goto error;
248 
249      /* Compute the distanse vector and value and the new step. */
250 
251      s1772_s9dir(&dist,diff,c_d, c0,c_t,c_tt,
252 		 s0,s_u,s_v,s_uu,s_uv,s_vv, dim,order,&kstat);
253      if (kstat < 0) goto error;
254      if (kstat == 1) 		/* Singular matrix. */
255      {
256 	if (order == 1) goto singular;
257      }
258      else break;
259   }
260 
261   /* Correct if we are not inside the parameter intervall. */
262 
263   s6crss(s_u,s_v,norm);
264   g_up = ((s6scpr(diff,norm,dim) >= DZERO) ? 1 : -1);
265   copy2(d,c_d,3);
266   s1772_s9corr(d,par_val, astart1,aend1,estart2,eend2,&corr);
267   prev_dist = dist;
268   copy2(prev_diff,diff,dim);
269 
270   /* Iterate to find the intersection point.  */
271 
272   for (knbit = 0; knbit < 30; knbit++)
273   {
274      incr2(par_val,d,3);
275 
276      while (1)
277      {
278 	/* Evaluate 0-2.st derivatives of curve */
279 
280 	if (par_val[2] == aend1)
281 	   s1227(pcurve,1+order,par_val[2],left+2,c0,&kstat);
282 	else
283 	   s1221(pcurve,1+order,par_val[2],left+2,c0,&kstat);
284 	if (kstat < 0) goto error;
285 
286 	/* Evaluate 0-2.st derivatives of surface */
287 
288 	s1424(psurf,1+order,1+order,par_val,left,left+1,s0,&kstat);
289 	if (kstat < 0) goto error;
290 
291 	/* Compute the distanse vector and value and the new step. */
292 
293 
294 	s1772_s9dir(&dist,diff,nc_d, c0,c_t,c_tt,
295 		    s0,s_u,s_v,s_uu,s_uv,s_vv, dim,order,&kstat);
296 	if (kstat < 0) goto error;
297 	if (kstat == 1) 		/* Singular matrix. */
298 	{
299 	   sing++;
300 	   if (order == 1) goto singular;
301 	   else	 set_order(2);		/* Change to order 2. */
302 	}
303 	else
304 	{
305 	   s6crss(s_u,s_v,norm);
306 	   ng_up = ((s6scpr(diff,norm,dim) >= DZERO) ? 1 : -1);
307 
308 	   g_dir = (ng_up+g_up != 0);			/* 0 if changed. */
309 	   p_dir = (s6scpr(c_d,nc_d,3) >= DZERO);	/* 0 if changed. */
310 
311 	   if (!order && g_dir && (!p_dir || dist > 0.3*prev_dist))
312 	   {
313 	      if (div2) div2 = 0;
314 	      set_order(2);
315 	      /*  if (debug_flag) printf("\n order-2 ");*/
316 	   }
317 	   else if (order && !g_dir)
318 	   {
319 	      if (sing) goto singular;
320 	      if (div2) div2 = 0;
321 	      set_order(1);
322 	      /*  if (debug_flag) printf("\n  order-1 "); */
323 	   }
324 	   else
325 	   {
326 	      if (sing) sing = 0;
327 	      break;
328 	   }
329 	}
330      }
331 
332      if (corr)
333 	if (!(p_dir && g_dir)) corr = 0;
334 
335      if (dist < prev_dist)
336      {
337 	if (div2) div2 = 0;
338 
339 	/* Corrigate if we are not inside the parameter intervall. */
340 
341 	g_up = ng_up;
342 	copy3(d,c_d,nc_d,3);
343 	s1772_s9corr(d,par_val, astart1,aend1,estart2,eend2,&corr);
344 	prev_dist = dist;
345 	copy2(prev_diff,diff,dim);
346 
347 	/* Testing */
348 	/*	if (quick && corr > 3) break; */
349 	if (corr > 3) break;
350      }
351      else if ( corr > 3 ||
352 	     ((fabs(d[0]/delta[0]) <= REL_COMP_RES) &&
353 	      (fabs(d[1]/delta[1]) <= REL_COMP_RES) &&
354 	      (fabs(d[2]/delta[2]) <= REL_COMP_RES)))     break;
355      else
356      {
357 	/* Not converging, corrigate and try again. */
358 	/*  if (debug_flag) printf(" *h*:%d ",knbit);*/
359 
360 	if (corr) corr++;
361 	if (dist > prev_dist && div2) break;
362 	div2++;
363         decr2(par_val,d,3);
364 	d[0] /= 2; d[1] /= 2; d[2] /= 2;
365      }
366   }
367 
368 	/* Iteration stopped, test if point found is within resolution */
369 
370   goto not_singular;
371 
372 singular:
373 
374    /*  if (!quick && dist > aepsge) */
375      if (dist > aepsge)
376      {
377 	ki = s1772_s6local_pretop(dist,diff,norm,c0,c_t,c_tt,
378 			    s0,s_u,s_v,s_uu,s_uv,s_vv,dim,&kstat);
379 	if (kstat < 0) goto error;
380 	if (ki == 0)
381 	{
382 	   s1772_s6sekant1(pcurve,psurf,par_val,c_d[2],&dist,aepsge,
383 			   astart1,estart2,aend1,eend2,c0,s0,norm,&kstat);
384 	   if (kstat < 0) goto error;
385 	}
386      }
387 
388 not_singular:
389   if (dist <= aepsge)
390   {
391      /* if (debug_flag) printf("\n FOUND: %d dist = %g",knbit,dist); */
392 
393     *jstat = 1;
394   }
395   else
396   {
397      /*if (debug_flag) printf("\n no: %d dist = %g",knbit,dist);*/
398 
399      s6crss(s_u,s_v,norm);
400      if ((PIHALF-s6ang(c_t,norm,dim)) < ANGULAR_TOLERANCE)
401 	*jstat = 3;
402      else
403 	*jstat = 2;
404   }
405 
406   /* if (knbit > 25)
407      if (debug_flag) printf("\n *****status: %d dist: %f \tknbit: %d",
408 			    *jstat,dist,knbit); */
409 
410   *cpos1 = par_val[2];
411   gpos2[0] = par_val[0];
412   gpos2[1] = par_val[1];
413 
414   /* Iteration completed.  */
415 
416   goto out;
417 
418   /* Error in allocation */
419 
420   err101:
421     *jstat = -101;
422     s6err("s1772",*jstat,kpos);
423     goto out;
424 
425   /* Error in input. Conflicting dimensions.  */
426 
427   err106:
428     *jstat = -106;
429     s6err("s1772",*jstat,kpos);
430     goto out;
431 
432   /* Error in lower level routine.  */
433 
434   error :
435     *jstat = kstat;
436     s6err("s1772",*jstat,kpos);
437     goto out;
438 
439   out:
440     if (c0 != local && c0 != SISL_NULL) freearray(c0);
441 }
442 
443 #if defined(SISLNEEDPROTOTYPES)
444 static
445 void
s1772_s9corr(double gd[],double acoef[],double astart1,double aend1,double astart2[],double aend2[],int * corr)446 s1772_s9corr(double gd[],double acoef[],double astart1,double aend1,
447 	     double astart2[],double aend2[],int *corr)
448 #else
449 static void s1772_s9corr(gd,acoef,astart1,aend1,astart2,aend2,corr)
450      double gd[];
451      double acoef[];
452      double astart1;
453      double aend1;
454      double astart2[];
455      double aend2[];
456      int *corr;
457 #endif
458 /*
459 *********************************************************************
460 *
461 *********************************************************************
462 *
463 * PURPOSE    : To be sure that we are inside the boorder of the
464 *              parameter plan. If we are outside clipping is used
465 *	       to corrigate the step value.
466 *
467 *
468 * INPUT      : acoef[]   - Parameter values.
469 *              astart1   - The lower boorder in curve.
470 *              aend1     - The higher boorder in curve.
471 *              estart2[] - The lower boorder in surface.
472 *              eend2[]   - The higher boorder in surface.
473 *
474 *
475 *
476 * INPUT/OUTPUT : gdn   - Old and new step value.
477 *
478 *
479 * METHOD     : We are cutting a line inside a rectangle.
480 *	       In this case we always know that the startpoint of
481 *	       the line is inside the rectangel, and we may therfor
482 *	       use a simple kind of clipping.
483 *
484 *
485 * REFERENCES :
486 *
487 *
488 * WRITTEN BY : Arne Laksaa, SI, Nov 1992.
489 *
490 *********************************************************************
491 */
492 {
493   int lcorr = 0;
494   if (acoef[0] + gd[0] < astart2[0])
495     {
496        gd[0] = astart2[0] - acoef[0];
497        lcorr=1;
498     }
499   else if (acoef[0] + gd[0] > aend2[0])
500     {
501        gd[0] = aend2[0] - acoef[0];
502        lcorr=1;
503     }
504 
505   if (acoef[1] + gd[1] < astart2[1])
506     {
507        gd[1] = astart2[1] - acoef[1];
508        lcorr=1;
509     }
510   else if (acoef[1] + gd[1] > aend2[1])
511     {
512        gd[1] = aend2[1] - acoef[1];
513        lcorr=1;
514     }
515 
516   if (acoef[2] + gd[2] < astart1)
517     {
518        gd[2] = astart1 - acoef[2];
519        lcorr=1;
520     }
521   else if (acoef[2] + gd[2] > aend1)
522     {
523        gd[2] = aend1 - acoef[2];
524        lcorr=1;
525     }
526 
527   if (lcorr)
528     (*corr)++;
529   else
530     (*corr) = 0;
531 }
532 
533 #if defined(SISLNEEDPROTOTYPES)
534    static
535       void
s1772_s9dir(double * dist,double diff[],double delta[],double f[],double f_t[],double f_tt[],double g[],double g_u[],double g_v[],double g_uu[],double g_uv[],double g_vv[],int dim,int second,int * jstat)536 s1772_s9dir(double *dist,double diff[],double delta[],
537 		  double f[],double f_t[],double f_tt[],
538 		  double g[],double g_u[],double g_v[],
539 		  double g_uu[],double g_uv[],double g_vv[],
540 		  int dim,int second,int* jstat)
541 #else
542 static void s1772_s9dir(dist,diff,delta,f,f_t,f_tt,g,g_u,g_v,g_uu,
543 			g_uv,g_vv,dim,second,jstat)
544      double *dist;
545      double diff[];
546      double delta[];
547      double f[];
548      double f_t[];
549      double f_tt[];
550      double g[];
551      double g_u[];
552      double g_v[];
553      double g_uu[];
554      double g_uv[];
555      double g_vv[];
556      int    dim;
557      int    second;
558      int*   jstat;
559 #endif
560 /*
561 *********************************************************************
562 *
563 *********************************************************************
564 *
565 * PURPOSE    : To compute the distance vector and the length of the
566 *              distance vector.
567 *	       And to compute a next step on all tree parameter direction
568 *	       towards an intersection or a closest point.
569 *
570 *
571 * INPUT      : f    - Value in point on curve.
572 *              f_t  - First derevative of the curve.
573 *              f_tt - Second derevative of the curve.
574 *              g    - Value in point on surface.
575 *	       g_u  - Derevative of the surface in first par-dir.
576 *	       g_u  - Derevative of the surface in second par-dir.
577 *	       g_uu - Second derevative of the surface in first par-dir.
578 *	       g_uv - Cross derevative of the surface.
579 *	       g_vv - Second derevative of the surface in second par-dir.
580 *	       dim    - Dimension of space the curve/surface lie in.
581 *              second - 1 if we have to use second order method
582 *			0 if only first order method.
583 *
584 * OUTPUT     : dist    - The lengt of the different vector.
585 *	       diff[]  - The differens vector.
586 *	       delta[] - Relative step parameter values towards intersection on
587 *                        the curve delta[2] and the surface (delta[0],delta[1]).
588 *
589 *
590 * METHOD     : We have a point on the curve and a point on the surface.
591 *	       The distance vector between this two point are going towards
592 *	       eider zero length or to be orthogonal to the derivative on
593 *	       the curve and the derivatives on the surface.
594 *	       The method is to use Newton itarations.
595 *	       The dot product between the distance vecore and the derivatives
596 *	       are going to be zero.
597 *	       We then use Taylor expasion bouth on the position and
598 *	       the derivatives. Then we just remove the second degree parts
599 *	       of the eqations. The matrix is then splited into a first order
600 *	       part A:
601 *		     | -g_u |
602 *		 K = | -g_v |    ,and       A = K*K(transpost)
603 *		     |  f_t |
604 *
605 *	         where f_t is the first derivative of the curve,
606 *	         and  g_u is the first derivative of the surface in first dir,
607 *	         and  g_v is the first derivative of the surface in second dir,
608 *
609 *	       and a second order part B:
610 *		     | -<d,g_uu>   -<d,g_uv> 		 |
611 *		 B = | -<d,g_uv>   -<d,g_vv>		 |
612 *		     |  			<d,f_tt> |
613 *
614 *	         where d is the distance vector,
615 *	         and f_tt is second derivative of the curve,
616 *	         and  g_uu is second derivative of the surface in first dir,
617 *	         and  g_vv is second derivative of the surface in second dir,
618 *	         and  g_uv is cross derivative of the surface.
619 *
620 *	       We then has the following possible eqations:
621 *
622 *	                 (A+B)*delta = -K*d, or
623 *		             A*delta = -K*d, or
624 *	          K(transpost)*delta = -d.
625 *
626 *
627 *	       The solutions of these matrix equations are the
628 *	       following function.
629 *
630 *
631 * REFERENCES :
632 *
633 *
634 * WRITTEN BY : Arne Laksaa, SI, Nov 1992.
635 *
636 *********************************************************************
637 */
638 {
639   int kstat;			/* Local status variable. 		  */
640   double a1,a2,a3,a4,a5,a6;	/* The A matrix, diagonal and A12 A13 A23.*/
641   double b1,b2,b3,b4;		/* The B matrix, diagonal and B23.	  */
642   double A[9],mat[9];		/* Matrix in linear equation to be solved */
643   double h[3];			/* Left side in the equation.		  */
644   double x[3];			/* Left side in the equation.		  */
645   double r[3];			/* Left side in the equation.		  */
646   double det;			/* Determinant for matrix.		  */
647   long double ss,aa,xx,bb;	/* For use in iterative improvement.      */
648   int    piv[3];		/* Pivotation array                       */
649   int k,k3,j;			/* Counters.				  */
650 
651   /* Initialize */
652   delta[0] = delta[1] = delta[2] = 0.0;
653 
654   /* Computing the different vector */
655 
656   s6diff(f,g,dim,diff);
657 
658   /* Computing the length of the different vector. */
659 
660   *dist = s6length(diff,dim,&kstat);
661   if (kstat<0) goto error;
662 
663   if (second || dim != 3)
664   {
665      a1 = s6scpr(f_t,f_t,dim);
666      a2 = s6scpr(g_u,g_u,dim);
667      a3 = s6scpr(g_v,g_v,dim);
668      a4 = s6scpr(f_t,g_u,dim);
669      a5 = s6scpr(f_t,g_v,dim);
670      a6 = s6scpr(g_u,g_v,dim);
671   }
672 
673   if (second)
674   {
675      b1 = s6scpr(diff,f_tt,dim);
676      b2 = s6scpr(diff,g_uu,dim);
677      b3 = s6scpr(diff,g_vv,dim);
678      b4 = s6scpr(diff,g_uv,dim);
679   }
680   else
681     b1=b2=b3=b4=0;
682 
683   if (second || dim != 3)
684   {
685      mat[0] = a2-b2;	mat[1] = a6-b4;		mat[2] = -a4;
686      mat[3] = a6-b4;	mat[4] = a3-b3;		mat[5] = -a5;
687      mat[6] = -a4;	mat[7] = -a5;		mat[8] = a1+b1;
688 
689      h[0] =  s6scpr(diff,g_u,dim);
690      h[1] =  s6scpr(diff,g_v,dim);
691      h[2] = -s6scpr(diff,f_t,dim);
692   }
693   else
694   {
695      mat[0] = g_u[0];	mat[1] = g_v[0];	mat[2] = -f_t[0];
696      mat[3] = g_u[1];	mat[4] = g_v[1];	mat[5] = -f_t[1];
697      mat[6] = g_u[2]; 	mat[7] = g_v[2];	mat[8] = -f_t[2];
698 
699      h[0] =  diff[0];
700      h[1] =  diff[1];
701      h[2] =  diff[2];
702   }
703 
704   for (k=0;k<9;k++) A[k]=mat[k];
705   for (k=0;k<3;k++) x[k]=h[k];
706 
707   det = A[0]*(A[4]*A[8]-A[5]*A[7])
708       - A[1]*(A[3]*A[8]-A[5]*A[6])
709       + A[2]*(A[3]*A[7]-A[4]*A[6]);
710   if (fabs(det) < 1.0e-16)
711   {
712      *jstat = 1;
713      goto out;
714   }
715 
716   /* solve the linear 3x3 system */
717 
718   /*  s1772_s6lufacp(mat,piv,&kstat); */
719   s6lufacp(mat,piv,3,&kstat);
720   if (kstat<0) goto error;
721   if (kstat == 1)
722   {
723      *jstat = 1;
724      goto out;
725   }
726 
727   s6lusolp(mat,x,piv,3,&kstat);
728   if (kstat<0) goto error;
729   if (kstat == 1)
730   {
731      *jstat = 1;
732      goto out;
733   }
734 
735   for (k=0;k<3;k++) delta[k] = x[k];
736 
737   for (k=k3=0; k<3; k++,k3+=3)
738   {
739      for (ss=0.0,j=0; j<3; j++)
740      {
741 	aa = A[j+k3];
742 	xx = x[j];
743 	ss += aa*xx;
744      }
745      bb = h[k];
746      ss = bb-ss;
747      r[k] = ss;
748   }
749   s6lusolp(mat,r,piv,3,&kstat);
750   if (kstat<0) goto error;
751   if (kstat == 1)
752   {
753      *jstat = 1;
754      goto out;
755   }
756 
757   for (k=0;k<3;k++) delta[k] = x[k] + r[k];
758 
759   /* if (debug_flag) printf("\nITERATIV IMPROVES: r = (%g %g %g) ",
760 			 delta[0]-x[0],delta[1]-x[1],delta[2]-x[2]); */
761 
762   *jstat = 0;
763   goto out;
764 
765   error :
766     *jstat = kstat;
767     s6err("s1772_s9dir",*jstat,0);
768     goto out;
769 
770   out:
771     return;
772 }
773 
774 
775 #if defined(SISLNEEDPROTOTYPES)
776    static
777       void
s1772_s6sekant1(SISLCurve * pcurve,SISLSurf * psurf,double par_val[],double delta,double * dist,double aepsge,double astart1,double estart2[],double aend1,double eend2[],double c0[],double s0[],double norm[],int * jstat)778 s1772_s6sekant1(SISLCurve *pcurve,SISLSurf *psurf,
779 		 double  par_val[], double delta, double *dist, double aepsge,
780 		 double astart1,double estart2[],double aend1,double eend2[],
781 		 double c0[], double s0[], double norm[],
782 		 int *jstat)
783 #else
784 static void s1772_s6sekant1(pcurve,psurf,par_val,delta,dist,aepsge,
785 			   astart1,estart2,aend1,eend2,c0,s0,norm,jstat)
786      SISLCurve  *pcurve;
787      SISLSurf   *psurf;
788      double  par_val[];
789      double  delta;
790      double  *dist;
791      double aepsge;
792      double astart1;
793      double estart2[];
794      double aend1;
795      double eend2[];
796      double c0[];
797      double s0[];
798      double norm[];
799      int    *jstat;
800 #endif
801 /*
802 *********************************************************************
803 *
804 *********************************************************************
805 *
806 * PURPOSE    : Sekant methode iteration on the distance function between
807 *              a curve and a surface to find a closest point
808 *              or an intersection point.
809 *
810 *
811 * INPUT      : pcurve    - Pointer to the curve in the intersection.
812 *              psurf     - Pointer to the surface in the intersection.
813 *              delta     - Parameter distance on curve beetveen start values.
814 *              aepsge    - Geometry resolution.
815 *              c0        - Array for use in evaluation.
816 *              s0        - Array for use in evaluation.
817 *              norm      - Array for use in evaluation.
818 * INPUT/
819 * OUTPUT     : par_val[] - Parameter value of the surface in
820 *                          intersection point.
821 *              dist      - Distance in space.
822 * OUTPUT     : jstat     - status messages
823 *                                = 3   : A minimum distanse found.
824 *                                = 2   : Nothing found.
825 *                                = 1   : Intersection found.
826 *                                < 0   : error.
827 *
828 *
829 * METHOD     : Sekant mothode in tree parameter directions.
830 *
831 *
832 * REFERENCES :
833 *
834 *
835 * WRITTEN BY : Arne Laksaa, SI, Nov 1992
836 * Revised by : Christophe Rene Birkeland, SINTEF Oslo, May 1993.
837 *
838 *********************************************************************
839 */
840 {
841   int ki,kj;		    /* Counter.					   */
842   int kstat = 0;            /* Local status variable.                      */
843   int kpos = 0;             /* Position of error.                          */
844   int dim;                  /* Dimension of space the curves lie in        */
845   int knbit;                /* Number of iterations                        */
846   double cu_val[2];	    /* Parameter values on curve.		   */
847   double new_cu_val;	    /* New parameter value on curve.		   */
848   double *diff;		    /* Difference vector between curve surface.    */
849   double y[2],new_y,delta_y;/* Signed distance.				   */
850   SISLPoint *pt=SISL_NULL;	    /* Point for use in closest point point/surface*/
851   int cu_left = 0;	    /* Keep left knot information for evaluator.   */
852   int s_left1 = 0;	    /* Keep left knot information for evaluator.   */
853   int s_left2 = 0;	    /* Keep left knot information for evaluator.   */
854   int shift = 0;	    /* Mark that the diriction have been changed.  */
855 
856   *jstat = 0;
857 
858   /* Test input.  */
859 
860   if (pcurve->idim != psurf->idim) goto err106;
861   dim = pcurve->idim;
862   diff = c0 + dim;
863 
864   if ((pt = newPoint(c0,dim,0)) == SISL_NULL) goto err101;
865 
866   if (delta == 0.0) delta =1e-15;
867 
868   if ((par_val[2] == astart1 && delta < 0.0) ||
869       (par_val[2] == aend1   && delta > 0.0))
870   {
871      delta = -delta;
872      shift++;
873   }
874 
875   if (fabs(delta) < (aend1 -astart1)/100.0)
876   {
877      if (delta < 0.0)
878 	delta = (astart1 - aend1)/100.0;
879      else
880 	delta = (aend1 - astart1)/100.0;
881   }
882   else if (fabs(delta) > (aend1 -astart1)/10.0)
883   {
884      if (delta < 0.0)
885 	delta = (astart1 - aend1)/10.0;
886      else
887 	delta = (aend1 - astart1)/10.0;
888   }
889 
890 
891   cu_val[0] = par_val[2];
892   s1221(pcurve,0,cu_val[0],&cu_left,pt->ecoef,&kstat);
893   if (kstat < 0) goto error;
894   s1773(pt,psurf,aepsge,estart2,eend2,par_val,par_val,&kstat);
895   if (kstat < 0) goto error;
896   s1421(psurf,1,par_val,&s_left1,&s_left2,s0,norm,&kstat);
897   if (kstat < 0) goto error;
898   for(kj=0; kj<dim; kj++) diff[kj] = s0[kj] - pt->ecoef[kj];
899   new_y = s6norm(norm,dim,norm,&kstat);
900   if (kstat == 0)
901   {
902      (*dist)=s6length(diff,dim,&kstat);
903      new_cu_val = cu_val[0];
904      goto out;
905   }
906   if (((*dist)=s6length(diff,dim,&kstat)) < aepsge)
907   {
908      new_cu_val = cu_val[0];
909      goto out;
910   }
911   y[0] = s6scpr(norm,diff,dim);
912   cu_val[1] = cu_val[0] + delta;
913 
914   for (ki=0; ki<20; ki++)
915   {
916      s1221(pcurve,0,cu_val[1],&cu_left,pt->ecoef,&kstat);
917      if (kstat < 0) goto error;
918      s1773(pt,psurf,aepsge,estart2,eend2,par_val,par_val,&kstat);
919      if (kstat < 0) goto error;
920      s1421(psurf,1,par_val,&s_left1,&s_left2,s0,norm,&kstat);
921      if (kstat < 0) goto error;
922      for(kj=0; kj<dim; kj++) diff[kj] = s0[kj] - pt->ecoef[kj];
923      new_y = s6norm(norm,dim,norm,&kstat);
924      if (kstat == 0)
925      {
926 	(*dist)=s6length(diff,dim,&kstat);
927 	new_cu_val = cu_val[1];
928 	goto out;
929      }
930      if (((*dist)=s6length(diff,dim,&kstat)) < aepsge)
931      {
932 	new_cu_val = cu_val[1];
933 	goto out;
934      }
935      y[1] = s6scpr(norm,diff,dim);
936      new_y = y[1]/y[0];
937      if (new_y > 1.0000000000001)
938      {
939 	if (shift)
940 	{
941 	   new_cu_val = cu_val[1];
942 	   goto out;
943 	}
944 	delta = -delta;
945 	/* ALA, UJK, sept 93, update cu_val[1]*/
946 	cu_val[1] = cu_val[0] + delta;
947 	shift++;
948      }
949      else if (y[0]*y[1] <= 0.0 || fabs(new_y) < 0.5) break;
950      else
951      {
952 	if (cu_val[1]+delta <= aend1 &&
953 	    cu_val[1]+delta >= astart1) cu_val[1] += delta;
954 	else if (cu_val[1] < aend1)  	cu_val[1] = aend1;
955 	else if (cu_val[1] > astart1)   cu_val[1] = astart1;
956 	else
957 	{
958 	   new_cu_val = cu_val[1];
959 	   goto out;
960 	}
961      }
962   }
963 
964   if (ki == 20)
965   {
966      *jstat = 2;
967      goto out;
968   }
969 
970   for (knbit=0; knbit < 50; knbit++)
971   {
972      delta_y = y[0]-y[1];
973      if (fabs(delta_y) < REL_COMP_RES) break;
974 
975      new_cu_val = cu_val[1] + y[1]*(cu_val[1]-cu_val[0])/delta_y;
976      if (new_cu_val >= aend1)
977      {
978 	new_cu_val = aend1;
979 	if (cu_val[0] == aend1 || cu_val[1] == aend1) goto out;
980      }
981      else if (new_cu_val <= astart1)
982      {
983 	new_cu_val = astart1;
984 	if (cu_val[0] == astart1 || cu_val[1] == astart1) goto out;
985      }
986 
987      s1221(pcurve,0,new_cu_val,&cu_left,pt->ecoef,&kstat);
988      if (kstat < 0) goto error;
989      s1773(pt,psurf,aepsge,estart2,eend2,par_val,par_val,&kstat);
990      if (kstat < 0) goto error;
991      s1421(psurf,1,par_val,&s_left1,&s_left2,s0,norm,&kstat);
992      if (kstat < 0) goto error;
993      for(kj=0; kj<dim; kj++) diff[kj] = s0[kj] - pt->ecoef[kj];
994      new_y = s6norm(norm,dim,norm,&kstat);
995      if (kstat == 0)
996      {
997 	(*dist) = s6length(diff,dim,&kstat);
998 	goto out;
999      }
1000      if (((*dist)=s6length(diff,dim,&kstat)) < aepsge) goto out;
1001      new_y = s6scpr(norm,diff,dim);
1002 
1003      if ((y[0] < 0.0 && y[1] > 0.0) ||
1004 	 (y[0] > 0.0 && y[1] < 0.0))
1005      {
1006 	if ((new_y > 0.0 && y[0] > 0.0) ||
1007 	    (new_y < 0.0 && y[0] < 0.0))
1008 	{
1009 	   cu_val[0] = new_cu_val;
1010 	   y[0] = new_y;
1011 	}
1012 	else
1013 	{
1014 	   cu_val[1] = new_cu_val;
1015 	   y[1] = new_y;
1016 	}
1017      }
1018      else
1019      {
1020 	if ( y[0] < 0.0 && new_y > 0.0)
1021 	{
1022 	   if (y[0] < y[1])
1023 	   {
1024 	      cu_val[0] = new_cu_val;
1025 	      y[0] = new_y;
1026 	   }
1027 	   else
1028 	   {
1029 	      cu_val[1] = new_cu_val;
1030 	      y[1] = new_y;
1031 	   }
1032 	}
1033 	else if ( y[0] > 0.0 && new_y < 0.0)
1034 	{
1035 	   if (y[0] > y[1])
1036 	   {
1037 	      cu_val[0] = new_cu_val;
1038 	      y[0] = new_y;
1039 	   }
1040 	   else
1041 	   {
1042 	      cu_val[1] = new_cu_val;
1043 	      y[1] = new_y;
1044 	   }
1045 	}
1046 	else if (y[0] > 0.0)
1047 	{
1048 	   if (y[0] > y[1])
1049 	   {
1050 	      if (new_y >=  y[0]) break;
1051 	      cu_val[0] = new_cu_val;
1052 	      y[0] = new_y;
1053 	   }
1054 	   else
1055 	   {
1056 	      if (new_y >=  y[1]) break;
1057 	      cu_val[1] = new_cu_val;
1058 	      y[1] = new_y;
1059 	   }
1060 
1061 	}
1062 	else if (y[0] < 0.0)
1063 	{
1064 	   if (y[0] < y[1])
1065 	   {
1066 	      if (new_y <=  y[0]) break;
1067 	      cu_val[0] = new_cu_val;
1068 	      y[0] = new_y;
1069 	   }
1070 	   else
1071 	   {
1072 	      if (new_y <=  y[1]) break;
1073 	      cu_val[1] = new_cu_val;
1074 	      y[1] = new_y;
1075 	   }
1076 	}
1077      }
1078   }
1079 
1080   /* Iteration completed.  */
1081 
1082   goto out;
1083 
1084   /* Error in allocation */
1085 
1086   err101:
1087     *jstat = -101;
1088     s6err("s1772_s6sekant1",*jstat,kpos);
1089     goto out;
1090 
1091   /* Error in input. Conflicting dimensions.  */
1092 
1093   err106:
1094     *jstat = -106;
1095     s6err("s1772_s6sekant1",*jstat,kpos);
1096     goto out;
1097 
1098   /* Error in lower level routine.  */
1099 
1100   error :
1101     *jstat = kstat;
1102     s6err("s1772_s6sekant1",*jstat,kpos);
1103     goto out;
1104 
1105   out:
1106     par_val[2] = new_cu_val;
1107     if(pt) freePoint(pt);
1108 }
1109 
1110 
1111 #if defined(SISLNEEDPROTOTYPES)
1112    static
1113       int
s1772_s6local_pretop(double dist,double diff[],double normal[],double f[],double f_t[],double f_tt[],double s[],double s_u[],double s_v[],double s_uu[],double s_uv[],double s_vv[],int dim,int * jstat)1114 s1772_s6local_pretop(double dist,double diff[],double normal[],
1115 		     double f[],double f_t[],double f_tt[],
1116 		     double s[],double s_u[],double s_v[],
1117 		     double s_uu[],double s_uv[],double s_vv[],
1118 		     int dim, int*jstat)
1119 #else
1120 static int s1772_s6local_pretop(dist,diff,normal,f,f_t,f_tt,s,s_u,s_v,s_uu,
1121 			s_uv,s_vv,dim,jstat)
1122      double dist;
1123      double diff[];
1124      double normal[];
1125      double f[];
1126      double f_t[];
1127      double f_tt[];
1128      double s[];
1129      double s_u[];
1130      double s_v[];
1131      double s_uu[];
1132      double s_uv[];
1133      double s_vv[];
1134      int    dim;
1135      int    *jstat;
1136 #endif
1137 /*
1138 ***********************************************************************
1139 *
1140 ************************************************************************
1141 *
1142 *   PURPOSE : To find if we have a minimum or a maximum or a turning
1143 *             point situation. This function assume that it is a singular
1144 *	      situation.
1145 *
1146 *
1147 *
1148 * INPUT      : dist      - The lengt of the different vector.
1149 *	       diff[]    - The differens vector.
1150 *	       normal[]  - The normal vector on surface.
1151 *              f    - Value in point on curve.
1152 *              f_t  - First derevative of the curve.
1153 *              f_tt - Second derevative of the curve.
1154 *              s    - Value in point on surface.
1155 *	       s_u  - Derevative of the surface in first par-dir.
1156 *	       s_u  - Derevative of the surface in second par-dir.
1157 *	       s_uu - Second derevative of the surface in first par-dir.
1158 *	       s_uv - Cross derevative of the surface.
1159 *	       s_vv - Second derevative of the surface in second par-dir.
1160 *	       dim    - Dimension of space the curve/surface lie in.
1161 *
1162 *   OUTPUT  :  return value - 	= -1: degenerated system.
1163 *				=  0: Max or turning point.
1164 *				=  1: Minimum position.
1165 *
1166 *              jstat        - Status variable.
1167 *                       	< 0 : error.
1168 *                       	= 0 : ok.
1169 *                       	> 0 : warning.
1170 *
1171 *
1172 *   METHOD  : Computing and interpretation of curvatures.
1173 *
1174 *   REFERENCES :
1175 *-
1176 *   CALLS      :
1177 *
1178 *   WRITTEN BY : Arne Laksaa, SI, Oslo, des. 1992.
1179 *
1180 ************************************************************************
1181 */
1182 {
1183   int kstat = 0;	/* Status variable.				*/
1184   int ki;		/* Counter.					*/
1185   int return_val;	/* For return value.				*/
1186   double a1,a2,a3,a4;   /* Matrix.					*/
1187   double *S_u = SISL_NULL;	/* Normalized s_u.				*/
1188   double *S_v;		/* Normalized s_v.				*/
1189   double *S_uxS_v;	/* Cross between S_u and S_v.			*/
1190   double *s_d;		/* Second derevative in diriction f_t.		*/
1191   double *N;		/* Normalized normal.				*/
1192   double *d_uv;		/* Normalized direction vector in par-plane.	*/
1193   double local[17];	/* Local array for allocations.			*/
1194 
1195   *jstat = 0;
1196 
1197   if (s6ang(diff,normal,dim) > ANGULAR_TOLERANCE) goto warn1;
1198 
1199   /* Allocate local used memory and set value pointers.*/
1200 
1201   if (dim > 3)
1202   {
1203      S_u = newarray(5*dim+2,double);
1204      if (S_u == SISL_NULL) goto err101;
1205   }
1206   else
1207      S_u  = local;
1208 
1209   S_v     = S_u+dim;
1210   S_uxS_v = S_v+dim;
1211   s_d     = S_uxS_v+dim;
1212   N       = s_d+dim;
1213   d_uv    = N+dim;
1214 
1215   s6norm(s_u,dim,S_u,&kstat);
1216   if (kstat == 0)  goto warn1;
1217   s6norm(s_v,dim,S_v,&kstat);
1218   if (kstat == 0)  goto warn1;
1219   s6crss(S_u,S_v,S_uxS_v);
1220   a1 = s6scpr(S_u,S_v,dim);
1221   a2 = s6scpr(f_t,S_u,dim);
1222   a3 = s6scpr(f_t,S_v,dim);
1223   if ((a4 = s6scpr(S_uxS_v,S_uxS_v,dim)) < SINGULAR) goto warn1;
1224 
1225   d_uv[0] = (a2 - a1*a3)/a4;
1226   d_uv[1] = (a3 - a1*a2)/a4;
1227   s6norm(d_uv,2,d_uv,&kstat);
1228   if (kstat == 0)  goto warn1;
1229 
1230   a1 = d_uv[0]*d_uv[0];
1231   a2 = d_uv[1]*d_uv[1];
1232   a3 = 2*d_uv[0]*d_uv[1];
1233 
1234   for (ki=0; ki<dim; ki++)
1235      s_d[ki] = a1*s_uu[ki] + a3*s_uv[ki] + a2*s_vv[ki];
1236 
1237   for (ki=0; ki<dim; ki++)
1238      N[ki] = diff[ki]/dist;
1239 
1240   a1 = s6scpr(N,f_tt,dim) - s6scpr(N,s_d,dim);
1241 
1242   return_val = a1 > 1.0e-10;
1243   goto out;
1244 
1245   /* Error in allocation */
1246 
1247   err101:
1248     *jstat = -101;
1249     s6err("s1772_s6local_pretop",*jstat,0);
1250     return_val = 0;
1251     goto out;
1252 
1253   /* Degenerated system.  */
1254 
1255   warn1:
1256     return_val = -1;
1257     goto out;
1258 
1259   out:
1260     if (S_u != local && S_u != SISL_NULL) freearray(S_u);
1261     return return_val;
1262 }
1263 
1264 
1265 
1266 
1267