source: trunk/anuga_core/anuga/fit_interpolate/p_test.c @ 9737

Last change on this file since 9737 was 8752, checked in by wilsonp, 12 years ago

Small changes to reduce compiler warnings

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