Re: Extracting data points from Plot[]
- To: mathgroup at christensen.cybernetics.net
- Subject: [mg837] Re: [mg773] Extracting data points from Plot[]
- From: Preston Nichols <pdn at godel.math.cmu.edu>
- Date: Tue, 25 Apr 1995 02:18:23 -0400
Jon Guyer wrote: ---------begin-excerpt---------------- The Plot[] function does some intelligent picking of points, such that it usually does a pretty good job of following twists and turns in a function without plotting an excessive number of points. I'm not ecstatic about using Mma for final output, though, so I like to export these curves to a graphing program. So far, I haven't been able to figure out any way to get at this point-picking algorithm without using Plot[]. What I'm then left with is doing: In[1]:= Plot[{x,x^2},{x,0,2}]; In[2]:= InputForm[%1][[1]][[1]][[1]][[1]][[1]][[1]] [Deletia] What I'm wondering, though, is if there isn't something a bit more straightforward than "InputForm[%1][[1]][[1]][[2]][[1]][[1]][[1]]" to get at the data points? ------------end-excerpt---------------- **************************** Here's something that picks the Parts more elegantly, though it still uses Plot: PointsFromPlot::usage = "PointsFromPlot[f, {x, xmin, xmax}] evaluates Plot[f, {x, xmin, xmax}] but returns a list of the points {x, f[x]} instead of a Graphics object. PointsFromPlot[{f1, f2, ...}, {x, xmin, xmax}] computes points for several functions fi. PointsFromPlot takes the same options as Plot."; PointsFromPlot[f_, {x_, xmin_,xmax_}, opts___] := Level[Cases[ Plot[f, {x, xmin, xmax}, opts, DisplayFunction->Identity], Line[_],Infinity], {-2,-2}] The strategy is to use Cases to extract all the graphics primitives (Line[_], in this case) at whatever level they may appear, and then to use Level to get the points, since there is no longer any doubt where they are (namely at level -2). The level is counted from the bottom because Cases might return a List of Lines, especially if more than one function is plotted. The definition is fixed so that Mathematica will not render the plot unless you specify the option DisplayFunction->$DisplayFunction, but in either case % will be the list of points. **************************** It's not hard to do a similar thing for Plot3D, though there is not so much motivation for it. (Other than rendering options, Plot3D doesn't do much that Table can't do equally well.) But you have to change the SurfaceGraphics returned by Plot3D to Graphics3D as an extra step: PointsFromPlot3D::usage = "PointsFromPlot3D[f, {x, xmin, xmax}, {y, ymin, ymax}] evaluates Plot3D[f, {x, xmin, xmax}, {y, ymin, ymax}] but returns a list of the points {x, y, f[x,y]} instead of a SurfaceGraphics object. PointsFromPlot3D takes the same options as Plot3D."; PointsFromPlot3D[f_, {x_, xmin_,xmax_}, {y_, ymin_,ymax_}, opts___] := Level[Cases[ Graphics3D[Plot3D[f, {x, xmin, xmax}, {y, ymin, ymax}, opts, DisplayFunction->Identity]], Polygon[_],Infinity], {-2,-2}]//Union This is definitely not the best way to do the job, because in the result of Graphics3D, every point appears at least twice, and most points appear four times! (Postfixing Union cleans up the duplicates.) **************************** Here's one for ParametricPlot (almost identical to PointsFromPlot): PointsFromParametricPlot::usage = "PointsFromParametricPlot[{fx, fy}, {t, tmin, tmax}] evaluates ParametricPlot[{fx, fy}, {t, tmin, tmax}] but returns a list of the points {fx[t], fy[t]} instead of a Graphics object. PointsFromParametricPlot[{{fx, fy}, {gx, gy}, ...}, {t, tmin, tmax}] computes points for several parametric curves. PointsFromParametricPlot takes the same options as ParametricPlot."; PointsFromParametricPlot[f_, {x_, xmin_,xmax_}, opts___] := Level[Cases[ ParametricPlot[f, {x, xmin, xmax}, opts, DisplayFunction->Identity], Line[_],Infinity], {-2,-2}] **************************** Unless someone advises me that this is a foolish procedure, I'll build these (and a few more?) into a package PointsFromPlot.m and send it to MathSource. Preston Nichols Department of Mathematics Carnegie Mellon University