# Is there a GraphicsPrimitiveQ (or a complete list of Heads of graphics primitives)?

For various reasons related to workflow associated with creating figures for journals, I am creating functions that will accept graphics primitives and a set of options and spit out a Graphics object with those primitives and those options in some configuration.

(Of course, this sounds like all I'm doing is re-creating Graphics, in that I can call

Graphics[ <List of primitives>, <Sequence of options>]


but it's more complicated than that.)

In any case, I would like to be able to check whether the inputs to the function are graphics primitives or not. We can create our own GraphicsPrimitiveQ if we have a list of the Heads of graphics primitives. For instance,

Clear[GraphicsPrimitiveQ, listOfHeads]
listOfHeads = {Line, Polygon, Point, Arrow, Tube};


in which case if we define

f[x__?GraphicsPrimitiveQ] := {x}


then

f[Point[{0, 0}], Line[{{1, 1}, {0, 0}}]]
(* {Point[{0, 0}], Line[{{1, 1}, {0, 0}}} *)


and

f[Point[{0, 0}], 1]
(* f[Point[{0, 0}], 1] *)

• So: Is there something like a GraphicsPrimitiveQ?

• Or: Is there hidden somewhere in Mathematica an easy way to get a list of all graphics primitives?

• Alternatively, if there's no built-in ListOfGraphicsPrimitives[], then Is there a programmatic way of making the function GraphicsPrimitiveQ? (Added this because I for some reason didn't anticipate the clever answers below.)

• Here's a parser I wrote for work. It has an almost complete list of primitives and directives. All that it is missing is the new stuff for 10.2. Jul 15, 2015 at 21:15
• @rcollyer. I saw this answer in my search before posting the question! I was hoping for something that could be called directly from Mathematica, but I can always deposit your primitives in a package if I need to. Thanks! Jul 15, 2015 at 21:19
• I think I have something that will work, programatically. Jul 15, 2015 at 21:20
• In the old days, I had to maintain a long list based on the list given in the docs. I like this question; maybe you should also ask about the possibility of a GraphicsDirectiveQ[]. :) Jul 16, 2015 at 0:32
• @march correction, now the parser has a complete list of primitives. I forgot to add the v10 and v10.2 primitives even in my local implementation. Jul 16, 2015 at 13:02

Edit: It was pointed out that the original form is not bullet-proof, e.g. GraphicsPrimitiveQ /@ {InputNotebook, Unique, Sequence} all returned True. However, when looking upon this answer about generating new graphics primitives, a superior answer came to light:

Clear[GraphicsPrimitiveQ];
GraphicsPrimitiveQ[s_Symbol | (s_)[___]] :=
0 < Count[DownValues[TypesetMakeBoxes],
Verbatim[HoldPattern][HoldPattern[TypesetMakeBoxes[s[___], __, Graphics]]], -1]


which is now bullet-proof:

GraphicsPrimitiveQ /@ {Rectangle, Pyramid, Sequence}
(* {True, False, False} *)


I need to look deeper for one dealing with Graphics3D, though.

This is the old version. It works, but has issues.

This works for Graphics primitives:

Clear[GraphicsPrimitiveQ];
GraphicsPrimitiveQ[s_Symbol] := !MatchQ[ToBoxes@Graphics[s[]], GraphicsBox[_s]]

GraphicsPrimitiveQ /@ {Line, Bob, CapsuleShape (*3d primitive*)}
(* {True, False, False} *)


GraphicsPrimitiveQ[e : (h_)[___]] := !MatchQ[ToBoxes@Graphics[e], GraphicsBox[_h]]

GraphicsPrimitiveQ[#[{{1,2},{3,4}}]]& /@ {Polygon, List}
(* {True, False} *)


This works because in the presence of Graphics, the primitives have a box form, e.g.

ToBoxes@Graphics@Line[{{1,2},{3,4}}]
(* GraphicsBox@LineBox[{{1,2},{3,4}}] *)


but non-primitives do not, even those that have box forms

ToBoxes@Subscript[x, 2]
(* SubscriptBox[x, 2] *)

ToBoxes@Graphics@Subscript[x, 2]
(* GraphicsBox[Subscript[x, 2]] *)


nor do primitives expand to their box form outside of Graphics, e.g.

ToBoxes@Line[]
(* RowBox[{"Line", "[", "]"}] *)


We can do the same with Graphics3D,

Clear[GraphicsPrimitiveQ];
Graphics3DPrimitiveQ[s_Symbol] :=
!MatchQ[ToBoxes@Graphics3D[s[]], Graphics3DBox[_s]]
Graphics3DPrimitiveQ[e : (h_)[___]] :=
!MatchQ[ToBoxes@Graphics3D[e], Graphics3DBox[_h]]


but it returns True for exclusively 2D primitives, e.g.

Graphics3DPrimitiveQ @ Rectangle
(* True *)


So, I do not know how to approach this, if you want something that will exclusively detect 3D primitives.

• That's... mysterious. I'll try to parse that later. In the meantime, +1. (I'm out of votes for the day, but I'll upvote in a couple of hours.) I will need it to find 3D primitives, in general. Also, in order to match the primitive and not just the Head, could we do instead GraphicsPrimitiveQ[s_Symbol[__]]? Jul 15, 2015 at 21:36
• @Mr.Wizard well, it's a good thing I found a better way. I'll post it shortly, I hope. Jul 16, 2015 at 2:33
• Using your own list of primitives from (32719) reveals that GraphicsPrimitiveQ fails more often that it succeeds. In 10.1.0 failures are: {AASTriangle, ASATriangle, BezierCurve, BSplineCurve, BSplineSurface, Circle, Circumsphere, Cone, Cylinder, Disk, EmptyRegion, FullRegion, Hexahedron, Parallelepiped, Parallelogram, Polygon, Prism, Pyramid, Raster, Raster3D, SASTriangle, SSSTriangle, Tetrahedron, Tube} Jul 16, 2015 at 13:35
• You'll notice the conspicuous lack of an answer from me. Happy fiddling! ;-) Jul 16, 2015 at 13:54
• I decided to post the only simple answer I can think of. It's not a good match for what the OP requested but I think it has potentially useful behavior of its own. I expect you'll inform me of its failings. :-) Jul 16, 2015 at 14:24

With WolframLanguageData your list of graphics primitives will stay up to date.

ListOfGraphicsPrimitives[] = Symbol /@
WolframLanguageData[
EntityClass["WolframLanguageSymbol", {"FunctionalityArea","GraphicsPrimitiveFunctions"}], "Name"]


{AASTriangle, AffineHalfSpace, AffineSpace, Annulus, Arrow, ASATriangle, Ball, BezierCurve, BSplineCurve, CapsuleShape, Circle, Circumsphere, Cone, ConicHullRegion, Cuboid, Cylinder, Disk, DiskSegment, Ellipsoid, EmptyRegion, FilledCurve, FullRegion, GraphicsComplex, HalfLine, HalfPlane, HalfSpace, Hexahedron, Hyperplane, Insphere, JoinedCurve, Line, Parallelepiped, Parallelogram, Point, Polygon, Prism, Rectangle, RegularPolygon, SASTriangle, Simplex, Sphere, SphericalShell, SSSTriangle, StadiumShape, Tetrahedron, Triangle, Tube}

ListOfGraphicsFunctions[] = Symbol /@
WolframLanguageData[
EntityClass["WolframLanguageSymbol", {"FunctionalityArea","GraphicsFunctions"}], "Name"]


{AbsoluteDashing, AbsolutePointSize, AbsoluteThickness, Antialiasing, Arrowheads, AspectRatio, Axes, AxesEdge, AxesLabel, AxesOrigin, AxesStyle, Axis, Back, Background, BezierFunction, BoundaryDiscretizeGraphics, Boxed, BoxRatios, BoxStyle, BSplineFunction, BSplineSurface, CapForm, ClippingStyle, ClipPlanes, ClipPlanesStyle, ClipRange, ContentSelectable, ContourLabels, Contours, ContourShading, CoordinatesToolOptions, CurveClosed, Dashing[{Small, Small}], Dashing, DataRange, DataReversed, DateTicksFormat, DefaultAxesStyle, DefaultBaseStyle, DefaultBoxStyle, DefaultFaceGridsStyle, DefaultFrameStyle, DefaultFrameTicksStyle, Directive, DiscretizeGraphics, DisplayFunction, Dashing[{0, Small, Small, Small}], Dashing[{0, Small}], EdgeForm, Epilog, Exclusions, ExtentElementFunction, ExtentMarkers, ExtentSize, FaceGrids, Filling, FillingStyle, Frame, FrameLabel, FrameMargins, FrameTicks, Front, FullGraphics, Graphics, Graphics3D, GraphicsColumn, GraphicsGrid, GraphicsGroup, GraphicsRow, GridLines, Inset, ItemAspectRatio, Joined, Lighting, LightingAngle, Mesh, MeshFunctions, MeshShading, NCache, NormalsFunction, Offset, Opacity, OpacityFunction, OpacityFunctionScaling, PixelConstrained, PointSize, PolarAxes, PolarAxesOrigin, PolarGridLines, PolarTicks, Prolog, Raster, Raster3D, Rasterize, RasterSize, RegionFunction, RevolutionAxis, Rotate, RotateLabel, RotationAction, RoundingRadius, Scale, Scaled, Show, Specularity, SphericalRegion, SplineClosed, SplineDegree, SplineKnots, SplineWeights, StreamScale, Texture, Thickness[Large], Thickness, Thickness[Tiny], Ticks, Translate, GrayLevel[ 0, 0], VertexColors, VertexDataCoordinates, VertexNormals, VertexTextureCoordinates, ViewAngle, ViewCenter, ViewMatrix, ViewPoint, ViewRange, ViewVector, ViewVertical}

Hop this helps.

• I tried to get this yesterday, but I think I will need a lot of time till I get intuition how to work entities :-/
– Kuba
Jan 26, 2016 at 7:13
• On my Mac with v11.3, ListOfGraphicsPrimitives gives me different results than shown here and does not include the following primitives listed in the documentation for Graphics: Disk, InfiniteLine, Inset, GraphicsGroup, Line, Locator, Point, Polygon, Raster, SASTriangle, and Text. The bolded entries are also not in your results. Oct 15, 2018 at 0:51

The answer to the question depends upon what exactly should be called as "graphics primitive". In this answer from the practical point of view I define it as a container which can be found inside of Graphics or Graphics3D, which draws something and is not a graphical directive or Dynamic wrapper. This definition differs from the usual meaning but covers all the key cases. Here is (I hope) complete list of such containers for version 10.2:

{Point, PointBox, Line, LineBox, Arrow, ArrowBox, Rectangle, RectangleBox, Parallelogram, Triangle, JoinedCurve, JoinedCurveBox, FilledCurve, FilledCurveBox, StadiumShape, DiskSegment, Annulus, BezierCurve, BezierCurveBox, BSplineCurve, BSplineCurveBox, BSplineSurface, BSplineSurface3DBox, SphericalShell, CapsuleShape, Raster, RasterBox, Raster3D, Raster3DBox, Polygon, PolygonBox, RegularPolygon, Disk, DiskBox, Circle, CircleBox, Sphere, SphereBox, Ball, Ellipsoid, Cylinder, CylinderBox, Tetrahedron, TetrahedronBox, Cuboid, CuboidBox, Parallelepiped, Hexahedron, HexahedronBox, Prism, PrismBox, Pyramid, PyramidBox, Simplex, ConicHullRegion, ConicHullRegionBox, Hyperplane, HalfSpace, AffineHalfSpace, AffineSpace, ConicHullRegion3DBox, Cone, ConeBox, InfiniteLine, InfinitePlane, HalfLine, InfinitePlane, HalfPlane, Tube, TubeBox, GraphicsComplex, GraphicsComplexBox, GraphicsGroup, GraphicsGroupBox, GeoGraphics, Graphics, GraphicsBox, Graphics3D, Graphics3DBox, MeshRegion, BoundaryMeshRegion, GeometricTransformation, GeometricTransformationBox, Rotate, Translate, Scale, SurfaceGraphics, Text, TextBox, Inset, InsetBox, Inset3DBox, Panel, PanelBox, Legended, Placed, LineLegend, Texture}

Since there seems no other simple answer at this time I propose the approach of rendering a Graphics expression and seeing if it has errors. By definition this will pass both primitives and directives, as well as inert expressions such as {}. I hope it nevertheless serves some purpose.

I rasterize the graphic and look for the tell-tale pink warning color. Of course it would be easy to create a false negative simply by creating an element with this very color but that is a corner case.

graphicsQ =
FreeQ[Union @@ ImageData @ Image[Graphics[#], ImageSize -> 30],
x_ /; x == {1., 0.9019607843137255, 0.9019607843137255}] &;


Positive examples:

graphicsQ /@ {Thick, Green, Rectangle[{0, -1}, {2, 1}], Red, Disk[], Blue, Circle[{2, 0}],
Yellow, Polygon[{{2, 0}, {4, 1}, {4, -1}}], Purple, Arrowheads[Large],
Arrow[{{4, 3/2}, {0, 3/2}, {0, 0}}], Black, Dashed, Line[{{-1, 0}, {4, 0}}]}


{True, True, True, True, True, True, True, True, True, True, True, True, True, True, True}

Some negative examples:

graphicsQ /@ {Circle["x"], Arrow[], Line[], Pi, 2.2}


{False, False, False, False, False}

Specifically I included malformed primitives to demonstrate that these are not passed. This may or may not be desirable depending on your application.

• The pink color works, but I think the superior method is to adapt this answer, and yes this was my ultimate fall back method. Jul 16, 2015 at 14:26
• @rcollyer I'm sad to say I forgot about that answer! Would you like to post a second answer using that method and I shall delete mine? Jul 16, 2015 at 14:29
• I'll might do that this afternoon. I might edit yours. Neither will happen until this afternoon. :P Jul 16, 2015 at 14:34
• I think the fact that it outputs False` for malformed primitives (something that I didn't think of) is extremely useful, for a number of reasons, so this is a good addition. Jul 16, 2015 at 16:40