drawable enforces structure on its subclasses: every drawable must
carry a style, a geometry, and expose a computed points property, of
class xy. It is not intended to be instantiated directly; use one
of its subclasses (shape_raw, shape_circle, shape_blob,
shape_ribbon, shape_twist, curve_raw, points_raw, ...) instead.
Usage
drawable(..., geometry = "polygon", trans = trans_identity(), pathlike = FALSE)Arguments
- ...
Arguments passed to
style().- geometry
One of
"polygon"(default),"path", or"points". Not exposed as a constructor argument by any concrete drawable – eachshape_*()/curve_*()/points_raw()constructor fixes one value internally instead (see details).- trans
A trans/trans_warp/trans_fn/trans_chain object. See details.
- pathlike
A single
TRUE/FALSE(defaultFALSE). Not exposed as a constructor argument by any concrete drawable – each fixes its own value internally, the same conventiongeometryfollows. See details.
Details
geometry tells draw() which grid grob a drawable's points map to,
following a dimensional reading: "points" (0D, grid::pointsGrob(),
e.g. points_raw()), "path" (1D, an open grid::polylineGrob(), e.g.
curve_line()/curve_raw()), or "polygon" (2D, a closed
grid::polygonGrob() – the default, and the only value any
shape_*() constructor uses). style@fill is ignored for
"points"/"path" geometries, since only a closed polygon has an
interior to fill.
trans is a trans (an affine map: trans_translate(),
trans_rotate(), trans_scale(), trans_reflect(), trans_shear(),
trans_affine()), a trans_warp (a non-rigid, noise-based
deformation), a trans_fn (a non-rigid deformation from an arbitrary
caller-supplied displacement function), or a trans_chain combining
several via +, applied to
a drawable's computed points as the very last step – after any
shape-specific geometry (and, for shape_blob()/shape_ribbon()/
shape_twist(), any noise-based distortion) has already been computed.
This means a drawable's own defining parameters (e.g. shape_circle()'s
centroid/radius) are never mutated or flattened by a transform – only
the final rendered coordinates are affected. Default trans_identity()
(no transform).
pathlike marks whether x/y (where present) hold a genuine,
caller-ordered, perturbable control-point path – as opposed to x/y
meaning something else entirely (e.g. shape_circle()'s centroid, or
one fixed endpoint of shape_ribbon()'s two-point segment). This is
the distinction effect_tremor()/effect_bristle() need to decide whether
jittering x/y produces a meaningful wobble; it's orthogonal to
geometry – a pathlike drawable can have any geometry (a future
points_*() constructor could reasonably be pathlike despite
geometry == "points"). Currently TRUE for shape_raw(),
curve_raw(), curve_line(), shape_stroke(), shape_bezier(),
curve_bezier(), and points_raw(); FALSE (the default) for every
other concrete drawable, including shape_ribbon()/shape_twist()/
curve_twist() – these do have a conceptual
backbone, but it's exposed via x/y/xend/yend (or additional
named control-point pairs), not a plain x/y vector. Whether a
pathlike subclass actually has x/y properties is not enforced by
drawable's own validator – every subclass constructor first builds
a scaffold drawable() instance (validated on its own, before any
subclass property exists) and only merges in x/y afterward via
S7::new_object(), so a cross-property check here would fire on that
scaffold and reject every pathlike subclass unconditionally (see
"Gotchas"). Setting pathlike = TRUE on a subclass with no x/y is
therefore an author error caught only when an effect tries to read
object@x/object@y, not at construction time.
Examples
circ <- shape_circle(radius = 1)
S7::S7_inherits(circ, drawable)
#> [1] TRUE
# geometry controls which grob draw() builds: a closed outline, an open
# stroke, or unconnected markers
draw(shape_circle(radius = 1, n = 8))
draw(curve_line(x = c(0, 1, 2, 3), y = c(0, 1, 0, 1), linewidth = 3))
draw(points_raw(x = runif(30), y = runif(30)))
# trans applies after a shape's own geometry/distortion is computed, so
# shape_rectangle()'s centroid/width/height stay fixed -- only the final
# rendered corners rotate
draw(shape_rectangle(
width = 1.5,
height = 0.5,
trans = trans_rotate(pi / 6)
))