]> icculus.org git repositories - btb/d2x.git/blob - main/editor/curves.c
more header cleanup
[btb/d2x.git] / main / editor / curves.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * curve generation stuff
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "conf.h"
22 #endif
23
24 #include <time.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <stdarg.h>
30 #ifdef __MSDOS__
31 #include <conio.h>
32 #include <dos.h>
33 #endif
34
35 #include "inferno.h"
36 #include "mono.h"
37 #include "maths.h"
38 #include "gr.h"
39 #include "key.h"
40 #include "editor.h"
41
42
43 #define ONE_OVER_SQRT2 F1_0 * 0.707106781
44 #define CURVE_RIGHT 1
45 #define CURVE_UP 2
46
47 segment *OriginalSeg;
48 segment *OriginalMarkedSeg;
49 int OriginalSide;
50 int OriginalMarkedSide;
51 segment *CurveSegs[MAX_SEGMENTS];
52 int CurveNumSegs;
53 const fix Mh[4][4] = { { 2*F1_0, -2*F1_0,  1*F1_0,  1*F1_0 },
54                        {-3*F1_0,  3*F1_0, -2*F1_0, -1*F1_0 },
55                        { 0*F1_0,  0*F1_0,  1*F1_0,  0*F1_0 },
56                        { 1*F1_0,  0*F1_0,  0*F1_0,  0*F1_0 } };
57
58 void generate_banked_curve(fix maxscale, vms_equation coeffs);
59
60 void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs) {
61 // Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t~3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4
62
63     coeffs->n.x3 = fixmul(2*F1_0,p1->x) - fixmul(2*F1_0,p4->x) + r1->x + r4->x;
64     coeffs->n.x2 = fixmul(-3*F1_0,p1->x) + fixmul(3*F1_0,p4->x) - fixmul(2*F1_0,r1->x) - fixmul(1*F1_0,r4->x);
65     coeffs->n.x1 = r1->x;
66     coeffs->n.x0 = p1->x;
67     coeffs->n.y3 = fixmul(2*F1_0,p1->y) - fixmul(2*F1_0,p4->y) + r1->y + r4->y;
68     coeffs->n.y2 = fixmul(-3*F1_0,p1->y) + fixmul(3*F1_0,p4->y) - fixmul(2*F1_0,r1->y) - fixmul(1*F1_0,r4->y);
69     coeffs->n.y1 = r1->y;
70     coeffs->n.y0 = p1->y;
71     coeffs->n.z3 = fixmul(2*F1_0,p1->z) - fixmul(2*F1_0,p4->z) + r1->z + r4->z;
72     coeffs->n.z2 = fixmul(-3*F1_0,p1->z) + fixmul(3*F1_0,p4->z) - fixmul(2*F1_0,r1->z) - fixmul(1*F1_0,r4->z);
73     coeffs->n.z1 = r1->z;
74     coeffs->n.z0 = p1->z;
75
76 }
77
78 vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t) {
79     fix t2, t3;
80     vms_vector coord;
81
82     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
83
84     t2 = fixmul(t,t); t3 = fixmul(t2,t);
85
86     coord.x = fixmul(coeffs->n.x3,t3) + fixmul(coeffs->n.x2,t2) + fixmul(coeffs->n.x1,t) + coeffs->n.x0;
87     coord.y = fixmul(coeffs->n.y3,t3) + fixmul(coeffs->n.y2,t2) + fixmul(coeffs->n.y1,t) + coeffs->n.y0;
88     coord.z = fixmul(coeffs->n.z3,t3) + fixmul(coeffs->n.z2,t2) + fixmul(coeffs->n.z1,t) + coeffs->n.z0;
89
90     return coord;
91 }
92
93
94 fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist) {
95          vms_vector coord;
96     fix t, diff;
97
98     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
99
100     for (t=t0;t<1*F1_0;t+=0.001*F1_0) {
101         coord = evaluate_curve(coeffs, 3, t);
102         diff = dist - vm_vec_dist(&coord, p0);
103         if (diff<ACCURACY)   //&&(diff>-ACCURACY))
104             return t;
105     }
106     return -1*F1_0;
107
108 }
109
110 void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) {
111     fix t2;
112
113     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
114
115     t2 = fixmul(t0,t0);
116
117     dir->x = fixmul(3*F1_0,fixmul(coeffs->n.x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.x2,t0)) + coeffs->n.x1;
118     dir->y = fixmul(3*F1_0,fixmul(coeffs->n.y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.y2,t0)) + coeffs->n.y1;
119     dir->z = fixmul(3*F1_0,fixmul(coeffs->n.z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.z2,t0)) + coeffs->n.z1;
120     vm_vec_normalize( dir );
121
122 }
123
124 void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t) {
125     vms_vector coord, dcoord;
126     fix t, dt;
127
128     gr_setcolor(15);
129     gr_box(  75,  40, 325, 290 );
130     gr_box(  75, 310, 325, 560 );
131     gr_box( 475, 310, 725, 560 );
132     //gr_pal_fade_in( grd_curscreen->pal );
133
134     for (t=min_t;t<max_t-del_t;t+=del_t) {
135         dt = t+del_t;
136
137         coord = evaluate_curve(coeffs, 3, t);
138         dcoord = evaluate_curve(coeffs, 3, dt);
139
140         gr_setcolor(9);
141         gr_line (  75*F1_0 + coord.x, 290*F1_0 - coord.z,  75*F1_0 + dcoord.x, 290*F1_0 - dcoord.z );
142         gr_setcolor(10);
143         gr_line (  75*F1_0 + coord.x, 560*F1_0 - coord.y,  75*F1_0 + dcoord.x, 560*F1_0 - dcoord.y );
144         gr_setcolor(12);
145         gr_line ( 475*F1_0 + coord.z, 560*F1_0 - coord.y, 475*F1_0 + dcoord.z, 560*F1_0 - dcoord.y );
146
147     }
148
149 }
150
151
152 vms_vector *vm_vec_interp(vms_vector *result, vms_vector *v0, vms_vector *v1, fix scale) {
153     vms_vector tvec;
154
155         vm_vec_sub(&tvec, v1, v0);
156     vm_vec_scale_add(result, v0, &tvec, scale);
157     vm_vec_normalize(result);
158     return result;
159 }
160
161 vms_vector p1, p4, r1, r4;
162 vms_vector r4t, r1save;
163
164 int generate_curve( fix r1scale, fix r4scale ) {
165     vms_vector vec_dir, tvec;
166     vms_vector coord,prev_point;
167     vms_equation coeffs;
168     fix enddist, nextdist;
169     int firstsegflag;
170     fix t, maxscale;
171     fixang rangle, uangle;
172
173     compute_center_point_on_side( &p1, Cursegp, Curside );
174
175     switch( Curside ) {
176         case WLEFT:
177             extract_right_vector_from_segment(Cursegp, &r1);
178             vm_vec_scale( &r1, -F1_0 );
179             break;
180         case WTOP:
181             extract_up_vector_from_segment(Cursegp, &r1);
182             break;
183         case WRIGHT:
184             extract_right_vector_from_segment(Cursegp, &r1);
185             break;
186         case WBOTTOM:
187             extract_up_vector_from_segment(Cursegp, &r1);
188             vm_vec_scale( &r1, -F1_0 );
189             break;
190         case WBACK:
191             extract_forward_vector_from_segment(Cursegp, &r1);
192             break;
193         case WFRONT:
194             extract_forward_vector_from_segment(Cursegp, &r1);
195             vm_vec_scale( &r1, -F1_0 );
196             break;
197         }            
198
199     compute_center_point_on_side( &p4, Markedsegp, Markedside );
200
201     switch( Markedside ) {
202         case WLEFT:
203             extract_right_vector_from_segment(Markedsegp, &r4);
204             extract_up_vector_from_segment(Markedsegp, &r4t);
205             break;
206         case WTOP:
207             extract_up_vector_from_segment(Markedsegp, &r4);
208             vm_vec_scale( &r4, -F1_0 );
209             extract_forward_vector_from_segment(Markedsegp, &r4t);
210             vm_vec_scale( &r4t, -F1_0 );
211             break;
212         case WRIGHT:
213             extract_right_vector_from_segment(Markedsegp, &r4);
214             vm_vec_scale( &r4, -F1_0 );
215             extract_up_vector_from_segment(Markedsegp, &r4t);
216             break;
217         case WBOTTOM:
218             extract_up_vector_from_segment(Markedsegp, &r4);
219             extract_forward_vector_from_segment(Markedsegp, &r4t);
220             break;
221         case WBACK:
222             extract_forward_vector_from_segment(Markedsegp, &r4);
223             vm_vec_scale( &r4, -F1_0 );
224             extract_up_vector_from_segment(Markedsegp, &r4t);
225             break;
226         case WFRONT:
227             extract_forward_vector_from_segment(Markedsegp, &r4);
228             extract_up_vector_from_segment(Markedsegp, &r4t);
229             break;
230         }
231
232     r1save = r1;
233     tvec = r1;
234     vm_vec_scale(&r1,r1scale);
235     vm_vec_scale(&r4,r4scale);
236
237     create_curve( &p1, &p4, &r1, &r4, &coeffs );
238     OriginalSeg = Cursegp;
239     OriginalMarkedSeg = Markedsegp;
240     OriginalSide = Curside;
241     OriginalMarkedSide = Markedside;
242     CurveNumSegs = 0;
243     coord = prev_point = p1;
244
245     t=0;
246     firstsegflag = 1;
247     enddist = F1_0; nextdist = 0;
248     while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
249             vms_matrix  rotmat,rotmat2;
250                         vms_vector      tdest;
251
252             if (firstsegflag==1)
253                 firstsegflag=0;
254             else
255                 extract_forward_vector_from_segment(Cursegp, &tvec);
256             nextdist = vm_vec_mag(&tvec);                                   // nextdist := distance to next point
257             t = curve_dist(&coeffs, 3, t, &prev_point, nextdist);               // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve)
258             coord = evaluate_curve(&coeffs, 3, t);                                          // coord := point about forward vector magnitude units away from prev_point
259             enddist = vm_vec_dist(&coord, &p4);                  // enddist := distance from current to end point, vec_dir used as a temporary variable
260             //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
261             vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
262         if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
263             med_extract_matrix_from_segment( Cursegp,&rotmat );                   // rotmat := matrix describing orientation of Cursegp
264                         vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp
265                         vec_dir = tdest;
266
267             vm_vector_2_matrix(&rotmat2,&vec_dir,NULL,NULL);
268 //            mprintf(0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3));
269 //           mprintf(0, "  [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6));
270 //            mprintf(0, "  [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9));
271
272             med_rotate_segment( Cursegp, &rotmat2 );
273                         prev_point = coord;
274             Curside = Side_opposite[AttachSide];
275
276             CurveSegs[CurveNumSegs]=Cursegp;
277             CurveNumSegs++;
278         } else return 0;
279         }
280
281     extract_up_vector_from_segment( Cursegp,&tvec );
282     uangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
283     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
284     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
285     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
286     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
287     extract_right_vector_from_segment( Cursegp,&tvec );
288     rangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
289     if (rangle >= F1_0/8) rangle -= F1_0/4;
290     if (rangle >= F1_0/8) rangle -= F1_0/4;
291     if (rangle <= -F1_0/8) rangle += F1_0/4;
292     if (rangle <= -F1_0/8) rangle += F1_0/4;
293
294     if ((uangle != 0) && (rangle != 0)) {
295         maxscale = CurveNumSegs*F1_0;
296 //        mprintf(0, "Banked Curve Generation.. %f.\n", f2fl(maxscale));
297         generate_banked_curve(maxscale, coeffs);
298     }
299
300     if (CurveNumSegs) {
301         med_form_bridge_segment( Cursegp, Side_opposite[AttachSide], Markedsegp, Markedside );
302         CurveSegs[CurveNumSegs] = &Segments[ Markedsegp->children[Markedside] ];
303         CurveNumSegs++;
304         }
305
306     Cursegp = OriginalSeg;
307     Curside = OriginalSide;
308
309         med_create_new_segment_from_cursegp();
310
311         //warn_if_concave_segments();
312
313     if (CurveNumSegs) return 1;
314         else return 0;
315 }
316
317 void generate_banked_curve(fix maxscale, vms_equation coeffs) {
318     vms_vector vec_dir, tvec, b4r4t;
319     vms_vector coord,prev_point;
320     fix enddist, nextdist;
321     int firstsegflag;
322     fixang rangle, uangle, angle, scaled_ang=0;
323     fix t;
324
325     if (CurveNumSegs) {
326
327     extract_up_vector_from_segment( Cursegp,&b4r4t );
328     uangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
329     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
330     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
331     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
332     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
333 //    mprintf(0, "up angle %f\n", f2fl(uangle)*360);
334
335     extract_right_vector_from_segment( Cursegp,&b4r4t );
336     rangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
337     if (rangle >= F1_0/8) rangle -= F1_0/4;
338     if (rangle >= F1_0/8) rangle -= F1_0/4;
339     if (rangle <= -F1_0/8) rangle += F1_0/4;
340     if (rangle <= -F1_0/8) rangle += F1_0/4;
341 //    mprintf(0, "right angle %f\n", f2fl(rangle)*360);
342
343     angle = uangle;
344     if (abs(rangle) < abs(uangle)) angle = rangle;
345
346         delete_curve();
347
348     coord = prev_point = p1;
349
350 #define MAGIC_NUM 0.707*F1_0
351
352     if (maxscale)
353         scaled_ang = fixdiv(angle,fixmul(maxscale,MAGIC_NUM));
354     mprintf((0, "scaled angle = %f\n", f2fl(scaled_ang)));
355
356     t=0; 
357     tvec = r1save;
358     firstsegflag = 1;
359     enddist = F1_0; nextdist = 0;
360     while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
361             vms_matrix  rotmat,rotmat2;
362             vms_vector  tdest;
363
364             if (firstsegflag==1)
365                 firstsegflag=0;
366             else
367                 extract_forward_vector_from_segment(Cursegp, &tvec);
368             nextdist = vm_vec_mag(&tvec);                                   // nextdist := distance to next point
369             t = curve_dist(&coeffs, 3, t, &prev_point, nextdist);               // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve)
370             coord = evaluate_curve(&coeffs, 3, t);                                          // coord := point about forward vector magnitude units away from prev_point
371             enddist = vm_vec_dist(&coord, &p4);                  // enddist := distance from current to end point, vec_dir used as a temporary variable
372             //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
373             vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
374         if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
375             med_extract_matrix_from_segment( Cursegp,&rotmat );                   // rotmat := matrix describing orientation of Cursegp
376                         vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp
377                         vec_dir = tdest;
378             vm_vec_ang_2_matrix(&rotmat2,&vec_dir,scaled_ang);
379 //            mprintf((0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3)));
380 //            mprintf((0, "  [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6)));
381 //            mprintf((0, "  [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9)));
382
383                         med_rotate_segment( Cursegp, &rotmat2 );
384                         prev_point = coord;
385             Curside = Side_opposite[AttachSide];
386
387             CurveSegs[CurveNumSegs]=Cursegp;
388             CurveNumSegs++;
389         }
390       }
391     }
392 }
393
394
395 void delete_curve() {
396     int i;
397
398         for (i=0; i<CurveNumSegs; i++) {
399 //        mprintf((0, "[%d] %d\n", i, CurveSegs[i]->segnum ));
400         if (CurveSegs[i]->segnum != -1)
401             med_delete_segment(CurveSegs[i]);
402     }
403     Markedsegp = OriginalMarkedSeg;
404     Markedside = OriginalMarkedSide;
405     Cursegp = OriginalSeg;
406     Curside = OriginalSide;
407         med_create_new_segment_from_cursegp();
408     CurveNumSegs = 0;
409 //    mprintf((0, "Num_segments %d\n", Num_segments));
410
411         //editor_status("");
412         //warn_if_concave_segments();
413 }
414
415 /*
416 void main() {
417     vms_vector p1;
418     vms_vector p4;
419     vms_vector r1;
420     vms_vector r4;
421     vms_equation coeffs;
422     float x, y, z;
423     vms_vector test, test2, tvec;
424     fix t, t0;
425     fix distance, dist;
426     int key;
427
428
429     key_init();
430     printf("Enter p1 (x,y,z): ");
431     scanf("%f %f %f", &x, &y, &z);
432     p1.x = x*F1_0; p1.y = y*F1_0; p1.z = z*F1_0;
433     printf("Enter p4 (x,y,z): ");
434     scanf("%f %f %f", &x, &y, &z);
435     p4.x = x*F1_0; p4.y = y*F1_0; p4.z = z*F1_0;
436     printf("Enter r1 <x,y,z>: ");
437     scanf("%f %f %f", &x, &y, &z);
438     r1.x = x*F1_0; r1.y = y*F1_0; r1.z = z*F1_0;
439     printf("Enter r4 <x,y,z>: ");
440     scanf("%f %f %f", &x, &y, &z);
441     r4.x = x*F1_0; r4.y = y*F1_0; r4.z = z*F1_0;
442
443     create_curve( &p1, &p4, &r1, &r4, &coeffs );
444
445     printf("\nQ(t) = ");
446     printf("x [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.x3), f2fl(coeffs.n.x2), f2fl(coeffs.n.x1), f2fl(coeffs.n.x0));
447     printf("       y [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.y3), f2fl(coeffs.n.y2), f2fl(coeffs.n.y1), f2fl(coeffs.n.y0));
448     printf("       z [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.z3), f2fl(coeffs.n.z2), f2fl(coeffs.n.z1), f2fl(coeffs.n.z0));
449
450     printf("\nChecking direction vectors.\n");
451
452     for (t=0*F1_0;t<1*F1_0;t+=0.1*F1_0) {
453         curve_dir(&coeffs, 3, t, &test);
454         printf(" t = %.3f  dir = <%6.3f, %6.3f, %6.3f >\n", f2fl(t), f2fl(test.x), f2fl(test.y), f2fl(test.z) );
455     }
456
457     printf("\nChecking distance function.\n");
458     printf("Enter a distance: ");
459     scanf("%f", &x);
460     distance = x*F1_0;
461     printf("Enter a (0<t<1) value: ");
462     scanf("%f", &y);
463     t0 = y*F1_0;
464
465     gr_init(15);  // 800x600 mode
466     plot_parametric(&coeffs, 0*F1_0, 1*F1_0, 0.05*F1_0);
467
468     test = evaluate_curve(&coeffs, 3, t0);
469     t = curve_dist(&coeffs, 3, t0, &test, distance);
470     test2 = evaluate_curve(&coeffs, 3, t);
471
472     dist = vm_vec_mag(vm_vec_sub(&tvec, &test, &test2));
473
474     if (t != -1*F1_0) {
475         gr_setcolor(14);
476         gr_rect(  74+f2fl(test.x), 289-f2fl(test.z),  76+f2fl(test.x), 291-f2fl(test.z) );
477         gr_rect(  74+f2fl(test.x), 559-f2fl(test.y),  76+f2fl(test.x), 561-f2fl(test.y) );
478         gr_rect( 474+f2fl(test.z), 559-f2fl(test.y), 476+f2fl(test.z), 561-f2fl(test.y) );
479         gr_setcolor(13);
480         gr_rect(  74+f2fl(test2.x), 289-f2fl(test2.z),  76+f2fl(test2.x), 291-f2fl(test2.z) );
481         gr_rect(  74+f2fl(test2.x), 559-f2fl(test2.y),  76+f2fl(test2.x), 561-f2fl(test2.y) );
482         gr_rect( 474+f2fl(test2.z), 559-f2fl(test2.y), 476+f2fl(test2.z), 561-f2fl(test2.y) );
483     }
484
485     key = -1;
486     while (1)
487         if (key == KEY_ESC) break;
488         else key = key_getch();
489
490     gr_close();
491     key_close();
492
493     if (t == -1*F1_0) {
494         printf("From t=%.3f to t=1.000, ", f2fl(t0));
495         printf("two points separated by the distance %.3f\n do not exist on this curve.\n", x);
496     }
497     else {
498         printf("\nThe distance between points at:\n");
499         printf(" t0 = %.3f  ( %6.3f,%6.3f,%6.3f ) and\n", f2fl(t0), f2fl(test.x), f2fl(test.y), f2fl(test.z));
500         printf(" t  = %.3f  ( %6.3f,%6.3f,%6.3f ) is:\n", f2fl(t), f2fl(test2.x), f2fl(test2.y), f2fl(test2.z));
501         printf(" expected: %.3f\n", x);
502         printf("  actual : %.3f\n", f2fl(dist) );
503     }
504
505 }
506 */
507
508