Re: rescalling(sp)
- To: mathgroup at yoda.physics.unc.edu
- Subject: Re: rescalling(sp)
- From: John Lee <lee at math.washington.edu>
- Date: Fri, 6 Nov 92 10:44:36 -0800
Sherman C. Reed (reed at ee.uta.edu) writes: > I need to know how to make the x and y axis on the printed copy > be equal to the units specified. Specifically a "1" on the x axis > should be equal to "1" inch or "1" meter or whatever. > I know how to rescale the plot but I do not know the point values of the > extra spaacing due to the y axis and space at the end of the x axis. > This is probably a medium problem, but it helps an optics person > use Mma to teach design. I had to confront this problem last year when teaching a calculus course in which I wanted to give my students graphs drawn to an accurate scale. Here's my solution. I've written a function called ShowScaled, which behaves essentially the same as Show, except that it accepts an additional argument, Scale -> n, which specifies that the plot is to be scaled so that the entire plot area is n units by n units (i.e. one unit on either axis corresponds to exactly 1/n of the total width of the graph). The default is Scale -> 10. The basic idea behind this solution is that, unlike axis labels and titles, graphics primitives plotted by Prolog or Epilog do not affect where the graph appears in the final output. So ShowScaled takes the given graphics object, and uses FullGraphics to turn it into a list of graphics primitives. It then plots a blank rectangle of the right size and scale to establish the position of the coordinates on the plot, and superimposes the list of primitives on that rectangle using Epilog. There are two limitations to this code as it stands, due to bugs in Mathematica 2.0 graphics. (I don't know whether these are fixed in later versions.) First, if your graphics object contains a "PlotLabel" option, the label will disappear when displayed by ShowScaled. This is because FullOptions apparently throws away the PlotLabel. The code below could be modified to pull out the PlotLabel option of "plot" and then put it back in as an argument to Show in the last statement, but you would have to do some fussing around to figure out where to position it; I didn't have the time to do it. Second, I would like to allow the Scale argument to specify the x and y scales separately. This would require using the AspectRatio option to rescale the axes in the final plot. However, there seems to be a bug in the way AspectRatio interacts with PlotRange; whenever I specify an explicit AspectRatio, the whole plot is scaled down to less than half the size it's supposed to be. I'd be interested in any comments or suggestions for improvements. Jack Lee Dept. of Mathematics University of Washington ========================================================================= (* Here's the code *) ShowScaled::usage = "ShowScaled[graphics, options, Scale -> n] displays a 2-dimensional graphics object, scaled so that one unit occupies exactly 1/n of the total width of the graph. It accepts the same options as Show."; ShowScaled[args__] := Module[{scaleargs,nonscaleargs,plot,xmin,xmax, ymin,ymax,gr,xcenter,ycenter,scale}, (* first pull out the Scale option from args for later use. Default=10. *) scaleargs = If [!MemberQ[{args},Scale->_], {Null}, Options[{args}, Scale] ]; (* nonscaleargs = all the rest of the arguments. Show doesn't want to see Scale. *) nonscaleargs = Complement[ {args}, scaleargs ]; (* Now create a graphics object containing all the user's options *) plot = Show @@ Join[ nonscaleargs, {DisplayFunction -> Identity} ]; (* Pull out the limits of data that was actually plotted, and find the center of the plot *) {{xmin,xmax},{ymin,ymax}} = FullOptions[plot,PlotRange][[{1,2}]]; (* Now turn the graphics object into a list of graphics primitives *) gr = List @@ FullGraphics[ plot ]; xcenter = (xmax+xmin)/2; ycenter = (ymax+ymin)/2; scale = If[ scaleargs === {Null}, 10, scaleargs[[1,2]] ]; (* Finally, display the scaled plot. *) Show[ Graphics[{}], PlotRange -> {{xcenter - scale/2, xcenter + scale/2}, {ycenter - scale/2, ycenter + scale/2}}, AspectRatio -> Automatic, Axes -> False, Epilog -> gr, DisplayFunction -> $DisplayFunction ] ];