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