00001
00002
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "plplotP.h"
00029
00030
00031
00032 #define BINC 50 // Block size for memory allocation
00033
00034 static PLINT pl3mode = 0;
00035 static PLINT pl3upv = 1;
00036
00037 static PLINT zbflg = 0, zbcol, zbwidth;
00038 static PLFLT zbtck;
00039
00040 static PLINT *oldhiview = NULL;
00041 static PLINT *oldloview = NULL;
00042 static PLINT *newhiview = NULL;
00043 static PLINT *newloview = NULL;
00044 static PLINT *utmp = NULL;
00045 static PLINT *vtmp = NULL;
00046 static PLFLT *ctmp = NULL;
00047
00048 static PLINT mhi, xxhi, newhisize;
00049 static PLINT mlo, xxlo, newlosize;
00050
00051
00052 static PLFLT xlight, ylight, zlight;
00053 static PLINT falsecolor = 0;
00054 static PLFLT fc_minz, fc_maxz;
00055
00056
00057
00058 static void plgrid3( PLFLT );
00059 static void plnxtv( PLINT *, PLINT *, PLFLT*, PLINT, PLINT );
00060 static void plside3( PLFLT *, PLFLT *, PLF2OPS, PLPointer, PLINT, PLINT, PLINT );
00061 static void plt3zz( PLINT, PLINT, PLINT, PLINT,
00062 PLINT, PLINT *, PLFLT *, PLFLT *, PLF2OPS, PLPointer,
00063 PLINT, PLINT, PLINT *, PLINT *, PLFLT* );
00064 static void plnxtvhi( PLINT *, PLINT *, PLFLT*, PLINT, PLINT );
00065 static void plnxtvlo( PLINT *, PLINT *, PLFLT*, PLINT, PLINT );
00066 static void plnxtvhi_draw( PLINT *u, PLINT *v, PLFLT* c, PLINT n );
00067
00068 static void savehipoint( PLINT, PLINT );
00069 static void savelopoint( PLINT, PLINT );
00070 static void swaphiview( void );
00071 static void swaploview( void );
00072 static void myexit( char * );
00073 static void myabort( char * );
00074 static void freework( void );
00075 static int plabv( PLINT, PLINT, PLINT, PLINT, PLINT, PLINT );
00076 static void pl3cut( PLINT, PLINT, PLINT, PLINT, PLINT,
00077 PLINT, PLINT, PLINT, PLINT *, PLINT * );
00078 static PLFLT plGetAngleToLight( PLFLT* x, PLFLT* y, PLFLT* z );
00079 static void plP_draw3d( PLINT x, PLINT y, PLFLT *c, PLINT j, PLINT move );
00080 static void plxyindexlimits( PLINT instart, PLINT inn,
00081 PLINT *inarray_min, PLINT *inarray_max,
00082 PLINT *outstart, PLINT *outn, PLINT outnmax,
00083 PLINT *outarray_min, PLINT *outarray_max );
00084
00085
00086
00087 #if MJL_HACK
00088 static void plP_fill3( PLINT x0, PLINT y0, PLINT x1, PLINT y1,
00089 PLINT x2, PLINT y2, PLINT j );
00090 static void plP_fill4( PLINT x0, PLINT y0, PLINT x1, PLINT y1,
00091 PLINT x2, PLINT y2, PLINT x3, PLINT y3, PLINT j );
00092 #endif
00093
00094
00095
00096
00097
00098
00099
00100 void
00101 c_pllightsource( PLFLT x, PLFLT y, PLFLT z )
00102 {
00103 xlight = x;
00104 ylight = y;
00105 zlight = z;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 void
00118 c_plmesh( const PLFLT *x, const PLFLT *y, const PLFLT **z, PLINT nx, PLINT ny, PLINT opt )
00119 {
00120 plfplot3dc( x, y, plf2ops_c(), (PLPointer) z, nx, ny, opt | MESH, NULL, 0 );
00121 }
00122
00123 void
00124 plfmesh( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00125 PLINT nx, PLINT ny, PLINT opt )
00126 {
00127 plfplot3dc( x, y, zops, zp, nx, ny, opt | MESH, NULL, 0 );
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 void
00150 c_plmeshc( const PLFLT *x, const PLFLT *y, const PLFLT **z, PLINT nx, PLINT ny, PLINT opt,
00151 const PLFLT *clevel, PLINT nlevel )
00152 {
00153 plfplot3dc( x, y, plf2ops_c(), (PLPointer) z, nx, ny, opt | MESH, clevel, nlevel );
00154 }
00155
00156 void
00157 plfmeshc( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00158 PLINT nx, PLINT ny, PLINT opt, const PLFLT *clevel, PLINT nlevel )
00159 {
00160 plfplot3dc( x, y, zops, zp, nx, ny, opt | MESH, clevel, nlevel );
00161 }
00162
00163
00164
00165 int
00166 plP_clip_poly( int Ni, PLFLT *Vi[3], int axis, PLFLT dir, PLFLT offset )
00167 {
00168 int anyout = 0;
00169 PLFLT _in[PL_MAXPOLY], _T[3][PL_MAXPOLY];
00170 PLFLT *in, *T[3], *TT;
00171 int No = 0;
00172 int i, j, k;
00173
00174 if ( Ni > PL_MAXPOLY )
00175 {
00176 in = (PLFLT *) malloc( sizeof ( PLFLT ) * Ni );
00177 TT = (PLFLT *) malloc( 3 * sizeof ( PLFLT ) * Ni );
00178
00179 if ( in == NULL || TT == NULL )
00180 {
00181 plexit( "plP_clip_poly: insufficient memory for large polygon" );
00182 }
00183
00184 T[0] = &TT[0];
00185 T[1] = &TT[Ni];
00186 T[2] = &TT[2 * Ni];
00187 }
00188 else
00189 {
00190 in = _in;
00191 T[0] = &_T[0][0];
00192 T[1] = &_T[1][0];
00193 T[2] = &_T[2][0];
00194 }
00195
00196 for ( i = 0; i < Ni; i++ )
00197 {
00198 in[i] = Vi[axis][i] * dir + offset;
00199 anyout += in[i] < 0;
00200 }
00201
00202
00203 if ( anyout == 0 )
00204 return Ni;
00205
00206
00207 if ( anyout == Ni )
00208 {
00209 return 0;
00210 }
00211
00212
00213
00214 for ( i = 0; i < 3; i++ )
00215 {
00216 for ( j = 0; j < Ni; j++ )
00217 {
00218 T[i][j] = Vi[i][j];
00219 }
00220 }
00221
00222 for ( i = 0; i < Ni; i++ )
00223 {
00224 j = ( i + 1 ) % Ni;
00225
00226 if ( in[i] >= 0 && in[j] >= 0 )
00227 {
00228 for ( k = 0; k < 3; k++ )
00229 Vi[k][No] = T[k][j];
00230 No++;
00231 }
00232 else if ( in[i] >= 0 && in[j] < 0 )
00233 {
00234 PLFLT u = in[i] / ( in[i] - in[j] );
00235 for ( k = 0; k < 3; k++ )
00236 Vi[k][No] = T[k][i] * ( 1 - u ) + T[k][j] * u;
00237 No++;
00238 }
00239 else if ( in[i] < 0 && in[j] >= 0 )
00240 {
00241 PLFLT u = in[i] / ( in[i] - in[j] );
00242 for ( k = 0; k < 3; k++ )
00243 Vi[k][No] = T[k][i] * ( 1 - u ) + T[k][j] * u;
00244 No++;
00245 for ( k = 0; k < 3; k++ )
00246 Vi[k][No] = T[k][j];
00247 No++;
00248 }
00249 }
00250
00251 if ( Ni > PL_MAXPOLY )
00252 {
00253 free( in );
00254 free( TT );
00255 }
00256
00257 return No;
00258 }
00259
00260
00261 static void
00262 shade_triangle( PLFLT x0, PLFLT y0, PLFLT z0,
00263 PLFLT x1, PLFLT y1, PLFLT z1,
00264 PLFLT x2, PLFLT y2, PLFLT z2 )
00265 {
00266 int i;
00267
00268 short u[6], v[6];
00269 PLFLT x[6], y[6], z[6];
00270 int n;
00271 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
00272 PLFLT *V[3];
00273
00274 plP_gdom( &xmin, &xmax, &ymin, &ymax );
00275 plP_grange( &zscale, &zmin, &zmax );
00276
00277 x[0] = x0; x[1] = x1; x[2] = x2;
00278 y[0] = y0; y[1] = y1; y[2] = y2;
00279 z[0] = z0; z[1] = z1; z[2] = z2;
00280 n = 3;
00281
00282 V[0] = x; V[1] = y; V[2] = z;
00283
00284 n = plP_clip_poly( n, V, 0, 1, -xmin );
00285 n = plP_clip_poly( n, V, 0, -1, xmax );
00286 n = plP_clip_poly( n, V, 1, 1, -ymin );
00287 n = plP_clip_poly( n, V, 1, -1, ymax );
00288 n = plP_clip_poly( n, V, 2, 1, -zmin );
00289 n = plP_clip_poly( n, V, 2, -1, zmax );
00290
00291 if ( n > 0 )
00292 {
00293 if ( falsecolor )
00294 plcol1( ( ( z[0] + z[1] + z[2] ) / 3. - fc_minz ) / ( fc_maxz - fc_minz ) );
00295 else
00296 plcol1( plGetAngleToLight( x, y, z ) );
00297
00298 for ( i = 0; i < n; i++ )
00299 {
00300 u[i] = plP_wcpcx( plP_w3wcx( x[i], y[i], z[i] ) );
00301 v[i] = plP_wcpcy( plP_w3wcy( x[i], y[i], z[i] ) );
00302 }
00303 u[n] = u[0];
00304 v[n] = v[0];
00305
00306 #ifdef SHADE_DEBUG // show triangles
00307 plcol0( 1 );
00308 x[3] = x[0]; y[3] = y[0]; z[3] = z[0];
00309 plline3( 4, x, y, z );
00310 #else // fill triangles
00311 plP_fill( u, v, n + 1 );
00312 #endif
00313 }
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 void
00326 c_plsurf3d( const PLFLT *x, const PLFLT *y, const PLFLT **z, PLINT nx, PLINT ny,
00327 PLINT opt, const PLFLT *clevel, PLINT nlevel )
00328 {
00329 plfsurf3d( x, y, plf2ops_c(), (PLPointer) z, nx, ny,
00330 opt, clevel, nlevel );
00331 }
00332
00333 void
00334 plfsurf3d( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00335 PLINT nx, PLINT ny, PLINT opt, const PLFLT *clevel, PLINT nlevel )
00336 {
00337 PLINT i;
00338 PLINT *indexymin = (PLINT *) malloc( (size_t) ( nx * sizeof ( PLINT ) ) );
00339 PLINT *indexymax = (PLINT *) malloc( (size_t) ( nx * sizeof ( PLINT ) ) );
00340
00341 if ( !indexymin || !indexymax )
00342 plexit( "plsurf3d: Out of memory." );
00343 for ( i = 0; i < nx; i++ )
00344 {
00345 indexymin[i] = 0;
00346 indexymax[i] = ny;
00347 }
00348 plfsurf3dl( x, y, zops, zp, nx, ny, opt, clevel, nlevel,
00349 0, nx, indexymin, indexymax );
00350 free_mem( indexymin );
00351 free_mem( indexymax );
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 void
00389 c_plsurf3dl( const PLFLT *x, const PLFLT *y, const PLFLT **z, PLINT nx, PLINT ny,
00390 PLINT opt, const PLFLT *clevel, PLINT nlevel,
00391 PLINT ixstart, PLINT ixn, const PLINT *indexymin, const PLINT *indexymax )
00392 {
00393 plfsurf3dl( x, y, plf2ops_c(), (PLPointer) z, nx, ny,
00394 opt, clevel, nlevel, ixstart, ixn, indexymin, indexymax );
00395 }
00396
00397 void
00398 plfsurf3dl( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp, PLINT nx, PLINT ny,
00399 PLINT opt, const PLFLT *clevel, PLINT nlevel,
00400 PLINT ixstart, PLINT ixn, const PLINT *indexymin, const PLINT *indexymax )
00401 {
00402 PLFLT cxx, cxy, cyx, cyy, cyz;
00403 PLINT i, j, k;
00404 PLINT ixDir, ixOrigin, iyDir, iyOrigin, nFast, nSlow;
00405 PLINT ixFast, ixSlow, iyFast, iySlow;
00406 PLINT iFast, iSlow;
00407 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
00408 PLFLT xm, ym, zm;
00409 PLINT ixmin = 0, ixmax = nx, iymin = 0, iymax = ny;
00410 PLFLT xx[3], yy[3], zz[3];
00411 PLFLT px[4], py[4], pz[4];
00412 CONT_LEVEL *cont, *clev;
00413 CONT_LINE *cline;
00414 int ct, ix, iy, iftriangle;
00415 PLINT color = plsc->icol0, width = plsc->width;
00416 PLFLT ( *getz )( PLPointer, PLINT, PLINT ) = zops->get;
00417
00418 if ( plsc->level < 3 )
00419 {
00420 myabort( "plsurf3dl: Please set up window first" );
00421 return;
00422 }
00423
00424 if ( nx <= 0 || ny <= 0 )
00425 {
00426 myabort( "plsurf3dl: Bad array dimensions." );
00427 return;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437 fc_minz = plsc->ranmi;
00438 fc_maxz = plsc->ranma;
00439 if ( fc_maxz == fc_minz )
00440 {
00441 plwarn( "plsurf3dl: Maximum and minimum Z values are equal! \"fixing\"..." );
00442 fc_maxz = fc_minz + 1e-6;
00443 }
00444
00445 if ( opt & MAG_COLOR )
00446 falsecolor = 1;
00447 else
00448 falsecolor = 0;
00449
00450 plP_gdom( &xmin, &xmax, &ymin, &ymax );
00451 plP_grange( &zscale, &zmin, &zmax );
00452 if ( zmin > zmax )
00453 {
00454 PLFLT t = zmin;
00455 zmin = zmax;
00456 zmax = t;
00457 }
00458
00459
00460
00461 for ( i = 0; i < nx - 1; i++ )
00462 {
00463 if ( x[i] >= x[i + 1] )
00464 {
00465 myabort( "plsurf3dl: X array must be strictly increasing" );
00466 return;
00467 }
00468 if ( x[i] < xmin && x[i + 1] >= xmin )
00469 ixmin = i;
00470 if ( x[i + 1] > xmax && x[i] <= xmax )
00471 ixmax = i + 2;
00472 }
00473 for ( i = 0; i < ny - 1; i++ )
00474 {
00475 if ( y[i] >= y[i + 1] )
00476 {
00477 myabort( "plsurf3dl: Y array must be strictly increasing" );
00478 return;
00479 }
00480 if ( y[i] < ymin && y[i + 1] >= ymin )
00481 iymin = i;
00482 if ( y[i + 1] > ymax && y[i] <= ymax )
00483 iymax = i + 2;
00484 }
00485
00486
00487 plP_gw3wc( &cxx, &cxy, &cyx, &cyy, &cyz );
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 if ( cxy >= 0 )
00499 {
00500 ixDir = 1;
00501 ixOrigin = ixmin;
00502 }
00503 else
00504 {
00505 ixDir = -1;
00506 ixOrigin = ixmax - 1;
00507 }
00508
00509 if ( cxx >= 0 )
00510 {
00511 iyDir = -1;
00512 iyOrigin = iymax - 1;
00513 }
00514 else
00515 {
00516 iyDir = 1;
00517 iyOrigin = iymin;
00518 }
00519
00520 if ( fabs( cxx ) > fabs( cxy ) )
00521 {
00522
00523 nFast = ixmax - ixmin;
00524 nSlow = iymax - iymin;
00525
00526 ixFast = ixDir; ixSlow = 0;
00527 iyFast = 0; iySlow = iyDir;
00528 }
00529 else
00530 {
00531 nFast = iymax - iymin;
00532 nSlow = ixmax - ixmin;
00533
00534 ixFast = 0; ixSlow = ixDir;
00535 iyFast = iyDir; iySlow = 0;
00536 }
00537
00538
00539 if ( zbflg )
00540 {
00541 PLFLT bx[3], by[3], bz[3];
00542 PLFLT tick = zbtck, tp;
00543 PLINT nsub = 0;
00544
00545
00546 pldtik( zmin, zmax, &tick, &nsub, FALSE );
00547
00548
00549 bx[0] = ( ixOrigin != ixmin && ixFast == 0 ) || ixFast > 0 ? xmax : xmin;
00550 by[0] = ( iyOrigin != iymin && iyFast == 0 ) || iyFast > 0 ? ymax : ymin;
00551 bx[1] = ixOrigin != ixmin ? xmax : xmin;
00552 by[1] = iyOrigin != iymin ? ymax : ymin;
00553 bx[2] = ( ixOrigin != ixmin && ixSlow == 0 ) || ixSlow > 0 ? xmax : xmin;
00554 by[2] = ( iyOrigin != iymin && iySlow == 0 ) || iySlow > 0 ? ymax : ymin;
00555
00556 plwid( zbwidth );
00557 plcol0( zbcol );
00558 for ( tp = tick * floor( zmin / tick ) + tick; tp <= zmax; tp += tick )
00559 {
00560 bz[0] = bz[1] = bz[2] = tp;
00561 plline3( 3, bx, by, bz );
00562 }
00563
00564 bx[0] = bx[1];
00565 by[0] = by[1];
00566 bz[0] = zmin;
00567 plline3( 2, bx, by, bz );
00568 plwid( width );
00569 plcol0( color );
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579 if ( clevel != NULL && opt & BASE_CONT )
00580 {
00581 #define NPTS 100
00582 int np = NPTS;
00583 PLFLT **zstore;
00584 PLcGrid2 cgrid2;
00585 PLFLT *zz = (PLFLT *) malloc( NPTS * sizeof ( PLFLT ) );
00586 if ( zz == NULL )
00587 plexit( "plsurf3dl: Insufficient memory" );
00588
00589
00590
00591
00592 cgrid2.nx = nx;
00593 cgrid2.ny = ny;
00594 plAlloc2dGrid( &cgrid2.xg, nx, ny );
00595 plAlloc2dGrid( &cgrid2.yg, nx, ny );
00596 plAlloc2dGrid( &zstore, nx, ny );
00597
00598 for ( i = ixstart; i < ixn; i++ )
00599 {
00600 for ( j = 0; j < indexymin[i]; j++ )
00601 {
00602 cgrid2.xg[i][j] = x[i];
00603 cgrid2.yg[i][j] = y[indexymin[i]];
00604 zstore[i][j] = getz( zp, i, indexymin[i] );
00605 }
00606 for ( j = indexymin[i]; j < indexymax[i]; j++ )
00607 {
00608 cgrid2.xg[i][j] = x[i];
00609 cgrid2.yg[i][j] = y[j];
00610 zstore[i][j] = getz( zp, i, j );
00611 }
00612 for ( j = indexymax[i]; j < ny; j++ )
00613 {
00614 cgrid2.xg[i][j] = x[i];
00615 cgrid2.yg[i][j] = y[indexymax[i] - 1];
00616 zstore[i][j] = getz( zp, i, indexymax[i] - 1 );
00617 }
00618 }
00619
00620 cont_store( (const PLFLT **) zstore, nx, ny, ixstart + 1, ixn, 1, ny,
00621 clevel, nlevel, pltr2, (void *) &cgrid2, &cont );
00622
00623
00624 plFree2dGrid( zstore, nx, ny );
00625 plFree2dGrid( cgrid2.xg, nx, ny );
00626 plFree2dGrid( cgrid2.yg, nx, ny );
00627
00628
00629 clev = cont;
00630 do
00631 {
00632 cline = clev->line;
00633 do
00634 {
00635 if ( cline->npts > np )
00636 {
00637 np = cline->npts;
00638 if ( ( zz = (PLFLT *) realloc( zz, np * sizeof ( PLFLT ) ) ) == NULL )
00639 {
00640 plexit( "plsurf3dl: Insufficient memory" );
00641 }
00642 }
00643 for ( j = 0; j < cline->npts; j++ )
00644 zz[j] = plsc->ranmi;
00645 if ( cline->npts > 0 )
00646 {
00647 plcol1( ( clev->level - fc_minz ) / ( fc_maxz - fc_minz ) );
00648 plline3( cline->npts, cline->x, cline->y, zz );
00649 }
00650 cline = cline->next;
00651 }
00652 while ( cline != NULL );
00653 clev = clev->next;
00654 }
00655 while ( clev != NULL );
00656
00657 cont_clean_store( cont );
00658 free( zz );
00659 }
00660
00661
00662 for ( iSlow = 0; iSlow < nSlow - 1; iSlow++ )
00663 {
00664 for ( iFast = 0; iFast < nFast - 1; iFast++ )
00665 {
00666
00667
00668
00669
00670
00671
00672
00673 xm = ym = zm = 0.;
00674
00675 iftriangle = 1;
00676 for ( i = 0; i < 2; i++ )
00677 {
00678 for ( j = 0; j < 2; j++ )
00679 {
00680
00681
00682 ix = ixFast * ( iFast + i ) + ixSlow * ( iSlow + j ) + ixOrigin;
00683 iy = iyFast * ( iFast + i ) + iySlow * ( iSlow + j ) + iyOrigin;
00684
00685 if ( ixstart <= ix && ix < ixn &&
00686 indexymin[ix] <= iy && iy < indexymax[ix] )
00687 {
00688 xm += px[2 * i + j] = x[ix];
00689 ym += py[2 * i + j] = y[iy];
00690 zm += pz[2 * i + j] = getz( zp, ix, iy );
00691 }
00692 else
00693 {
00694 iftriangle = 0;
00695 break;
00696 }
00697 }
00698 if ( iftriangle == 0 )
00699 break;
00700 }
00701
00702 if ( iftriangle == 0 )
00703 continue;
00704
00705
00706
00707 xm /= 4.; ym /= 4.; zm /= 4.;
00708
00709
00710
00711 for ( i = 1; i < 3; i++ )
00712 {
00713 for ( j = 0; j < 4; j += 3 )
00714 {
00715 shade_triangle( px[j], py[j], pz[j], xm, ym, zm, px[i], py[i], pz[i] );
00716
00717
00718
00719 #define min3( a, b, c ) ( MIN( ( MIN( a, b ) ), c ) )
00720 #define max3( a, b, c ) ( MAX( ( MAX( a, b ) ), c ) )
00721
00722 if ( clevel != NULL && ( opt & SURF_CONT ) )
00723 {
00724 for ( k = 0; k < nlevel; k++ )
00725 {
00726 if ( clevel[k] >= min3( pz[i], zm, pz[j] ) && clevel[k] < max3( pz[i], zm, pz[j] ) )
00727 {
00728 ct = 0;
00729 if ( clevel[k] >= MIN( pz[i], zm ) && clevel[k] < MAX( pz[i], zm ) )
00730 {
00731 xx[ct] = ( ( clevel[k] - pz[i] ) * ( xm - px[i] ) ) / ( zm - pz[i] ) + px[i];
00732 yy[ct] = ( ( clevel[k] - pz[i] ) * ( ym - py[i] ) ) / ( zm - pz[i] ) + py[i];
00733 ct++;
00734 }
00735
00736 if ( clevel[k] >= MIN( pz[i], pz[j] ) && clevel[k] < MAX( pz[i], pz[j] ) )
00737 {
00738 xx[ct] = ( ( clevel[k] - pz[i] ) * ( px[j] - px[i] ) ) / ( pz[j] - pz[i] ) + px[i];
00739 yy[ct] = ( ( clevel[k] - pz[i] ) * ( py[j] - py[i] ) ) / ( pz[j] - pz[i] ) + py[i];
00740 ct++;
00741 }
00742
00743 if ( clevel[k] >= MIN( pz[j], zm ) && clevel[k] < MAX( pz[j], zm ) )
00744 {
00745 xx[ct] = ( ( clevel[k] - pz[j] ) * ( xm - px[j] ) ) / ( zm - pz[j] ) + px[j];
00746 yy[ct] = ( ( clevel[k] - pz[j] ) * ( ym - py[j] ) ) / ( zm - pz[j] ) + py[j];
00747 ct++;
00748 }
00749
00750 if ( ct == 2 )
00751 {
00752
00753
00754
00755
00756 if ( opt & SURF_CONT )
00757 {
00758
00759 plcol0( color );
00760 zz[0] = zz[1] = clevel[k];
00761 plline3( 2, xx, yy, zz );
00762 }
00763
00764
00765 }
00766 else
00767 plwarn( "plsurf3dl: ***ERROR***\n" );
00768 }
00769 }
00770 }
00771 }
00772 }
00773 }
00774 }
00775
00776 if ( opt & FACETED )
00777 {
00778 plcol0( 0 );
00779 plfplot3dcl( x, y, zops, zp, nx, ny, MESH | DRAW_LINEXY, NULL, 0,
00780 ixstart, ixn, indexymin, indexymax );
00781 }
00782
00783 if ( opt & DRAW_SIDES )
00784 {
00785 PLFLT zscale, zmin, zmax;
00786
00787 plP_grange( &zscale, &zmin, &zmax );
00788
00789 iSlow = nSlow - 1;
00790 iftriangle = 1;
00791 for ( iFast = 0; iFast < nFast - 1; iFast++ )
00792 {
00793 for ( i = 0; i < 2; i++ )
00794 {
00795 ix = ixFast * ( iFast + i ) + ixSlow * iSlow + ixOrigin;
00796 iy = iyFast * ( iFast + i ) + iySlow * iSlow + iyOrigin;
00797 if ( ixstart <= ix && ix < ixn &&
00798 indexymin[ix] <= iy && iy < indexymax[ix] )
00799 {
00800 px[2 * i] = x[ix];
00801 py[2 * i] = y[iy];
00802 pz[2 * i] = getz( zp, ix, iy );
00803 }
00804 else
00805 {
00806 iftriangle = 0;
00807 break;
00808 }
00809 }
00810 if ( iftriangle == 0 )
00811 break;
00812
00813
00814 shade_triangle( px[0], py[0], pz[0], px[2], py[2], pz[2], px[0], py[0], zmin );
00815 shade_triangle( px[2], py[2], pz[2], px[2], py[2], zmin, px[0], py[0], zmin );
00816 }
00817
00818 iFast = nFast - 1;
00819 iftriangle = 1;
00820 for ( iSlow = 0; iSlow < nSlow - 1; iSlow++ )
00821 {
00822 for ( i = 0; i < 2; i++ )
00823 {
00824 ix = ixFast * iFast + ixSlow * ( iSlow + i ) + ixOrigin;
00825 iy = iyFast * iFast + iySlow * ( iSlow + i ) + iyOrigin;
00826 if ( ixstart <= ix && ix < ixn &&
00827 indexymin[ix] <= iy && iy < indexymax[ix] )
00828 {
00829 px[2 * i] = x[ix];
00830 py[2 * i] = y[iy];
00831 pz[2 * i] = getz( zp, ix, iy );
00832 }
00833 else
00834 {
00835 iftriangle = 0;
00836 break;
00837 }
00838 }
00839 if ( iftriangle == 0 )
00840 break;
00841
00842
00843 shade_triangle( px[0], py[0], pz[0], px[2], py[2], pz[2], px[0], py[0], zmin );
00844 shade_triangle( px[2], py[2], pz[2], px[2], py[2], zmin, px[0], py[0], zmin );
00845 }
00846 }
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858 void
00859 c_plot3d( const PLFLT *x, const PLFLT *y, const PLFLT **z,
00860 PLINT nx, PLINT ny, PLINT opt, PLBOOL side )
00861 {
00862 plfplot3dc( x, y, plf2ops_c(), (PLPointer) z, nx, ny, opt | ( side != 0 ? DRAW_SIDES : 0 ), NULL, 0 );
00863 }
00864
00865 void
00866 plfplot3d( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00867 PLINT nx, PLINT ny, PLINT opt, PLBOOL side )
00868 {
00869 plfplot3dc( x, y, zops, zp, nx, ny, opt | ( side != 0 ? DRAW_SIDES : 0 ), NULL, 0 );
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 void
00882 c_plot3dc( const PLFLT *x, const PLFLT *y, const PLFLT **z,
00883 PLINT nx, PLINT ny, PLINT opt,
00884 const PLFLT *clevel, PLINT nlevel )
00885 {
00886 plfplot3dcl( x, y, plf2ops_c(), (PLPointer) z, nx, ny, opt, clevel, nlevel, 0, 0, NULL, NULL );
00887 }
00888
00889 void
00890 plfplot3dc( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00891 PLINT nx, PLINT ny, PLINT opt, const PLFLT *clevel, PLINT nlevel )
00892 {
00893 plfplot3dcl( x, y, zops, zp, nx, ny, opt, clevel, nlevel, 0, 0, NULL, NULL );
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 void
00920 c_plot3dcl( const PLFLT *x, const PLFLT *y, const PLFLT **z,
00921 PLINT nx, PLINT ny, PLINT opt,
00922 const PLFLT *clevel, PLINT nlevel,
00923 PLINT ixstart, PLINT ixn, const PLINT *indexymin, const PLINT *indexymax )
00924 {
00925 plfplot3dcl( x, y, plf2ops_c(), (PLPointer) z, nx, ny,
00926 opt, clevel, nlevel, ixstart, ixn, indexymin, indexymax );
00927 }
00928
00929
00968
00969
00970 void
00971 plfplot3dcl( const PLFLT *x, const PLFLT *y, PLF2OPS zops, PLPointer zp,
00972 PLINT nx, PLINT ny, PLINT opt,
00973 const PLFLT *clevel, PLINT nlevel,
00974 PLINT ixstart, PLINT ixn, const PLINT *indexymin, const PLINT *indexymax )
00975 {
00976 PLFLT cxx, cxy, cyx, cyy, cyz;
00977 PLINT init, i, ix, iy, color, width;
00978 PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale;
00979 PLINT ixmin = 0, ixmax = nx - 1, iymin = 0, iymax = ny - 1;
00980 PLINT clipped = 0, base_cont = 0, side = 0;
00981 PLFLT ( *getz )( PLPointer, PLINT, PLINT ) = zops->get;
00982 PLFLT *_x, *_y, **_z;
00983 PLFLT *x_modified, *y_modified;
00984
00985 pl3mode = 0;
00986
00987 if ( plsc->level < 3 )
00988 {
00989 myabort( "plot3dcl: Please set up window first" );
00990 return;
00991 }
00992
00993 if ( ( opt & 3 ) == 0 )
00994 {
00995 myabort( "plot3dcl: Bad option" );
00996 return;
00997 }
00998
00999 if ( nx <= 0 || ny <= 0 )
01000 {
01001 myabort( "plot3dcl: Bad array dimensions." );
01002 return;
01003 }
01004
01005 plP_gdom( &xmin, &xmax, &ymin, &ymax );
01006 plP_grange( &zscale, &zmin, &zmax );
01007 if ( zmin > zmax )
01008 {
01009 PLFLT t = zmin;
01010 zmin = zmax;
01011 zmax = t;
01012 }
01013
01014
01015
01016 for ( i = 0; i < nx - 1; i++ )
01017 {
01018 if ( x[i] >= x[i + 1] )
01019 {
01020 myabort( "plot3dcl: X array must be strictly increasing" );
01021 return;
01022 }
01023 }
01024 for ( i = 0; i < ny - 1; i++ )
01025 {
01026 if ( y[i] >= y[i + 1] )
01027 {
01028 myabort( "plot3dcl: Y array must be strictly increasing" );
01029 return;
01030 }
01031 }
01032
01033 if ( opt & MESH )
01034 pl3mode = 1;
01035
01036 if ( opt & DRAW_SIDES )
01037 side = 1;
01038
01039
01040 if ( xmin < x[0] )
01041 xmin = x[0];
01042 if ( xmax > x[nx - 1] )
01043 xmax = x[nx - 1];
01044 if ( ymin < y[0] )
01045 ymin = y[0];
01046 if ( ymax > y[ny - 1] )
01047 ymax = y[ny - 1];
01048 for ( ixmin = 0; ixmin < nx - 1 && x[ixmin + 1] < xmin; ixmin++ )
01049 {
01050 }
01051 for ( ixmax = nx - 1; ixmax > 0 && x[ixmax - 1] > xmax; ixmax-- )
01052 {
01053 }
01054 for ( iymin = 0; iymin < ny - 1 && y[iymin + 1] < ymin; iymin++ )
01055 {
01056 }
01057 for ( iymax = ny - 1; iymax > 0 && y[iymax - 1] > ymax; iymax-- )
01058 {
01059 }
01060
01061
01062 if ( ixmin > 0 || ixmax < nx - 1 || iymin > 0 || iymax < ny - 1 )
01063 {
01064
01065 int _nx = ixmax - ixmin + 1;
01066 int _ny = iymax - iymin + 1;
01067 PLFLT ty0, ty1, tx0, tx1;
01068 int i, j;
01069
01070 if ( _nx <= 1 || _ny <= 1 )
01071 {
01072 myabort( "plot3dcl: selected x or y range has no data" );
01073 return;
01074 }
01075
01076
01077 if ( ( ( _x = (PLFLT *) malloc( _nx * sizeof ( PLFLT ) ) ) == NULL ) ||
01078 ( ( _y = (PLFLT *) malloc( _ny * sizeof ( PLFLT ) ) ) == NULL ) ||
01079 ( ( _z = (PLFLT **) malloc( _nx * sizeof ( PLFLT* ) ) ) == NULL ) )
01080 {
01081 plexit( "c_plot3dcl: Insufficient memory" );
01082 }
01083
01084 clipped = 1;
01085
01086
01087 _x[0] = xmin;
01088 _x[_nx - 1] = xmax;
01089 for ( i = 1; i < _nx - 1; i++ )
01090 _x[i] = x[ixmin + i];
01091 _y[0] = ymin;
01092 _y[_ny - 1] = ymax;
01093 for ( i = 1; i < _ny - 1; i++ )
01094 _y[i] = y[iymin + i];
01095
01096
01097 for ( i = 0; i < _nx; i++ )
01098 {
01099 if ( ( _z[i] = (PLFLT *) malloc( _ny * sizeof ( PLFLT ) ) ) == NULL )
01100 {
01101 plexit( "c_plot3dcl: Insufficient memory" );
01102 }
01103 }
01104
01105
01106 ty0 = ( _y[0] - y[iymin] ) / ( y[iymin + 1] - y[iymin] );
01107 ty1 = ( _y[_ny - 1] - y[iymax - 1] ) / ( y[iymax] - y[iymax - 1] );
01108 tx0 = ( _x[0] - x[ixmin] ) / ( x[ixmin + 1] - x[ixmin] );
01109 tx1 = ( _x[_nx - 1] - x[ixmax - 1] ) / ( x[ixmax] - x[ixmax - 1] );
01110 for ( i = 0; i < _nx; i++ )
01111 {
01112 if ( i == 0 )
01113 {
01114 _z[i][0] = getz( zp, ixmin, iymin ) * ( 1 - ty0 ) * ( 1 - tx0 ) + getz( zp, ixmin, iymin + 1 ) * ( 1 - tx0 ) * ty0
01115 + getz( zp, ixmin + 1, iymin ) * tx0 * ( 1 - ty0 ) + getz( zp, ixmin + 1, iymin + 1 ) * tx0 * ty0;
01116 for ( j = 1; j < _ny - 1; j++ )
01117 _z[i][j] = getz( zp, ixmin, iymin + j ) * ( 1 - tx0 ) + getz( zp, ixmin + 1, iymin + j ) * tx0;
01118 _z[i][_ny - 1] = getz( zp, ixmin, iymax - 1 ) * ( 1 - tx0 ) * ( 1 - ty1 ) + getz( zp, ixmin, iymax ) * ( 1 - tx0 ) * ty1
01119 + getz( zp, ixmin + 1, iymax - 1 ) * tx0 * ( 1 - ty1 ) + getz( zp, ixmin + 1, iymax ) * tx0 * ty1;
01120 }
01121 else if ( i == _nx - 1 )
01122 {
01123 _z[i][0] = getz( zp, ixmax - 1, iymin ) * ( 1 - tx1 ) * ( 1 - ty0 ) + getz( zp, ixmax - 1, iymin + 1 ) * ( 1 - tx1 ) * ty0
01124 + getz( zp, ixmax, iymin ) * tx1 * ( 1 - ty0 ) + getz( zp, ixmax, iymin + 1 ) * tx1 * ty0;
01125 for ( j = 1; j < _ny - 1; j++ )
01126 _z[i][j] = getz( zp, ixmax - 1, iymin + j ) * ( 1 - tx1 ) + getz( zp, ixmax, iymin + j ) * tx1;
01127 _z[i][_ny - 1] = getz( zp, ixmax - 1, iymax - 1 ) * ( 1 - tx1 ) * ( 1 - ty1 ) + getz( zp, ixmax, iymax ) * ( 1 - tx1 ) * ty1
01128 + getz( zp, ixmax, iymax - 1 ) * tx1 * ( 1 - ty1 ) + getz( zp, ixmax, iymax ) * tx1 * ty1;
01129 }
01130 else
01131 {
01132 _z[i][0] = getz( zp, ixmin + i, iymin ) * ( 1 - ty0 ) + getz( zp, ixmin + i, iymin + 1 ) * ty0;
01133 for ( j = 1; j < _ny - 1; j++ )
01134 _z[i][j] = getz( zp, ixmin + i, iymin + j );
01135 _z[i][_ny - 1] = getz( zp, ixmin + i, iymax - 1 ) * ( 1 - ty1 ) + getz( zp, ixmin + i, iymax ) * ty1;
01136 }
01137 for ( j = 0; j < _ny; j++ )
01138 {
01139 if ( _z[i][j] < zmin )
01140 _z[i][j] = zmin;
01141 else if ( _z[i][j] > zmax )
01142 _z[i][j] = zmax;
01143 }
01144 }
01145
01146 zp = (PLPointer) _z;
01147 getz = plf2ops_c()->get;
01148 nx = _nx;
01149 ny = _ny;
01150
01151 x_modified = _x;
01152 y_modified = _y;
01153 }
01154 else
01155 {
01156 x_modified = (PLFLT *) x;
01157 y_modified = (PLFLT *) y;
01158 }
01159
01160
01161
01162 if ( ( opt & BASE_CONT ) || ( opt & TOP_CONT ) || ( opt && MAG_COLOR ) )
01163 {
01164
01165
01166
01167
01168
01169
01170
01171 fc_minz = plsc->ranmi;
01172 fc_maxz = plsc->ranma;
01173
01174 if ( fc_maxz == fc_minz )
01175 {
01176 plwarn( "plot3dcl: Maximum and minimum Z values are equal! \"fixing\"..." );
01177 fc_maxz = fc_minz + 1e-6;
01178 }
01179 }
01180
01181 if ( opt & BASE_CONT )
01182 {
01183 if ( clevel != NULL && nlevel != 0 )
01184 {
01185 base_cont = 1;
01186
01187
01188 pl3mode = 1;
01189 }
01190 }
01191
01192 if ( opt & MAG_COLOR )
01193 {
01194 if ( ( ctmp = (PLFLT *) malloc( (size_t) ( 2 * MAX( nx, ny ) * sizeof ( PLFLT ) ) ) ) == NULL )
01195 {
01196 plexit( "c_plot3dcl: Insufficient memory" );
01197 }
01198 }
01199 else
01200 ctmp = NULL;
01201
01202
01203 opt &= DRAW_LINEXY;
01204
01205
01206
01207 utmp = (PLINT *) malloc( (size_t) ( 2 * MAX( nx, ny ) * sizeof ( PLINT ) ) );
01208 vtmp = (PLINT *) malloc( (size_t) ( 2 * MAX( nx, ny ) * sizeof ( PLINT ) ) );
01209
01210 if ( !utmp || !vtmp )
01211 myexit( "plot3dcl: Out of memory." );
01212
01213 plP_gw3wc( &cxx, &cxy, &cyx, &cyy, &cyz );
01214 init = 1;
01215
01216
01217 if ( cxx >= 0.0 && cxy <= 0.0 )
01218 {
01219 if ( opt == DRAW_LINEY )
01220 plt3zz( 1, ny, 1, -1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01221 else
01222 {
01223 for ( iy = 2; iy <= ny; iy++ )
01224 plt3zz( 1, iy, 1, -1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01225 }
01226 if ( opt == DRAW_LINEX )
01227 plt3zz( 1, ny, 1, -1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01228 else
01229 {
01230 for ( ix = 1; ix <= nx - 1; ix++ )
01231 plt3zz( ix, ny, 1, -1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01232 }
01233 }
01234
01235 else if ( cxx <= 0.0 && cxy <= 0.0 )
01236 {
01237 if ( opt == DRAW_LINEX )
01238 plt3zz( nx, ny, -1, -1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01239 else
01240 {
01241 for ( ix = 2; ix <= nx; ix++ )
01242 plt3zz( ix, ny, -1, -1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01243 }
01244 if ( opt == DRAW_LINEY )
01245 plt3zz( nx, ny, -1, -1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01246 else
01247 {
01248 for ( iy = ny; iy >= 2; iy-- )
01249 plt3zz( nx, iy, -1, -1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01250 }
01251 }
01252
01253 else if ( cxx <= 0.0 && cxy >= 0.0 )
01254 {
01255 if ( opt == DRAW_LINEY )
01256 plt3zz( nx, 1, -1, 1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01257 else
01258 {
01259 for ( iy = ny - 1; iy >= 1; iy-- )
01260 plt3zz( nx, iy, -1, 1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01261 }
01262 if ( opt == DRAW_LINEX )
01263 plt3zz( nx, 1, -1, 1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01264 else
01265 {
01266 for ( ix = nx; ix >= 2; ix-- )
01267 plt3zz( ix, 1, -1, 1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01268 }
01269 }
01270
01271 else if ( cxx >= 0.0 && cxy >= 0.0 )
01272 {
01273 if ( opt == DRAW_LINEX )
01274 plt3zz( 1, 1, 1, 1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01275 else
01276 {
01277 for ( ix = nx - 1; ix >= 1; ix-- )
01278 plt3zz( ix, 1, 1, 1, opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01279 }
01280 if ( opt == DRAW_LINEY )
01281 plt3zz( 1, 1, 1, 1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01282 else
01283 {
01284 for ( iy = 1; iy <= ny - 1; iy++ )
01285 plt3zz( 1, iy, 1, 1, -opt, &init, x_modified, y_modified, zops, zp, nx, ny, utmp, vtmp, ctmp );
01286 }
01287 }
01288
01289
01290
01291 if ( base_cont )
01292 {
01293 int np = NPTS, j;
01294 CONT_LEVEL *cont, *clev;
01295 CONT_LINE *cline;
01296
01297 PLINT *uu = (PLINT *) malloc( NPTS * sizeof ( PLINT ) );
01298 PLINT *vv = (PLINT *) malloc( NPTS * sizeof ( PLINT ) );
01299
01300 PLFLT **zstore;
01301 PLcGrid2 cgrid2;
01302
01303 if ( ( uu == NULL ) || ( vv == NULL ) )
01304 {
01305 plexit( "c_plot3dcl: Insufficient memory" );
01306 }
01307
01308 cgrid2.nx = nx;
01309 cgrid2.ny = ny;
01310 plAlloc2dGrid( &cgrid2.xg, nx, ny );
01311 plAlloc2dGrid( &cgrid2.yg, nx, ny );
01312 plAlloc2dGrid( &zstore, nx, ny );
01313
01314 for ( i = 0; i < nx; i++ )
01315 {
01316 for ( j = 0; j < ny; j++ )
01317 {
01318 cgrid2.xg[i][j] = x_modified[i];
01319 cgrid2.yg[i][j] = y_modified[j];
01320 zstore[i][j] = getz( zp, i, j );
01321 }
01322 }
01323
01324 pl3upv = 0;
01325
01326
01327 cont_store( (const PLFLT **) zstore, nx, ny, 1, nx, 1, ny,
01328 clevel, nlevel, pltr2, (void *) &cgrid2, &cont );
01329
01330
01331 plFree2dGrid( zstore, nx, ny );
01332 plFree2dGrid( cgrid2.xg, nx, ny );
01333 plFree2dGrid( cgrid2.yg, nx, ny );
01334
01335
01336 clev = cont;
01337 do
01338 {
01339 cline = clev->line;
01340 do
01341 {
01342 int cx, i, k, l, m, start, end;
01343 PLFLT tx, ty;
01344 if ( cline->npts > np )
01345 {
01346 np = cline->npts;
01347 if ( ( ( uu = (PLINT *) realloc( uu, np * sizeof ( PLINT ) ) ) == NULL ) ||
01348 ( ( vv = (PLINT *) realloc( vv, np * sizeof ( PLINT ) ) ) == NULL ) )
01349 {
01350 plexit( "c_plot3dcl: Insufficient memory" );
01351 }
01352 }
01353
01354
01355
01356
01357 i = 0;
01358 if ( cline->npts > 0 )
01359 {
01360 do
01361 {
01362 plcol1( ( clev->level - fc_minz ) / ( fc_maxz - fc_minz ) );
01363 cx = plP_wcpcx( plP_w3wcx( cline->x[i], cline->y[i], plsc->ranmi ) );
01364 for ( j = i; j < cline->npts; j++ )
01365 {
01366 uu[j] = plP_wcpcx( plP_w3wcx( cline->x[j], cline->y[j], plsc->ranmi ) );
01367 vv[j] = plP_wcpcy( plP_w3wcy( cline->x[j], cline->y[j], plsc->ranmi ) );
01368 if ( uu[j] < cx )
01369 break;
01370 else
01371 cx = uu[j];
01372 }
01373 plnxtv( &uu[i], &vv[i], NULL, j - i, 0 );
01374
01375 if ( j < cline->npts )
01376 {
01377 start = j - 1;
01378 for ( i = start; i < cline->npts; i++ )
01379 {
01380 uu[i] = plP_wcpcx( plP_w3wcx( cline->x[i], cline->y[i], plsc->ranmi ) );
01381 if ( uu[i] > cx )
01382 break;
01383 else
01384 cx = uu[i];
01385 }
01386 end = i - 1;
01387
01388 for ( k = 0; k < ( end - start + 1 ) / 2; k++ )
01389 {
01390 l = start + k;
01391 m = end - k;
01392 tx = cline->x[l];
01393 ty = cline->y[l];
01394 cline->x[l] = cline->x[m];
01395 cline->y[l] = cline->y[m];
01396 cline->x[m] = tx;
01397 cline->y[m] = ty;
01398 }
01399
01400
01401 for ( j = start; j <= end; j++ )
01402 {
01403 uu[j] = plP_wcpcx( plP_w3wcx( cline->x[j], cline->y[j], plsc->ranmi ) );
01404 vv[j] = plP_wcpcy( plP_w3wcy( cline->x[j], cline->y[j], plsc->ranmi ) );
01405 }
01406 plnxtv( &uu[start], &vv[start], NULL, end - start + 1, 0 );
01407
01408 cline->x[end] = cline->x[start];
01409 cline->y[end] = cline->y[start];
01410 i = end;
01411 }
01412 } while ( j < cline->npts && i < cline->npts );
01413 }
01414 cline = cline->next;
01415 }
01416 while ( cline != NULL );
01417 clev = clev->next;
01418 }
01419 while ( clev != NULL );
01420
01421 cont_clean_store( cont );
01422 pl3upv = 1;
01423 free( uu );
01424 free( vv );
01425 }
01426
01427
01428
01429 if ( side )
01430 plside3( x_modified, y_modified, zops, zp, nx, ny, opt );
01431
01432 if ( zbflg )
01433 {
01434 color = plsc->icol0;
01435 width = plsc->width;
01436 plwid( zbwidth );
01437 plcol0( zbcol );
01438 plgrid3( zbtck );
01439 plwid( width );
01440 plcol0( color );
01441 }
01442
01443 freework();
01444
01445 if ( clipped )
01446 {
01447 free( _x );
01448 free( _y );
01449 for ( i = 0; i < nx; i++ )
01450 free( _z[i] );
01451 free( _z );
01452 }
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 static void
01475 plxyindexlimits( PLINT instart, PLINT inn,
01476 PLINT *inarray_min, PLINT *inarray_max,
01477 PLINT *outstart, PLINT *outn, PLINT outnmax,
01478 PLINT *outarray_min, PLINT *outarray_max )
01479 {
01480 PLINT i, j;
01481 if ( inn < 0 )
01482 {
01483 myabort( "plxyindexlimits: Must have instart >= 0" );
01484 return;
01485 }
01486 if ( inn - instart <= 0 )
01487 {
01488 myabort( "plxyindexlimits: Must have at least 1 defined point" );
01489 return;
01490 }
01491 *outstart = inarray_min[instart];
01492 *outn = inarray_max[instart];
01493 for ( i = instart; i < inn; i++ )
01494 {
01495 *outstart = MIN( *outstart, inarray_min[i] );
01496 *outn = MAX( *outn, inarray_max[i] );
01497 if ( i + 2 < inn )
01498 {
01499 if ( inarray_min[i] < inarray_min[i + 1] &&
01500 inarray_min[i + 1] > inarray_min[i + 2] )
01501 {
01502 myabort( "plxyindexlimits: inarray_min must not have a maximum" );
01503 return;
01504 }
01505 if ( inarray_max[i] > inarray_max[i + 1] &&
01506 inarray_max[i + 1] < inarray_max[i + 2] )
01507 {
01508 myabort( "plxyindexlimits: inarray_max must not have a minimum" );
01509 return;
01510 }
01511 }
01512 }
01513 if ( *outstart < 0 )
01514 {
01515 myabort( "plxyindexlimits: Must have all elements of inarray_min >= 0" );
01516 return;
01517 }
01518 if ( *outn > outnmax )
01519 {
01520 myabort( "plxyindexlimits: Must have all elements of inarray_max <= outnmax" );
01521 return;
01522 }
01523 for ( j = *outstart; j < *outn; j++ )
01524 {
01525 i = instart;
01526
01527 while ( i < inn && !( inarray_min[i] <= j && j < inarray_max[i] ) )
01528 i++;
01529 if ( i < inn )
01530 outarray_min[j] = i;
01531 else
01532 {
01533 myabort( "plxyindexlimits: bad logic; invalid i should never happen" );
01534 return;
01535 }
01536
01537 while ( i < inn && ( inarray_min[i] <= j && j < inarray_max[i] ) )
01538 i++;
01539 outarray_max[j] = i;
01540 }
01541 }
01542
01543
01544
01545
01546
01547
01548
01549 void
01550 plP_gzback( PLINT **zbf, PLINT **zbc, PLFLT **zbt, PLINT **zbw )
01551 {
01552 *zbf = &zbflg;
01553 *zbc = &zbcol;
01554 *zbt = &zbtck;
01555 *zbw = &zbwidth;
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 static PLFLT
01567 plGetAngleToLight( PLFLT* x, PLFLT* y, PLFLT* z )
01568 {
01569 PLFLT vx1, vx2, vy1, vy2, vz1, vz2;
01570 PLFLT px, py, pz;
01571 PLFLT vlx, vly, vlz;
01572 PLFLT mag1, mag2;
01573 PLFLT cosangle;
01574
01575 vx1 = x[1] - x[0];
01576 vx2 = x[2] - x[1];
01577 vy1 = y[1] - y[0];
01578 vy2 = y[2] - y[1];
01579 vz1 = z[1] - z[0];
01580 vz2 = z[2] - z[1];
01581
01582
01583 px = vy1 * vz2 - vz1 * vy2;
01584 py = vz1 * vx2 - vx1 * vz2;
01585 pz = vx1 * vy2 - vy1 * vx2;
01586 mag1 = px * px + py * py + pz * pz;
01587
01588
01589 if ( mag1 == 0 )
01590 return 1;
01591
01592 vlx = xlight - x[0];
01593 vly = ylight - y[0];
01594 vlz = zlight - z[0];
01595 mag2 = vlx * vlx + vly * vly + vlz * vlz;
01596 if ( mag2 == 0 )
01597 return 1;
01598
01599
01600 cosangle = fabs( ( vlx * px + vly * py + vlz * pz ) / sqrt( mag1 * mag2 ) );
01601
01602
01603 if ( cosangle > 1 )
01604 cosangle = 1;
01605 return cosangle;
01606 }
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620 static void
01621 plt3zz( PLINT x0, PLINT y0, PLINT dx, PLINT dy, PLINT flag, PLINT *init,
01622 PLFLT *x, PLFLT *y, PLF2OPS zops, PLPointer zp, PLINT nx, PLINT ny,
01623 PLINT *u, PLINT *v, PLFLT* c )
01624 {
01625 PLINT n = 0;
01626 PLFLT x2d, y2d;
01627 PLFLT ( *getz )( PLPointer, PLINT, PLINT ) = zops->get;
01628
01629 while ( 1 <= x0 && x0 <= nx && 1 <= y0 && y0 <= ny )
01630 {
01631 x2d = plP_w3wcx( x[x0 - 1], y[y0 - 1], getz( zp, x0 - 1, y0 - 1 ) );
01632 y2d = plP_w3wcy( x[x0 - 1], y[y0 - 1], getz( zp, x0 - 1, y0 - 1 ) );
01633 u[n] = plP_wcpcx( x2d );
01634 v[n] = plP_wcpcy( y2d );
01635 if ( c != NULL )
01636 c[n] = ( getz( zp, x0 - 1, y0 - 1 ) - fc_minz ) / ( fc_maxz - fc_minz );
01637
01638 switch ( flag )
01639 {
01640 case -3:
01641 y0 += dy;
01642 flag = -flag;
01643 break;
01644 case -2:
01645 y0 += dy;
01646 break;
01647 case -1:
01648 y0 += dy;
01649 flag = -flag;
01650 break;
01651 case 1:
01652 x0 += dx;
01653 break;
01654 case 2:
01655 x0 += dx;
01656 flag = -flag;
01657 break;
01658 case 3:
01659 x0 += dx;
01660 flag = -flag;
01661 break;
01662 }
01663 n++;
01664 }
01665
01666 if ( flag == 1 || flag == -2 )
01667 {
01668 if ( flag == 1 )
01669 {
01670 x0 -= dx;
01671 y0 += dy;
01672 }
01673 else if ( flag == -2 )
01674 {
01675 y0 -= dy;
01676 x0 += dx;
01677 }
01678 if ( 1 <= x0 && x0 <= nx && 1 <= y0 && y0 <= ny )
01679 {
01680 x2d = plP_w3wcx( x[x0 - 1], y[y0 - 1], getz( zp, x0 - 1, y0 - 1 ) );
01681 y2d = plP_w3wcy( x[x0 - 1], y[y0 - 1], getz( zp, x0 - 1, y0 - 1 ) );
01682 u[n] = plP_wcpcx( x2d );
01683 v[n] = plP_wcpcy( y2d );
01684 if ( c != NULL )
01685 c[n] = ( getz( zp, x0 - 1, y0 - 1 ) - fc_minz ) / ( fc_maxz - fc_minz );
01686 n++;
01687 }
01688 }
01689
01690
01691
01692 plnxtv( u, v, c, n, *init );
01693 *init = 0;
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703 static void
01704 plside3( PLFLT *x, PLFLT *y, PLF2OPS zops, PLPointer zp, PLINT nx, PLINT ny, PLINT opt )
01705 {
01706 PLINT i;
01707 PLFLT cxx, cxy, cyx, cyy, cyz;
01708 PLFLT xmin, ymin, zmin, xmax, ymax, zmax, zscale;
01709 PLFLT tx, ty, ux, uy;
01710 PLFLT ( *getz )( PLPointer, PLINT, PLINT ) = zops->get;
01711
01712 plP_gw3wc( &cxx, &cxy, &cyx, &cyy, &cyz );
01713 plP_gdom( &xmin, &xmax, &ymin, &ymax );
01714 plP_grange( &zscale, &zmin, &zmax );
01715
01716
01717
01718 if ( cxx >= 0.0 && cxy <= 0.0 )
01719 {
01720 if ( opt != 1 )
01721 {
01722 for ( i = 0; i < nx; i++ )
01723 {
01724 tx = plP_w3wcx( x[i], y[0], zmin );
01725 ty = plP_w3wcy( x[i], y[0], zmin );
01726 ux = plP_w3wcx( x[i], y[0], getz( zp, i, 0 ) );
01727 uy = plP_w3wcy( x[i], y[0], getz( zp, i, 0 ) );
01728 pljoin( tx, ty, ux, uy );
01729 }
01730 }
01731 if ( opt != 2 )
01732 {
01733 for ( i = 0; i < ny; i++ )
01734 {
01735 tx = plP_w3wcx( x[0], y[i], zmin );
01736 ty = plP_w3wcy( x[0], y[i], zmin );
01737 ux = plP_w3wcx( x[0], y[i], getz( zp, 0, i ) );
01738 uy = plP_w3wcy( x[0], y[i], getz( zp, 0, i ) );
01739 pljoin( tx, ty, ux, uy );
01740 }
01741 }
01742 }
01743 else if ( cxx <= 0.0 && cxy <= 0.0 )
01744 {
01745 if ( opt != 1 )
01746 {
01747 for ( i = 0; i < nx; i++ )
01748 {
01749 tx = plP_w3wcx( x[i], y[ny - 1], zmin );
01750 ty = plP_w3wcy( x[i], y[ny - 1], zmin );
01751 ux = plP_w3wcx( x[i], y[ny - 1], getz( zp, i, ny - 1 ) );
01752 uy = plP_w3wcy( x[i], y[ny - 1], getz( zp, i, ny - 1 ) );
01753 pljoin( tx, ty, ux, uy );
01754 }
01755 }
01756 if ( opt != 2 )
01757 {
01758 for ( i = 0; i < ny; i++ )
01759 {
01760 tx = plP_w3wcx( x[0], y[i], zmin );
01761 ty = plP_w3wcy( x[0], y[i], zmin );
01762 ux = plP_w3wcx( x[0], y[i], getz( zp, 0, i ) );
01763 uy = plP_w3wcy( x[0], y[i], getz( zp, 0, i ) );
01764 pljoin( tx, ty, ux, uy );
01765 }
01766 }
01767 }
01768 else if ( cxx <= 0.0 && cxy >= 0.0 )
01769 {
01770 if ( opt != 1 )
01771 {
01772 for ( i = 0; i < nx; i++ )
01773 {
01774 tx = plP_w3wcx( x[i], y[ny - 1], zmin );
01775 ty = plP_w3wcy( x[i], y[ny - 1], zmin );
01776 ux = plP_w3wcx( x[i], y[ny - 1], getz( zp, i, ny - 1 ) );
01777 uy = plP_w3wcy( x[i], y[ny - 1], getz( zp, i, ny - 1 ) );
01778 pljoin( tx, ty, ux, uy );
01779 }
01780 }
01781 if ( opt != 2 )
01782 {
01783 for ( i = 0; i < ny; i++ )
01784 {
01785 tx = plP_w3wcx( x[nx - 1], y[i], zmin );
01786 ty = plP_w3wcy( x[nx - 1], y[i], zmin );
01787 ux = plP_w3wcx( x[nx - 1], y[i], getz( zp, nx - 1, i ) );
01788 uy = plP_w3wcy( x[nx - 1], y[i], getz( zp, nx - 1, i ) );
01789 pljoin( tx, ty, ux, uy );
01790 }
01791 }
01792 }
01793 else if ( cxx >= 0.0 && cxy >= 0.0 )
01794 {
01795 if ( opt != 1 )
01796 {
01797 for ( i = 0; i < nx; i++ )
01798 {
01799 tx = plP_w3wcx( x[i], y[0], zmin );
01800 ty = plP_w3wcy( x[i], y[0], zmin );
01801 ux = plP_w3wcx( x[i], y[0], getz( zp, i, 0 ) );
01802 uy = plP_w3wcy( x[i], y[0], getz( zp, i, 0 ) );
01803 pljoin( tx, ty, ux, uy );
01804 }
01805 }
01806 if ( opt != 2 )
01807 {
01808 for ( i = 0; i < ny; i++ )
01809 {
01810 tx = plP_w3wcx( x[nx - 1], y[i], zmin );
01811 ty = plP_w3wcy( x[nx - 1], y[i], zmin );
01812 ux = plP_w3wcx( x[nx - 1], y[i], getz( zp, nx - 1, i ) );
01813 uy = plP_w3wcy( x[nx - 1], y[i], getz( zp, nx - 1, i ) );
01814 pljoin( tx, ty, ux, uy );
01815 }
01816 }
01817 }
01818 }
01819
01820
01821
01822
01823
01824
01825
01826
01827 static void
01828 plgrid3( PLFLT tick )
01829 {
01830 PLFLT xmin, ymin, zmin, xmax, ymax, zmax, zscale;
01831 PLFLT cxx, cxy, cyx, cyy, cyz, zmin_in, zmax_in;
01832 PLINT u[3], v[3];
01833 PLINT nsub = 0;
01834 PLFLT tp;
01835
01836 plP_gw3wc( &cxx, &cxy, &cyx, &cyy, &cyz );
01837 plP_gdom( &xmin, &xmax, &ymin, &ymax );
01838 plP_grange( &zscale, &zmin_in, &zmax_in );
01839 zmin = ( zmax_in > zmin_in ) ? zmin_in : zmax_in;
01840 zmax = ( zmax_in > zmin_in ) ? zmax_in : zmin_in;
01841
01842 pldtik( zmin, zmax, &tick, &nsub, FALSE );
01843 tp = tick * floor( zmin / tick ) + tick;
01844 pl3upv = 0;
01845
01846 if ( cxx >= 0.0 && cxy <= 0.0 )
01847 {
01848 while ( tp <= zmax )
01849 {
01850 u[0] = plP_wcpcx( plP_w3wcx( xmin, ymax, tp ) );
01851 v[0] = plP_wcpcy( plP_w3wcy( xmin, ymax, tp ) );
01852 u[1] = plP_wcpcx( plP_w3wcx( xmax, ymax, tp ) );
01853 v[1] = plP_wcpcy( plP_w3wcy( xmax, ymax, tp ) );
01854 u[2] = plP_wcpcx( plP_w3wcx( xmax, ymin, tp ) );
01855 v[2] = plP_wcpcy( plP_w3wcy( xmax, ymin, tp ) );
01856 plnxtv( u, v, 0, 3, 0 );
01857
01858 tp += tick;
01859 }
01860 u[0] = plP_wcpcx( plP_w3wcx( xmax, ymax, zmin ) );
01861 v[0] = plP_wcpcy( plP_w3wcy( xmax, ymax, zmin ) );
01862 u[1] = plP_wcpcx( plP_w3wcx( xmax, ymax, zmax ) );
01863 v[1] = plP_wcpcy( plP_w3wcy( xmax, ymax, zmax ) );
01864 plnxtv( u, v, 0, 2, 0 );
01865 }
01866 else if ( cxx <= 0.0 && cxy <= 0.0 )
01867 {
01868 while ( tp <= zmax )
01869 {
01870 u[0] = plP_wcpcx( plP_w3wcx( xmax, ymax, tp ) );
01871 v[0] = plP_wcpcy( plP_w3wcy( xmax, ymax, tp ) );
01872 u[1] = plP_wcpcx( plP_w3wcx( xmax, ymin, tp ) );
01873 v[1] = plP_wcpcy( plP_w3wcy( xmax, ymin, tp ) );
01874 u[2] = plP_wcpcx( plP_w3wcx( xmin, ymin, tp ) );
01875 v[2] = plP_wcpcy( plP_w3wcy( xmin, ymin, tp ) );
01876 plnxtv( u, v, 0, 3, 0 );
01877
01878 tp += tick;
01879 }
01880 u[0] = plP_wcpcx( plP_w3wcx( xmax, ymin, zmin ) );
01881 v[0] = plP_wcpcy( plP_w3wcy( xmax, ymin, zmin ) );
01882 u[1] = plP_wcpcx( plP_w3wcx( xmax, ymin, zmax ) );
01883 v[1] = plP_wcpcy( plP_w3wcy( xmax, ymin, zmax ) );
01884 plnxtv( u, v, 0, 2, 0 );
01885 }
01886 else if ( cxx <= 0.0 && cxy >= 0.0 )
01887 {
01888 while ( tp <= zmax )
01889 {
01890 u[0] = plP_wcpcx( plP_w3wcx( xmax, ymin, tp ) );
01891 v[0] = plP_wcpcy( plP_w3wcy( xmax, ymin, tp ) );
01892 u[1] = plP_wcpcx( plP_w3wcx( xmin, ymin, tp ) );
01893 v[1] = plP_wcpcy( plP_w3wcy( xmin, ymin, tp ) );
01894 u[2] = plP_wcpcx( plP_w3wcx( xmin, ymax, tp ) );
01895 v[2] = plP_wcpcy( plP_w3wcy( xmin, ymax, tp ) );
01896 plnxtv( u, v, 0, 3, 0 );
01897
01898 tp += tick;
01899 }
01900 u[0] = plP_wcpcx( plP_w3wcx( xmin, ymin, zmin ) );
01901 v[0] = plP_wcpcy( plP_w3wcy( xmin, ymin, zmin ) );
01902 u[1] = plP_wcpcx( plP_w3wcx( xmin, ymin, zmax ) );
01903 v[1] = plP_wcpcy( plP_w3wcy( xmin, ymin, zmax ) );
01904 plnxtv( u, v, 0, 2, 0 );
01905 }
01906 else if ( cxx >= 0.0 && cxy >= 0.0 )
01907 {
01908 while ( tp <= zmax )
01909 {
01910 u[0] = plP_wcpcx( plP_w3wcx( xmin, ymin, tp ) );
01911 v[0] = plP_wcpcy( plP_w3wcy( xmin, ymin, tp ) );
01912 u[1] = plP_wcpcx( plP_w3wcx( xmin, ymax, tp ) );
01913 v[1] = plP_wcpcy( plP_w3wcy( xmin, ymax, tp ) );
01914 u[2] = plP_wcpcx( plP_w3wcx( xmax, ymax, tp ) );
01915 v[2] = plP_wcpcy( plP_w3wcy( xmax, ymax, tp ) );
01916 plnxtv( u, v, 0, 3, 0 );
01917
01918 tp += tick;
01919 }
01920 u[0] = plP_wcpcx( plP_w3wcx( xmin, ymax, zmin ) );
01921 v[0] = plP_wcpcy( plP_w3wcy( xmin, ymax, zmin ) );
01922 u[1] = plP_wcpcx( plP_w3wcx( xmin, ymax, zmax ) );
01923 v[1] = plP_wcpcy( plP_w3wcy( xmin, ymax, zmax ) );
01924 plnxtv( u, v, 0, 2, 0 );
01925 }
01926 pl3upv = 1;
01927 }
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 static void
01945 plnxtv( PLINT *u, PLINT *v, PLFLT* c, PLINT n, PLINT init )
01946 {
01947 plnxtvhi( u, v, c, n, init );
01948
01949 if ( pl3mode )
01950 plnxtvlo( u, v, c, n, init );
01951 }
01952
01953
01954
01955
01956
01957
01958
01959 static void
01960 plnxtvhi( PLINT *u, PLINT *v, PLFLT* c, PLINT n, PLINT init )
01961 {
01962
01963
01964
01965
01966 if ( init == 1 )
01967 {
01968 int i;
01969 oldhiview = (PLINT *) malloc( (size_t) ( 2 * n * sizeof ( PLINT ) ) );
01970 if ( !oldhiview )
01971 myexit( "plnxtvhi: Out of memory." );
01972
01973 oldhiview[0] = u[0];
01974 oldhiview[1] = v[0];
01975 plP_draw3d( u[0], v[0], c, 0, 1 );
01976 for ( i = 1; i < n; i++ )
01977 {
01978 oldhiview[2 * i] = u[i];
01979 oldhiview[2 * i + 1] = v[i];
01980 plP_draw3d( u[i], v[i], c, i, 0 );
01981 }
01982 mhi = n;
01983 return;
01984 }
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999 xxhi = 0;
02000 if ( pl3upv != 0 )
02001 {
02002 newhisize = 2 * ( mhi + BINC );
02003 if ( newhiview != NULL )
02004 {
02005 newhiview =
02006 (PLINT *) realloc( (void *) newhiview,
02007 (size_t) ( newhisize * sizeof ( PLINT ) ) );
02008 }
02009 else
02010 {
02011 newhiview =
02012 (PLINT *) malloc( (size_t) ( newhisize * sizeof ( PLINT ) ) );
02013 }
02014 if ( !newhiview )
02015 myexit( "plnxtvhi: Out of memory." );
02016 }
02017
02018
02019
02020 plnxtvhi_draw( u, v, c, n );
02021
02022
02023
02024 swaphiview();
02025 }
02026
02027
02028
02029
02030
02031
02032
02033 static void
02034 plnxtvhi_draw( PLINT *u, PLINT *v, PLFLT* c, PLINT n )
02035 {
02036 PLINT i = 0, j = 0, first = 1;
02037 PLINT sx1 = 0, sx2 = 0, sy1 = 0, sy2 = 0;
02038 PLINT su1, su2, sv1, sv2;
02039 PLINT cx, cy, px, py;
02040 PLINT seg, ptold, lstold = 0, pthi, pnewhi = 0, newhi, change, ochange = 0;
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053 while ( i < mhi || j < n )
02054 {
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064 ptold = ( j >= n || ( i < mhi && oldhiview[2 * i] < u[j] ) );
02065 if ( ptold )
02066 {
02067 px = oldhiview[2 * i];
02068 py = oldhiview[2 * i + 1];
02069 seg = j > 0 && j < n;
02070 if ( seg )
02071 {
02072 sx1 = u[j - 1];
02073 sy1 = v[j - 1];
02074 sx2 = u[j];
02075 sy2 = v[j];
02076 }
02077 }
02078 else
02079 {
02080 px = u[j];
02081 py = v[j];
02082 seg = i > 0 && i < mhi;
02083 if ( seg )
02084 {
02085 sx1 = oldhiview[2 * ( i - 1 )];
02086 sy1 = oldhiview[2 * ( i - 1 ) + 1];
02087 sx2 = oldhiview[2 * i];
02088 sy2 = oldhiview[2 * i + 1];
02089 }
02090 }
02091
02092
02093
02094
02095
02096
02097
02098 if ( seg )
02099 pthi = plabv( px, py, sx1, sy1, sx2, sy2 );
02100 else
02101 pthi = 1;
02102
02103 newhi = ( ptold && !pthi ) || ( !ptold && pthi );
02104
02105
02106
02107
02108 change = ( newhi && !pnewhi ) || ( !newhi && pnewhi );
02109
02110
02111
02112
02113
02114 if ( first )
02115 {
02116 plP_draw3d( px, py, c, j, 1 );
02117 first = 0;
02118 lstold = ptold;
02119 savehipoint( px, py );
02120 pthi = 0;
02121 ochange = 0;
02122 }
02123 else if ( change )
02124 {
02125
02126
02127
02128
02129 if ( pl3upv == 0 && ( ( !ptold && j == 0 ) || ( ptold && i == 0 ) ) )
02130 {
02131 plP_draw3d( px, py, c, j, 1 );
02132 lstold = ptold;
02133 pthi = 0;
02134 ochange = 0;
02135 }
02136 else if ( pl3upv == 0 &&
02137 ( ( !ptold && i >= mhi ) || ( ptold && j >= n ) ) )
02138 {
02139 plP_draw3d( px, py, c, j, 1 );
02140 lstold = ptold;
02141 pthi = 0;
02142 ochange = 0;
02143 }
02144 else
02145 {
02146
02147
02148
02149
02150
02151 if ( i == 0 )
02152 {
02153 sx1 = oldhiview[0];
02154 sy1 = -1;
02155 sx2 = oldhiview[0];
02156 sy2 = oldhiview[1];
02157 }
02158 else if ( i >= mhi )
02159 {
02160 sx1 = oldhiview[2 * ( mhi - 1 )];
02161 sy1 = oldhiview[2 * ( mhi - 1 ) + 1];
02162 sx2 = oldhiview[2 * ( mhi - 1 )];
02163 sy2 = -1;
02164 }
02165 else
02166 {
02167 sx1 = oldhiview[2 * ( i - 1 )];
02168 sy1 = oldhiview[2 * ( i - 1 ) + 1];
02169 sx2 = oldhiview[2 * i];
02170 sy2 = oldhiview[2 * i + 1];
02171 }
02172
02173 if ( j == 0 )
02174 {
02175 su1 = u[0];
02176 sv1 = -1;
02177 su2 = u[0];
02178 sv2 = v[0];
02179 }
02180 else if ( j >= n )
02181 {
02182 su1 = u[n - 1];
02183 sv1 = v[n - 1];
02184 su2 = u[n - 1];
02185 sv2 = -1;
02186 }
02187 else
02188 {
02189 su1 = u[j - 1];
02190 sv1 = v[j - 1];
02191 su2 = u[j];
02192 sv2 = v[j];
02193 }
02194
02195
02196
02197 pl3cut( sx1, sy1, sx2, sy2, su1, sv1, su2, sv2, &cx, &cy );
02198 if ( cx == px && cy == py )
02199 {
02200 if ( lstold && !ochange )
02201 plP_draw3d( px, py, c, j, 1 );
02202 else
02203 plP_draw3d( px, py, c, j, 0 );
02204
02205 savehipoint( px, py );
02206 lstold = 1;
02207 pthi = 0;
02208 }
02209 else
02210 {
02211 if ( lstold && !ochange )
02212 plP_draw3d( cx, cy, c, j, 1 );
02213 else
02214 plP_draw3d( cx, cy, c, j, 0 );
02215
02216 lstold = 1;
02217 savehipoint( cx, cy );
02218 }
02219 ochange = 1;
02220 }
02221 }
02222
02223
02224
02225 if ( pthi )
02226 {
02227 if ( lstold && ptold )
02228 plP_draw3d( px, py, c, j, 1 );
02229 else
02230 plP_draw3d( px, py, c, j, 0 );
02231
02232 savehipoint( px, py );
02233 lstold = ptold;
02234 ochange = 0;
02235 }
02236 pnewhi = newhi;
02237
02238 if ( ptold )
02239 i++;
02240 else
02241 j++;
02242 }
02243 }
02244
02245
02246
02247
02248
02249
02250
02251 static void
02252 plP_draw3d( PLINT x, PLINT y, PLFLT *c, PLINT j, PLINT move )
02253 {
02254 if ( move )
02255 plP_movphy( x, y );
02256 else
02257 {
02258 if ( c != NULL )
02259 plcol1( c[j - 1] );
02260 plP_draphy( x, y );
02261 }
02262 }
02263
02264
02265
02266
02267
02268
02269
02270 static void
02271 plnxtvlo( PLINT *u, PLINT *v, PLFLT*c, PLINT n, PLINT init )
02272 {
02273 PLINT i, j, first;
02274 PLINT sx1 = 0, sx2 = 0, sy1 = 0, sy2 = 0;
02275 PLINT su1, su2, sv1, sv2;
02276 PLINT cx, cy, px, py;
02277 PLINT seg, ptold, lstold = 0, ptlo, pnewlo, newlo, change, ochange = 0;
02278
02279 first = 1;
02280 pnewlo = 0;
02281
02282
02283
02284
02285
02286 if ( init == 1 )
02287 {
02288 oldloview = (PLINT *) malloc( (size_t) ( 2 * n * sizeof ( PLINT ) ) );
02289 if ( !oldloview )
02290 myexit( "\nplnxtvlo: Out of memory." );
02291
02292 plP_draw3d( u[0], v[0], c, 0, 1 );
02293 oldloview[0] = u[0];
02294 oldloview[1] = v[0];
02295 for ( i = 1; i < n; i++ )
02296 {
02297 plP_draw3d( u[i], v[i], c, i, 0 );
02298 oldloview[2 * i] = u[i];
02299 oldloview[2 * i + 1] = v[i];
02300 }
02301 mlo = n;
02302 return;
02303 }
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318 xxlo = 0;
02319 i = 0;
02320 j = 0;
02321 if ( pl3upv != 0 )
02322 {
02323 newlosize = 2 * ( mlo + BINC );
02324 if ( newloview != NULL )
02325 {
02326 newloview =
02327 (PLINT *) realloc( (void *) newloview,
02328 (size_t) ( newlosize * sizeof ( PLINT ) ) );
02329 }
02330 else
02331 {
02332 newloview =
02333 (PLINT *) malloc( (size_t) ( newlosize * sizeof ( PLINT ) ) );
02334 }
02335 if ( !newloview )
02336 myexit( "plnxtvlo: Out of memory." );
02337 }
02338
02339
02340
02341
02342
02343 while ( i < mlo || j < n )
02344 {
02345
02346
02347
02348
02349
02350
02351
02352
02353 ptold = ( j >= n || ( i < mlo && oldloview[2 * i] < u[j] ) );
02354 if ( ptold )
02355 {
02356 px = oldloview[2 * i];
02357 py = oldloview[2 * i + 1];
02358 seg = j > 0 && j < n;
02359 if ( seg )
02360 {
02361 sx1 = u[j - 1];
02362 sy1 = v[j - 1];
02363 sx2 = u[j];
02364 sy2 = v[j];
02365 }
02366 }
02367 else
02368 {
02369 px = u[j];
02370 py = v[j];
02371 seg = i > 0 && i < mlo;
02372 if ( seg )
02373 {
02374 sx1 = oldloview[2 * ( i - 1 )];
02375 sy1 = oldloview[2 * ( i - 1 ) + 1];
02376 sx2 = oldloview[2 * i];
02377 sy2 = oldloview[2 * i + 1];
02378 }
02379 }
02380
02381
02382
02383
02384
02385
02386
02387 if ( seg )
02388 ptlo = !plabv( px, py, sx1, sy1, sx2, sy2 );
02389 else
02390 ptlo = 1;
02391
02392 newlo = ( ptold && !ptlo ) || ( !ptold && ptlo );
02393 change = ( newlo && !pnewlo ) || ( !newlo && pnewlo );
02394
02395
02396
02397
02398
02399 if ( first )
02400 {
02401 plP_draw3d( px, py, c, j, 1 );
02402 first = 0;
02403 lstold = ptold;
02404 savelopoint( px, py );
02405 ptlo = 0;
02406 ochange = 0;
02407 }
02408 else if ( change )
02409 {
02410
02411
02412
02413
02414 if ( pl3upv == 0 && ( ( !ptold && j == 0 ) || ( ptold && i == 0 ) ) )
02415 {
02416 plP_draw3d( px, py, c, j, 1 );
02417 lstold = ptold;
02418 ptlo = 0;
02419 ochange = 0;
02420 }
02421 else if ( pl3upv == 0 &&
02422 ( ( !ptold && i >= mlo ) || ( ptold && j >= n ) ) )
02423 {
02424 plP_draw3d( px, py, c, j, 1 );
02425 lstold = ptold;
02426 ptlo = 0;
02427 ochange = 0;
02428 }
02429
02430
02431
02432
02433
02434
02435 else
02436 {
02437 if ( i == 0 )
02438 {
02439 sx1 = oldloview[0];
02440 sy1 = 100000;
02441 sx2 = oldloview[0];
02442 sy2 = oldloview[1];
02443 }
02444 else if ( i >= mlo )
02445 {
02446 sx1 = oldloview[2 * ( mlo - 1 )];
02447 sy1 = oldloview[2 * ( mlo - 1 ) + 1];
02448 sx2 = oldloview[2 * ( mlo - 1 )];
02449 sy2 = 100000;
02450 }
02451 else
02452 {
02453 sx1 = oldloview[2 * ( i - 1 )];
02454 sy1 = oldloview[2 * ( i - 1 ) + 1];
02455 sx2 = oldloview[2 * i];
02456 sy2 = oldloview[2 * i + 1];
02457 }
02458
02459 if ( j == 0 )
02460 {
02461 su1 = u[0];
02462 sv1 = 100000;
02463 su2 = u[0];
02464 sv2 = v[0];
02465 }
02466 else if ( j >= n )
02467 {
02468 su1 = u[n - 1];
02469 sv1 = v[n - 1];
02470 su2 = u[n];
02471 sv2 = 100000;
02472 }
02473 else
02474 {
02475 su1 = u[j - 1];
02476 sv1 = v[j - 1];
02477 su2 = u[j];
02478 sv2 = v[j];
02479 }
02480
02481
02482
02483 pl3cut( sx1, sy1, sx2, sy2, su1, sv1, su2, sv2, &cx, &cy );
02484 if ( cx == px && cy == py )
02485 {
02486 if ( lstold && !ochange )
02487 plP_draw3d( px, py, c, j, 1 );
02488 else
02489 plP_draw3d( px, py, c, j, 0 );
02490
02491 savelopoint( px, py );
02492 lstold = 1;
02493 ptlo = 0;
02494 }
02495 else
02496 {
02497 if ( lstold && !ochange )
02498 plP_draw3d( cx, cy, c, j, 1 );
02499 else
02500 plP_draw3d( cx, cy, c, j, 0 );
02501
02502 lstold = 1;
02503 savelopoint( cx, cy );
02504 }
02505 ochange = 1;
02506 }
02507 }
02508
02509
02510
02511 if ( ptlo )
02512 {
02513 if ( lstold && ptold )
02514 plP_draw3d( px, py, c, j, 1 );
02515 else
02516 plP_draw3d( px, py, c, j, 0 );
02517
02518 savelopoint( px, py );
02519 lstold = ptold;
02520 ochange = 0;
02521 }
02522
02523 pnewlo = newlo;
02524
02525 if ( ptold )
02526 i = i + 1;
02527 else
02528 j = j + 1;
02529 }
02530
02531
02532
02533 swaploview();
02534 }
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544 static void
02545 savehipoint( PLINT px, PLINT py )
02546 {
02547 if ( pl3upv == 0 )
02548 return;
02549
02550 if ( xxhi >= newhisize )
02551 {
02552 newhisize += 2 * BINC;
02553 newhiview = (PLINT *) realloc( (void *) newhiview,
02554 (size_t) ( newhisize * sizeof ( PLINT ) ) );
02555 if ( !newhiview )
02556 myexit( "savehipoint: Out of memory." );
02557 }
02558
02559 newhiview[xxhi] = px;
02560 xxhi++;
02561 newhiview[xxhi] = py;
02562 xxhi++;
02563 }
02564
02565 static void
02566 savelopoint( PLINT px, PLINT py )
02567 {
02568 if ( pl3upv == 0 )
02569 return;
02570
02571 if ( xxlo >= newlosize )
02572 {
02573 newlosize += 2 * BINC;
02574 newloview = (PLINT *) realloc( (void *) newloview,
02575 (size_t) ( newlosize * sizeof ( PLINT ) ) );
02576 if ( !newloview )
02577 myexit( "savelopoint: Out of memory." );
02578 }
02579
02580 newloview[xxlo] = px;
02581 xxlo++;
02582 newloview[xxlo] = py;
02583 xxlo++;
02584 }
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594 static void
02595 swaphiview( void )
02596 {
02597 PLINT *tmp;
02598
02599 if ( pl3upv != 0 )
02600 {
02601 mhi = xxhi / 2;
02602 tmp = oldhiview;
02603 oldhiview = newhiview;
02604 newhiview = tmp;
02605 }
02606 }
02607
02608 static void
02609 swaploview( void )
02610 {
02611 PLINT *tmp;
02612
02613 if ( pl3upv != 0 )
02614 {
02615 mlo = xxlo / 2;
02616 tmp = oldloview;
02617 oldloview = newloview;
02618 newloview = tmp;
02619 }
02620 }
02621
02622
02623
02624
02625
02626
02627
02628 static void
02629 freework( void )
02630 {
02631 free_mem( oldhiview );
02632 free_mem( oldloview );
02633 free_mem( newhiview );
02634 free_mem( newloview );
02635 free_mem( vtmp );
02636 free_mem( utmp );
02637 free_mem( ctmp );
02638 }
02639
02640
02641
02642
02643
02644
02645
02646 static void
02647 myexit( char *msg )
02648 {
02649 freework();
02650 plexit( msg );
02651 }
02652
02653
02654
02655
02656
02657
02658
02659
02660 static void
02661 myabort( char *msg )
02662 {
02663 freework();
02664 plabort( msg );
02665 }
02666
02667
02668
02669
02670
02671
02672
02673
02674 static int
02675 plabv( PLINT px, PLINT py, PLINT sx1, PLINT sy1, PLINT sx2, PLINT sy2 )
02676 {
02677 int above;
02678
02679 if ( py >= sy1 && py >= sy2 )
02680 above = 1;
02681 else if ( py < sy1 && py < sy2 )
02682 above = 0;
02683 else if ( (double) ( sx2 - sx1 ) * ( py - sy1 ) >=
02684 (double) ( px - sx1 ) * ( sy2 - sy1 ) )
02685 above = 1;
02686 else
02687 above = 0;
02688
02689 return above;
02690 }
02691
02692
02693
02694
02695
02696
02697
02698
02699 static void
02700 pl3cut( PLINT sx1, PLINT sy1, PLINT sx2, PLINT sy2,
02701 PLINT su1, PLINT sv1, PLINT su2, PLINT sv2, PLINT *cx, PLINT *cy )
02702 {
02703 PLINT x21, y21, u21, v21, yv1, xu1, a, b;
02704 double fa, fb;
02705
02706 x21 = sx2 - sx1;
02707 y21 = sy2 - sy1;
02708 u21 = su2 - su1;
02709 v21 = sv2 - sv1;
02710 yv1 = sy1 - sv1;
02711 xu1 = sx1 - su1;
02712
02713 a = x21 * v21 - y21 * u21;
02714 fa = (double) a;
02715 if ( a == 0 )
02716 {
02717 if ( sx2 < su2 )
02718 {
02719 *cx = sx2;
02720 *cy = sy2;
02721 }
02722 else
02723 {
02724 *cx = su2;
02725 *cy = sv2;
02726 }
02727 return;
02728 }
02729 else
02730 {
02731 b = yv1 * u21 - xu1 * v21;
02732 fb = (double) b;
02733 *cx = (PLINT) ( sx1 + ( fb * x21 ) / fa + .5 );
02734 *cy = (PLINT) ( sy1 + ( fb * y21 ) / fa + .5 );
02735 }
02736 }
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765 void
02766 plRotationShear( PLFLT *xFormMatrix, PLFLT *rotation, PLFLT *shear, PLFLT *stride )
02767 {
02768 PLFLT smr;
02769 *stride = sqrt( xFormMatrix[0] * xFormMatrix[0] + xFormMatrix[2] * xFormMatrix[2] );
02770
02771
02772 *rotation = atan2( xFormMatrix[2], xFormMatrix[0] );
02773
02774
02775 smr = atan2( xFormMatrix[1], xFormMatrix[3] );
02776
02777
02778 *shear = smr + *rotation;
02779
02780
02781 if ( *shear < -PI )
02782 *shear += 2. * PI;
02783 else if ( *shear > PI )
02784 *shear -= 2. * PI;
02785
02786
02787
02788 *shear = -*shear;
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808 }
02809