// Functions dealing with viewports. // // Copyright (C) 2004 Joao Cardoso // // This file is part of PLplot. // // PLplot is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published // by the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PLplot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with PLplot; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #include "plplotP.h" static void c_plenvi( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis, PLINT old ); //-------------------------------------------------------------------------- // void plenv() // // Simple interface for defining viewport and window. // // The "just" parameter control how the axes will be scaled: // // just=-1 : The scales will not be set, the user must set up the scale // before calling plenv() using plsvpa(), plvasp() or other; // just= 0 : The scales will be set up to optimize plot area; // just= 1 : The scales will be the same; // just= 2 : The axes will be equal, the plot box will be square. // // The "axis" parameter is interpreted as follows: // // axis=-2 : draw no box, no tick marks, no numeric tick labels, no axes. // axis=-1 : draw box only. // axis= 0 : Draw box, ticks, and numeric tick labels. // axis= 1 : Also draw coordinate axes at X=0, and Y=0. // axis= 2 : Also draw a grid at major tick positions in both coordinates. // axis= 3 : Same as 2, but the grid will be also at the minor ticks. // axis=10 : Same as 0 except Logarithmic X tick marks. (The X data have // to be converted to logarithms separately.) // axis=11 : Same as 1 except Logarithmic X tick marks. (The X data have // to be converted to logarithms separately.) // axis=12 : Same as 2 except Logarithmic X tick marks. (The X data have // to be converted to logarithms separately.) // axis=13 : Same as 12, but the grid will be also at the minor ticks. // axis=20 : Same as 0 except Logarithmic Y tick marks. (The Y data have // to be converted to logarithms separately.) // axis=21 : Same as 1 except Logarithmic Y tick marks. (The Y data have // to be converted to logarithms separately.) // axis=22 : Same as 2 except Logarithmic Y tick marks. (The Y data have // to be converted to logarithms separately.) // axis=23 : Same as 22, but the grid will be also at the minor ticks. // axis=30 : Same as 0 except Logarithmic X,Y tick marks. (The X,Y data have // to be converted to logarithms separately.) // axis=31 : Same as 1 except Logarithmic X,Y tick marks. (The X,Y data have // to be converted to logarithms separately.) // axis=32 : Same as 2 except Logarithmic X,Y tick marks. (The X,Y data have // to be converted to logarithms separately.) // axis=33 : Same as 32, but the grid will be also at the minor ticks. // axis=40 : Same as 0 except date / time X tick marks. // axis=41 : Same as 1 except date / time X tick marks. // axis=42 : Same as 2 except date / time X tick marks. // axis=43 : Same as 42, but the grid will be also at the minor ticks. // axis=50 : Same as 0 except date / time Y tick marks. // axis=51 : Same as 1 except date / time Y tick marks. // axis=52 : Same as 2 except date / time Y tick marks. // axis=53 : Same as 52, but the grid will be also at the minor ticks. // axis=60 : Same as 0 except date / time X,Y tick marks. // axis=61 : Same as 1 except date / time X,Y tick marks. // axis=62 : Same as 2 except date / time X,Y tick marks. // axis=63 : Same as 62, but the grid will be also at the minor ticks. // axis=70 : Same as 0 except custom X,Y labels. // axis=71 : Same as 1 except custom X,Y labels. // axis=72 : Same as 2 except custom X,Y labels. // axis=73 : Same as 72, but the grid will be also at the minor ticks. //-------------------------------------------------------------------------- void c_plenv( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis ) { c_plenvi( xmin, xmax, ymin, ymax, just, axis, 1 ); } //-------------------------------------------------------------------------- // void plenv0() // // same as plenv() above, but if in multiplot mode does not advance the subpage, // instead clears it. //-------------------------------------------------------------------------- void c_plenv0( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis ) { c_plenvi( xmin, xmax, ymin, ymax, just, axis, 0 ); } static void c_plenvi( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis, PLINT old ) { PLFLT lb, rb, tb, bb, dx, dy; PLFLT xsize, ysize, size, xscale, yscale, scale; PLFLT spxmin, spxmax, spymin, spymax; PLFLT vpxmin, vpxmax, vpymin, vpymax; if ( plsc->level < 1 ) { plabort( "plenv: Please call plinit first" ); return; } if ( xmin == xmax ) { plabort( "plenv: Invalid xmin and xmax arguments" ); return; } if ( ymin == ymax ) { plabort( "plenv: Invalid ymin and ymax arguments" ); return; } if ( just < -1 || just > 2 ) { plabort( "plenv: Invalid just option" ); return; } if ( plsc->nsubx * plsc->nsuby == 1 ) // not multiplot mode old = 1; if ( old == 1 ) pladv( 0 ); else plclear(); if ( just == 0 ) plvsta(); else if ( just == 1 ) { lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; dx = ABS( xmax - xmin ); dy = ABS( ymax - ymin ); plgspa( &spxmin, &spxmax, &spymin, &spymax ); xsize = spxmax - spxmin; ysize = spymax - spymin; xscale = dx / ( xsize - lb - rb ); yscale = dy / ( ysize - tb - bb ); scale = MAX( xscale, yscale ); vpxmin = MAX( lb, 0.5 * ( xsize - dx / scale ) ); vpxmax = vpxmin + ( dx / scale ); vpymin = MAX( bb, 0.5 * ( ysize - dy / scale ) ); vpymax = vpymin + ( dy / scale ); plsvpa( vpxmin, vpxmax, vpymin, vpymax ); } else if ( just == 2 ) { lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; plgspa( &spxmin, &spxmax, &spymin, &spymax ); xsize = spxmax - spxmin; ysize = spymax - spymin; size = MIN( xsize - lb - rb, ysize - tb - bb ); dx = ( xsize - size - lb - rb ) / 2; vpxmin = lb + dx; vpxmax = vpxmin + size; dy = ( ysize - size - bb - tb ) / 2; vpymin = bb + dy; vpymax = vpymin + size; plsvpa( vpxmin, vpxmax, vpymin, vpymax ); } plwind( xmin, xmax, ymin, ymax ); switch ( axis ) { case -2: break; case -1: plbox( "bc", (PLFLT) 0.0, 0, "bc", (PLFLT) 0.0, 0 ); break; case 0: plbox( "bcnst", (PLFLT) 0.0, 0, "bcnstv", (PLFLT) 0.0, 0 ); break; case 1: plbox( "abcnst", (PLFLT) 0.0, 0, "abcnstv", (PLFLT) 0.0, 0 ); break; case 2: plbox( "abcgnst", (PLFLT) 0.0, 0, "abcgnstv", (PLFLT) 0.0, 0 ); break; case 3: plbox( "abcgnsth", (PLFLT) 0.0, 0, "abcgnstvh", (PLFLT) 0.0, 0 ); break; case 10: plbox( "bclnst", (PLFLT) 0.0, 0, "bcnstv", (PLFLT) 0.0, 0 ); break; case 11: plbox( "abclnst", (PLFLT) 0.0, 0, "abcnstv", (PLFLT) 0.0, 0 ); break; case 12: plbox( "abcglnst", (PLFLT) 0.0, 0, "abcgnstv", (PLFLT) 0.0, 0 ); break; case 13: plbox( "abcglnsth", (PLFLT) 0.0, 0, "abcgnstvh", (PLFLT) 0.0, 0 ); break; case 20: plbox( "bcnst", (PLFLT) 0.0, 0, "bclnstv", (PLFLT) 0.0, 0 ); break; case 21: plbox( "abcnst", (PLFLT) 0.0, 0, "abclnstv", (PLFLT) 0.0, 0 ); break; case 22: plbox( "abcgnst", (PLFLT) 0.0, 0, "abcglnstv", (PLFLT) 0.0, 0 ); break; case 23: plbox( "abcgnsth", (PLFLT) 0.0, 0, "abcglnstvh", (PLFLT) 0.0, 0 ); break; case 30: plbox( "bclnst", (PLFLT) 0.0, 0, "bclnstv", (PLFLT) 0.0, 0 ); break; case 31: plbox( "abclnst", (PLFLT) 0.0, 0, "abclnstv", (PLFLT) 0.0, 0 ); break; case 32: plbox( "abcglnst", (PLFLT) 0.0, 0, "abcglnstv", (PLFLT) 0.0, 0 ); break; case 33: plbox( "abcglnsth", (PLFLT) 0.0, 0, "abcglnstvh", (PLFLT) 0.0, 0 ); break; case 40: plbox( "bcdnst", (PLFLT) 0.0, 0, "bcnstv", (PLFLT) 0.0, 0 ); break; case 41: plbox( "abcdnst", (PLFLT) 0.0, 0, "abcnstv", (PLFLT) 0.0, 0 ); break; case 42: plbox( "abcgdnst", (PLFLT) 0.0, 0, "abcgnstv", (PLFLT) 0.0, 0 ); break; case 43: plbox( "abcgdnsth", (PLFLT) 0.0, 0, "abcgnstvh", (PLFLT) 0.0, 0 ); break; case 50: plbox( "bcnst", (PLFLT) 0.0, 0, "bcdnstv", (PLFLT) 0.0, 0 ); break; case 51: plbox( "abcnst", (PLFLT) 0.0, 0, "abcdnstv", (PLFLT) 0.0, 0 ); break; case 52: plbox( "abcgnst", (PLFLT) 0.0, 0, "abcgdnstv", (PLFLT) 0.0, 0 ); break; case 53: plbox( "abcgnsth", (PLFLT) 0.0, 0, "abcgdnstvh", (PLFLT) 0.0, 0 ); break; case 60: plbox( "bcdnst", (PLFLT) 0.0, 0, "bcdnstv", (PLFLT) 0.0, 0 ); break; case 61: plbox( "abcdnst", (PLFLT) 0.0, 0, "abcdnstv", (PLFLT) 0.0, 0 ); break; case 62: plbox( "abcgdnst", (PLFLT) 0.0, 0, "abcgdnstv", (PLFLT) 0.0, 0 ); break; case 63: plbox( "abcgdnsth", (PLFLT) 0.0, 0, "abcgdnstvh", (PLFLT) 0.0, 0 ); break; case 70: plbox( "bcnost", (PLFLT) 0.0, 0, "bcnostv", (PLFLT) 0.0, 0 ); break; case 71: plbox( "abcnost", (PLFLT) 0.0, 0, "abcnostv", (PLFLT) 0.0, 0 ); break; case 72: plbox( "abcgnost", (PLFLT) 0.0, 0, "abcgnostv", (PLFLT) 0.0, 0 ); break; case 73: plbox( "abcgnosth", (PLFLT) 0.0, 0, "abcgnostvh", (PLFLT) 0.0, 0 ); break; default: plwarn( "plenv: Invalid axis argument" ); } } //-------------------------------------------------------------------------- // void plvsta() // // Defines a "standard" viewport with seven character heights for // the left margin and four character heights everywhere else. //-------------------------------------------------------------------------- void c_plvsta( void ) { PLFLT xmin, xmax, ymin, ymax; PLFLT lb, rb, tb, bb; if ( plsc->level < 1 ) { plabort( "plvsta: Please call plinit first" ); return; } // Find out position of subpage boundaries in millimetres, reduce by // the desired border, and convert back into normalized subpage // coordinates lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; xmin = plP_dcscx( plP_mmdcx( (PLFLT) ( plP_dcmmx( plsc->spdxmi ) + lb ) ) ); xmax = plP_dcscx( plP_mmdcx( (PLFLT) ( plP_dcmmx( plsc->spdxma ) - rb ) ) ); ymin = plP_dcscy( plP_mmdcy( (PLFLT) ( plP_dcmmy( plsc->spdymi ) + tb ) ) ); ymax = plP_dcscy( plP_mmdcy( (PLFLT) ( plP_dcmmy( plsc->spdyma ) - bb ) ) ); plvpor( xmin, xmax, ymin, ymax ); } //-------------------------------------------------------------------------- // void plvpor() // // Creates a viewport with the specified normalized subpage coordinates. //-------------------------------------------------------------------------- void c_plvpor( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ) { if ( plsc->level < 1 ) { plabort( "plvpor: Please call plinit first" ); return; } if ( ( xmin >= xmax ) || ( ymin >= ymax ) ) { plabort( "plvpor: Invalid limits" ); return; } if ( ( plsc->cursub <= 0 ) || ( plsc->cursub > ( plsc->nsubx * plsc->nsuby ) ) ) { plabort( "plvpor: Please call pladv or plenv to go to a subpage" ); return; } plsc->vpdxmi = plsc->spdxmi + ( plsc->spdxma - plsc->spdxmi ) * xmin; plsc->vpdxma = plsc->spdxmi + ( plsc->spdxma - plsc->spdxmi ) * xmax; plsc->vpdymi = plsc->spdymi + ( plsc->spdyma - plsc->spdymi ) * ymin; plsc->vpdyma = plsc->spdymi + ( plsc->spdyma - plsc->spdymi ) * ymax; plsc->vppxmi = plP_dcpcx( plsc->vpdxmi ); plsc->vppxma = plP_dcpcx( plsc->vpdxma ); plsc->vppymi = plP_dcpcy( plsc->vpdymi ); plsc->vppyma = plP_dcpcy( plsc->vpdyma ); plP_sclp( MAX( plsc->vppxmi, plsc->phyxmi ), MIN( plsc->vppxma, plsc->phyxma ), MAX( plsc->vppymi, plsc->phyymi ), MIN( plsc->vppyma, plsc->phyyma ) ); plsc->level = 2; } //-------------------------------------------------------------------------- // void plvpas() // // Creates the largest viewport of the specified aspect ratio that fits // within the specified normalized subpage coordinates. //-------------------------------------------------------------------------- void c_plvpas( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT aspect ) { PLFLT spxmin, spxmax, spymin, spymax; PLFLT vpxmin, vpxmax, vpymin, vpymax; PLFLT xsize, ysize, nxsize, nysize; PLFLT xoffset, yoffset; if ( plsc->level < 1 ) { plabort( "plvpas: Please call plinit first" ); return; } if ( ( xmin >= xmax ) || ( ymin >= ymax ) ) { plabort( "plvpas: Invalid limits" ); return; } if ( aspect <= 0.0 ) { c_plvpor( xmin, xmax, ymin, ymax ); return; } plgspa( &spxmin, &spxmax, &spymin, &spymax ); xsize = spxmax - spxmin; ysize = spymax - spymin; xoffset = xsize * xmin; yoffset = ysize * ymin; spxmax = spxmin + xsize * xmax; spxmin = spxmin + xsize * xmin; spymax = spymin + ysize * ymax; spymin = spymin + ysize * ymin; // Adjust size for the requested edging xsize = spxmax - spxmin; ysize = spymax - spymin; if ( aspect * xsize > ysize ) { nxsize = ysize / aspect; nysize = ysize; } else { nxsize = xsize; nysize = xsize * aspect; } // center plot within page vpxmin = 0.5 * ( xsize - nxsize ) + xoffset; vpxmax = vpxmin + nxsize; vpymin = 0.5 * ( ysize - nysize ) + yoffset; vpymax = vpymin + nysize; plsvpa( vpxmin, vpxmax, vpymin, vpymax ); } //-------------------------------------------------------------------------- // void plvasp() // // Sets the edges of the viewport with the given aspect ratio, leaving // room for labels. //-------------------------------------------------------------------------- void c_plvasp( PLFLT aspect ) { PLFLT spxmin, spxmax, spymin, spymax; PLFLT vpxmin, vpxmax, vpymin, vpymax; PLFLT xsize, ysize, nxsize, nysize; PLFLT lb, rb, tb, bb; if ( plsc->level < 1 ) { plabort( "plvasp: Please call plinit first" ); return; } lb = 8.0 * plsc->chrht; rb = 5.0 * plsc->chrht; tb = 5.0 * plsc->chrht; bb = 5.0 * plsc->chrht; plgspa( &spxmin, &spxmax, &spymin, &spymax ); xsize = spxmax - spxmin; ysize = spymax - spymin; xsize -= lb + rb; // adjust for labels ysize -= bb + tb; if ( aspect * xsize > ysize ) { nxsize = ysize / aspect; nysize = ysize; } else { nxsize = xsize; nysize = xsize * aspect; } // center plot within page vpxmin = .5 * ( xsize - nxsize ) + lb; vpxmax = vpxmin + nxsize; vpymin = .5 * ( ysize - nysize ) + bb; vpymax = vpymin + nysize; plsvpa( vpxmin, vpxmax, vpymin, vpymax ); } //-------------------------------------------------------------------------- // void plsvpa() // // Sets the edges of the viewport to the specified absolute coordinates // (mm), measured with respect to the current subpage boundaries. //-------------------------------------------------------------------------- void c_plsvpa( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ) { PLFLT sxmin, symin; if ( plsc->level < 1 ) { plabort( "plsvpa: Please call plinit first" ); return; } if ( ( xmin >= xmax ) || ( ymin >= ymax ) ) { plabort( "plsvpa: Invalid limits" ); return; } if ( ( plsc->cursub <= 0 ) || ( plsc->cursub > ( plsc->nsubx * plsc->nsuby ) ) ) { plabort( "plsvpa: Please call pladv or plenv to go to a subpage" ); return; } sxmin = plP_dcmmx( plsc->spdxmi ); symin = plP_dcmmy( plsc->spdymi ); plsc->vpdxmi = plP_mmdcx( (PLFLT) ( sxmin + xmin ) ); plsc->vpdxma = plP_mmdcx( (PLFLT) ( sxmin + xmax ) ); plsc->vpdymi = plP_mmdcy( (PLFLT) ( symin + ymin ) ); plsc->vpdyma = plP_mmdcy( (PLFLT) ( symin + ymax ) ); plsc->vppxmi = plP_dcpcx( plsc->vpdxmi ); plsc->vppxma = plP_dcpcx( plsc->vpdxma ); plsc->vppymi = plP_dcpcy( plsc->vpdymi ); plsc->vppyma = plP_dcpcy( plsc->vpdyma ); plP_sclp( plP_dcpcx( plsc->vpdxmi ), plP_dcpcx( plsc->vpdxma ), plP_dcpcy( plsc->vpdymi ), plP_dcpcy( plsc->vpdyma ) ); plsc->level = 2; }