source: anuga_core/source/anuga/fit_interpolate/p_test.c @ 5571

Last change on this file since 5571 was 4656, checked in by duncan, 17 years ago

Ponit in polygon C code. Currently not connected to ANUGA.

File size: 24.2 KB
Line 
1/* p_test.c - point in polygon inside/outside tester.  This is
2 * simply testing and display code, the actual algorithms are in ptinpoly.c.
3 *
4 * Probably the most important thing to set for timings is TEST_RATIO (too
5 * low and the timings are untrustworthy, too high and you wait forever).
6 * Start low and see how consistent separate runs appear to be.
7 *
8 * To add a new algorithm to the test suite, add code at the spots marked
9 * with '+++'.
10 *
11 * See Usage() for command line options (or just do "p_test -?").
12 *
13 * by Eric Haines, 3D/Eye Inc, erich@eye.com
14 */
15
16/* Define TIMER to perform timings on code (need system timing function) */
17/* #define TIMER */
18
19/* Number of times to try a single point vs. a polygon, per vertex.
20 * This should be greater than 1 / ( HZ * approx. single test time in seconds )
21 * in order to get a meaningful timings difference.  200 is reasonable for a
22 * IBM PC 25 MHz 386 with no FPU, 50000 is good for an HP 720 workstation.
23 * Start low and see how consistent separate runs appear to be.
24 */
25
26#ifndef M_PI
27#define M_PI    3.14159265358979323846
28#endif
29
30#ifdef  TIMER
31#define MACHINE_TEST_RATIO      50000
32#else
33#define MACHINE_TEST_RATIO          1
34#endif
35
36/* ===========  that's all the easy stuff than can be changed  ============ */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <math.h>
41#include "ptinpoly.h"
42
43#ifdef  TIMER
44#ifdef  IBM_PC
45#include <bios.h>
46#include <time.h>
47#define HZ      CLK_TCK
48#define mGetTime(t)     (t) = biostime(0,0L) ;
49
50#else   /* UNIX */
51#include <sys/types.h>
52#include <sys/param.h>
53#include <sys/times.h>
54struct  tms     Timebuf ;
55
56#define mGetTime(t)     (t) = times(&Timebuf) ;
57#if (!(defined(sparc)||defined(__sparc__)))
58#define mGetTime(t)     (t) = times(&Timebuf) ;
59#else /* sparc (and others, you figure it out) */
60/* for Sun and others do something like: */
61#define mGetTime(t)  times(&Timebuf) ;                               \
62   (t) = Timebuf.tms_utime + Timebuf.tms_stime ;
63#endif /* sparc */
64
65#endif
66#endif
67
68#ifdef  DISPLAY
69#include <starbase.c.h>         /* HP display */
70#endif
71
72#ifndef TRUE
73#define TRUE    1
74#define FALSE   0
75#endif
76
77#ifndef HUGE
78#define HUGE    1.79769313486232e+308
79#endif
80
81#define X       0
82#define Y       1
83
84#ifdef  DISPLAY
85int     Display_Tests = 0 ;
86double  Display_Scale ;
87double  Display_OffsetX ;
88double  Display_OffsetY ;
89int     Fd ;
90#endif
91
92typedef struct {
93        double  time_total ;
94        int     test_ratio ;
95        int     test_times ;
96        int     work ;
97        char    *name ;
98        int     flag ;
99} Statistics, *pStatistics ;
100
101#define ANGLE_TEST               0
102#define BARYCENTRIC_TEST         1
103#define CROSSINGS_TEST           2
104#define EXTERIOR_TEST            3
105#define GRID_TEST                4
106#define INCLUSION_TEST           5
107#define CROSSMULT_TEST           6
108#define PLANE_TEST               7
109#define SPACKMAN_TEST            8
110#define TRAPEZOID_TEST           9
111#define WEILER_TEST              10
112/* +++ add new name here and increment TOT_NUM_TESTS +++ */
113#define TOT_NUM_TESTS            11
114
115Statistics      St[TOT_NUM_TESTS] ;
116
117char    *TestName[] = {
118        "angle",
119        "barycentric",
120        "crossings",
121        "exterior",
122        "grid",
123        "inclusion",
124        "cross-mult",
125        "plane",
126        "spackman",
127        "trapezoid",
128        "weiler" } ;
129/* +++ add new name here +++ */
130
131/* minimum & maximum number of polygon vertices to generate */
132#define TOT_VERTS       1000
133static int      Min_Verts = 3 ;
134static int      Max_Verts = 6 ;
135
136/* Test polygons are generated by going CCW in a circle around the origin from
137 * the X+ axis around and generating vertices.  The radius is how big the
138 * circumscribing circle is, the perturbation is how much each vertex is varied.
139 * So, radius 1 and perturbation 0 gives a regular, inscribed polygon;
140 * radius 0 and perturbation 1 gives a totally random polygon in the
141 * space [-1,1)
142 */
143static double   Vertex_Radius = 1.0 ;
144static double   Vertex_Perturbation = 0.0 ;
145
146/* A box is circumscribed around the test polygon.  Making this box bigger
147 * is useful for a higher rejection rate.  For example, a ray tracing bounding
148 * box usually contains a few polygons, so making the box ratio say 2 or so
149 * could simulate this type of box.
150 */
151static double   Box_Ratio = 1.0 ;
152
153/* for debugging purposes, you might want to set Test_Polygons and Test_Points
154 * high (say 1000), and then set the *_Test_Times to 1.  The timings will be
155 * useless, but you'll test 1000 polygons each with 1000 points.  You'll also
156 * probably want to set the Vertex_Perturbation to something > 0.0.
157 */
158/* number of different polygons to try - I like 50 or so; left low for now */
159static int      Test_Polygons = 20 ;
160
161/* number of different intersection points to try - I like 50 or so */
162static int      Test_Points = 20 ;
163
164/* for debugging or constrained test purposes, this value constrains the value
165 * of the polygon points and the test points to those on a grid emanating from
166 * the origin with this increment.  Points are shifted to the closest grid
167 * point.  0.0 means no grid.  NOTE:  by setting this value, a large number
168 * of points will be generated exactly on interior (triangle fan) or exterior
169 * edges.  Interior edge points will cause problems for the algorithms that
170 * generate interior edges (triangle fan).  "On edge" points are arbitrarily
171 * determined to be inside or outside the polygon, so results can differ.
172 */
173static double   Constraint_Increment = 0.0 ;
174
175/* default resolutions */
176static  int     Grid_Resolution = 20 ;
177static  int     Trapezoid_Bins = 20 ;
178
179#define Max(a,b)        (((a)>(b))?(a):(b))
180
181#define FPRINTF_POLYGON                                         \
182                fprintf( stderr, "point %g %g\n",               \
183                    (float)point[X], (float)point[Y] ) ;        \
184                fprintf( stderr, "polygon (%d vertices):\n",    \
185                        numverts ) ;                            \
186                for ( n = 0 ; n < numverts ; n++ ) {            \
187                    fprintf( stderr, "  %g %g\n",               \
188                        (float)pgon[n][X], (float)pgon[n][Y]);  \
189                }
190
191/* timing functions */
192#ifdef  TIMER
193
194#define START_TIMER( test_id )                                          \
195        /* do the test a bunch of times to get a useful time reading */ \
196        mGetTime( timestart ) ;                                         \
197        for ( tcnt = St[test_id].test_times+1 ; --tcnt ; )
198
199#define STOP_TIMER( test_id )                                           \
200        mGetTime( timestop ) ;                                          \
201        /* time in microseconds */                                      \
202        St[test_id].time_total +=                                       \
203            1000000.0 * (double)(timestop - timestart) /                \
204            (double)(HZ * St[test_id].test_times) ;
205#else
206#define START_TIMER( test_id )
207#define STOP_TIMER( test_id )
208#endif
209
210char    *getenv() ;
211void    Usage() ;
212void    ScanOpts() ;
213void    ConstrainPoint() ;
214void    BreakString() ;
215#ifdef  DISPLAY
216void    DisplayPolygon() ;
217void    DisplayPoint() ;
218#endif
219
220
221/* test program - see Usage() for command line options */
222main(argc,argv)
223int argc;  char *argv[];
224{
225#ifdef  TIMER
226register long   tcnt ;
227long    timestart ;
228long    timestop ;
229#endif
230
231int     i, j, k, n, numverts, inside_flag, inside_tot, numrec ;
232double  pgon[TOT_VERTS][2], point[2], angle, ran_offset ;
233double  rangex, rangey, scale, minx, maxx, diffx, miny, maxy, diffy ;
234double  offx, offy ;
235char    str[256], *strplus ;
236GridSet grid_set ;
237pPlaneSet       p_plane_set ;
238pSpackmanSet    p_spackman_set ;
239TrapezoidSet    trap_set ;
240
241#ifdef  CONVEX
242pPlaneSet       p_ext_set ;
243pInclusionAnchor        p_inc_anchor ;
244#endif
245
246    SRAN() ;
247
248    ScanOpts( argc, argv ) ;
249
250    for ( i = 0 ; i < TOT_NUM_TESTS ; i++ ) {
251        St[i].time_total = 0.0 ;
252        if ( i == ANGLE_TEST ) {
253            /* angle test is real slow, so test it fewer times */
254            St[i].test_ratio = MACHINE_TEST_RATIO / 10 ;
255        } else {
256            St[i].test_ratio = MACHINE_TEST_RATIO ;
257        }
258        St[i].name = TestName[i] ;
259        St[i].flag = 0 ;
260    }
261
262    inside_tot = 0 ;
263
264#ifdef  CONVEX
265    if ( Vertex_Perturbation > 0.0 && Max_Verts > 3 ) {
266        fprintf( stderr,
267                "warning: vertex perturbation is > 0.0, which is exciting\n");
268        fprintf( stderr,
269                "    when using convex-only algorithms!\n" ) ;
270    }
271#endif
272
273    if ( Min_Verts == Max_Verts ) {
274        sprintf( str, "\nPolygons with %d vertices, radius %g, "
275                "perturbation +/- %g, bounding box scale %g",
276            Min_Verts, Vertex_Radius, Vertex_Perturbation, Box_Ratio ) ;
277    } else {
278        sprintf( str, "\nPolygons with %d to %d vertices, radius %g, "
279                "perturbation +/- %g, bounding box scale %g",
280            Min_Verts, Max_Verts, Vertex_Radius, Vertex_Perturbation,
281            Box_Ratio ) ;
282    }
283    strplus = &str[strlen(str)] ;
284    if ( St[TRAPEZOID_TEST].work ) {
285        sprintf( strplus, ", %d trapezoid bins", Trapezoid_Bins ) ;
286        strplus = &str[strlen(str)] ;
287    }
288    if ( St[GRID_TEST].work ) {
289        sprintf( strplus, ", %d grid resolution", Grid_Resolution ) ;
290        strplus = &str[strlen(str)] ;
291    }
292#ifdef  CONVEX
293    sprintf( strplus, ", convex" ) ;
294    strplus = &str[strlen(str)] ;
295#ifdef  HYBRID
296    sprintf( strplus, ", hybrid" ) ;
297    strplus = &str[strlen(str)] ;
298#endif
299#endif
300#ifdef  SORT
301    if ( St[PLANE_TEST].work || St[SPACKMAN_TEST].work ) {
302        sprintf( strplus, ", using triangles sorted by edge lengths" ) ;
303        strplus = &str[strlen(str)] ;
304#ifdef  CONVEX
305        sprintf( strplus, " and areas" ) ;
306        strplus = &str[strlen(str)] ;
307#endif
308    }
309#endif
310#ifdef  RANDOM
311    if ( St[EXTERIOR_TEST].work ) {
312        sprintf( strplus, ", exterior edges' order randomized" ) ;
313        strplus = &str[strlen(str)] ;
314    }
315#endif
316    sprintf( strplus, ".\n" ) ;
317    strplus = &str[strlen(str)] ;
318    BreakString( str ) ;
319    printf( "%s", str ) ;
320
321    printf(
322        " Testing %d polygons with %d points\n", Test_Polygons, Test_Points ) ;
323
324#ifdef  TIMER
325    printf( "doing timings" ) ;
326    fflush( stdout ) ;
327#endif
328    for ( i = 0 ; i < Test_Polygons ; i++ ) {
329
330        /* make an arbitrary polygon fitting 0-1 range in x and y */
331        numverts = Min_Verts +
332                (int)(RAN01() * (double)(Max_Verts-Min_Verts+1)) ;
333
334        /* add a random offset to the angle so that each polygon is not in
335         * some favorable (or unfavorable) alignment.
336         */
337        ran_offset = 2.0 * M_PI * RAN01() ;
338        minx = miny =  99999.0 ;
339        maxx = maxy = -99999.0 ;
340        for ( j = 0 ; j < numverts ; j++ ) {
341            angle = 2.0 * M_PI * (double)j / (double)numverts + ran_offset ;
342            pgon[j][X] = cos(angle) * Vertex_Radius +
343                ( RAN01() * 2.0 - 1.0 ) * Vertex_Perturbation ;
344            pgon[j][Y] = sin(angle) * Vertex_Radius +
345                ( RAN01() * 2.0 - 1.0 ) * Vertex_Perturbation ;
346
347            ConstrainPoint( pgon[j] ) ;
348
349            if ( pgon[j][X] < minx ) minx = pgon[j][X] ;
350            if ( pgon[j][X] > maxx ) maxx = pgon[j][X] ;
351            if ( pgon[j][Y] < miny ) miny = pgon[j][Y] ;
352            if ( pgon[j][Y] > maxy ) maxy = pgon[j][Y] ;
353        }
354
355        offx = ( maxx + minx ) / 2.0 ;
356        offy = ( maxy + miny ) / 2.0 ;
357        if ( (diffx = maxx - minx ) > ( diffy = maxy - miny ) ) {
358            scale = 2.0 / (Box_Ratio * diffx) ;
359            rangex = 1.0 ;
360            rangey = diffy / diffx ;
361        } else {
362            scale = 2.0 / (Box_Ratio * diffy) ;
363            rangex = diffx / diffy ;
364            rangey = 1.0 ;
365        }
366
367        for ( j = 0 ; j < numverts ; j++ ) {
368            pgon[j][X] = ( pgon[j][X] - offx ) * scale ;
369            pgon[j][Y] = ( pgon[j][Y] - offy ) * scale ;
370        }
371
372        /* Set up number of times to test a point against a polygon, for
373         * the sake of getting a reasonable timing.  We already know how
374         * most of these will perform, so scale their # tests accordingly.
375         */
376        for ( j = 0 ; j < TOT_NUM_TESTS ; j++ ) {
377            if ( ( j == GRID_TEST ) || ( j == TRAPEZOID_TEST ) ) {
378                St[j].test_times = Max( St[j].test_ratio /
379                    (int)sqrt((double)numverts), 1 ) ;
380            } else {
381                St[j].test_times = Max( St[j].test_ratio / numverts, 1 ) ;
382            }
383        }
384
385        /* set up tests */
386#ifdef  CONVEX
387        if ( St[EXTERIOR_TEST].work ) {
388            p_ext_set = ExteriorSetup( pgon, numverts ) ;
389        }
390#endif
391
392        if ( St[GRID_TEST].work ) {
393            GridSetup( pgon, numverts, Grid_Resolution, &grid_set ) ;
394        }
395
396#ifdef  CONVEX
397        if ( St[INCLUSION_TEST].work ) {
398            p_inc_anchor = InclusionSetup( pgon, numverts ) ;
399        }
400#endif
401
402        if ( St[PLANE_TEST].work ) {
403            p_plane_set = PlaneSetup( pgon, numverts ) ;
404        }
405
406        if ( St[SPACKMAN_TEST].work ) {
407            p_spackman_set = SpackmanSetup( pgon, numverts, &numrec ) ;
408        }
409
410        if ( St[TRAPEZOID_TEST].work ) {
411            TrapezoidSetup( pgon, numverts, Trapezoid_Bins, &trap_set ) ;
412        }
413
414#ifdef  DISPLAY
415        if ( Display_Tests ) {
416            DisplayPolygon( pgon, numverts, i ) ;
417        }
418#endif
419
420        /* now try # of points against it */
421        for ( j = 0 ; j < Test_Points ; j++ ) {
422            point[X] = RAN01() * rangex * 2.0 - rangex ;
423            point[Y] = RAN01() * rangey * 2.0 - rangey ;
424
425            ConstrainPoint( point ) ;
426
427#ifdef  DISPLAY
428            if ( Display_Tests ) {
429                DisplayPoint( point, TRUE ) ;
430            }
431#endif
432
433            if ( St[ANGLE_TEST].work ) {
434                START_TIMER( ANGLE_TEST )
435                    St[ANGLE_TEST].flag = AngleTest( pgon, numverts, point ) ;
436                STOP_TIMER( ANGLE_TEST )
437            }
438            if ( St[BARYCENTRIC_TEST].work ) {
439                START_TIMER( BARYCENTRIC_TEST )
440                    St[BARYCENTRIC_TEST].flag =
441                            BarycentricTest( pgon, numverts, point ) ;
442                STOP_TIMER( BARYCENTRIC_TEST )
443            }
444            if ( St[CROSSINGS_TEST].work ) {
445                START_TIMER( CROSSINGS_TEST )
446                    St[CROSSINGS_TEST].flag =
447                            CrossingsTest( pgon, numverts, point ) ;
448                STOP_TIMER( CROSSINGS_TEST )
449            }
450#ifdef  CONVEX
451            if ( St[EXTERIOR_TEST].work ) {
452                START_TIMER( EXTERIOR_TEST )
453                    St[EXTERIOR_TEST].flag =
454                            ExteriorTest( p_ext_set, numverts, point );
455                STOP_TIMER( EXTERIOR_TEST )
456            }
457#endif
458            if ( St[GRID_TEST].work ) {
459                START_TIMER( GRID_TEST )
460                    St[GRID_TEST].flag = GridTest( &grid_set, point ) ;
461                STOP_TIMER( GRID_TEST )
462            }
463#ifdef  CONVEX
464            if ( St[INCLUSION_TEST].work ) {
465                START_TIMER( INCLUSION_TEST )
466                    St[INCLUSION_TEST].flag =
467                            InclusionTest( p_inc_anchor, point );
468                STOP_TIMER( INCLUSION_TEST )
469            }
470#endif
471            if ( St[CROSSMULT_TEST].work ) {
472                START_TIMER( CROSSMULT_TEST )
473                    St[CROSSMULT_TEST].flag = CrossingsMultiplyTest(
474                                pgon, numverts, point ) ;
475                STOP_TIMER( CROSSMULT_TEST )
476            }
477            if ( St[PLANE_TEST].work ) {
478                START_TIMER( PLANE_TEST )
479                    St[PLANE_TEST].flag =
480                            PlaneTest( p_plane_set, numverts, point ) ;
481                STOP_TIMER( PLANE_TEST )
482            }
483            if ( St[SPACKMAN_TEST].work ) {
484                START_TIMER( SPACKMAN_TEST )
485                    St[SPACKMAN_TEST].flag =
486                        SpackmanTest( pgon[0], p_spackman_set, numrec, point ) ;
487                STOP_TIMER( SPACKMAN_TEST )
488            }
489            if ( St[TRAPEZOID_TEST].work ) {
490                START_TIMER( TRAPEZOID_TEST )
491                    St[TRAPEZOID_TEST].flag =
492                            TrapezoidTest( pgon, numverts, &trap_set, point ) ;
493                STOP_TIMER( TRAPEZOID_TEST )
494            }
495            if ( St[WEILER_TEST].work ) {
496                START_TIMER( WEILER_TEST )
497                    St[WEILER_TEST].flag =
498                            WeilerTest( pgon, numverts, point ) ;
499                STOP_TIMER( WEILER_TEST )
500            }
501/* +++ add new procedure call here +++ */
502
503            /* reality check if crossings test is used */
504            if ( St[CROSSINGS_TEST].work ) {
505                for ( k = 0 ; k < TOT_NUM_TESTS ; k++ ) {
506                    if ( St[k].work &&
507                            ( St[k].flag != St[CROSSINGS_TEST].flag ) ) {
508                        fprintf( stderr,
509                                "%s test says %s, crossings test says %s\n",
510                            St[k].name,
511                            St[k].flag ? "INSIDE" : "OUTSIDE",
512                            St[CROSSINGS_TEST].flag ? "INSIDE" : "OUTSIDE" ) ;
513                        FPRINTF_POLYGON ;
514                    }
515                }
516            }
517
518            /* see if any flag is TRUE (i.e. the test point is inside) */
519            for ( k = 0, inside_flag = 0
520                ; k < TOT_NUM_TESTS && !inside_flag
521                ; k++ ) {
522                inside_flag = St[k].flag ;
523            }
524            inside_tot += inside_flag ;
525
526            /* turn off highlighting for this point */
527#ifdef  DISPLAY
528            if ( Display_Tests ) {
529                DisplayPoint( point, FALSE ) ;
530            }
531#endif
532        }
533
534        /* clean up test structures */
535#ifdef  CONVEX
536        if ( St[EXTERIOR_TEST].work ) {
537            ExteriorCleanup( p_ext_set ) ;
538            p_ext_set = NULL ;
539        }
540#endif
541
542        if ( St[GRID_TEST].work ) {
543            GridCleanup( &grid_set ) ;
544        }
545
546#ifdef  CONVEX
547        if ( St[INCLUSION_TEST].work ) {
548            InclusionCleanup( p_inc_anchor ) ;
549            p_inc_anchor = NULL ;
550        }
551#endif
552
553        if ( St[PLANE_TEST].work ) {
554            PlaneCleanup( p_plane_set ) ;
555            p_plane_set = NULL ;
556        }
557
558        if ( St[SPACKMAN_TEST].work ) {
559            SpackmanCleanup( p_spackman_set ) ;
560            p_spackman_set = NULL ;
561        }
562
563        if ( St[TRAPEZOID_TEST].work ) {
564            TrapezoidCleanup( &trap_set ) ;
565        }
566
567#ifdef  TIMER
568        /* print a "." every polygon done to give the user a warm feeling */
569        printf( "." ) ;
570        fflush( stdout ) ;
571#endif
572    }
573
574    printf( "\n%g %% of all points were inside polygons\n",
575        (float)inside_tot * 100.0 / (float)(Test_Points*Test_Polygons) ) ;
576
577#ifdef  TIMER
578    for ( i = 0 ; i < TOT_NUM_TESTS ; i++ ) {
579        if ( St[i].work ) {
580            printf( "  %s test time: %g microseconds per test\n",
581                St[i].name,
582            (float)( St[i].time_total/(double)(Test_Points*Test_Polygons) ) ) ;
583        }
584    }
585#endif
586
587    return 0 ;
588}
589
590void Usage()
591{
592/* +++ add new routine here +++ */
593printf("p_test [options] -{ABCEGIMPSTW}\n");
594printf("  -v minverts [maxverts] = variation in number of polygon vertices\n");
595printf("  -r radius = radius of polygon vertices generated\n");
596printf("  -p perturbation = perturbation of polygon vertices generated\n");
597printf("       These first three determine the type of polygon tested.\n");
598printf("       No perturbation gives regular polygons, while no radius\n");
599printf("       gives random polygons, and a mix gives semi-random polygons\n");
600printf("  -s size = scale of test point box around polygon (1.0 default)\n");
601printf("       A larger size means more points generated outside the\n");
602printf("       polygon.  By default test points are in the bounding box.\n");
603printf("  -b bins = number of y bins for trapezoid test\n");
604printf("  -g resolution = grid resolution for grid test\n");
605printf("  -n polygons = number of polygons to test (default %d)\n",
606                Test_Polygons);
607printf("  -i points = number of points to test per polygon (default %d)\n",
608                Test_Points);
609printf("  -c increment = constrain polygon and test points to grid\n");
610/* +++ add new routine here +++ */
611printf("  -{ABCEGIMPSTW} = angle/bary/crossings/exterior/grid/inclusion/cross-mult/\n");
612printf("       plane/spackman/trapezoid (bin)/weiler test (default is all)\n");
613printf("  -d = display polygons and points using starbase\n");
614}
615
616void    ScanOpts( argc, argv )
617int argc;  char *argv[];
618{
619float   f1 ;
620int     i1 ;
621int     test_flag = FALSE ;
622
623    for ( argc--, argv++; argc > 0; argc--, argv++ ) {
624        if ( **argv == '-' ) {
625            switch ( *++(*argv)) {
626
627            case 'v':   /* vertex min & max */
628                argv++ ; argc-- ;
629                if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
630                    Min_Verts = i1 ;
631                    argv++ ; argc-- ;
632                    if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
633                        Max_Verts = i1 ;
634                    } else {
635                        argv-- ; argc++ ;
636                        Max_Verts = Min_Verts ;
637                    }
638                } else {
639                    Usage() ;
640                    exit(1) ;
641                }
642                break;
643
644            case 'r':   /* vertex radius */
645                argv++ ; argc-- ;
646                if ( argc && sscanf ( *argv, "%f", &f1 ) == 1 ) {
647                    Vertex_Radius = (double)f1 ;
648                } else {
649                    Usage() ;
650                    exit(1) ;
651                }
652                break;
653
654            case 'p':   /* vertex perturbation */
655                argv++ ; argc-- ;
656                if ( argc && sscanf ( *argv, "%f", &f1 ) == 1 ) {
657                    Vertex_Perturbation = (double)f1 ;
658                } else {
659                    Usage() ;
660                    exit(1) ;
661                }
662                break;
663
664            case 's':   /* centered box size ratio - higher is bigger */
665                argv++ ; argc-- ;
666                if ( argc && sscanf ( *argv, "%f", &f1 ) == 1 ) {
667                    Box_Ratio = (double)f1 ;
668                    if ( Box_Ratio < 1.0 ) {
669                        fprintf(stderr,"warning: ratio is smaller than 1.0\n");
670                    }
671                } else {
672                    Usage() ;
673                    exit(1) ;
674                }
675                break;
676
677            case 'b':   /* number of bins for trapezoid test */
678                argv++ ; argc-- ;
679                if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
680                    Trapezoid_Bins = i1 ;
681                } else {
682                    Usage() ;
683                    exit(1) ;
684                }
685                break;
686
687            case 'g':   /* grid resolution for grid test */
688                argv++ ; argc-- ;
689                if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
690                    Grid_Resolution = i1 ;
691                } else {
692                    Usage() ;
693                    exit(1) ;
694                }
695                break;
696
697            case 'n':   /* number of polygons to test */
698                argv++ ; argc-- ;
699                if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
700                    Test_Polygons = i1 ;
701                } else {
702                    Usage() ;
703                    exit(1) ;
704                }
705                break;
706
707            case 'i':   /* number of intersections per polygon to test */
708                argv++ ; argc-- ;
709                if ( argc && sscanf ( *argv, "%d", &i1 ) == 1 ) {
710                    Test_Points = i1 ;
711                } else {
712                    Usage() ;
713                    exit(1) ;
714                }
715                break;
716
717            case 'c':   /* constrain increment (0 means don't use) */
718                argv++ ; argc-- ;
719                if ( argc && sscanf ( *argv, "%f", &f1 ) == 1 ) {
720                    Constraint_Increment = (double)f1 ;
721                } else {
722                    Usage() ;
723                    exit(1) ;
724                }
725                break;
726
727            case 'd':   /* display polygon & test points */
728#ifdef  DISPLAY
729                Display_Tests = 1 ;
730#else
731                fprintf( stderr,
732                    "warning: display mode not compiled in - ignored\n" ) ;
733#endif
734                break;
735
736            /* +++ add new symbol here +++ */
737            case 'A':   /* do tests specified */
738            case 'B':
739            case 'C':
740            case 'E':
741            case 'G':
742            case 'I':
743            case 'M':
744            case 'P':
745            case 'S':
746            case 'T':
747            case 'W':
748                test_flag = TRUE ;
749                if ( strchr( *argv, 'A' ) ) {
750                    St[ANGLE_TEST].work = 1 ;
751                }
752                if ( strchr( *argv, 'B' ) ) {
753                    St[BARYCENTRIC_TEST].work = 1 ;
754                }
755                if ( strchr( *argv, 'C' ) ) {
756                    St[CROSSINGS_TEST].work = 1 ;
757                }
758                if ( strchr( *argv, 'E' ) ) {
759#ifdef  CONVEX
760                    St[EXTERIOR_TEST].work = 1 ;
761#else
762                    fprintf( stderr,
763                    "warning: exterior test for -DCONVEX only - ignored\n" ) ;
764#endif
765                }
766                if ( strchr( *argv, 'G' ) ) {
767                    St[GRID_TEST].work = 1 ;
768                }
769                if ( strchr( *argv, 'I' ) ) {
770#ifdef  CONVEX
771                    St[INCLUSION_TEST].work = 1 ;
772#else
773                    fprintf( stderr,
774                    "warning: inclusion test for -DCONVEX only - ignored\n" ) ;
775#endif
776                }
777                if ( strchr( *argv, 'M' ) ) {
778                    St[CROSSMULT_TEST].work = 1 ;
779                }
780                if ( strchr( *argv, 'P' ) ) {
781                    St[PLANE_TEST].work = 1 ;
782                }
783                if ( strchr( *argv, 'S' ) ) {
784                    St[SPACKMAN_TEST].work = 1 ;
785                }
786                if ( strchr( *argv, 'T' ) ) {
787                    St[TRAPEZOID_TEST].work = 1 ;
788                }
789                if ( strchr( *argv, 'W' ) ) {
790                    St[WEILER_TEST].work = 1 ;
791                }
792                /* +++ add new symbol test here +++ */
793                break;
794
795            default:
796                Usage() ;
797                exit(1) ;
798                break ;
799            }
800
801        } else {
802            Usage() ;
803            exit(1) ;
804        }
805    }
806
807    if ( !test_flag ) {
808        fprintf( stderr,
809            "error: no point in polygon tests were specified, e.g. -PCS\n" ) ;
810        Usage() ;
811        exit(1) ;
812    }
813}
814
815void ConstrainPoint( pt )
816double  *pt ;
817{
818double  val ;
819
820    if ( Constraint_Increment > 0.0 ) {
821        pt[X] -=
822                ( val = fmod( pt[X], Constraint_Increment ) ) ;
823        if ( fabs(val) > Constraint_Increment * 0.5 ) {
824            pt[X] += (val > 0.0) ? Constraint_Increment :
825                                        -Constraint_Increment ;
826        }
827        pt[Y] -=
828                ( val = fmod( pt[Y], Constraint_Increment ) ) ;
829        if ( fabs(val) > Constraint_Increment * 0.5 ) {
830            pt[Y] += (val > 0.0) ? Constraint_Increment :
831                                        -Constraint_Increment ;
832        }
833    }
834}
835
836/* break long strings into 80 or less character output.  Not foolproof, but
837 * good enough.
838 */
839void BreakString( str )
840char    *str ;
841{
842int     length, i, last_space, col ;
843
844    length = strlen( str ) ;
845    last_space = 0 ;
846    col = 0 ;
847    for ( i = 0 ; i < length ; i++ ) {
848        if ( str[i] == ' ' ) {
849            last_space = i ;
850        }
851        if ( col == 79 ) {
852            str[last_space] = '\n' ;
853            col = i - last_space ;
854            last_space = 0 ;
855        } else {
856            col++ ;
857        }
858    }
859}
860
861#ifdef  DISPLAY
862/* ================================= display routines ====================== */
863/* Currently for HP Starbase - pretty easy to modify */
864void DisplayPolygon( pgon, numverts, id )
865double  pgon[][2] ;
866int     numverts ;
867{
868static  int     init_flag = 0 ;
869int     i ;
870char    str[256] ;
871
872    if ( !init_flag ) {
873        init_flag = 1 ;
874        /* make things big enough to avoid clipping */
875        Display_Scale = 0.45 / ( Vertex_Radius + Vertex_Perturbation ) ;
876        Display_OffsetX = Display_Scale + 0.05 ;
877        Display_OffsetY = Display_Scale + 0.10 ;
878
879        Fd = DevOpen(OUTDEV,INIT) ;
880        shade_mode( Fd, CMAP_FULL|INIT, 0 ) ;
881        background_color( Fd, 0.1, 0.2, 0.4 ) ;
882        line_color( Fd, 1.0, 0.9, 0.7 ) ;
883        text_color( Fd, 1.0, 1.0, 0.2 ) ;
884        character_height( Fd, 0.08 ) ;
885        marker_type( Fd, 3 ) ;
886    }
887    clear_view_surface( Fd ) ;
888
889    move2d( Fd,
890        (float)( pgon[numverts-1][X] * Display_Scale + Display_OffsetX ),
891        (float)( pgon[numverts-1][Y] * Display_Scale + Display_OffsetY ) ) ;
892    for ( i = 0 ; i < numverts ; i++ ) {
893        draw2d( Fd,
894            (float)( pgon[i][X] * Display_Scale + Display_OffsetX ),
895            (float)( pgon[i][Y] * Display_Scale + Display_OffsetY ) ) ;
896    }
897
898    sprintf( str, "%4d sides, %3d of %d\n", numverts, id+1, Test_Polygons ) ;
899    text2d( Fd, 0.01, 0.01, str, VDC_TEXT, 0 ) ;
900    flush_buffer( Fd ) ;
901}
902
903void DisplayPoint( point, hilit )
904double  point[2] ;
905int     hilit ;
906{
907float   clist[2] ;
908
909    if ( hilit ) {
910        marker_color( Fd, 1.0, 0.0, 0.0 ) ;
911    } else {
912        marker_color( Fd, 0.2, 1.0, 1.0 ) ;
913    }
914
915    clist[0] = (float)( point[0] * Display_Scale + Display_OffsetX ) ;
916    clist[1] = (float)( point[1] * Display_Scale + Display_OffsetY ) ;
917    polymarker2d( Fd, clist, 1, 0 ) ;
918    flush_buffer( Fd ) ;
919}
920
921int DevOpen(dev_kind,init_mode)
922int dev_kind,init_mode;
923{
924char    *dev, *driver;
925int     fildes ;
926
927    if ( dev_kind == OUTDEV ) {
928        dev = getenv("OUTINDEV");
929        if (!dev) dev = getenv("OUTDEV");
930        if (!dev) dev = "/dev/crt" ;
931        driver = getenv("OUTDRIVER");
932        if (!driver) driver = "hp98731" ;
933    } else {
934        dev = getenv("OUTINDEV");
935        if (!dev) dev = getenv("INDEV");
936        if (!dev) dev = "/dev/hil2" ;
937        driver = getenv("INDRIVER");
938        if (!driver) driver = "hp-hil" ;
939    }
940
941    /* driver?  we don't need no stinking driver... */
942    fildes = gopen(dev,dev_kind,NULL,init_mode);
943
944    return(fildes) ;
945}
946#endif
Note: See TracBrowser for help on using the repository browser.