00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "plplotP.h"
00027
00028 #define INSIDE( ix, iy ) ( BETW( ix, xmin, xmax ) && BETW( iy, ymin, ymax ) )
00029
00030 #define DTOR ( PI / 180. )
00031 #define BINC 50
00032
00033 #define PL_NBCC 2
00034
00035 #define BETW_NBCC( ix, ia, ib ) ( ( ( ix ) <= ( ia + PL_NBCC ) && ( ix ) >= ( ib - PL_NBCC ) ) || ( ( ix ) >= ( ia - PL_NBCC ) && ( ix ) <= ( ib + PL_NBCC ) ) )
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 enum PL_CrossedStatus
00062 {
00063 PL_NOT_CROSSED = 0x1,
00064 PL_NEAR_A1 = 0x2,
00065 PL_NEAR_A2 = 0x4,
00066 PL_NEAR_B1 = 0x8,
00067 PL_NEAR_B2 = 0x10,
00068 PL_NEAR_PARALLEL = 0x20,
00069 PL_PARALLEL = 0x40
00070 };
00071
00072 struct point
00073 {
00074 PLINT x, y;
00075 };
00076 static PLINT bufferleng, buffersize, *buffer;
00077
00078
00079
00080 static int
00081 compar( const void *, const void * );
00082
00083 static void
00084 addcoord( PLINT, PLINT );
00085
00086 static void
00087 tran( PLINT *, PLINT *, PLFLT, PLFLT );
00088
00089 static void
00090 buildlist( PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT );
00091
00092 static int
00093 notpointinpolygon( PLINT n, const PLINT *x, const PLINT *y, PLINT xp, PLINT yp );
00094
00095 static int
00096 circulation( PLINT *x, PLINT *y, PLINT npts );
00097
00098 static void
00099 fill_intersection_polygon( PLINT recursion_depth, PLINT ifextrapolygon,
00100 PLINT fill_status,
00101 void ( *fill )( short *, short *, PLINT ),
00102 const PLINT *x1, const PLINT *y1,
00103 PLINT i1start, PLINT n1,
00104 const PLINT *x2, const PLINT *y2,
00105 const PLINT *if2, PLINT n2 );
00106
00107 static int
00108 notcrossed( PLINT *xintersect, PLINT *yintersect,
00109 PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2,
00110 PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 );
00111
00112 static int
00113 positive_orientation( PLINT n, const PLINT *x, const PLINT *y );
00114
00115 static int
00116 number_crossings( PLINT *xcross, PLINT *ycross, PLINT *i2cross, PLINT ncross,
00117 PLINT i1, PLINT n1, const PLINT *x1, const PLINT *y1,
00118 PLINT n2, const PLINT *x2, const PLINT *y2 );
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 void
00133 c_plfill( PLINT n, const PLFLT *x, const PLFLT *y )
00134 {
00135 PLINT _xpoly[PL_MAXPOLY], _ypoly[PL_MAXPOLY];
00136 PLINT *xpoly, *ypoly;
00137 PLINT i, npts;
00138 PLFLT xt, yt;
00139
00140 if ( plsc->level < 3 )
00141 {
00142 plabort( "plfill: Please set up window first" );
00143 return;
00144 }
00145 if ( n < 3 )
00146 {
00147 plabort( "plfill: Not enough points in object" );
00148 return;
00149 }
00150 npts = n;
00151 if ( n > PL_MAXPOLY - 1 )
00152 {
00153 xpoly = (PLINT *) malloc( ( n + 1 ) * sizeof ( PLINT ) );
00154 ypoly = (PLINT *) malloc( ( n + 1 ) * sizeof ( PLINT ) );
00155
00156 if ( ( xpoly == NULL ) || ( ypoly == NULL ) )
00157 {
00158 plexit( "plfill: Insufficient memory for large polygon" );
00159 }
00160 }
00161 else
00162 {
00163 xpoly = _xpoly;
00164 ypoly = _ypoly;
00165 }
00166
00167 for ( i = 0; i < n; i++ )
00168 {
00169 TRANSFORM( x[i], y[i], &xt, &yt );
00170 xpoly[i] = plP_wcpcx( xt );
00171 ypoly[i] = plP_wcpcy( yt );
00172 }
00173
00174 if ( xpoly[0] != xpoly[n - 1] || ypoly[0] != ypoly[n - 1] )
00175 {
00176 n++;
00177 xpoly[n - 1] = xpoly[0];
00178 ypoly[n - 1] = ypoly[0];
00179 }
00180
00181 plP_plfclp( xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma,
00182 plsc->clpymi, plsc->clpyma, plP_fill );
00183
00184 if ( npts > PL_MAXPOLY - 1 )
00185 {
00186 free( xpoly );
00187 free( ypoly );
00188 }
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 void
00203 c_plfill3( PLINT n, const PLFLT *x, const PLFLT *y, const PLFLT *z )
00204 {
00205 PLFLT _tx[PL_MAXPOLY], _ty[PL_MAXPOLY], _tz[PL_MAXPOLY];
00206 PLFLT *tx, *ty, *tz;
00207 PLFLT *V[3];
00208 PLINT _xpoly[PL_MAXPOLY], _ypoly[PL_MAXPOLY];
00209 PLINT *xpoly, *ypoly;
00210 PLINT i;
00211 PLINT npts;
00212 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
00213
00214 if ( plsc->level < 3 )
00215 {
00216 plabort( "plfill3: Please set up window first" );
00217 return;
00218 }
00219 if ( n < 3 )
00220 {
00221 plabort( "plfill3: Not enough points in object" );
00222 return;
00223 }
00224
00225 npts = n;
00226 if ( n > PL_MAXPOLY - 1 )
00227 {
00228 tx = (PLFLT *) malloc( ( n + 1 ) * sizeof ( PLFLT ) );
00229 ty = (PLFLT *) malloc( ( n + 1 ) * sizeof ( PLFLT ) );
00230 tz = (PLFLT *) malloc( ( n + 1 ) * sizeof ( PLFLT ) );
00231 xpoly = (PLINT *) malloc( ( n + 1 ) * sizeof ( PLINT ) );
00232 ypoly = (PLINT *) malloc( ( n + 1 ) * sizeof ( PLINT ) );
00233
00234 if ( ( tx == NULL ) || ( ty == NULL ) || ( tz == NULL ) ||
00235 ( xpoly == NULL ) || ( ypoly == NULL ) )
00236 {
00237 plexit( "plfill3: Insufficient memory for large polygon" );
00238 }
00239 }
00240 else
00241 {
00242 tx = _tx;
00243 ty = _ty;
00244 tz = _tz;
00245 xpoly = _xpoly;
00246 ypoly = _ypoly;
00247 }
00248
00249 plP_gdom( &xmin, &xmax, &ymin, &ymax );
00250 plP_grange( &zscale, &zmin, &zmax );
00251
00252
00253 for ( i = 0; i < n; i++ )
00254 {
00255 tx[i] = x[i]; ty[i] = y[i]; tz[i] = z[i];
00256 }
00257 if ( tx[0] != tx[n - 1] || ty[0] != ty[n - 1] || tz[0] != tz[n - 1] )
00258 {
00259 n++;
00260 tx[n - 1] = tx[0]; ty[n - 1] = ty[0]; tz[n - 1] = tz[0];
00261 }
00262 V[0] = tx; V[1] = ty; V[2] = tz;
00263 n = plP_clip_poly( n, V, 0, 1, -xmin );
00264 n = plP_clip_poly( n, V, 0, -1, xmax );
00265 n = plP_clip_poly( n, V, 1, 1, -ymin );
00266 n = plP_clip_poly( n, V, 1, -1, ymax );
00267 n = plP_clip_poly( n, V, 2, 1, -zmin );
00268 n = plP_clip_poly( n, V, 2, -1, zmax );
00269 for ( i = 0; i < n; i++ )
00270 {
00271 xpoly[i] = plP_wcpcx( plP_w3wcx( tx[i], ty[i], tz[i] ) );
00272 ypoly[i] = plP_wcpcy( plP_w3wcy( tx[i], ty[i], tz[i] ) );
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 plP_plfclp( xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma,
00288 plsc->clpymi, plsc->clpyma, plP_fill );
00289
00290
00291 if ( npts > PL_MAXPOLY - 1 )
00292 {
00293 free( tx );
00294 free( ty );
00295 free( tz );
00296 free( xpoly );
00297 free( ypoly );
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306
00307 void
00308 plfill_soft( short *x, short *y, PLINT n )
00309 {
00310 PLINT i, j;
00311 PLINT xp1, yp1, xp2, yp2, xp3, yp3;
00312 PLINT k, dinc;
00313 PLFLT ci, si;
00314 double temp;
00315
00316 buffersize = 2 * BINC;
00317 buffer = (PLINT *) malloc( (size_t) buffersize * sizeof ( PLINT ) );
00318 if ( !buffer )
00319 {
00320 plabort( "plfill: Out of memory" );
00321 return;
00322 }
00323
00324
00325
00326 for ( k = 0; k < plsc->nps; k++ )
00327 {
00328 bufferleng = 0;
00329
00330 temp = DTOR * plsc->inclin[k] * 0.1;
00331 si = sin( temp ) * plsc->ypmm;
00332 ci = cos( temp ) * plsc->xpmm;
00333
00334
00335
00336 temp = sqrt( (double) ( si * si + ci * ci ) );
00337 si /= temp;
00338 ci /= temp;
00339
00340 dinc = (PLINT) ( plsc->delta[k] * SSQR( plsc->ypmm * ABS( ci ),
00341 plsc->xpmm * ABS( si ) ) / 1000. );
00342
00343 if ( dinc < 0 )
00344 dinc = -dinc;
00345 if ( dinc == 0 )
00346 dinc = 1;
00347
00348 xp1 = x[n - 2];
00349 yp1 = y[n - 2];
00350 tran( &xp1, &yp1, (PLFLT) ci, (PLFLT) si );
00351
00352 xp2 = x[n - 1];
00353 yp2 = y[n - 1];
00354 tran( &xp2, &yp2, (PLFLT) ci, (PLFLT) si );
00355
00356
00357
00358 for ( i = 0; i < n; i++ )
00359 {
00360 xp3 = x[i];
00361 yp3 = y[i];
00362 tran( &xp3, &yp3, (PLFLT) ci, (PLFLT) si );
00363 buildlist( xp1, yp1, xp2, yp2, xp3, yp3, dinc );
00364 xp1 = xp2;
00365 yp1 = yp2;
00366 xp2 = xp3;
00367 yp2 = yp3;
00368 }
00369
00370
00371
00372 qsort( (void *) buffer, (size_t) bufferleng / 2,
00373 (size_t) sizeof ( struct point ), compar );
00374
00375
00376
00377 i = 0;
00378
00379 while ( i < bufferleng )
00380 {
00381 xp1 = buffer[i];
00382 yp1 = buffer[i + 1];
00383 i += 2;
00384 xp2 = xp1;
00385 yp2 = yp1;
00386 tran( &xp1, &yp1, (PLFLT) ci, (PLFLT) ( -si ) );
00387 plP_movphy( xp1, yp1 );
00388 xp1 = buffer[i];
00389 yp1 = buffer[i + 1];
00390 i += 2;
00391 if ( yp2 != yp1 )
00392 {
00393 fprintf( stderr, "plfill: oh oh we are lost\n" );
00394 for ( j = 0; j < bufferleng; j += 2 )
00395 {
00396 fprintf( stderr, "plfill: %d %d\n",
00397 (int) buffer[j], (int) buffer[j + 1] );
00398 }
00399 continue;
00400 }
00401 tran( &xp1, &yp1, (PLFLT) ci, (PLFLT) ( -si ) );
00402 plP_draphy( xp1, yp1 );
00403 }
00404 }
00405 free( (void *) buffer );
00406 }
00407
00408
00409
00410
00411
00412 void
00413 tran( PLINT *a, PLINT *b, PLFLT c, PLFLT d )
00414 {
00415 PLINT ta, tb;
00416
00417 ta = *a;
00418 tb = *b;
00419
00420 *a = (PLINT) floor( (double) ( ta * c + tb * d + 0.5 ) );
00421 *b = (PLINT) floor( (double) ( tb * c - ta * d + 0.5 ) );
00422 }
00423
00424 void
00425 buildlist( PLINT xp1, PLINT yp1, PLINT xp2, PLINT yp2, PLINT xp3, PLINT yp3,
00426 PLINT dinc )
00427 {
00428 PLINT min_y, max_y;
00429 PLINT dx, dy, cstep, nstep, ploty, plotx;
00430
00431 dx = xp2 - xp1;
00432 dy = yp2 - yp1;
00433
00434 if ( dy == 0 )
00435 {
00436 if ( yp2 > yp3 && ( ( yp2 % dinc ) == 0 ) )
00437 addcoord( xp2, yp2 );
00438 return;
00439 }
00440
00441 if ( dy > 0 )
00442 {
00443 cstep = 1;
00444 min_y = yp1;
00445 max_y = yp2;
00446 }
00447 else
00448 {
00449 cstep = -1;
00450 min_y = yp2;
00451 max_y = yp1;
00452 }
00453
00454 nstep = ( yp3 > yp2 ? 1 : -1 );
00455 if ( yp3 == yp2 )
00456 nstep = 0;
00457
00458
00459
00460 ploty = ( min_y / dinc ) * dinc;
00461 if ( ploty < min_y )
00462 ploty += dinc;
00463
00464 for (; ploty <= max_y; ploty += dinc )
00465 {
00466 if ( ploty == yp1 )
00467 continue;
00468 if ( ploty == yp2 )
00469 {
00470 if ( cstep == -nstep )
00471 continue;
00472 if ( yp2 == yp3 && yp1 > yp2 )
00473 continue;
00474 }
00475 plotx = xp1 + (PLINT) floor( ( (double) ( ploty - yp1 ) * dx ) / dy + 0.5 );
00476 addcoord( plotx, ploty );
00477 }
00478 }
00479
00480 void
00481 addcoord( PLINT xp1, PLINT yp1 )
00482 {
00483 PLINT *temp;
00484
00485 if ( bufferleng + 2 > buffersize )
00486 {
00487 buffersize += 2 * BINC;
00488 temp = (PLINT *) realloc( (void *) buffer,
00489 (size_t) buffersize * sizeof ( PLINT ) );
00490 if ( !temp )
00491 {
00492 free( (void *) buffer );
00493 plexit( "plfill: Out of memory!" );
00494 }
00495 buffer = temp;
00496 }
00497
00498 buffer[bufferleng++] = xp1;
00499 buffer[bufferleng++] = yp1;
00500 }
00501
00502 int
00503 compar( const void *pnum1, const void *pnum2 )
00504 {
00505 const struct point *pnt1, *pnt2;
00506
00507 pnt1 = (const struct point *) pnum1;
00508 pnt2 = (const struct point *) pnum2;
00509
00510 if ( pnt1->y < pnt2->y )
00511 return -1;
00512 else if ( pnt1->y > pnt2->y )
00513 return 1;
00514
00515
00516
00517 if ( pnt1->x < pnt2->x )
00518 return -1;
00519 else if ( pnt1->x > pnt2->x )
00520 return 1;
00521
00522 return 0;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 void
00532 plP_plfclp( PLINT *x, PLINT *y, PLINT npts,
00533 PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax,
00534 void ( *draw )( short *, short *, PLINT ) )
00535 {
00536 #ifdef USE_FILL_INTERSECTION_POLYGON
00537 PLINT *x10, *y10, *x1, *y1, *if1, i1start = 0, i, im1, n1, n1m1,
00538 ifnotpointinpolygon;
00539 PLINT x2[4] = { xmin, xmax, xmax, xmin };
00540 PLINT y2[4] = { ymin, ymin, ymax, ymax };
00541 PLINT if2[4] = { 0, 0, 0, 0 };
00542 PLINT n2 = 4;
00543
00544
00545 if ( npts < 3 || !draw )
00546 return;
00547
00548 if ( ( x10 = (PLINT *) malloc( npts * sizeof ( PLINT ) ) ) == NULL )
00549 {
00550 plexit( "plP_plfclp: Insufficient memory" );
00551 }
00552 if ( ( y10 = (PLINT *) malloc( npts * sizeof ( PLINT ) ) ) == NULL )
00553 {
00554 plexit( "plP_plfclp: Insufficient memory" );
00555 }
00556
00557
00558
00559
00560 im1 = npts - 1;
00561 n1 = 0;
00562 for ( i = 0; i < npts; i++ )
00563 {
00564 if ( !( x[i] == x[im1] && y[i] == y[im1] ) )
00565 {
00566 x10[n1] = x[i];
00567 y10[n1++] = y[i];
00568 }
00569 im1 = i;
00570 }
00571
00572
00573 if ( n1 < 3 )
00574 {
00575 free( x10 );
00576 free( y10 );
00577 return;
00578 }
00579
00580
00581
00582
00583
00584
00585 if ( positive_orientation( n1, x10, y10 ) )
00586 {
00587 x1 = x10;
00588 y1 = y10;
00589 }
00590 else
00591 {
00592 if ( ( x1 = (PLINT *) malloc( n1 * sizeof ( PLINT ) ) ) == NULL )
00593 {
00594 plexit( "plP_plfclp: Insufficient memory" );
00595 }
00596 if ( ( y1 = (PLINT *) malloc( n1 * sizeof ( PLINT ) ) ) == NULL )
00597 {
00598 plexit( "plP_plfclp: Insufficient memory" );
00599 }
00600 n1m1 = n1 - 1;
00601 for ( i = 0; i < n1; i++ )
00602 {
00603 x1[n1m1 - i] = x10[i];
00604 y1[n1m1 - i] = y10[i];
00605 }
00606 free( x10 );
00607 free( y10 );
00608 }
00609
00610
00611
00612
00613 im1 = n1 - 1;
00614 for ( i = 0; i < n1; i++ )
00615 {
00616 if ( ( ifnotpointinpolygon =
00617 notpointinpolygon( n2, x2, y2, x1[im1], y1[im1] ) ) != 1 )
00618 break;
00619 im1 = i;
00620 }
00621
00622 if ( ifnotpointinpolygon )
00623 fill_intersection_polygon( 0, 0, 0, draw, x1, y1, i1start, n1, x2, y2, if2, n2 );
00624 else
00625 {
00626 if ( ( if1 = (PLINT *) calloc( n1, sizeof ( PLINT ) ) ) == NULL )
00627 {
00628 plexit( "plP_plfclp: Insufficient memory" );
00629 }
00630 fill_intersection_polygon( 0, 0, 0, draw, x2, y2, i1start, n2, x1, y1, if1, n1 );
00631 free( if1 );
00632 }
00633 free( x1 );
00634 free( y1 );
00635 return;
00636 }
00637 #else // USE_FILL_INTERSECTION_POLYGON
00638
00639 PLINT i, x1, x2, y1, y2;
00640 int iclp = 0, iout = 2;
00641 short _xclp[2 * PL_MAXPOLY + 2], _yclp[2 * PL_MAXPOLY + 2];
00642 short *xclp, *yclp;
00643 int drawable;
00644 int crossed_xmin1 = 0, crossed_xmax1 = 0;
00645 int crossed_ymin1 = 0, crossed_ymax1 = 0;
00646 int crossed_xmin2 = 0, crossed_xmax2 = 0;
00647 int crossed_ymin2 = 0, crossed_ymax2 = 0;
00648 int crossed_up = 0, crossed_down = 0;
00649 int crossed_left = 0, crossed_right = 0;
00650 int inside_lb;
00651 int inside_lu;
00652 int inside_rb;
00653 int inside_ru;
00654
00655
00656 if ( npts < 3 || !draw )
00657 return;
00658
00659 if ( npts < PL_MAXPOLY )
00660 {
00661 xclp = _xclp;
00662 yclp = _yclp;
00663 }
00664 else
00665 {
00666 if ( ( ( xclp = (short *) malloc( ( 2 * npts + 2 ) * sizeof ( short ) ) ) == NULL ) ||
00667 ( ( yclp = (short *) malloc( ( 2 * npts + 2 ) * sizeof ( short ) ) ) == NULL ) )
00668 {
00669 plexit( "plP_plfclp: Insufficient memory" );
00670 }
00671 }
00672 inside_lb = !notpointinpolygon( npts, x, y, xmin, ymin );
00673 inside_lu = !notpointinpolygon( npts, x, y, xmin, ymax );
00674 inside_rb = !notpointinpolygon( npts, x, y, xmax, ymin );
00675 inside_ru = !notpointinpolygon( npts, x, y, xmax, ymax );
00676
00677 for ( i = 0; i < npts - 1; i++ )
00678 {
00679 x1 = x[i]; x2 = x[i + 1];
00680 y1 = y[i]; y2 = y[i + 1];
00681
00682 drawable = ( INSIDE( x1, y1 ) && INSIDE( x2, y2 ) );
00683 if ( !drawable )
00684 drawable = !plP_clipline( &x1, &y1, &x2, &y2,
00685 xmin, xmax, ymin, ymax );
00686
00687 if ( drawable )
00688 {
00689
00690 crossed_xmin2 = ( x1 == xmin ); crossed_xmax2 = ( x1 == xmax );
00691 crossed_ymin2 = ( y1 == ymin ); crossed_ymax2 = ( y1 == ymax );
00692
00693 crossed_left = ( crossed_left || crossed_xmin2 );
00694 crossed_right = ( crossed_right || crossed_xmax2 );
00695 crossed_down = ( crossed_down || crossed_ymin2 );
00696 crossed_up = ( crossed_up || crossed_ymax2 );
00697 iout = iclp + 2;
00698
00699
00700 if ( iclp == 0 )
00701 {
00702 xclp[iclp] = x1; yclp[iclp] = y1; iclp++;
00703 xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
00704 }
00705
00706
00707
00708
00709 else if ( x1 == xclp[iclp - 1] && y1 == yclp[iclp - 1] )
00710 {
00711 xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
00712 }
00713
00714
00715
00716
00717
00718
00719 else
00720 {
00721
00722
00723
00724
00725 xclp[iclp + 1] = x2; yclp[iclp + 1] = y2;
00726 xclp[iclp + 2] = x1; yclp[iclp + 2] = y1;
00727 iout = iout - iclp + 1;
00728
00729 if ( ( ( crossed_xmin1 && crossed_xmax2 ) ||
00730 ( crossed_xmin2 && crossed_xmax1 ) ) &&
00731 inside_lu )
00732 {
00733 if ( crossed_xmin1 )
00734 {
00735 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00736 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00737 }
00738 else
00739 {
00740 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00741 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00742 }
00743 }
00744
00745 else if ( ( ( crossed_xmin1 && crossed_xmax2 ) ||
00746 ( crossed_xmin2 && crossed_xmax1 ) ) &&
00747 inside_lb )
00748 {
00749 if ( crossed_xmin1 )
00750 {
00751 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00752 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00753 }
00754 else
00755 {
00756 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00757 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00758 }
00759 }
00760
00761 else if ( ( ( crossed_ymin1 && crossed_ymax2 ) ||
00762 ( crossed_ymin2 && crossed_ymax1 ) ) &&
00763 inside_lb )
00764 {
00765 if ( crossed_ymin1 )
00766 {
00767 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00768 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00769 }
00770 else
00771 {
00772 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00773 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00774 }
00775 }
00776
00777 else if ( ( ( crossed_ymin1 && crossed_ymax2 ) ||
00778 ( crossed_ymin2 && crossed_ymax1 ) ) &&
00779 inside_rb )
00780 {
00781 if ( crossed_ymin1 )
00782 {
00783 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00784 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00785 }
00786 else
00787 {
00788 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00789 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00790 }
00791 }
00792
00793
00794 else if ( ( crossed_xmin1 && crossed_ymin2 ) ||
00795 ( crossed_ymin1 && crossed_xmin2 ) )
00796 {
00797 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00798 }
00799
00800 else if ( ( crossed_xmax1 && crossed_ymin2 ) ||
00801 ( crossed_ymin1 && crossed_xmax2 ) )
00802 {
00803 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00804 }
00805
00806 else if ( ( crossed_xmin1 && crossed_ymax2 ) ||
00807 ( crossed_ymax1 && crossed_xmin2 ) )
00808 {
00809 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00810 }
00811
00812 else if ( ( crossed_xmax1 && crossed_ymax2 ) ||
00813 ( crossed_ymax1 && crossed_xmax2 ) )
00814 {
00815 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00816 }
00817
00818
00819 xclp[iclp] = x1; yclp[iclp] = y1; iclp++;
00820 xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
00821 }
00822
00823
00824 crossed_xmin1 = ( x2 == xmin ); crossed_xmax1 = ( x2 == xmax );
00825 crossed_ymin1 = ( y2 == ymin ); crossed_ymax1 = ( y2 == ymax );
00826 }
00827 }
00828
00829
00830
00831
00832 if ( iclp == 0 )
00833 {
00834 if ( inside_lb )
00835 {
00836 xclp[0] = xmin; yclp[0] = ymin;
00837 xclp[1] = xmax; yclp[1] = ymin;
00838 xclp[2] = xmax; yclp[2] = ymax;
00839 xclp[3] = xmin; yclp[3] = ymax;
00840 xclp[4] = xmin; yclp[4] = ymin;
00841 ( *draw )( xclp, yclp, 5 );
00842
00843 if ( xclp != _xclp )
00844 {
00845 free( xclp );
00846 free( yclp );
00847 }
00848
00849 return;
00850 }
00851 }
00852
00853
00854
00855 if ( iclp >= 2 )
00856 {
00857 int debug = 0;
00858 int dir = circulation( x, y, npts );
00859 if ( debug )
00860 {
00861 if ( ( xclp[0] == xmin && xclp[iclp - 1] == xmax ) ||
00862 ( xclp[0] == xmax && xclp[iclp - 1] == xmin ) ||
00863 ( yclp[0] == ymin && yclp[iclp - 1] == ymax ) ||
00864 ( yclp[0] == ymax && yclp[iclp - 1] == ymin ) ||
00865 ( xclp[0] == xmin && yclp[iclp - 1] == ymin ) ||
00866 ( yclp[0] == ymin && xclp[iclp - 1] == xmin ) ||
00867 ( xclp[0] == xmax && yclp[iclp - 1] == ymin ) ||
00868 ( yclp[0] == ymin && xclp[iclp - 1] == xmax ) ||
00869 ( xclp[0] == xmax && yclp[iclp - 1] == ymax ) ||
00870 ( yclp[0] == ymax && xclp[iclp - 1] == xmax ) ||
00871 ( xclp[0] == xmin && yclp[iclp - 1] == ymax ) ||
00872 ( yclp[0] == ymax && xclp[iclp - 1] == xmin ) )
00873 {
00874 printf( "dir=%d, clipped points:\n", dir );
00875 for ( i = 0; i < iclp; i++ )
00876 printf( " x[%d]=%d y[%d]=%d", i, xclp[i], i, yclp[i] );
00877 printf( "\n" );
00878 printf( "pre-clipped points:\n" );
00879 for ( i = 0; i < npts; i++ )
00880 printf( " x[%d]=%d y[%d]=%d", i, x[i], i, y[i] );
00881 printf( "\n" );
00882 }
00883 }
00884
00885
00886
00887 if ( xclp[0] == xmin && xclp[iclp - 1] == xmax )
00888 {
00889 if ( dir > 0 )
00890 {
00891 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00892 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00893 }
00894 else
00895 {
00896 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00897 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00898 }
00899 }
00900 else if ( xclp[0] == xmax && xclp[iclp - 1] == xmin )
00901 {
00902 if ( dir > 0 )
00903 {
00904 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00905 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00906 }
00907 else
00908 {
00909 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00910 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00911 }
00912 }
00913
00914
00915 else if ( yclp[0] == ymin && yclp[iclp - 1] == ymax )
00916 {
00917 if ( dir > 0 )
00918 {
00919 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00920 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00921 }
00922 else
00923 {
00924 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00925 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00926 }
00927 }
00928 else if ( yclp[0] == ymax && yclp[iclp - 1] == ymin )
00929 {
00930 if ( dir > 0 )
00931 {
00932 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00933 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00934 }
00935 else
00936 {
00937 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00938 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00939 }
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 else if ( ( xclp[0] == xmin && yclp[iclp - 1] == ymin && dir < 0 ) ||
00955 ( yclp[0] == ymin && xclp[iclp - 1] == xmin && dir > 0 ) )
00956 {
00957 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00958 }
00959
00960 else if ( ( xclp[0] == xmin && yclp[iclp - 1] == ymin && dir > 0 ) )
00961 {
00962 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00963 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00964 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00965 }
00966
00967 else if ( ( yclp[0] == ymin && xclp[iclp - 1] == xmin && dir < 0 ) )
00968 {
00969 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00970 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00971 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00972 }
00973
00974 else if ( ( xclp[0] == xmax && yclp[iclp - 1] == ymin && dir > 0 ) ||
00975 ( yclp[0] == ymin && xclp[iclp - 1] == xmax && dir < 0 ) )
00976 {
00977 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
00978 }
00979
00980 else if ( yclp[0] == ymin && xclp[iclp - 1] == xmax && dir > 0 )
00981 {
00982 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00983 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00984 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00985 }
00986
00987 else if ( xclp[0] == xmax && yclp[iclp - 1] == ymin && dir < 0 )
00988 {
00989 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
00990 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
00991 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00992 }
00993
00994 else if ( ( xclp[0] == xmax && yclp[iclp - 1] == ymax && dir < 0 ) ||
00995 ( yclp[0] == ymax && xclp[iclp - 1] == xmax && dir > 0 ) )
00996 {
00997 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
00998 }
00999
01000 else if ( xclp[0] == xmax && yclp[iclp - 1] == ymax && dir > 0 )
01001 {
01002 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
01003 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
01004 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
01005 }
01006
01007 else if ( yclp[0] == ymax && xclp[iclp - 1] == xmax && dir < 0 )
01008 {
01009 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
01010 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
01011 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
01012 }
01013
01014 else if ( ( xclp[0] == xmin && yclp[iclp - 1] == ymax && dir > 0 ) ||
01015 ( yclp[0] == ymax && xclp[iclp - 1] == xmin && dir < 0 ) )
01016 {
01017 xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
01018 }
01019
01020 else if ( yclp[0] == ymax && xclp[iclp - 1] == xmin && dir > 0 )
01021 {
01022 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
01023 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
01024 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
01025 }
01026
01027 else if ( xclp[0] == xmin && yclp[iclp - 1] == ymax && dir < 0 )
01028 {
01029 xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
01030 xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
01031 xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040 if ( inside_lb + inside_rb + inside_lu + inside_ru == 4 )
01041 {
01042 int dir = circulation( x, y, npts );
01043 PLINT xlim[4], ylim[4];
01044 int insert;
01045 int incr;
01046
01047 xlim[0] = xmin; ylim[0] = ymin;
01048 xlim[1] = xmax; ylim[1] = ymin;
01049 xlim[2] = xmax; ylim[2] = ymax;
01050 xlim[3] = xmin; ylim[3] = ymax;
01051
01052 if ( crossed_left + crossed_right + crossed_down + crossed_up == 1 )
01053 {
01054 if ( dir > 0 )
01055 {
01056 incr = 1;
01057 insert = 0 * crossed_left + 1 * crossed_down + 2 * crossed_right +
01058 3 * crossed_up;
01059 }
01060 else
01061 {
01062 incr = -1;
01063 insert = 3 * crossed_left + 2 * crossed_up + 1 * crossed_right +
01064 0 * crossed_down;
01065 }
01066 }
01067
01068 if ( crossed_left + crossed_right == 2 && crossed_down + crossed_up == 0 )
01069 {
01070 if ( xclp[iclp - 1] == xmin )
01071 {
01072 if ( dir == 1 )
01073 {
01074 incr = 1;
01075 insert = 0;
01076 }
01077 else
01078 {
01079 incr = -1;
01080 insert = 3;
01081 }
01082 }
01083 else
01084 {
01085 if ( dir == 1 )
01086 {
01087 incr = 1;
01088 insert = 1;
01089 }
01090 else
01091 {
01092 incr = -1;
01093 insert = 2;
01094 }
01095 }
01096 }
01097
01098 if ( crossed_left + crossed_right == 0 && crossed_down + crossed_up == 2 )
01099 {
01100 if ( yclp[iclp - 1] == ymin )
01101 {
01102 if ( dir == 1 )
01103 {
01104 incr = 1;
01105 insert = 1;
01106 }
01107 else
01108 {
01109 incr = -1;
01110 insert = 0;
01111 }
01112 }
01113 else
01114 {
01115 if ( dir == 1 )
01116 {
01117 incr = 1;
01118 insert = 3;
01119 }
01120 else
01121 {
01122 incr = -1;
01123 insert = 2;
01124 }
01125 }
01126 }
01127
01128 for ( i = 0; i < 4; i++ )
01129 {
01130 xclp[iclp] = xlim[insert];
01131 yclp[iclp] = ylim[insert];
01132 iclp++;
01133 insert += incr;
01134 if ( insert > 3 )
01135 insert = 0;
01136 if ( insert < 0 )
01137 insert = 3;
01138 }
01139 }
01140
01141
01142 if ( iclp >= 3 )
01143 ( *draw )( xclp, yclp, iclp );
01144
01145 if ( xclp != _xclp )
01146 {
01147 free( xclp );
01148 free( yclp );
01149 }
01150 }
01151 #endif // USE_FILL_INTERSECTION_POLYGON
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 int
01177 circulation( PLINT *x, PLINT *y, PLINT npts )
01178 {
01179 PLFLT xproduct;
01180 int direction = 0;
01181 PLFLT x1, y1, x2, y2, x3, y3;
01182 int i;
01183
01184 xproduct = 0.0;
01185 x1 = x[0];
01186 y1 = y[0];
01187 for ( i = 1; i < npts - 2; i++ )
01188 {
01189 x2 = x[i + 1];
01190 y2 = y[i + 1];
01191 x3 = x[i + 2];
01192 y3 = y[i + 2];
01193 xproduct = xproduct + ( x2 - x1 ) * ( y3 - y2 ) - ( y2 - y1 ) * ( x3 - x2 );
01194 }
01195
01196 if ( xproduct > 0.0 )
01197 direction = 1;
01198 if ( xproduct < 0.0 )
01199 direction = -1;
01200 return direction;
01201 }
01202
01203
01204
01205 int
01206 plP_pointinpolygon( PLINT n, const PLFLT *x, const PLFLT *y, PLFLT xp, PLFLT yp )
01207 {
01208 int i, return_value;
01209 PLINT *xint, *yint;
01210 PLFLT xmaximum = fabs( xp ), ymaximum = fabs( yp ), xscale, yscale;
01211 if ( ( xint = (PLINT *) malloc( n * sizeof ( PLINT ) ) ) == NULL )
01212 {
01213 plexit( "PlP_pointinpolygon: Insufficient memory" );
01214 }
01215 if ( ( yint = (PLINT *) malloc( n * sizeof ( PLINT ) ) ) == NULL )
01216 {
01217 plexit( "PlP_pointinpolygon: Insufficient memory" );
01218 }
01219 for ( i = 0; i < n; i++ )
01220 {
01221 xmaximum = MAX( xmaximum, fabs( x[i] ) );
01222 ymaximum = MAX( ymaximum, fabs( y[i] ) );
01223 }
01224 xscale = 1.e8 / xmaximum;
01225 yscale = 1.e8 / ymaximum;
01226 for ( i = 0; i < n; i++ )
01227 {
01228 xint[i] = (PLINT) ( xscale * x[i] );
01229 yint[i] = (PLINT) ( yscale * y[i] );
01230 }
01231 return_value = !notpointinpolygon( n, xint, yint,
01232 (PLINT) ( xscale * xp ), (PLINT) ( yscale * yp ) );
01233 free( xint );
01234 free( yint );
01235 return return_value;
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 #define NEW_NOTPOINTINPOLYGON_CODE
01251 static int
01252 notpointinpolygon( PLINT n, const PLINT *x, const PLINT *y, PLINT xp, PLINT yp )
01253 {
01254 #ifdef NEW_NOTPOINTINPOLYGON_CODE
01255 int i, im1, ifnotcrossed;
01256 int count_crossings = 0;
01257 PLINT xmin, xout, yout, xintersect, yintersect;
01258
01259
01260
01261
01262 xmin = x[0];
01263 xout = x[0];
01264 yout = y[0];
01265 for ( i = 1; i < n; i++ )
01266 {
01267 xout = MAX( xout, x[i] );
01268 xmin = MIN( xmin, x[i] );
01269 }
01270
01271 xout = xout + ( xout - xmin ) + 10;
01272
01273
01274
01275
01276 im1 = n - 1;
01277 for ( i = 0; i < n; i++ )
01278 {
01279 if ( !( x[im1] == x[i] && y[im1] == y[i] ) )
01280 {
01281 ifnotcrossed = notcrossed( &xintersect, &yintersect,
01282 x[im1], y[im1], x[i], y[i],
01283 xp, yp, xout, yout );
01284
01285 if ( !ifnotcrossed )
01286 count_crossings++;
01287 else if ( ifnotcrossed & ( PL_NEAR_A1 | PL_NEAR_A2 | PL_NEAR_B1 | PL_NEAR_B2 ) )
01288 return 1;
01289 }
01290 im1 = i;
01291 }
01292
01293
01294
01295
01296
01297 if ( ( count_crossings % 2 ) == 1 )
01298 return 0;
01299 else
01300 return 2;
01301 }
01302 #else // NEW_NOTPOINTINPOLYGON_CODE
01303 int i;
01304 int count_crossings;
01305 PLFLT x1, y1, x2, y2, xpp, ypp, xout, yout, xmax;
01306 PLFLT xvp, yvp, xvv, yvv, xv1, yv1, xv2, yv2;
01307 PLFLT inprod1, inprod2;
01308
01309 xpp = (PLFLT) xp;
01310 ypp = (PLFLT) yp;
01311
01312 count_crossings = 0;
01313
01314
01315
01316
01317 xmax = x[0];
01318 xout = x[0];
01319 yout = y[0];
01320 for ( i = 0; i < n; i++ )
01321 {
01322 if ( xout > x[i] )
01323 {
01324 xout = x[i];
01325 }
01326 if ( xmax < x[i] )
01327 {
01328 xmax = x[i];
01329 }
01330 }
01331 xout = xout - ( xmax - xout );
01332
01333
01334
01335
01336 xpp = (PLFLT) xp;
01337 ypp = (PLFLT) yp;
01338
01339 xvp = xpp - xout;
01340 yvp = ypp - yout;
01341
01342 for ( i = 0; i < n; i++ )
01343 {
01344 x1 = (PLFLT) x[i];
01345 y1 = (PLFLT) y[i];
01346 if ( i < n - 1 )
01347 {
01348 x2 = (PLFLT) x[i + 1];
01349 y2 = (PLFLT) y[i + 1];
01350 }
01351 else
01352 {
01353 x2 = (PLFLT) x[0];
01354 y2 = (PLFLT) y[0];
01355 }
01356
01357
01358 if ( x1 == x2 && y1 == y2 )
01359 {
01360 continue;
01361 }
01362
01363
01364
01365 xv1 = x1 - xout;
01366 yv1 = y1 - yout;
01367 xv2 = x2 - xout;
01368 yv2 = y2 - yout;
01369 inprod1 = xv1 * yvp - yv1 * xvp;
01370 inprod2 = xv2 * yvp - yv2 * xvp;
01371 if ( inprod1 * inprod2 >= 0.0 )
01372 {
01373
01374 continue;
01375 }
01376
01377
01378
01379 xvv = x2 - x1;
01380 yvv = y2 - y1;
01381 xv1 = xpp - x1;
01382 yv1 = ypp - y1;
01383 xv2 = xout - x1;
01384 yv2 = yout - y1;
01385 inprod1 = xv1 * yvv - yv1 * xvv;
01386 inprod2 = xv2 * yvv - yv2 * xvv;
01387 if ( inprod1 * inprod2 >= 0.0 )
01388 {
01389
01390 continue;
01391 }
01392
01393
01394 count_crossings++;
01395 }
01396
01397
01398
01399
01400 return !( count_crossings % 2 );
01401 }
01402 #endif // NEW_NOTPOINTINPOLYGON_CODE
01403
01404 #define MAX_RECURSION_DEPTH 10
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 void
01453 fill_intersection_polygon( PLINT recursion_depth, PLINT ifextrapolygon,
01454 PLINT fill_status,
01455 void ( *fill )( short *, short *, PLINT ),
01456 const PLINT *x1, const PLINT *y1,
01457 PLINT i1start, PLINT n1,
01458 const PLINT *x2, const PLINT *y2,
01459 const PLINT *if2, PLINT n2 )
01460 {
01461 PLINT i1, i1m1, i1start_new,
01462 i2, i2m1,
01463 kk, kkstart1, kkstart21, kkstart22,
01464 k, kstart, range1,
01465 range21, range22, ncrossed, ncrossed_change,
01466 nsplit1, nsplit2, nsplit2m1;
01467 PLINT xintersect[2], yintersect[2], i1intersect[2],
01468 i2intersect[2], ifnotcrossed;
01469 PLINT *xsplit1, *ysplit1, *ifsplit1,
01470 *xsplit2, *ysplit2, *ifsplit2;
01471 PLINT ifill, nfill = 0,
01472 ifnotpolygon1inpolygon2, ifnotpolygon2inpolygon1;
01473 const PLINT *xfiller, *yfiller;
01474 short *xfill, *yfill;
01475
01476 if ( recursion_depth > MAX_RECURSION_DEPTH )
01477 {
01478 plwarn( "fill_intersection_polygon: Recursion_depth too large. "
01479 "Probably an internal error figuring out intersections. " );
01480 return;
01481 }
01482
01483 if ( n1 < 3 )
01484 {
01485 plwarn( "fill_intersection_polygon: Internal error; n1 < 3." );
01486 return;
01487 }
01488
01489 if ( n2 < 3 )
01490 {
01491 plwarn( "fill_intersection_polygon: Internal error; n2 < 3." );
01492 return;
01493 }
01494
01495 if ( i1start < 0 || i1start >= n1 )
01496 {
01497 plwarn( "fill_intersection_polygon: invalid i1start." );
01498 return;
01499 }
01500
01501
01502 i1m1 = i1start - 1;
01503 if ( i1m1 < 0 )
01504 i1m1 = n1 - 1;
01505
01506 for ( i1 = i1start; i1 < n1; i1++ )
01507 {
01508 if ( x1[i1] == x1[i1m1] && y1[i1] == y1[i1m1] )
01509 break;
01510 i1m1 = i1;
01511 }
01512
01513 if ( i1 < n1 )
01514 {
01515 plwarn( "fill_intersection_polygon: Internal error; i1 < n1." );
01516 return;
01517 }
01518
01519 i2m1 = n2 - 1;
01520 for ( i2 = 0; i2 < n2; i2++ )
01521 {
01522 if ( x2[i2] == x2[i2m1] && y2[i2] == y2[i2m1] )
01523 break;
01524 i2m1 = i2;
01525 }
01526
01527 if ( i2 < n2 )
01528 {
01529 plwarn( "fill_intersection_polygon: Internal error; i2 < n2." );
01530 return;
01531 }
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 ncrossed = 0;
01589 i1m1 = i1start - 1;
01590 if ( i1m1 < 0 )
01591 i1m1 += n1;
01592 for ( i1 = i1start; i1 < n1; i1++ )
01593 {
01594 ncrossed_change = number_crossings(
01595 &xintersect[ncrossed], &yintersect[ncrossed],
01596 &i2intersect[ncrossed], 2 - ncrossed,
01597 i1, n1, x1, y1, n2, x2, y2 );
01598 if ( ncrossed_change > 0 )
01599 {
01600 i1intersect[ncrossed] = i1;
01601 if ( ncrossed_change == 2 )
01602 ;
01603 i1intersect[1] = i1;
01604
01605 ncrossed += ncrossed_change;
01606 if ( ncrossed == 2 )
01607 {
01608
01609
01610
01611
01612
01613
01614 i1start_new = i1;
01615
01616
01617
01618
01619
01620
01621 range1 = i1intersect[1] - i1intersect[0];
01622
01623
01624
01625
01626
01627
01628 kkstart1 = i1intersect[0];
01629
01630
01631
01632
01633 range21 = i2intersect[0] - i2intersect[1];
01634 if ( range21 < 0 )
01635 range21 += n2;
01636
01637
01638
01639
01640
01641
01642
01643
01644 if ( range21 == 0 )
01645 {
01646 int ifxsort, ifascend;
01647
01648
01649
01650
01651
01652 i2 = i2intersect[1];
01653 i2m1 = i2 - 1;
01654 if ( i2m1 < 0 )
01655 i2m1 += n2;
01656
01657 ifxsort = abs( x2[i2] - x2[i2m1] ) > abs( y2[i2] - y2[i2m1] );
01658 ifascend = ( ifxsort && x2[i2] > x2[i2m1] ) ||
01659 ( !ifxsort && y2[i2] > y2[i2m1] );
01660 if ( ( ifxsort && ifascend && xintersect[0] < xintersect[1] ) ||
01661 ( !ifxsort && ifascend && yintersect[0] < yintersect[1] ) ||
01662 ( ifxsort && !ifascend && xintersect[0] >= xintersect[1] ) ||
01663 ( !ifxsort && !ifascend && yintersect[0] >= yintersect[1] ) )
01664 {
01665 range21 = n2;
01666 }
01667 }
01668
01669 kkstart21 = i2intersect[1];
01670 nsplit1 = 2 + range1 + range21;
01671
01672
01673
01674
01675
01676 range22 = n2 - range21;
01677
01678 kkstart22 = i2intersect[1] - 1;
01679 if ( kkstart22 < 0 )
01680 kkstart22 += n2;
01681 nsplit2 = 2 + range1 + range22;
01682
01683 if ( ( xsplit1 = (PLINT *) malloc( nsplit1 * sizeof ( PLINT ) ) ) == NULL )
01684 {
01685 plexit( "fill_intersection_polygon: Insufficient memory" );
01686 }
01687 if ( ( ysplit1 = (PLINT *) malloc( nsplit1 * sizeof ( PLINT ) ) ) == NULL )
01688 {
01689 plexit( "fill_intersection_polygon: Insufficient memory" );
01690 }
01691 if ( ( ifsplit1 = (PLINT *) malloc( nsplit1 * sizeof ( PLINT ) ) ) == NULL )
01692 {
01693 plexit( "fill_intersection_polygon: Insufficient memory" );
01694 }
01695
01696 if ( ( xsplit2 = (PLINT *) malloc( nsplit2 * sizeof ( PLINT ) ) ) == NULL )
01697 {
01698 plexit( "fill_intersection_polygon: Insufficient memory" );
01699 }
01700 if ( ( ysplit2 = (PLINT *) malloc( nsplit2 * sizeof ( PLINT ) ) ) == NULL )
01701 {
01702 plexit( "fill_intersection_polygon: Insufficient memory" );
01703 }
01704 if ( ( ifsplit2 = (PLINT *) malloc( nsplit2 * sizeof ( PLINT ) ) ) == NULL )
01705 {
01706 plexit( "fill_intersection_polygon: Insufficient memory" );
01707 }
01708
01709
01710
01711
01712
01713
01714
01715
01716 k = 0;
01717 xsplit1[k] = xintersect[0];
01718 ysplit1[k] = yintersect[0];
01719 ifsplit1[k] = 1;
01720 nsplit2m1 = nsplit2 - 1;
01721 xsplit2[nsplit2m1 - k] = xintersect[0];
01722 ysplit2[nsplit2m1 - k] = yintersect[0];
01723 ifsplit2[nsplit2m1 - k] = 1;
01724 kstart = k + 1;
01725 kk = kkstart1;
01726
01727
01728
01729 for ( k = kstart; k < range1 + 1; k++ )
01730 {
01731 xsplit1[k] = x1[kk];
01732 ysplit1[k] = y1[kk];
01733 ifsplit1[k] = 2;
01734 xsplit2[nsplit2m1 - k] = x1[kk];
01735 ysplit2[nsplit2m1 - k] = y1[kk++];
01736 ifsplit2[nsplit2m1 - k] = 2;
01737 }
01738 xsplit1[k] = xintersect[1];
01739 ysplit1[k] = yintersect[1];
01740 ifsplit1[k] = 1;
01741 xsplit2[nsplit2m1 - k] = xintersect[1];
01742 ysplit2[nsplit2m1 - k] = yintersect[1];
01743 ifsplit2[nsplit2m1 - k] = 1;
01744
01745
01746
01747 kstart = k + 1;
01748 kk = kkstart21;
01749 for ( k = kstart; k < nsplit1; k++ )
01750 {
01751 xsplit1[k] = x2[kk];
01752 ysplit1[k] = y2[kk];
01753 ifsplit1[k] = if2[kk++];
01754 if ( kk >= n2 )
01755 kk -= n2;
01756 }
01757
01758
01759
01760
01761
01762
01763 fill_intersection_polygon(
01764 recursion_depth + 1, ifextrapolygon, 1, fill,
01765 x1, y1, i1start_new, n1,
01766 xsplit1, ysplit1, ifsplit1, nsplit1 );
01767 free( xsplit1 );
01768 free( ysplit1 );
01769 free( ifsplit1 );
01770
01771
01772
01773 kk = kkstart22;
01774 for ( k = kstart; k < nsplit2; k++ )
01775 {
01776 xsplit2[nsplit2m1 - k] = x2[kk];
01777 ysplit2[nsplit2m1 - k] = y2[kk];
01778 ifsplit2[nsplit2m1 - k] = if2[kk--];
01779 if ( kk < 0 )
01780 kk += n2;
01781 }
01782
01783
01784
01785
01786
01787
01788 fill_intersection_polygon(
01789 recursion_depth + 1, ifextrapolygon, -1, fill,
01790 x1, y1, i1start_new, n1,
01791 xsplit2, ysplit2, ifsplit2, nsplit2 );
01792 free( xsplit2 );
01793 free( ysplit2 );
01794 free( ifsplit2 );
01795 return;
01796 }
01797 }
01798 i1m1 = i1;
01799 }
01800
01801 if ( ncrossed != 0 )
01802 {
01803 plwarn( "fill_intersection_polygon: Internal error; ncrossed != 0." );
01804 return;
01805 }
01806
01807
01808
01809
01810
01811
01812 if ( fill_status == -1 )
01813 return;
01814 else if ( fill_status == 1 )
01815 {
01816 nfill = n2;
01817 xfiller = x2;
01818 yfiller = y2;
01819 }
01820 else if ( fill_status == 0 )
01821
01822 {
01823 if ( recursion_depth != 0 )
01824 {
01825 plwarn( "fill_intersection_polygon: Internal error; fill_status == 0 for recursion_depth > 0" );
01826 return;
01827 }
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 for ( i1 = 0; i1 < n1; i1++ )
01839 {
01840 if ( ( ifnotpolygon1inpolygon2 =
01841 notpointinpolygon( n2, x2, y2, x1[i1], y1[i1] ) ) != 1 )
01842 break;
01843 }
01844
01845
01846
01847 ifnotpolygon2inpolygon1 = 1;
01848 for ( i2 = 0; i2 < n2; i2++ )
01849 {
01850
01851
01852 if ( !if2[i2] && ( ifnotpolygon2inpolygon1 =
01853 notpointinpolygon( n1, x1, y1, x2[i2], y2[i2] ) ) != 1 )
01854 break;
01855 }
01856
01857 if ( ifnotpolygon2inpolygon1 == 0 && ifnotpolygon1inpolygon2 == 0 )
01858 plwarn( "fill_intersection_polygon: Internal error; no intersections found but each polygon definitely inside the other!" );
01859 else if ( ifnotpolygon2inpolygon1 == 2 && ifnotpolygon1inpolygon2 == 2 )
01860
01861
01862 return;
01863 else if ( ifnotpolygon2inpolygon1 == 0 )
01864 {
01865
01866 nfill = n2;
01867 xfiller = x2;
01868 yfiller = y2;
01869 }
01870 else if ( ifnotpolygon1inpolygon2 == 0 )
01871 {
01872
01873 nfill = n1;
01874 xfiller = x1;
01875 yfiller = y1;
01876 }
01877 else if ( ifnotpolygon2inpolygon1 == 1 && ifnotpolygon1inpolygon2 == 1 )
01878 {
01879
01880
01881 nfill = n2;
01882 xfiller = x2;
01883 yfiller = y2;
01884 }
01885 else
01886 {
01887
01888
01889
01890 plwarn( "fill_intersection_polygon: inscribed polygons are still ToDo" );
01891 }
01892 }
01893
01894 if ( nfill > 0 )
01895 {
01896 if ( ( xfill = (short *) malloc( nfill * sizeof ( short ) ) ) == NULL )
01897 {
01898 plexit( "fill_intersection_polygon: Insufficient memory" );
01899 }
01900 if ( ( yfill = (short *) malloc( nfill * sizeof ( short ) ) ) == NULL )
01901 {
01902 plexit( "fill_intersection_polygon: Insufficient memory" );
01903 }
01904 for ( ifill = 0; ifill < nfill; ifill++ )
01905 {
01906 xfill[ifill] = xfiller[ifill];
01907 yfill[ifill] = yfiller[ifill];
01908 }
01909 ( *fill )( xfill, yfill, nfill );
01910 free( xfill );
01911 free( yfill );
01912 }
01913
01914 return;
01915 }
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927 int
01928 notcrossed( PLINT * xintersect, PLINT * yintersect,
01929 PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2,
01930 PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 )
01931 {
01932 PLFLT factor, factor_NBCC, fxintersect, fyintersect;
01933
01934
01935 PLFLT xA2A1, yA2A1, xB2B1, yB2B1;
01936 PLFLT xB1A1, yB1A1, xB2A1, yB2A1;
01937 PLINT status = 0;
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 xA2A1 = xA2 - xA1;
01957 yA2A1 = yA2 - yA1;
01958 xB2B1 = xB2 - xB1;
01959 yB2B1 = yB2 - yB1;
01960
01961 factor = xA2A1 * yB2B1 - yA2A1 * xB2B1;
01962 factor_NBCC = PL_NBCC * ( fabs( xA2A1 ) + fabs( yB2B1 ) + fabs( yA2A1 ) + fabs( xB2B1 ) );
01963 if ( fabs( factor ) <= factor_NBCC )
01964 {
01965 if ( fabs( factor ) > 0. )
01966 status = status | PL_NEAR_PARALLEL;
01967 else
01968 status = status | PL_PARALLEL;
01969
01970
01971
01972 if ( ( BETW_NBCC( xA1, xB1, xB2 ) && BETW_NBCC( yA1, yB1, yB2 ) ) )
01973 {
01974 fxintersect = xA1;
01975 fyintersect = yA1;
01976 }
01977 else if ( ( BETW_NBCC( xA2, xB1, xB2 ) && BETW_NBCC( yA2, yB1, yB2 ) ) )
01978 {
01979 fxintersect = xA2;
01980 fyintersect = yA2;
01981 }
01982 else if ( ( BETW_NBCC( xB1, xA1, xA2 ) && BETW_NBCC( yB1, yA1, yA2 ) ) )
01983 {
01984 fxintersect = xB1;
01985 fyintersect = yB1;
01986 }
01987 else if ( ( BETW_NBCC( xB2, xA1, xA2 ) && BETW_NBCC( yB2, yA1, yA2 ) ) )
01988 {
01989 fxintersect = xB2;
01990 fyintersect = yB2;
01991 }
01992 else
01993 {
01994 fxintersect = 0.25 * ( xA1 + xA2 + xB1 + xB2 );
01995 fyintersect = 0.25 * ( yA1 + yA2 + yB1 + yB2 );
01996 }
01997 }
01998 else
01999 {
02000 xB1A1 = xB1 - xA1;
02001 yB1A1 = yB1 - yA1;
02002 xB2A1 = xB2 - xA1;
02003 yB2A1 = yB2 - yA1;
02004
02005 factor = ( xB1A1 * yB2A1 - yB1A1 * xB2A1 ) / factor;
02006 fxintersect = factor * xA2A1 + xA1;
02007 fyintersect = factor * yA2A1 + yA1;
02008 }
02009
02010
02011 if ( ( BETW_NBCC( fxintersect, xA1, xA2 ) && BETW_NBCC( fyintersect, yA1, yA2 ) ) &&
02012 ( BETW_NBCC( fxintersect, xB1, xB2 ) && BETW_NBCC( fyintersect, yB1, yB2 ) ) )
02013 {
02014
02015
02016
02017 if ( fabs( fxintersect - xA1 ) <= PL_NBCC && fabs( fyintersect - yA1 ) <= PL_NBCC )
02018 status = status | PL_NEAR_A1;
02019 else if ( fabs( fxintersect - xA2 ) <= PL_NBCC && fabs( fyintersect - yA2 ) <= PL_NBCC )
02020 status = status | PL_NEAR_A2;
02021 else if ( fabs( fxintersect - xB1 ) <= PL_NBCC && fabs( fyintersect - yB1 ) <= PL_NBCC )
02022 status = status | PL_NEAR_B1;
02023 else if ( fabs( fxintersect - xB2 ) <= PL_NBCC && fabs( fyintersect - yB2 ) <= PL_NBCC )
02024 status = status | PL_NEAR_B2;
02025
02026
02027 }
02028 else
02029 status = status | PL_NOT_CROSSED;
02030 *xintersect = fxintersect;
02031 *yintersect = fyintersect;
02032
02033 return status;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047 int
02048 positive_orientation( PLINT n, const PLINT *x, const PLINT *y )
02049 {
02050 PLINT i, im1;
02051
02052
02053
02054 PLFLT twice_area = 0.;
02055 if ( n < 3 )
02056 {
02057 plwarn( "positive_orientation: internal logic error, n < 3" );
02058 return 0;
02059 }
02060 im1 = n - 1;
02061 for ( i = 0; i < n; i++ )
02062 {
02063 twice_area += (PLFLT) x[im1] * (PLFLT) y[i] - (PLFLT) x[i] * (PLFLT) y[im1];
02064 im1 = i;
02065 }
02066 if ( twice_area == 0. )
02067 {
02068 plwarn( "positive_orientation: internal logic error, twice_area == 0." );
02069 return 0;
02070 }
02071 else
02072 return twice_area > 0.;
02073 }
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087 int
02088 number_crossings( PLINT *xcross, PLINT *ycross, PLINT *i2cross, PLINT ncross,
02089 PLINT i1, PLINT n1, const PLINT *x1, const PLINT *y1,
02090 PLINT n2, const PLINT *x2, const PLINT *y2 )
02091 {
02092 int i1m1, i2, i2m1, ifnotcrossed;
02093 int ifxsort, ifascend, count_crossings = 0, status = 0;
02094 PLINT xintersect, yintersect;
02095
02096 i1m1 = i1 - 1;
02097 if ( i1m1 < 0 )
02098 i1m1 += n1;
02099 if ( !( ncross == 1 || ncross == 2 ) ||
02100 ( x1[i1m1] == x1[i1] && y1[i1m1] == y1[i1] ) || n1 < 2 || n2 < 2 )
02101 {
02102 plwarn( "findcrossings: invalid call" );
02103 return -1;
02104 }
02105
02106 ifxsort = abs( x1[i1] - x1[i1m1] ) > abs( y1[i1] - y1[i1m1] );
02107 ifascend = ( ifxsort && x1[i1] > x1[i1m1] ) ||
02108 ( !ifxsort && y1[i1] > y1[i1m1] );
02109
02110
02111
02112
02113
02114
02115
02116 i1m1 = i1 - 1;
02117 if ( i1m1 < 0 )
02118 i1m1 += n1;
02119 i2m1 = n2 - 1;
02120 for ( i2 = 0; i2 < n2; i2++ )
02121 {
02122 if ( !( x2[i2m1] == x2[i2] && y2[i2m1] == y2[i2] ) )
02123 {
02124 ifnotcrossed = notcrossed( &xintersect, &yintersect,
02125 x1[i1m1], y1[i1m1], x1[i1], y1[i1],
02126 x2[i2m1], y2[i2m1], x2[i2], y2[i2] );
02127
02128 if ( !ifnotcrossed )
02129 {
02130 count_crossings++;
02131 if ( count_crossings == 1 )
02132 {
02133 xcross[0] = xintersect;
02134 ycross[0] = yintersect;
02135 i2cross[0] = i2;
02136 status = 1;
02137 }
02138 else
02139 {
02140 if ( ( ifxsort && ifascend && xintersect < xcross[0] ) ||
02141 ( !ifxsort && ifascend && yintersect < ycross[0] ) ||
02142 ( ifxsort && !ifascend && xintersect >= xcross[0] ) ||
02143 ( !ifxsort && !ifascend && yintersect >= ycross[0] ) )
02144 {
02145 if ( ncross == 2 )
02146 {
02147 xcross[1] = xcross[0];
02148 ycross[1] = ycross[0];
02149 i2cross[1] = i2cross[0];
02150 status = 2;
02151 }
02152 xcross[0] = xintersect;
02153 ycross[0] = yintersect;
02154 i2cross[0] = i2;
02155 }
02156 else if ( ncross == 2 && ( count_crossings == 2 || (
02157 ( ifxsort && ifascend && xintersect < xcross[1] ) ||
02158 ( !ifxsort && ifascend && yintersect < ycross[1] ) ||
02159 ( ifxsort && !ifascend && xintersect >= xcross[1] ) ||
02160 ( !ifxsort && !ifascend && yintersect >= ycross[1] ) ) ) )
02161 {
02162 xcross[1] = xintersect;
02163 ycross[1] = yintersect;
02164 i2cross[1] = i2;
02165 status = 2;
02166 }
02167 }
02168 }
02169 }
02170 i2m1 = i2;
02171 }
02172 return status;
02173 }