MathGroup Archive 2001

[Date Index] [Thread Index] [Author Index]

Search the Archive

Combining Plots in a Natural Manner

  • To: mathgroup at smc.vnet.net
  • Subject: [mg29786] Combining Plots in a Natural Manner
  • From: "David Park" <djmp at earthlink.net>
  • Date: Tue, 10 Jul 2001 20:25:26 -0400 (EDT)
  • Sender: owner-wri-mathgroup at wolfram.com

Dear MathGroup,

I have, perhaps too often, mentioned my DrawingPaper package on MathGroup.
Many people, naturally enough, are reluctant to depend too heavily on third
party, and non WRI Mathematica software. However, there are two simple
routines which easily implement the core idea. I thought I would present and
illustrate these routines because they provide an easy alternative to the
standard methods of combining plots, and can be used without DrawingPaper.
The core idea is to reduce plots to primitive graphics, which can then be
easily intermixed with other graphics primitives and directives in one
statement.

I will present the routines and two examples first, and then give some
discussion.

Needs["Graphics`Colors`"]
Needs["Graphics`ImplicitPlot`"]
Needs["Graphics`FilledPlot`"]
Needs["Graphics`Graphics`"]

The first routine serves to extract the primitive graphics and is so simple
I am almost embarrassed to present it.

Attributes[DrawGraphics] = {HoldAll};
DrawGraphics[plot_] :=
  Block[{$DisplayFunction = Identity},
    First[Graphics[plot]]]

The second routine is equally trivial but serves to get rid of one level of
unnecessary complexity and confusion.

Draw2D[primitives_List, opts___?OptionQ] := Show[Graphics[primitives], opts]

But look how we can use them. Here I combine a ContourPlot, a Disk, a
Circle, a DensityPlot, a regular Plot, a ParametricPlot, an ImplicitPlot,
the points Mathematica used in generating the ImplicitPlot, some Text and
color directives, all in one statement, which contains only a list of the
graphical elements and the overall plot options. We just wrap DrawGraphics
around each of the plot statements.

Draw2D[
    {ContourPlot[Sin[x y], {x, -Pi/2, Pi/2}, {y, -1, 1}] // DrawGraphics,
      Orchid, Disk[{0, 0}, Sqrt[2]/4],
      Black, Circle[{0, 0}, Sqrt[2]/4],
      DensityPlot[Sin[x y], {x, -1/4, 1/4}, {y, -1/4, 1/4},
          ColorFunction -> Hue, PlotPoints -> 8] // DrawGraphics,
      Peacock, Plot[Sin[x], {x, -Pi/2, Pi/2}] // DrawGraphics,
      Blue, ParametricPlot[{Cos[t], Sin[t]}, {t, 0, 2Pi}] // DrawGraphics,
      Red,
      ellipse = ImplicitPlot[x^2 + 3y^2 == 1, {x, -1, 1}] // DrawGraphics,
      LightBlue, PointSize[0.01], ellipse /. Line[pts_] :> Point /@ pts,
      Gold, Text["Draw It!", Scaled[{0.95, 0.1}], {1, -1}]},
    Frame -> True, AspectRatio -> Automatic, Background -> Linen,
    ImageSize -> 500,
    PlotLabel ->
      "Combining Plots, Graphics Primitives\n\t and Graphics Directives"];

It is very useful to have the primitive graphics from a plot because then we
can do further manipulations on them. In the example above, we could
immediately convert a line from one of the plots into points. In the second
example below, I color the area inside a cardioid but outside a unit circle.
(I imagine there is also a way to do this with InequalityPlot.) It is
difficult to use FilledPlot directly because of the shape of the region. But
we can use FilledPlot in the theta-r plane and then transform to the xy
plane. So here I draw the filled area and the polar plots for the cardioid
and circle in one statement.

Draw2D[
    {(FilledPlot[{1, 1 + Cos[t]}, {t, -Pi/2, Pi/2}, Fills -> LightSteelBlue,
              Curves -> None, PlotPoints -> 31] //
            DrawGraphics) /. {t_?NumberQ, r_?NumberQ} -> {r Cos[t],
            r Sin[t]},
      PolarPlot[1 + Cos[t], {t, 0, 2Pi}, PlotPoints -> 31] // DrawGraphics,
	PolarPlot[1, {t, 0, 2Pi}] // DrawGraphics},
    AspectRatio -> Automatic, Background -> Linen,
    ImageSize -> 500,
    PlotLabel -> "Primitive Graphics Can\n Be Easily Transformed"];

The advantages of this approach are:
1) There is no need to produce side plots, or to turn the display on and
off.
2) All graphical elements are on the same level, whether they are ordinary
graphics primitives or primitives generated by some plot command.
3) Graphical elements can be drawn one after the other, and mixed with
graphics directives, just in the order you wish. (And in 2D graphics, the
order matters.) This, after all, is the natural way that one would draw a
picture.
4) Graphical elements are immediately available for manipulation.
5) The overall plot options, such as Axes, Frame, FrameTicks, PlotLabel,
etc., are specified in the Draw2D (or Show) statement itself, where they
logically belong, and not in some plot command which produced only one
element of the overall graphics.
6) It is not necessary to use Prolog or Epilog, or wonder, and be surprised
by which options are actually picked up when you use the regular Mathematica
paradigm for combining plots in a Show statement or with DisplayTogether.
(Show and DisplayTogether pick up options only from the first plot listed.
So Epilog items which might naturally be associated with other plots must be
shifted to the first plot or moved to the Show or DisplayTogether statement.
That is not only not the natural way of doing things, but it loses precise
ordering control for laying down all the elements.)

By adhering to the paradigm that "Everything is an Expression" the designers
of Mathematica made a system which is both powerful and easy to use. While
plots are also expressions, they are not easy to use. For graphical
programming, I would have liked to have seen the subordinate paradigm,
"Everything is Primitive Graphics", implemented. The designers, rather, went
for set-piece plots, and then seem to have worked out methods of combining
them as an afterthought. The DrawGraphics approach goes a long way toward
implementing the "Everything is Primitive Graphics" paradigm.

David Park
djmp at earthlink.net
http://home.earthlink.net/~djmp/



  • Prev by Date: Re: RE: Should Pure Functions Require &
  • Next by Date: about ConstrainedMin
  • Previous by thread: Fitting multiple nonlinear equations to unequal length datasets
  • Next by thread: about ConstrainedMin