Function Repository Resource:

ExtractGraphicsPrimitives

Source Notebook

Extract the underlying graphical primitives from plots and graphics

Contributed by: Jaroslav Kysela

ResourceFunction["ExtractGraphicsPrimitives"][gr]

extracts the geometric primitives from the graphics object gr.

ResourceFunction["ExtractGraphicsPrimitives"][gr,lev]

extracts the primitives together with lev enclosing levels.

ResourceFunction["ExtractGraphicsPrimitives"][gr,lev,False]

removes all styling directives and options.

Details

Graphical objects characterized by the heads Graphics, Graphics3D, and GeoGraphics are internally stored as expressions with a hierarchical structure that contains information about the graphics primitives as well as their styling. Usually the primitives form the last level of the hierarchy and styling options and directives reside in higher levels. ExtractGraphicsPrimitives takes the entire structure and returns only those parts of it that correspond to graphics primitives. Since some styling information might be lost this way, the second argument lev allows one to include also levels above the primitives.
Sometimes a plotting function returns a GraphicsComplex expression, which represents a standalone unit that contains both the primitives and their styling. For the purposes of ResourceFunction["ExtractGraphicsPrimitives"], this unit is understood as a single primitive, even though it might contain actual primitives such as Polygon or Line. Analogously, an Input expression is also considered a single primitive.
The default value of the second argument lev is 0. This argument can be any non-negative integer.
The default value of the third argument is True.

Examples

Basic Examples (2) 

Form a Graphics object:

In[1]:=
gr = Graphics[{RGBColor[0, 1, 0], Disk[{0, 0}], RGBColor[1, 0, 0], Rectangle[{0, 0}]}]
Out[1]=

Extract the underlying primitives:

In[2]:=
ResourceFunction["ExtractGraphicsPrimitives"][gr]
Out[2]=

Apart from the primitives, also include their accompanying directives one level up:

In[3]:=
ResourceFunction["ExtractGraphicsPrimitives"][gr, 1]
Out[3]=

Keep the primitives but remove the directives:

In[4]:=
ResourceFunction["ExtractGraphicsPrimitives"][gr, 1, False]
Out[4]=

Extract primitives from a plot:

In[5]:=
plot = ParametricPlot3D[{Sin[u], Cos[u], u/10}, {u, 0, 20}]
Out[5]=
In[6]:=
Short[helix = ResourceFunction["ExtractGraphicsPrimitives"][plot]]
Out[6]=

Display the primitives:

In[7]:=
Graphics3D[helix]
Out[3]=

Apply a different styling to the extracted primitive:

In[8]:=
Graphics3D[{Green, Thickness[0.1], helix /. Line[pts_] :> Tube[pts, 0.1]}]
Out[8]=

Scope (8) 

Input objects (4) 

Extract primitives from Graphics objects generated by 2D plotting functions:

In[9]:=
plot = Plot[Sin[x], {x, 0, 2 \[Pi]}]
Out[9]=
In[10]:=
curve = ResourceFunction["ExtractGraphicsPrimitives"][plot];
Shallow[curve, 3]
Out[3]=

Show the primitive:

In[11]:=
Graphics[curve]
Out[11]=

Extract primitives from Graphics3D objects generated by 3D plotting functions:

In[12]:=
plot = Plot3D[Sin[x y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}]
Out[13]=
In[14]:=
surface = ResourceFunction["ExtractGraphicsPrimitives"][plot];
Shallow[surface, 3]
Out[3]=

Show the primitive:

In[15]:=
Graphics3D[surface]
Out[16]=

Extract primitives from GeoGraphics objects generated by geo plotting functions:

In[17]:=
plot = GeoListPlot[Entity["Country", "Andorra"]]
Out[18]=
In[19]:=
map = ResourceFunction["ExtractGraphicsPrimitives"][plot];
Shallow[map, 3]
Out[3]=

Show the primitives:

In[20]:=
GeoGraphics[map[[4]], GeoBackground -> "StreetMap"]
Out[20]=

The input object can be more general:

In[21]:=
list = {1, 5, \[FormalX], {Rectangle[{-1, -2}, {5, 4}], SparseArray[{1, 2, 3}]}, Graphics3D[{Ball[]}]}
Out[21]=
In[22]:=
ResourceFunction["ExtractGraphicsPrimitives"][list]
Out[22]=

Level specification (2) 

By default, only the primitives themselves are extracted, which might lead to the loss of styling:

In[23]:=
plot = Plot[Cos[x], {x, 0, 2 \[Pi]}, PlotStyle -> Orange]
Out[23]=
In[24]:=
curve = ResourceFunction["ExtractGraphicsPrimitives"][plot];
Graphics[curve]
Out[3]=

Include also the styling by increasing the level parameter:

In[25]:=
curve = ResourceFunction["ExtractGraphicsPrimitives"][plot, 1];
Graphics[curve]
Out[26]=

Usually only a certain range of level values gives useful results:

In[27]:=
pie = PieChart[{{1, 2, 3}}, PerformanceGoal -> "Speed"]
Out[27]=
In[28]:=
Framed@Graphics[ResourceFunction["ExtractGraphicsPrimitives"][pie, #],
     PlotLabel -> "Level = " <> ToString[#]] & /@ {0, 1, 20}
Out[28]=

Styling preservation (2) 

By default, the styling is preserved (provided that the level specification is correct):

In[29]:=
plot = Plot3D[{Sin[x y], Cos[x y]}, {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}, PlotStyle -> {Red, Green}]
Out[29]=
In[30]:=
Graphics3D[ResourceFunction["ExtractGraphicsPrimitives"][plot, 0]]
Out[30]=

Remove the styling:

In[31]:=
Graphics3D[
 ResourceFunction["ExtractGraphicsPrimitives"][plot, 0, False]]
Out[31]=

Properties and Relations (2) 

The internal structure of graphics objects can be examined using InputForm:

In[32]:=
plot = Plot[Sin[x], {x, 0, 2 \[Pi]}]
Out[32]=
In[33]:=
Shallow[InputForm[plot], 6]
Out[33]=

Relevant primitives can be retrieved from this expression using Cases or Position:

In[34]:=
line = Cases[plot, _Line, Infinity];
Graphics[line]
Out[25]=
In[35]:=
posline = Position[plot, _Line];
Graphics[Extract[plot, posline]]
Out[36]=

Removing the styling of a graphical object via the third argument in ExtractGraphicsPrimitives gives similar results to menu option Format ▶ Clear Formatting:

In[37]:=
Plot3D[Sin[x y], {x, -\[Pi], \[Pi]}, {y, -\[Pi], \[Pi]}]
Out[38]=
In[39]:=
Graphics3D@ResourceFunction["ExtractGraphicsPrimitives"][%, 0, False]
Out[35]=

Compare with the approach when the output of Plot3D above is selected and then shortcut  +  +  (for Windows) is pressed:

Possible Issues (5) 

Charts are by default interactive, which may cause problems when extracting the primitives:

In[40]:=
pie = PieChart[{{1, 2, 3}, {2, 2, 1}}]
Out[40]=
In[41]:=
Graphics[ResourceFunction["ExtractGraphicsPrimitives"][pie, 5]]
Out[41]=

Effectively turn off interactivity by setting PerformanceGoal to "Speed":

In[42]:=
pie = PieChart[{{1, 2, 3}, {2, 2, 1}}, PerformanceGoal -> "Speed"];
Graphics[ResourceFunction["ExtractGraphicsPrimitives"][pie, 5]]
Out[43]=

Some charts and plots store styling information in the higher levels of the hierarchy:

In[44]:=
pie = PieChart[{{1, 2, 3}, {2, 2, 1}}, PerformanceGoal -> "Speed"]
Out[44]=
In[45]:=
Graphics[ResourceFunction["ExtractGraphicsPrimitives"][pie]]
Out[45]=

Increment the level parameter to include also the styling information:

In[46]:=
Graphics[ResourceFunction["ExtractGraphicsPrimitives"][pie, 5]]
Out[46]=

Some plotting functions adjust the aspect ratio to accommodate the plot. Extracting the primitives resets this ratio:

In[47]:=
{plot, dateplot} = {LogPlot[x, {x, 0, 10^8}], DateListStepPlot[{{DateObject[{2006, 10, 1}, "Day", "Gregorian", -6.`], 10}, {DateObject[{2006, 10, 15}, "Day", "Gregorian", -6.`], 12}, {DateObject[{2006, 10, 30}, "Day", "Gregorian", -6.`], 15}, {DateObject[{2006, 11, 20}, "Day", "Gregorian", -6.`], 20}}]}
Out[47]=
In[48]:=
line = ResourceFunction["ExtractGraphicsPrimitives"][plot, 2];
Framed@Graphics[line]
Out[46]=

The line appears flat due to disproportionate values in the horizontal and vertical axes. Set the aspect ratio appropriately:

In[49]:=
Graphics[line, AspectRatio -> 1]
Out[49]=

Similar problems arise when plotting against dates:

In[50]:=
Framed@Graphics@
  ResourceFunction["ExtractGraphicsPrimitives"][dateplot]
Out[50]=
In[51]:=
Framed@Graphics[
  ResourceFunction["ExtractGraphicsPrimitives"][dateplot], AspectRatio -> 1]
Out[51]=

The output of geographics functions contains more primitives than are directly visible:

In[52]:=
{plot1, plot2} = {GeoListPlot[Entity["Country", "SanMarino"]], GeoListPlot[{Entity["Country", "Indonesia"], Entity["Country", "Malaysia"], Entity["Country", "Thailand"], Entity["Country", "Vietnam"]}]}
Out[49]=
In[53]:=
{map1, map2} = ResourceFunction["ExtractGraphicsPrimitives"] /@ {plot1, plot2};
Shallow[map1, 3]
Out[54]=

Plotting all these primitives may lead to unexpected results:

In[55]:=
{GeoGraphics[map1, GeoBackground -> "StreetMap"], GeoGraphics[map2, GeoBackground -> "StreetMap"]}
Out[55]=

Choose only the relevant primitives:

In[56]:=
GeoGraphics[map1[[4]], GeoBackground -> "StreetMap"]
Out[56]=

Additional primitives might be stored inside the value for the option Method. Remove it to obtain better results:

In[57]:=
Graphics[
 ResourceFunction["ExtractGraphicsPrimitives"][
  plot2 /. (Method -> _) -> {}, 2]]
Out[46]=

The output of some plotting functions contains more graphics wrapped in Inset, which may lead to unexpected results:

In[58]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/61d4812d-eb05-4947-b31e-bce0fe4c2c29"]
Out[58]=
In[59]:=
gr = ResourceFunction["ExtractGraphicsPrimitives"][plot]
Out[59]=
In[60]:=
Graphics[gr]
Out[60]=

Adjust manually the position of Inset objects or fix the PlotRange:

In[61]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/2d85216d-1194-427d-a7bf-ed5f26fbd845"]
Out[61]=

Neat Examples (1) 

Create a still life with a glass containing green liquid:

In[62]:=
rim = ResourceFunction["Annulus3D"][{0, 0, 5}, {0, 0, 1}, {3 - 0.3, 3}];
In[63]:=
outer = ResourceFunction["ExtractGraphicsPrimitives"][#, 0, False] &@
   RevolutionPlot3D[-10 + 5 x, {x, 2, 3}, Mesh -> None];
inner = ResourceFunction["ExtractGraphicsPrimitives"][#, 0, False] &@
   RevolutionPlot3D[-7.7 + 4.7 x, {x, 1.7, 2.7}, Mesh -> None];
liquid = ResourceFunction["ExtractGraphicsPrimitives"][#, 0, False] &@
   RevolutionPlot3D[-7.71 + 4.7 x, {x, 1.69, 2.19}, Mesh -> None];
In[64]:=
surface = ParametricPlot3D[{r Cos[\[Theta]], r Sin[\[Theta]], 5 BesselJ[3, r] Sin[3 \[Theta]] Sin[0.8]}, {r, 0, BesselJZero[3, 3]}, {\[Theta], 0, 2 \[Pi]}, Mesh -> None]
Out[64]=
In[65]:=
Graphics3D[{Opacity[0.5, LightBlue], EdgeForm[], rim, outer, inner, Green, liquid, Translate[
     Scale[#, {1, 1, 1} (2.5 - 0.4)/BesselJZero[3, 3]], {0, 0, 2.5}] &@ResourceFunction["ExtractGraphicsPrimitives"][surface, 0, False]}, Boxed -> False]
Out[62]=

Publisher

Jaroslav Kysela

Version History

  • 1.0.0 – 01 March 2023

Related Resources

License Information