Creating new graphics primitive (EdgeForm, FaceForm)

I think you will need to use FilledCurve to create objects with holes in.

For example:

points[r1_, r2_, n_] := With[{dphi = 2.0 Pi/(n - 1)}, 
   Table[r {Cos[phi], Sin[phi]}, {phi, 0, 2 Pi, dphi}, {r, {r1, r2}}]];

poly = Polygon[Function[{p1, p2}, Join[p1, Reverse[p2]]] @@@ 
    Partition[points[0.3, 0.7, 30], 2, 1]];

prim = FilledCurve[Thread[Graphics`Mesh`PolygonCombine @ poly] /. 
    Polygon[data_] :> {Line[data]}];

To make something that behaves more like a graphics primitive I will use my answer from here

SetAttributes[createPrimitive, HoldAll];
createPrimitive[patt_, expr_] := 
 Typeset`MakeBoxes[p : patt, fmt_, Graphics] := 
  Typeset`MakeBoxes[Interpretation[expr, p], fmt, Graphics]

createPrimitive[donut, Evaluate@prim]

Now you can use donut in Graphics:

Graphics@{EdgeForm[{Black, Thick}], FaceForm[Opacity[0.3, Red]], donut}

enter image description here

Because donut has no downvalues, it remains unevaluated in the graphics expression:

InputForm[%]
(* Graphics[{EdgeForm[{GrayLevel[0], Thickness[Large]}], 
    FaceForm[Opacity[0.3, RGBColor[1, 0, 0]]], donut}] *)

You can use the undocumented PolygonCombine to create a single polygon which behaves well with EdgeForm and FaceForm:

Boing2[] := Graphics`Mesh`PolygonCombine@Boing[]
Graphics[{EdgeForm[Black], FaceForm[Opacity[0.3, Blue]], Boing2[]}, AspectRatio -> Automatic]

In Mathematica 10/Wolfram Language/Mathematica-RPi, the function can be found under Graphics`PolygonUtils`. There might be some issues with self-intersecting polygons (I haven't looked into it), but this is a good start.


In Mathematica 12 BoundaryMeshRegion objects can be used as a Graphics primitive. So, another idea is to use a BoundaryMeshRegion as your primitive. For example:

Typeset`MakeBoxes[
    CutoutEllipse[center_, out_, in_],
    form_,
    Graphics
] := With[
    {
    new = Replace[
        RegionDifference[Disk[center, out], Disk[center, in]],
        b_BooleanRegion :> BoundaryDiscretizeRegion[b]
    ]
    },
    Typeset`MakeBoxes[new, form, Graphics]
]

Examples:

Graphics[{Pink, EdgeForm[Blue], CutoutEllipse[{0,0}, {4,2}, .9 {1,2}]}]

enter image description here

Graphics[{Pink, EdgeForm[Blue], CutoutEllipse[{0,0}, {4,2}, 1.1 {1,2}]}]

enter image description here

You can use this answer to get the above approach to work in earlier versions of Mathematica.

Tags:

Graphics