17
$\begingroup$

I'm looking for a description of the structure of Graphics objects, aimed at the advanced Mathematica programmer.


The motivation for this question is the following. I have several Module-type functions that, as part of their operation, have to manipulate Graphics objects (primarily those generated by plotting commands). I find that these functions often produce undesired results, and the reason is, invariably, that the function has assumed something about the structure of Graphics objects that turns out not to hold in general. Hence, I want to learn more about the internal structure of the Graphics objects generated by Plot, ListPlot, and friends.

Unfortunately, I cannot distill my overall state of confusion into one or two concrete questions. I have a ton of questions, but from my ignorant vantage point, I cannot rank these questions in order of importance. Here's an example out of many I could give: "why do the lists of "primitives" in so many of the Graphics objects that I produce with plotting commands begin and end with empty lists?" For all I know, the answer to this question could just as easily be hugely illuminating, or be utterly banal, or, worse yet, may give rise to further questions.


I've read the documentation for Graphics and the tutorial The Structure of Graphics (which, despite the promising-sounding title, did not shed as much light as I'd hoped). (I've also watched the Graphics Language Quick Start, which is generally instructive, but, as its name suggests, far more high-level and beginner-oriented than what I'm looking for.)

$\endgroup$
2
  • $\begingroup$ How much do you know about computer 3D graphics in general? Mathematica's approach makes a lot of sense if you have some background in say Direct3D or OpenGL. $\endgroup$
    – Hector
    Commented Sep 20, 2013 at 16:47
  • $\begingroup$ @Hector: the answer is "not much", I'm afraid. I'm interested in 2D graphics at the moment, though... $\endgroup$
    – kjo
    Commented Sep 20, 2013 at 16:55

1 Answer 1

22
$\begingroup$

A Graphics object essentially describes a state-machine. Each object allowed in the primitive list has one of three actions associated with it

  1. add to state,
  2. display something while accounting for the current state, and
  3. save/restore state.

Note, this can be modeled by a stack based system quite easily. According to the documentation, the first two make up the primitives and the last one is done by encapsulating primitives in a List. Truthfully, I think the language used by the documentation is a little rough here, so I would like to make the distinction between directives which add to the state and primitives which are displayed. In light of the above model, let us examine a simple Graphics object

Graphics[{Blue, {EdgeForm[{Red, Thick}], Disk[]}, Disk[{1,0}]}]

enter image description here

which can be interpreted in terms of the following steps:

  1. { -> Save state. state == {}
  2. Blue -> AppendTo[state, Blue]. state == {Blue}
  3. { -> Save state. state == {Blue}
  4. EdgeForm[{Red, Thick}] -> AppendTo[state, EdgeForm[{Red, Thick}]]. state == {Blue, EdgeForm[{Red, Thick}]}
  5. Disk[] -> Display {Blue, EdgeForm[{Red, Thick}]], Disk[]}
  6. } -> Restore state. state == {Blue}
  7. Disk[{1,0}] -> Display {Blue, Disk[{1,0}]}

So, then

Graphics[{Blue, {Red}, Disk[]}]

should result in a blue disk because Red has been isolated by being wrapped in a List. This also explains why

Graphics[{Blue, {}, Disk[]}]

also generates a blue disk. An empty list has no effect, and just hinders readability.

This is a slight over-simplification, as state should be thought of as a set of registers, and each directive only effects a specific one. In most cases, only a single function effects a specific register, the color register, though, is effected by many, such as Hue, RGBColor, etc. For example,

Graphics[{Blue, Red, Disk[]}]

produces a red disk because Red changed the color register, but

Graphics[{Blue, EdgeForm[Red], Disk[]}]

produces a blue disk with a red edge because EdgeForm does not effect the color register.

There are four additional primitives that need to be discussed: Directive, GraphicsGroup, GraphicsComplex, and Inset. For all purposes that I'm aware of,

Directive[{directive..}] == Directive[directive ..] == Sequence[directive ..]

as far as Graphics is concerned. Its primary use is to group directives together where otherwise you can only supply one, such as in BaseStyle. The last three are container types like List in that they save and restore state upon entry and exit.

$\endgroup$
3
  • 2
    $\begingroup$ Wow. Reading this post was one of the most eye-opening moment I have had on MMA SE. I have been struggling to understand how to use Graphics properly since I've started using Mathematica, and it had never clicked before. Now I think I finally got it: I wish the official documentation was worded this clearly! Thank you very much! $\endgroup$
    – MarcoB
    Commented Jul 16, 2015 at 2:30
  • $\begingroup$ @MarcoB you're very welcome. $\endgroup$
    – rcollyer
    Commented Jul 16, 2015 at 2:48
  • $\begingroup$ @rcollyer Really nice explanation. Thanks. While MMA comes with quite thorough help, tutorials provided within the help are often left unfinished and lack insight for deep understanding. Perhaps Wolfram should use MMA SE as a source for tutorials. :) $\endgroup$
    – ercegovac
    Commented Feb 8, 2017 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.