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