Skip to contents

Plot JamPolygon object

Usage

plot.JamPolygon(
  x,
  y,
  xlim = NULL,
  ylim = NULL,
  flip_sign = 1,
  render_vectorized = FALSE,
  render_thin_border = TRUE,
  linejoin = c("bevel", "mitre", "round"),
  mitrelimit = -20,
  show_labels = TRUE,
  buffer = 0.05,
  do_newpage = TRUE,
  do_viewport = TRUE,
  do_pop_viewport = TRUE,
  do_draw = TRUE,
  verbose = FALSE,
  debug = FALSE,
  ...
)

Arguments

x

JamPolygon object

y

not used.

xlim, ylim

numeric optionally used to define the x- and y-axis range to be rendered. When NULL they are defined using the observed range of values.

flip_sign

logical indicating whether to flip the polygon orientation, or numeric where the sign is multiplied by the polygon orientation. The polygon orientation is used to define inner/outer border, relative to whether the border represents a solid inner polygon, or the hole inside a solid polygon. In most cases, the orientation is automatically recognized and applied appropriately. Specifically:

  • TRUE or -1 reverses the polygon orientation of inner/outer border

  • FALSE or 1 keeps the polygon orientation unchanged.

render_vectorized

logical indicating whether to render all polygons in one call, thereby ignoring innerborder values. All border values are rendered as regular polygon borders. This option may be substantially faster for large collections of polygons.

render_thin_border

logical indicating whether to render a thin border on the border itself, default TRUE renders a thin grey line.

linejoin

character string (default "bevel") passed to grid::grid.path() and vwline::grid.vwline() when rendering polygons, and inner/outer polygon borders, respectively. Note that vwline version 0.2.2 displayed some graphical glitches when used with "mitre" and "round", so "bevel" is the new default.

mitrelimit

numeric passed to vwline::grid.vwline() to adjust the maximum extension at a line join caused by linejoin="mitre".

show_labels

logical indicating whether to render labels for each polygon. Note that labels are rendered after all polygons are drawn, so they will not be covered by other polygons.

buffer

numeric used to expand the x- and y-axis range beyond the polygons to be drawn.

do_newpage

logical (default TRUE) indicating whether to call grid::grid.newpage() to open a new graphical output page.

do_viewport

logical (default TRUE) indicating whether to define and push a new grid viewport with grid::grid.pushViewport().

do_pop_viewport

logical (default TRUE) indicating whether to close/pop the grid viewport with grid::popViewport(). This action is only performed when do_viewport=TRUE. This option is intended to allow layering multiple calls to this or other grid functions.

do_draw

logical (default TRUE) indicating whether to call grid::grid.draw() for each graphical object. When do_draw=FALSE, it also forces do_newpage=FALSE, do_viewport=FALSE, and do_pop_viewport=FALSE.

verbose

logical indicating whether to print verbose output.

debug

logical (default FALSE) indicating whether to enable debug operations. When debug=TRUE it is also passed to grid functions such as vwline::grid.vwline() to display internal calculations in the graphical output.

...

additional arguments are recognized to customize plot features.

Value

JamPolygon object, invisibly. Some grid attributes are added to the returned object:

  • "adjx","adjy": functions to adjust native x/y values to the corresponding grid units in "snpc".

  • "viewport": the grid::viewport() object suitable to push the same viewport in order to add features to an existing plot.

  • "xrange","yrange": x- and y-axis ranges used to determine the viewport to be used.

  • "grob_tree": a grid::gTree object suitable to call grid::grid.draw(). It includes the same viewport, so it does not need to have the viewport defined.

Details

This function is a general purpose function to plot JamPolygon objects using grid graphics.

It currently calls direct rendering functions, for example grid::pathGrob(), grid::grid.lines(), gridGeometry::polyoffsetGrob() to render complex, potentially nested polygons with or without holes, and with inner, outer, and/or direct border.

Rendering guidelines used by this function:

  • Each polygon is rendered in order, and in series, with no parallelization.

  • All polygon labels are rendered afterward, so that labels are not covered by subsequent polygons. Labels are intended to appear "on top" of all rendered polygons.

  • Borders are drawn after each polygon "fill" is performed, so the border can modify the look of the fill. Borders are rendered with inner, outer, then direct border, in that order. The polygon area "fill" is also shrunk by the width defined by innerborder.lwd, unless innerborder is NA, so that the inner border does not affect the same region represented by the area fill.

  • Since polygons are drawn in the order they are provided by the JamPolygon object, one polygon may be drawn on top of another polygon, using default R methods to overlay one color onto another, for example with optional alpha transparency.

Rendering options recognized in jp@polygons:

  • name, label - name and display label. A label of NA or "" will not be rendered.

  • label_color - color used to render each polygon label.

  • family, fontsize - font family, and font point size used to render each polygon label, passed to grid::gpar() by default. Note that venndir() and render_venndir() may internally call marquee::marquee_grob() which does not use grid::gpar().

  • x, y - x- and y-coordinates to define each polygon or multipolygon. These columns are required for a JamPolygon object.

  • fill - polygon fill color, or NA for no fill color.

  • innerborder, innerborder.lwd - inner border and line width. The inner border is drawn inside the polygon absolute boundary.

  • outerborder, outerborder.lwd - inner border and line width The inner border is drawn outside the polygon absolute boundary.

  • border, border.lwd - border color and line width (outer border). The border is drawn on top of the polygon absolute boundary. Note that when two polygons share the same border, one border will necessarily overwrite the other. For this reason, the innerborder may be useful in order to preserve the color of each polygon border without overlap.

Return grobs

  • To return the list of grobs to be drawn without drawing them, use do_draw=FALSE, which also does not call grid::grid.newpage().

Todo

  1. Enable arguments in ... to override equivalent values in columns of jp@polygons. Partially complete.

  2. Convert grid rendering to generate graphical objects (grobs) which can be optionally rendered, or returned as a gTree. Mostly complete.

  3. Continue debugging the vwline graphical glitches which are apparent when rendering outer borders. Complete. See https://github.com/pmur002/vwline/issues/2.

    • Current recommendation is to render outer border after the inner border, and with outer border at least the same or larger width as the inner border. Otherwise, for acute angles, inner border may exceed the outer border because of its line width. However, if the outer border is drawn afterward, it will fully cover the inner border. With sufficiently small inner border width, the graphical glitch may not be apparent.

  4. Consider allowing labels for each multi-part polygon. Low priotity.

  5. Consider drawing optional x- and y-axis, although both could be added using grid functions. Low priority.

  6. Consider using different approach than "snpc" to enforce aspect ratio, for example ggplot2 uses respect=TRUE then leaves the x/y axis ranges intact. Making that change would affect other venndir functions that may assume scaled units are between 0 and 1.

Examples

dfx <- data.frame(name=c("polygon1", "polygon2"),
   x=I(list(
      list(c(1, 4, 4, 1),
         c(2, 3, 3, 2)),
      c(5, 6, 6, 5))),
   y=I(list(
      list(c(1, 1, 4, 4),
         c(2, 2, 3, 3)),
      c(1, 1, 2, 2))),
   fill=c("gold", "firebrick"))
jpx <- new("JamPolygon", polygons=dfx);
plot(jpx);


# if you want to add to the plot, you must capture output
# to use the viewport
jpxout <- plot(jpx);
vp <- attr(jpxout, "viewport");
adjx <- attr(jpxout, "adjx");
adjy <- attr(jpxout, "adjy");
grid::grid.path(x=adjx(c(4, 5, 5, 4) + 0.5),
   y=adjy(c(3, 3, 4, 4)),
   vp=vp,
   gp=grid::gpar(fill="purple", col="red1", lwd=2),
   default.units="snpc")
grid::grid.text(x=adjx(5), y=adjy(3.5),
   label="new grob",
   vp=vp,
   gp=grid::gpar(col="yellow", fontsize=20),
   default.units="snpc")


dfz <- data.frame(name=c("polygon1", "polygon2", "polygon3"),
   x=I(list(
      list(c(1, 4, 4, 1),
         c(2, 3, 3, 2)),
      list(c(4.5, 6.5, 6.5, 4.5),
         c(5, 6, 6, 5)),
      list(c(1, 4, 4, 1),
         c(2, 3, 3, 2),
         c(5, 6, 6, 5)))),
   y=I(list(
      list(c(1, 1, 4, 4),
         c(2, 2, 3, 3)),
      list(c(1, 1, 3, 3),
         c(3, 3, 4, 4)+0.5),
      list(c(5, 5, 8, 8),
         c(6, 6, 7, 7),
         c(6, 6, 7, 7)))),
   fill=c("gold", "firebrick", "dodgerblue"));
jpz <- new("JamPolygon", polygons=dfz);
jpz@polygons[, c("label_x", "label_y")] <- as.data.frame(labelr_JamPolygon(jpz))
jpz@polygons$outerborder <- c("orange", "gold", "purple");
jpz@polygons$outerborder.lwd <- 0;
jpz@polygons$outerborder.lwd <- c(3, 4, 5);
jpz@polygons$innerborder <- c("orange4", "gold3", "purple4");
jpz@polygons$innerborder.lwd <- c(3, 4, 5);
jpz@polygons$border.lwd <- 1;
jpz@polygons$border.lty <- 2;
#jpz <- add_orientation_JamPolygon(jpz);
plot(jpz);