Title: | Flexible Segment Geoms with Arrows for 'ggplot2' |
---|---|
Description: | Geoms for placing arrowheads at multiple points along a segment, not just at the end; position function to shift starts and ends of arrows to avoid exactly intersecting points. |
Authors: | Matthew Hall [aut, cre] |
Maintainer: | Matthew Hall <[email protected]> |
License: | GPL-3 |
Version: | 0.4.3 |
Built: | 2024-11-22 03:51:03 UTC |
Source: | https://github.com/mdhall272/ggarchery |
ggplot2::draw_key_path
and displays all the requested arrowheads.This function replaces ggplot2::draw_key_path
and displays all the requested arrowheads.
draw_key_arrowpath(data, params, size)
draw_key_arrowpath(data, params, size)
data |
A single row data frame containing the scaled aesthetics to display in this key |
params |
A list of additional parameters supplied to the geom. |
size |
Width and height of key in mm. |
A grid grob.
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_segment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow = arrow(), key_glyph = draw_key_arrowpath)
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_segment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow = arrow(), key_glyph = draw_key_arrowpath)
The basic geom_arrowsegment()
is equivalent to geom_segment(arrow = arrow())
.
(It is assumed that the user wants some kind of arrow.) The extended functionality
is to allow free placement of the arrowhead anywhere along the segment, and also
multiple arrowheads, and to allow a fill aesthetic (which will only be visible for
closed arrowheads).
The function works by dividing the line up into 1 or more segment grobs, each of
which is generated by grid::arrow()
except potentially the last (the one closest
to the point (xend
, yend
)). The vector arrow_positions
, whose entries must
lie between 0 and 1, defines where each arrow segment ends, as a proportional
position along the line. If the last entry of arrow_positions
is 1, then the last
grob has an arrow; otherwise it does not.
The function is designed with the expectation that arrows point from (x
, y
) to
(xend
, yend
) but the arrows
argument will happily accept arrow(ends = "first")
or arrow(ends = "both")
if you prefer. Just remember that the final segment is
only an arrow at all if the last entry of arrow_positions
is 1.
geom_arrowsegment( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., arrows = list(arrow()), arrow_fills = NULL, arrow_positions = 1, lineend = "butt", linejoin = "round", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
geom_arrowsegment( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., arrows = list(arrow()), arrow_fills = NULL, arrow_positions = 1, lineend = "butt", linejoin = "round", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
mapping |
Set of aesthetic mappings created by |
data |
The data to be displayed in this layer. There are three options: If A A |
stat |
The statistical transformation to use on the data for this
layer, either as a |
position |
Position adjustment, either as a string naming the adjustment
(e.g. |
... |
Other arguments passed on to |
arrows |
Either an arrow generated by |
arrow_fills |
A vector of fill colours for the arrowheads, behaves as
the |
arrow_positions |
A vector of distinct points on the unit interval. 0 is not
permitted but arbitrarily small values are; 1 is permitted. The default behaviour is that
arrowheads will be placed proportionally along the line connecting ( |
lineend |
Line end style (round, butt, square). |
linejoin |
Line join style (round, mitre, bevel). |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
A ggproto object
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) # Default behaviour ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end)) # Midpoint arrowheads ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = 0.5) # Double arrows ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 0.75)) # Double arrows, last arrowhead at the end point ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 1)) # Double arrowheads of varying appearance and position ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 0.75), arrows = list(arrow(angle = 45, type = "closed"), arrow(angle = 25, ends = "both")), arrow_fills = "indianred")
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) # Default behaviour ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end)) # Midpoint arrowheads ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = 0.5) # Double arrows ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 0.75)) # Double arrows, last arrowhead at the end point ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 1)) # Double arrowheads of varying appearance and position ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), arrow_positions = c(0.25, 0.75), arrows = list(arrow(angle = 45, type = "closed"), arrow(angle = 25, ends = "both")), arrow_fills = "indianred")
This position function is primarily intended for use with ggplot2::geom_segment()
or geom_arrowsegment()
,
and solves the problem that the user may, for reasons of clarity or aesthetics, not want their arrows to actually
start or end at the position that they are "pointing from" or "pointing to". It works by shifting the points towards
each other along the line joining them, by either a proportional amount or a fixed distance.
position_attractsegment( start_shave = 0, end_shave = 0, type_shave = c("proportion", "distance") )
position_attractsegment( start_shave = 0, end_shave = 0, type_shave = c("proportion", "distance") )
start_shave , end_shave
|
The amount of distance to "shave" off the line between ( |
type_shave |
If |
A ggproto object
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) # Ten percent off the start and end ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), position = position_attractsegment(start_shave = 0.1, end_shave = 0.1)) # Absolute distance of 0.02 at the end only ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), position = position_attractsegment(end_shave = 0.02, type_shave = "distance")) + coord_fixed()
library(ggplot2) library(magrittr) library(tidyr) # Generate some dummy data ten.points <- data.frame(line.no = rep(1:5, each = 2), x = runif(10), y = runif(10), position = rep(c("start", "end"), 5)) five.segments <- ten.points %>% pivot_wider(names_from = position, values_from = c(x,y)) # Ten percent off the start and end ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), position = position_attractsegment(start_shave = 0.1, end_shave = 0.1)) # Absolute distance of 0.02 at the end only ggplot(five.segments) + geom_point(data = ten.points, aes(x = x, y = y)) + geom_arrowsegment(aes(x = x_start, xend = x_end, y = y_start, yend = y_end), position = position_attractsegment(end_shave = 0.02, type_shave = "distance")) + coord_fixed()