From: <arj...@us...> - 2010-12-30 08:41:10
|
Revision: 11405 http://plplot.svn.sourceforge.net/plplot/?rev=11405&view=rev Author: arjenmarkus Date: 2010-12-30 08:41:03 +0000 (Thu, 30 Dec 2010) Log Message: ----------- Implement a flexible scheme for dealing with large polygons: instead of accepting only polygons of moderate size (defined by PL_MAXPOLY) the functions involved now either use small statically defined arrays if the polygon is small enough or allocate arrays of an appropriate size that later get freed again. It should therefore no longer matter how large the polygons are. Note: not all source code has been compiled and the current tests do not involve such large polygons. The "ordinary" case, small polygons, has been tested though. Modified Paths: -------------- trunk/bindings/tk/plr.c trunk/drivers/tkwin.c trunk/drivers/xfig.c trunk/drivers/xwin.c trunk/src/plbuf.c trunk/src/plfill.c trunk/src/plgradient.c trunk/src/plot3d.c trunk/utils/plrender.c Modified: trunk/bindings/tk/plr.c =================================================================== --- trunk/bindings/tk/plr.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/bindings/tk/plr.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -323,9 +323,21 @@ static int get_ncoords( PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n ) { - int i; - short xs[PL_MAXPOLY], ys[PL_MAXPOLY]; + PLINT i; + short _xs[PL_MAXPOLY], _ys[PL_MAXPOLY]; + short *xs, *ys; + if ( n > PL_MAXPOLY ) + { + xs = (short *) malloc( sizeof(short) * n ); + ys = (short *) malloc( sizeof(short) * n ); + } + else + { + xs = _xs; + ys = _ys; + } + plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) xs, n ) ); plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) ys, n ) ); @@ -334,6 +346,13 @@ x[i] = xs[i]; y[i] = ys[i]; } + + if ( n > PL_MAXPOLY ) + { + free( xs ); + free( ys ); + } + return 0; } Modified: trunk/drivers/tkwin.c =================================================================== --- trunk/drivers/tkwin.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/drivers/tkwin.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -487,13 +487,20 @@ TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd; PLINT i; - XPoint pts[PL_MAXPOLY]; + XPoint _pts[PL_MAXPOLY]; + XPoint *pts; if ( dev->flags & 1 ) return; if ( npts > PL_MAXPOLY ) - plexit( "plD_polyline_tkw: Too many points in polyline\n" ); + { + pts = (XPoint *) malloc( sizeof(XPoint) * npts ); + } + else + { + pts = _pts; + } for ( i = 0; i < npts; i++ ) { @@ -508,6 +515,11 @@ if ( dev->write_to_pixmap ) XDrawLines( tkwd->display, dev->pixmap, dev->gc, pts, npts, CoordModeOrigin ); + + if ( npts > PL_MAXPOLY ) + { + free( pts ); + } } //-------------------------------------------------------------------------- @@ -838,13 +850,19 @@ { TkwDev *dev = (TkwDev *) pls->dev; TkwDisplay *tkwd = (TkwDisplay *) dev->tkwd; - XPoint pts[PL_MAXPOLY]; + XPoint _pts[PL_MAXPOLY]; + XPoint *pts; int i; if ( pls->dev_npts > PL_MAXPOLY ) - plexit( "FillPolygonCmd: Too many points in polygon\n" ); + { + pts = (XPoint *) malloc( sizeof(XPoint) * npts ); + } + else + { + pts = _pts; + } - for ( i = 0; i < pls->dev_npts; i++ ) { pts[i].x = (short) ( dev->xscale * pls->dev_x[i] ); @@ -878,6 +896,11 @@ XSetForeground( tkwd->display, dev->gc, dev->curcolor.pixel ); } #endif + + if ( pls->dev_npts > PL_MAXPOLY ) + { + free( pts ); + } } //-------------------------------------------------------------------------- Modified: trunk/drivers/xfig.c =================================================================== --- trunk/drivers/xfig.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/drivers/xfig.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -431,8 +431,6 @@ case PLESC_FILL: npts = pls->dev_npts; - if ( npts > PL_MAXPOLY ) - plexit( "FillPolygonCmd: Too many points in polygon\n" ); flushbuffer( pls ); fprintf( pls->OutFile, "2 1 0 1 %d %d 50 0 20 0.0 0 0 0 0 0 %d\n", Modified: trunk/drivers/xwin.c =================================================================== --- trunk/drivers/xwin.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/drivers/xwin.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -421,10 +421,17 @@ XwDisplay *xwd = (XwDisplay *) dev->xwd; PLINT i; - XPoint pts[PL_MAXPOLY]; + XPoint _pts[PL_MAXPOLY]; + XPoint *pts; if ( npts > PL_MAXPOLY ) - plexit( "plD_polyline_xw: Too many points in polyline\n" ); + { + pts = (XPoint *) malloc( sizeof(XPoint) * npts ); + } + else + { + pts = _pts; + } dbug_enter( "plD_polyline_xw" ); @@ -453,6 +460,11 @@ if ( usepthreads ) pthread_mutex_unlock( &events_mutex ); #endif + + if ( npts > PL_MAXPOLY ) + { + free( pts ); + } } //-------------------------------------------------------------------------- @@ -830,11 +842,18 @@ { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; - XPoint pts[PL_MAXPOLY]; + XPoint _pts[PL_MAXPOLY]; + XPoint *pts; int i; if ( pls->dev_npts > PL_MAXPOLY ) - plexit( "FillPolygonCmd: Too many points in polygon\n" ); + { + pts = (XPoint *) malloc( sizeof(XPoint) * npts ); + } + else + { + pts = _pts; + } CheckForEvents( pls ); @@ -871,6 +890,11 @@ XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel ); } #endif + + if ( npts > PL_MAXPOLY ) + { + free( pts ); + } } //-------------------------------------------------------------------------- Modified: trunk/src/plbuf.c =================================================================== --- trunk/src/plbuf.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/src/plbuf.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -490,16 +490,40 @@ static void rdbuf_polyline( PLStream *pls ) { - short xpl[PL_MAXPOLY], ypl[PL_MAXPOLY]; + short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY]; + short *xpl, *ypl; PLINT npts; dbug_enter( "rdbuf_polyline" ); rd_data( pls, &npts, sizeof ( PLINT ) ); + + if ( npts > PL_MAXPOLY ) { + xpl = (short *) malloc( ( npts + 1 ) * sizeof( PLINT ) ); + ypl = (short *) malloc( ( npts + 1 ) * sizeof( PLINT ) ); + + if (( xpl == NULL ) || ( ypl == NULL )) + { + plexit( "rdbuf_polyline: Insufficient memory for large polyline" ); + } + } + else + { + xpl = _xpl; + ypl = _ypl; + } + + rd_data( pls, xpl, sizeof ( short ) * npts ); rd_data( pls, ypl, sizeof ( short ) * npts ); plP_polyline( xpl, ypl, npts ); + + if ( npts > PL_MAXPOLY ) + { + free(xpl); + free(ypl); + } } //-------------------------------------------------------------------------- @@ -701,16 +725,39 @@ static void rdbuf_fill( PLStream *pls ) { - short xpl[PL_MAXPOLY], ypl[PL_MAXPOLY]; + short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY]; + short *xpl, *ypl; PLINT npts; dbug_enter( "rdbuf_fill" ); rd_data( pls, &npts, sizeof ( PLINT ) ); + + if ( npts > PL_MAXPOLY ) { + xpl = (short *) malloc( ( npts + 1 ) * sizeof( PLINT ) ); + ypl = (short *) malloc( ( npts + 1 ) * sizeof( PLINT ) ); + + if (( xpl == NULL ) || ( ypl == NULL )) + { + plexit( "rdbuf_polyline: Insufficient memory for large polyline" ); + } + } + else + { + xpl = _xpl; + ypl = _ypl; + } + rd_data( pls, xpl, sizeof ( short ) * npts ); rd_data( pls, ypl, sizeof ( short ) * npts ); plP_fill( xpl, ypl, npts ); + + if ( npts > PL_MAXPOLY ) + { + free(xpl); + free(ypl); + } } //-------------------------------------------------------------------------- Modified: trunk/src/plfill.c =================================================================== --- trunk/src/plfill.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/src/plfill.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -130,7 +130,8 @@ void c_plfill( PLINT n, PLFLT *x, PLFLT *y ) { - PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; + PLINT _xpoly[PL_MAXPOLY], _ypoly[PL_MAXPOLY]; + PLINT *xpoly, *ypoly; PLINT i; PLFLT xt, yt; @@ -146,9 +147,20 @@ } if ( n > PL_MAXPOLY - 1 ) { - plwarn( "plfill: too many points in polygon" ); - n = PL_MAXPOLY; + xpoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + ypoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + + if (( xpoly == NULL ) || ( ypoly == NULL )) + { + plexit( "plfill: Insufficient memory for large polygon" ); + } } + else + { + xpoly = _xpoly; + ypoly = _ypoly; + } + for ( i = 0; i < n; i++ ) { TRANSFORM( x[i], y[i], &xt, &yt ); @@ -158,8 +170,7 @@ if ( x[0] != x[n - 1] || y[0] != y[n - 1] ) { - if ( n < PL_MAXPOLY ) - n++; + n++; TRANSFORM( x[0], y[0], &xt, &yt ); xpoly[n - 1] = plP_wcpcx( xt ); ypoly[n - 1] = plP_wcpcy( yt ); @@ -167,6 +178,12 @@ plP_plfclp( xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma, plsc->clpymi, plsc->clpyma, plP_fill ); + + if ( n > PL_MAXPOLY - 1 ) + { + free(xpoly); + free(ypoly); + } } //-------------------------------------------------------------------------- @@ -181,10 +198,13 @@ void c_plfill3( PLINT n, PLFLT *x, PLFLT *y, PLFLT *z ) { - PLFLT tx[PL_MAXPOLY], ty[PL_MAXPOLY], tz[PL_MAXPOLY]; + PLFLT _tx[PL_MAXPOLY], _ty[PL_MAXPOLY], _tz[PL_MAXPOLY]; + PLFLT *tx, *ty, *tz; PLFLT *V[3]; - PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; + PLINT _xpoly[PL_MAXPOLY], _ypoly[PL_MAXPOLY]; + PLINT *xpoly, *ypoly; PLINT i; + PLINT npts; PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale; if ( plsc->level < 3 ) @@ -197,11 +217,30 @@ plabort( "plfill3: Not enough points in object" ); return; } + + npts = n; if ( n > PL_MAXPOLY - 1 ) { - plwarn( "plfill3: too many points in polygon" ); - n = PL_MAXPOLY; + tx = (PLFLT *) malloc( ( n + 1 ) * sizeof( PLFLT ) ); + ty = (PLFLT *) malloc( ( n + 1 ) * sizeof( PLFLT ) ); + ty = (PLFLT *) malloc( ( n + 1 ) * sizeof( PLFLT ) ); + xpoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + ypoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + + if (( tx == NULL ) || ( ty == NULL ) || ( tz == NULL ) || + ( xpoly == NULL ) || ( ypoly == NULL )) + { + plexit( "plfill3: Insufficient memory for large polygon" ); + } } + else + { + tx = _tx; + ty = _ty; + tz = _tz; + xpoly = _xpoly; + ypoly = _ypoly; + } plP_gdom( &xmin, &xmax, &ymin, &ymax ); plP_grange( &zscale, &zmin, &zmax ); @@ -213,8 +252,7 @@ } if ( tx[0] != tx[n - 1] || ty[0] != ty[n - 1] || tz[0] != tz[n - 1] ) { - if ( n < PL_MAXPOLY ) - n++; + n++; tx[n - 1] = tx[0]; ty[n - 1] = ty[0]; tz[n - 1] = tz[0]; } V[0] = tx; V[1] = ty; V[2] = tz; @@ -244,6 +282,16 @@ // plP_plfclp( xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma, plsc->clpymi, plsc->clpyma, plP_fill ); + +// If the original number of points is large, then free the arrays + if ( npts > PL_MAXPOLY - 1 ) + { + free(tx); + free(ty); + free(tz); + free(xpoly); + free(ypoly); + } } //-------------------------------------------------------------------------- Modified: trunk/src/plgradient.c =================================================================== --- trunk/src/plgradient.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/src/plgradient.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -78,13 +78,15 @@ { #define NGRAD 2 int i, irot_min, irot_max; - PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; + PLINT _xpoly[PL_MAXPOLY], _ypoly[PL_MAXPOLY]; + PLINT *xpoly, *ypoly; PLINT xgrad[NGRAD], ygrad[NGRAD], clpxmi, clpxma, clpymi, clpyma; PLFLT dxgrad[NGRAD], dygrad[NGRAD], xrot, xrot_min, xrot_max; + PLINT npts; // Find (x1, y1) and (x2, y2) corresponding to beginning and end // of gradient vector. - double cosangle = cos( PI * angle / 180. ); + double cosangle = cos( PI * angle / 10. ); double sinangle = sin( PI * angle / 180. ); xrot = x[0] * cosangle + y[0] * sinangle; xrot_min = xrot; @@ -126,12 +128,23 @@ plsc->ygradient = ygrad; plsc->ngradient = NGRAD; - + npts = n; if ( n > PL_MAXPOLY - 1 ) { - plwarn( "plgradient: too many points in polygon" ); - n = PL_MAXPOLY; + xpoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + ypoly = (PLINT *) malloc( ( n + 1 ) * sizeof( PLINT ) ); + + if (( xpoly == NULL ) || ( ypoly == NULL )) + { + plexit( "plgradient: Insufficient memory for large polygon" ); + } } + else + { + xpoly = _xpoly; + ypoly = _ypoly; + } + for ( i = 0; i < n; i++ ) { xpoly[i] = plP_wcpcx( x[i] ); @@ -139,8 +152,7 @@ } if ( x[0] != x[n - 1] || y[0] != y[n - 1] ) { - if ( n < PL_MAXPOLY ) - n++; + n++; xpoly[n - 1] = plP_wcpcx( x[0] ); ypoly[n - 1] = plP_wcpcy( y[0] ); } @@ -149,6 +161,13 @@ // Plot line corresponding to gradient to give visual // debugging cue. plline( NGRAD, dxgrad, dygrad ); + + // Check the original number of points + if ( npts > PL_MAXPOLY - 1 ) + { + free(xpoly); + free(ypoly); + } } } @@ -231,7 +250,8 @@ // Define NEDGE shade edges (or NEDGE-1 shade levels) // from 0. to 1. if ( ( edge = (PLFLT *) malloc( NEDGE * sizeof ( PLFLT ) ) ) == NULL ) - plexit( "plgradient_soft: Insufficient memory" ); + plexit( "plgradient_soft: Insufficient memory for large polygon" +); for ( i = 0; i < NEDGE; i++ ) edge[i] = (PLFLT) i / (PLFLT) ( NEDGE - 1 ); Modified: trunk/src/plot3d.c =================================================================== --- trunk/src/plot3d.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/src/plot3d.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -164,10 +164,32 @@ plP_clip_poly( int Ni, PLFLT *Vi[3], int axis, PLFLT dir, PLFLT offset ) { int anyout = 0; - PLFLT in[PL_MAXPOLY], T[3][PL_MAXPOLY]; + PLFLT _in[PL_MAXPOLY], _T[3][PL_MAXPOLY]; + PLFLT *in, *T[3], *TT; int No = 0; int i, j, k; + if ( Ni > PL_MAXPOLY ) + { + in = (PLFLT *) malloc( sizeof(PLFLT) * Ni ); + TT = (PLFLT *) malloc( 3 * sizeof(PLFLT) * Ni ); + + if ( in == NULL || TT == NULL ) { + plexit("plP_clip_poly: insufficient memory for large polygon"); + } + + T[0] = &TT[0]; + T[1] = &TT[Ni]; + T[2] = &TT[2*Ni]; + } + else + { + in = _in; + T[0] = &_T[0][0]; + T[1] = &_T[1][0]; + T[2] = &_T[2][0]; + } + for ( i = 0; i < Ni; i++ ) { in[i] = Vi[axis][i] * dir + offset; @@ -222,6 +244,13 @@ No++; } } + + if ( Ni > PL_MAXPOLY ) + { + free(in); + free(TT); + } + return No; } Modified: trunk/utils/plrender.c =================================================================== --- trunk/utils/plrender.c 2010-12-30 08:35:28 UTC (rev 11404) +++ trunk/utils/plrender.c 2010-12-30 08:41:03 UTC (rev 11405) @@ -833,17 +833,37 @@ static void get_ncoords( PLFLT *x, PLFLT *y, PLINT n ) { - short xs[PL_MAXPOLY], ys[PL_MAXPOLY]; PLINT i; + short _xs[PL_MAXPOLY], _ys[PL_MAXPOLY]; + short *xs, *ys; - plm_rd( pdf_rd_2nbytes( pdfs, (U_SHORT *) xs, n ) ); - plm_rd( pdf_rd_2nbytes( pdfs, (U_SHORT *) ys, n ) ); + if ( n > PL_MAXPOLY ) + { + xs = (short *) malloc( sizeof(short) * n ); + ys = (short *) malloc( sizeof(short) * n ); + } + else + { + xs = _xs; + ys = _ys; + } + plr_rdn( pdf_rd_2nbytes( pdfs, (U_SHORT *) xs, n ) ); + plr_rdn( pdf_rd_2nbytes( pdfs, (U_SHORT *) ys, n ) ); + for ( i = 0; i < n; i++ ) { x[i] = xs[i]; y[i] = ys[i]; } + + if ( n > PL_MAXPOLY ) + { + free( xs ); + free( ys ); + } + + return 0; } //-------------------------------------------------------------------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |