├── .DS_Store ├── .Rbuildignore ├── .covrignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── R ├── Hypotrochoid.R ├── aaa.R ├── epitrochoid.R ├── ggpronto-classes.R ├── lissajous.R ├── rose.R ├── shape.R └── star.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── cran-comments.md ├── ggshapes.Rproj └── man ├── example.gif ├── figures ├── README-example-1.png ├── README-unnamed-chunk-2-1.png ├── README-unnamed-chunk-3-1.png ├── README-unnamed-chunk-4-1.png └── README-unnamed-chunk-5-1.png ├── geom_epitrochoid.Rd ├── geom_hypotrochoid.Rd ├── geom_lissajous.Rd ├── geom_rose.Rd ├── geom_star.Rd ├── ggshapes-extensions.Rd ├── rotate_df.Rd └── weave.Rd /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/.DS_Store -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^cran-comments\.md$ 2 | ^\.covrignore$ 3 | ^codecov\.yml$ 4 | ^\.travis\.yml$ 5 | ^README\.Rmd$ 6 | ^LICENSE\.md$ 7 | ^ggshapes\.Rproj$ 8 | ^\.Rproj\.user$ 9 | ^_pkgdown\.yml$ 10 | -------------------------------------------------------------------------------- /.covrignore: -------------------------------------------------------------------------------- 1 | R/deprec-*.R 2 | R/compat-*.R 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | cache: packages 5 | 6 | r_github_packages: 7 | - r-lib/pkgdown 8 | 9 | matrix: 10 | include: 11 | - r: devel 12 | - r: release 13 | after_success: 14 | - Rscript -e 'covr::codecov()' 15 | 16 | deploy: 17 | provider: script 18 | script: Rscript -e 'pkgdown::deploy_site_github(verbose = TRUE, run_dont_run = TRUE)' 19 | skip_cleanup: true 20 | - r: oldrel 21 | - r: 3.3 22 | - r: 3.2 23 | - r: 3.1 24 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggshapes 2 | Title: Adds Geoms That Produces Shapes And Curves 3 | Version: 0.0.0.9000 4 | Authors@R: 5 | person(given = "Emil", 6 | family = "Hvitfeldt", 7 | role = c("aut", "cre"), 8 | email = "emilhhvitfeldt@gmail.com") 9 | Description: This will add various practical and impractical shapes to be 10 | produced in 'ggplot2'. These shapes and curves will complement the 11 | circle and regular polygon geoms in the 'ggforce' package. 12 | URL: https://github.com/EmilHvitfeldt/ggshapes 13 | BugReports: https://github.com/EmilHvitfeldt/ggshapes/issues 14 | License: MIT + file LICENSE 15 | Encoding: UTF-8 16 | LazyData: true 17 | Depends: 18 | ggplot2 (>= 2.2.0), 19 | R (>= 3.1) 20 | RoxygenNote: 6.1.1 21 | Suggests: 22 | covr 23 | Imports: 24 | tidyr 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Emil Hvitfeldt 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Emil Hvitfeldt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(GeomShape) 4 | export(StatEpitrochoid) 5 | export(StatHypotrochoid) 6 | export(StatLissajous) 7 | export(StatRose) 8 | export(StatStar) 9 | export(geom_epitrochoid) 10 | export(geom_hypotrochoid) 11 | export(geom_lissajous) 12 | export(geom_rose) 13 | export(geom_star) 14 | export(stat_epitrochoid) 15 | export(stat_hypotrochoid) 16 | export(stat_lissajous) 17 | export(stat_rose) 18 | export(stat_star) 19 | importFrom(ggplot2,Stat) 20 | importFrom(ggplot2,aes) 21 | importFrom(ggplot2,ggproto) 22 | importFrom(ggplot2,layer) 23 | -------------------------------------------------------------------------------- /R/Hypotrochoid.R: -------------------------------------------------------------------------------- 1 | #' Draw a rose or Hypotrochoid curve 2 | #' 3 | #' This geom allows you to draw the hypotrochoid curve. A hypotrochoid is a 4 | #' curve traced by a point attached to a circle of radius r_min rolling around 5 | #' the inside of a fixed circle of radius r_max, where the point is at a 6 | #' distance h from the center of the interior circle. 7 | #' 8 | #' To unscale the curve, please set xscale and yscale to abs(r_max - r_min) + h. 9 | #' 10 | #' The curve follows the the parameterized form 11 | #' 12 | #' \deqn{x = (r_max - r_min) cos(\theta) + h * cos(\frac{r_max - r_min}{r_min} \theta)} 13 | #' \deqn{x = (r_max - r_min) sin(\theta) + h * sin(\frac{r_max - r_min}{r_min} \theta)} 14 | #' 15 | #' these curves are closed when the radion \eqn{a / b} is rational. delta have 16 | #' been scaled to be in the interval [0, 1]. 17 | #' 18 | #' @references \url{https://en.wikipedia.org/wiki/Hypocycloid} 19 | #' \url{http://xahlee.info/SpecialPlaneCurves_dir/Hypotrochoid_dir/hypotrochoid.html} 20 | #' @section Aesthetics: 21 | #' geom_arc understand the following aesthetics (required aesthetics are in 22 | #' bold): 23 | #' 24 | #' - **r_max** 25 | #' - **r_min** 26 | #' - h 27 | #' - x0 28 | #' - y0 29 | #' - xscale 30 | #' - yscale 31 | #' - rotation 32 | #' - color 33 | #' - fill 34 | #' - size 35 | #' - linetype 36 | #' - alpha 37 | #' - lineend 38 | #' 39 | #' @section Computed variables: 40 | #' 41 | #' \describe{ 42 | #' \item{x, y}{The coordinates for the points along the rose curve} 43 | #' } 44 | #' 45 | #' @inheritParams ggplot2::geom_path 46 | #' @inheritParams ggplot2::stat_identity 47 | #' 48 | #' @param n_points The number of points to sample along the curve. 49 | #' 50 | #' @author Emil Hvitfeldt 51 | #' 52 | #' @name geom_hypotrochoid 53 | #' @rdname geom_hypotrochoid 54 | #' @seealso [geom_epitrochoid()] 55 | #' 56 | #' @examples 57 | #' 58 | #' # When h is missing a hypocycloid is generated 59 | #' ggplot() + 60 | #' geom_hypotrochoid(aes(r_max = 4, r_min = 1)) 61 | #' 62 | #' ggplot() + 63 | #' geom_hypotrochoid(aes(r_max = 8, r_min = 1)) 64 | #' 65 | #' ggplot() + 66 | #' geom_hypotrochoid(aes(r_max = c(4, 6, 8), r_min = 1)) 67 | #' 68 | #' # specifying h 69 | #' ggplot() + 70 | #' geom_hypotrochoid(aes(r_max = 4, r_min = 9, h = 4)) 71 | #' 72 | #' ggplot() + 73 | #' geom_hypotrochoid(aes(r_max = 4, r_min = 3, h = 20 / 13)) 74 | #' 75 | #' # changing rotation 76 | #' ggplot() + 77 | #' geom_hypotrochoid(aes(r_max = 4, r_min = 1, rotation = pi / 4)) 78 | #' 79 | #' # When things go wild 80 | #' ggplot(expand.grid(seq(4, 20, by = 2), c(1, 3, 5, 9))) + 81 | #' geom_hypotrochoid(aes(r_max = Var1, r_min = Var2, color = Var1, 82 | #' xscale = abs(Var1 - Var2) + Var2, 83 | #' yscale = abs(Var1 - Var2) + Var2)) + 84 | #' coord_fixed() + 85 | #' theme_minimal() + 86 | #' scale_color_viridis_c(option = "B") + 87 | #' guides(color = "none") + 88 | #' facet_wrap(~ Var2) 89 | NULL 90 | 91 | #' @rdname ggshapes-extensions 92 | #' @format NULL 93 | #' @usage NULL 94 | #' @importFrom ggplot2 ggproto Stat aes 95 | #' @export 96 | StatHypotrochoid <- ggproto('StatHypotrochoid', Stat, 97 | compute_layer = function(self, data, params, layout) { 98 | if (is.null(data)) return(data) 99 | if (is.null(data$x0)) data$x0 <- 0 100 | if (is.null(data$y0)) data$y0 <- 0 101 | if (is.null(data$xscale)) data$xscale <- 1 102 | if (is.null(data$yscale)) data$yscale <- 1 103 | if (is.null(data$h)) data$h <- data$r_min 104 | if (is.null(data$rotation)) data$rotation <- 0 105 | data$group <- seq_len(nrow(data)) 106 | 107 | data <- tidyr::nest(data, r_min, r_max, h, x0, y0, xscale, yscale, rotation) 108 | data$data <- lapply(data$data, hypotrochoid_calc, params = params) 109 | tidyr::unnest(data) 110 | }, 111 | required_aes = c('r_min', 'r_max'), 112 | default_aes = aes(x0 = 0, y0 = 0, h = NULL, xscale = 1, yscale = 1, rotation = 0), 113 | extra_params = c('n_points', 'na.rm') 114 | ) 115 | 116 | hypotrochoid_calc <- function(data, params) { 117 | t <- seq(from = 0, to = 2 * pi * data$r_min, length.out = params$n_points) 118 | 119 | out <- data.frame( 120 | x = data$x0 + data$xscale * ((data$r_max - data$r_min) * cos(t) + 121 | data$h * cos((data$r_max - data$r_min) / data$r_min * t)) / (abs(data$r_max - data$r_min) + data$h), 122 | y = data$y0 + data$yscale * ((data$r_max - data$r_min) * sin(t) - 123 | data$h * sin((data$r_max - data$r_min) / data$r_min * t)) / (abs(data$r_max - data$r_min) + data$h) 124 | ) 125 | 126 | rotate_df(out, data$rotation) 127 | } 128 | 129 | #' @rdname geom_hypotrochoid 130 | #' @importFrom ggplot2 layer 131 | #' @export 132 | stat_hypotrochoid <- function(mapping = NULL, data = NULL, geom = "hypotrochoid", 133 | position = "identity", n_points = 360, na.rm = FALSE, show.legend = NA, 134 | inherit.aes = TRUE, ...) { 135 | layer( 136 | stat = StatHypotrochoid, data = data, mapping = mapping, geom = geom, 137 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 138 | params = list(na.rm = na.rm, n_points = n_points, ...) 139 | ) 140 | } 141 | 142 | #' @rdname geom_hypotrochoid 143 | #' @importFrom ggplot2 layer 144 | #' @export 145 | geom_hypotrochoid <- function(mapping = NULL, data = NULL, stat = "hypotrochoid", 146 | position = "identity", n_points = 360, na.rm = FALSE, 147 | show.legend = NA, inherit.aes = TRUE, ...) { 148 | layer(data = data, mapping = mapping, stat = stat, geom = GeomShape, 149 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 150 | params = list(n_points = n_points, na.rm = na.rm, ...)) 151 | } 152 | -------------------------------------------------------------------------------- /R/aaa.R: -------------------------------------------------------------------------------- 1 | #' Weaves two vectors together using alternating indecies 2 | #' 3 | #' @param a Vector 4 | #' @param b Vector 5 | 6 | #' @return A vector 7 | weave <- function(a, b) { 8 | x <- vector(class(a), length(c(a, b))) 9 | x[c(TRUE, FALSE)] <- a 10 | x[c(FALSE, TRUE)] <- b 11 | x 12 | } 13 | 14 | #' Rotates a parametric data.frame 15 | #' 16 | #' @param df a data frame with two columns x and y 17 | #' @param theta a numeric denoting the amount of rotation 18 | #' 19 | #' @return a data frame with two columns x and y 20 | rotate_df <- function(df, theta) { 21 | if (theta %% (pi * 2) == 0) { 22 | return(df) 23 | } 24 | out <- df 25 | out$x <- df$x * cos(theta) - df$y * sin(theta) 26 | out$y <- df$x * sin(theta) + df$y * cos(theta) 27 | out 28 | } 29 | -------------------------------------------------------------------------------- /R/epitrochoid.R: -------------------------------------------------------------------------------- 1 | #' Draw a rose or Epitrochoid curve 2 | #' 3 | #' This geom allows you to draw the epitrochoid curve. A epitrochoid is a 4 | #' curve traced by a point attached to a circle of radius r_min rolling around 5 | #' the outside of a fixed circle of radius r_max, where the point is at a 6 | #' distance h from the center of the interior circle. h is the same as r_min 7 | #' by default. 8 | #' 9 | #' To unscale the curve, please set xscale and yscale to r_max + r_min + h. 10 | #' 11 | #' The curve follows the the parameterized form 12 | #' 13 | #' \deqn{x = (r_max + r_min) cos(\theta) - h * cos(\frac{r_max + r_min}{r_min} \theta)} 14 | #' \deqn{x = (r_max + r_min) sin(\theta) - h * sin(\frac{r_max + r_min}{r_min} \theta)} 15 | #' 16 | #' these curves are closed when the radion \eqn{a / b} is rational. delta have 17 | #' been scaled to be in the interval [0, 1]. 18 | #' 19 | #' @references \url{http://mathworld.wolfram.com/Epitrochoid.html} 20 | #' \url{http://xahlee.info/SpecialPlaneCurves_dir/Epitrochoid_dir/epitrochoid.html} 21 | #' @section Aesthetics: 22 | #' geom_arc understand the following aesthetics (required aesthetics are in 23 | #' bold): 24 | #' 25 | #' - **r_max** 26 | #' - **r_min** 27 | #' - h 28 | #' - x0 29 | #' - y0 30 | #' - xscale 31 | #' - yscale 32 | #' - rotation 33 | #' - color 34 | #' - fill 35 | #' - size 36 | #' - linetype 37 | #' - alpha 38 | #' - lineend 39 | #' 40 | #' @section Computed variables: 41 | #' 42 | #' \describe{ 43 | #' \item{x, y}{The coordinates for the points along the rose curve} 44 | #' } 45 | #' 46 | #' @inheritParams ggplot2::geom_path 47 | #' @inheritParams ggplot2::stat_identity 48 | #' 49 | #' @param n_points The number of points to sample along the curve. 50 | #' 51 | #' @author Emil Hvitfeldt 52 | #' 53 | #' @name geom_epitrochoid 54 | #' @rdname geom_epitrochoid 55 | #' @seealso [geom_hypotrochoid()] 56 | #' 57 | #' @examples 58 | #' 59 | #' # When h is missing a hypocycloid is generated 60 | #' ggplot() + 61 | #' geom_epitrochoid(aes(r_max = 4, r_min = 1)) 62 | #' 63 | #' ggplot() + 64 | #' geom_epitrochoid(aes(r_max = 8, r_min = 1)) 65 | #' 66 | #' ggplot() + 67 | #' geom_epitrochoid(aes(r_max = c(4, 6, 8), r_min = 1)) 68 | #' 69 | #' # specifying h 70 | #' ggplot() + 71 | #' geom_epitrochoid(aes(r_max = 4, r_min = 1, h = 4)) 72 | #' 73 | #' ggplot() + 74 | #' geom_epitrochoid(aes(r_max = 4, r_min = 3, h = 20 / 13)) 75 | #' 76 | #' # Changing the horizontal and vertical scale 77 | #' 78 | #' ggplot() + 79 | #' geom_epitrochoid(aes(r_max = 4, r_min = 3, xscale = 10, yscale = 3)) 80 | #' 81 | #' # Rotating shape 82 | #' ggplot() + 83 | #' geom_epitrochoid(aes(r_max = 4, r_min = 3, rotation = pi / 4)) 84 | #' 85 | #' # When things go wild 86 | #' ggplot(expand.grid(seq(4, 20, by = 2), c(1, 3, 5, 9))) + 87 | #' geom_epitrochoid(aes(r_max = Var1, r_min = Var2, color = Var1, 88 | #' xscale = Var1 + Var2, yscale = Var1 + Var2)) + 89 | #' coord_fixed() + 90 | #' theme_minimal() + 91 | #' scale_color_viridis_c(option = "B") + 92 | #' guides(color = "none") + 93 | #' facet_wrap(~ Var2) 94 | NULL 95 | 96 | #' @rdname ggshapes-extensions 97 | #' @format NULL 98 | #' @usage NULL 99 | #' @importFrom ggplot2 ggproto Stat aes 100 | #' @export 101 | StatEpitrochoid <- ggproto('StatEpitrochoid', Stat, 102 | compute_layer = function(self, data, params, layout) { 103 | 104 | if (is.null(data)) return(data) 105 | if (is.null(data$x0)) data$x0 <- 0 106 | if (is.null(data$y0)) data$y0 <- 0 107 | if (is.null(data$xscale)) data$xscale <- 1 108 | if (is.null(data$yscale)) data$yscale <- 1 109 | if (is.null(data$h)) data$h <- data$r_min 110 | if (is.null(data$rotation)) data$rotation <- 0 111 | data$group <- seq_len(nrow(data)) 112 | 113 | data <- tidyr::nest(data, r_min, r_max, h, x0, y0, xscale, yscale, rotation) 114 | data$data <- lapply(data$data, epitrochoid_calc, params = params) 115 | tidyr::unnest(data) 116 | }, 117 | required_aes = c('r_min', 'r_max'), 118 | default_aes = aes(x0 = 0, y0 = 0, h = NULL, xscale = 1, yscale = 1, rotation = 0), 119 | extra_params = c('n_points', 'na.rm') 120 | ) 121 | 122 | epitrochoid_calc <- function(data, params) { 123 | t <- seq(from = 0, to = 2 * pi * data$r_min, length.out = params$n_points) 124 | 125 | out <- data.frame( 126 | x = data$x0 + data$xscale * ((data$r_max + data$r_min) * cos(t) - 127 | data$h * cos((data$r_max + data$r_min) / data$r_min * t)) / (data$r_max + data$r_min + data$h), 128 | y = data$y0 + data$yscale * ((data$r_max + data$r_min) * sin(t) - 129 | data$h * sin((data$r_max + data$r_min) / data$r_min * t)) / (data$r_max + data$r_min + data$h) 130 | ) 131 | 132 | rotate_df(out, data$rotation) 133 | } 134 | 135 | #' @rdname geom_epitrochoid 136 | #' @importFrom ggplot2 layer 137 | #' @export 138 | stat_epitrochoid <- function(mapping = NULL, data = NULL, geom = "epitrochoid", 139 | position = "identity", n_points = 360, na.rm = FALSE, show.legend = NA, 140 | inherit.aes = TRUE, ...) { 141 | layer( 142 | stat = StatEpitrochoid, data = data, mapping = mapping, geom = geom, 143 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 144 | params = list(na.rm = na.rm, n_points = n_points, ...) 145 | ) 146 | } 147 | 148 | #' @rdname geom_epitrochoid 149 | #' @importFrom ggplot2 layer 150 | #' @export 151 | geom_epitrochoid <- function(mapping = NULL, data = NULL, stat = "epitrochoid", 152 | position = "identity", n_points = 360, na.rm = FALSE, 153 | show.legend = NA, inherit.aes = TRUE, ...) { 154 | layer(data = data, mapping = mapping, stat = stat, geom = GeomShape, 155 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 156 | params = list(n_points = n_points, na.rm = na.rm, ...)) 157 | } 158 | -------------------------------------------------------------------------------- /R/ggpronto-classes.R: -------------------------------------------------------------------------------- 1 | #' ggshapes extensions to ggplot2 2 | #' 3 | #' ggshapes makes heavy use of the ggproto class system to extend the 4 | #' functionality of ggplot2. In general the actual classes should be of little 5 | #' interest to users as the standard ggplot2 api of using geom_* and stat_* 6 | #' functions for building up the plot is encouraged. 7 | #' 8 | #' @name ggshapes-extensions 9 | #' @rdname ggshapes-extensions 10 | #' 11 | NULL 12 | -------------------------------------------------------------------------------- /R/lissajous.R: -------------------------------------------------------------------------------- 1 | #' Draw a rose or lissajous curve 2 | #' 3 | #' This geom allows you to draw the lissajous curve. 4 | #' 5 | #' The curve follows the the parameterized form 6 | #' 7 | #' \deqn{x = sin(a\theta + \delta)} 8 | #' \deqn{y = sin(b\theta)} 9 | #' 10 | #' these curves are closed when the radion \eqn{a / b} is rational. delta have 11 | #' been scaled to be in the interval [0, 1]. 12 | #' 13 | #' @references \url{https://en.wikipedia.org/wiki/Lissajous_curve} 14 | #' @section Aesthetics: 15 | #' geom_arc understand the following aesthetics (required aesthetics are in 16 | #' bold): 17 | #' 18 | #' - **a** 19 | #' - **b** 20 | #' - **delta** 21 | #' - x0 22 | #' - y0 23 | #' - xscale 24 | #' - yscale 25 | #' - rotation 26 | #' - color 27 | #' - fill 28 | #' - size 29 | #' - linetype 30 | #' - alpha 31 | #' - lineend 32 | #' 33 | #' @section Computed variables: 34 | #' 35 | #' \describe{ 36 | #' \item{x, y}{The coordinates for the points along the rose curve} 37 | #' } 38 | #' 39 | #' @inheritParams ggplot2::geom_path 40 | #' @inheritParams ggplot2::stat_identity 41 | #' 42 | #' @param n_points The number of points to sample along the curve. 43 | #' 44 | #' @author Emil Hvitfeldt 45 | #' 46 | #' @name geom_lissajous 47 | #' @rdname geom_lissajous 48 | #' 49 | #' @examples 50 | #' ggplot() + 51 | #' geom_lissajous(aes(a = 5, b = 4, delta = 2)) 52 | #' 53 | #' ggplot() + 54 | #' geom_lissajous(aes(a = 2, b = 3, delta = 1)) 55 | #' 56 | #' ggplot() + 57 | #' geom_lissajous(aes(a = 1:3, b = 3, delta = 1, x0 = c(1, 4, 7))) 58 | #' 59 | #' # Scaling shapes 60 | #' ggplot() + 61 | #' geom_lissajous(aes(a = 2, b = 3, delta = 1, xscale = 5, yscale = 2)) 62 | #' 63 | #' # Rotation shapes 64 | #' ggplot() + 65 | #' geom_lissajous(aes(a = 2, b = 3, delta = 1, rotation = pi / 4)) 66 | #' 67 | NULL 68 | 69 | #' @rdname ggshapes-extensions 70 | #' @format NULL 71 | #' @usage NULL 72 | #' @importFrom ggplot2 ggproto Stat aes 73 | #' @export 74 | StatLissajous <- ggproto('StatLissajous', Stat, 75 | compute_layer = function(self, data, params, layout) { 76 | if (is.null(data)) return(data) 77 | if (is.null(data$x0)) data$x0 <- 0 78 | if (is.null(data$y0)) data$y0 <- 0 79 | if (is.null(data$xscale)) data$xscale <- 1 80 | if (is.null(data$yscale)) data$yscale <- 1 81 | if (is.null(data$rotation)) data$rotation <- 0 82 | data$group <- seq_len(nrow(data)) 83 | 84 | data <- tidyr::nest(data, a, b, delta, x0, y0, xscale, yscale, rotation) 85 | data$data <- lapply(data$data, lissajous_calc, params = params) 86 | tidyr::unnest(data) 87 | }, 88 | required_aes = c('a', 'b', 'delta'), 89 | default_aes = aes(x0 = 0, y0 = 0, xscale = 1, yscale = 1, rotation = 0), 90 | extra_params = c('n_points', 'na.rm') 91 | ) 92 | 93 | lissajous_calc <- function(data, params) { 94 | t <- seq(from = 0, to = 2 * pi, length.out = params$n_points) 95 | 96 | out <- data.frame( 97 | x = data$x0 + data$xscale * sin(data$a * t + data$delta * pi), 98 | y = data$y0 + data$yscale * sin(data$b * t) 99 | ) 100 | 101 | rotate_df(out, data$rotation) 102 | } 103 | 104 | #' @rdname geom_lissajous 105 | #' @importFrom ggplot2 layer 106 | #' @export 107 | stat_lissajous <- function(mapping = NULL, data = NULL, geom = "lissajous", 108 | position = "identity", n_points = 360, na.rm = FALSE, show.legend = NA, 109 | inherit.aes = TRUE, ...) { 110 | layer( 111 | stat = StatLissajous, data = data, mapping = mapping, geom = geom, 112 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 113 | params = list(na.rm = na.rm, n_points = n_points, ...) 114 | ) 115 | } 116 | 117 | #' @rdname geom_lissajous 118 | #' @importFrom ggplot2 layer 119 | #' @export 120 | geom_lissajous <- function(mapping = NULL, data = NULL, stat = "lissajous", 121 | position = "identity", n_points = 360, na.rm = FALSE, 122 | show.legend = NA, inherit.aes = TRUE, ...) { 123 | layer(data = data, mapping = mapping, stat = stat, geom = GeomShape, 124 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 125 | params = list(n_points = n_points, na.rm = na.rm, ...)) 126 | } 127 | -------------------------------------------------------------------------------- /R/rose.R: -------------------------------------------------------------------------------- 1 | #' Draw a rose or rhodonea curve 2 | #' 3 | #' This geom allows you to draw mathematical roses. A rose is a sinusoid 4 | #' plotted in polar coordinates. 5 | #' 6 | #' the shape follows the following parameterized form 7 | #' 8 | #' \deqn{x = (cos(k\theta) + c)cos(\theta)} 9 | #' \deqn{y = (cos(k\theta) + c)sin(\theta)} 10 | #' 11 | #' where 12 | #' 13 | #' \deqn{k = n / d} 14 | #' 15 | #' the rose will be a closed loop when k is rational. this can easily be 16 | #' achived by keeping n and d whole numbers. c is the internal offset parameter 17 | #' changing how much the flower spreads out. 18 | #' 19 | #' @references \url{https://en.wikipedia.org/wiki/Rose_(mathematics)} 20 | #' @section Aesthetics: 21 | #' geom_arc understand the following aesthetics (required aesthetics are in 22 | #' bold): 23 | #' 24 | #' - **n** 25 | #' - **d** 26 | #' - **c** 27 | #' - x0 28 | #' - y0 29 | #' - xscale 30 | #' - yscale 31 | #' - rotation 32 | #' - color 33 | #' - fill 34 | #' - size 35 | #' - linetype 36 | #' - alpha 37 | #' - lineend 38 | #' 39 | #' @section Computed variables: 40 | #' 41 | #' \describe{ 42 | #' \item{x, y}{The coordinates for the points along the rose curve} 43 | #' } 44 | #' 45 | #' @inheritParams ggplot2::geom_path 46 | #' @inheritParams ggplot2::stat_identity 47 | #' 48 | #' @param n_points The number of points to sample along the curve. 49 | #' 50 | #' @author Emil Hvitfeldt 51 | #' 52 | #' @name geom_rose 53 | #' @rdname geom_rose 54 | #' 55 | #' @examples 56 | #' 57 | #' ggplot() + 58 | #' geom_rose(aes(n = 2, d = 1, c = 0)) 59 | #' 60 | #' ggplot() + 61 | #' geom_rose(aes(n = 2, d = 8, c = 0)) 62 | #' 63 | #' ggplot() + 64 | #' geom_rose(aes(n = 5, d = 4, c = 4)) 65 | #' 66 | #' # Rescaling 67 | #' ggplot() + 68 | #' geom_rose(aes(n = 5, d = 4, c = 4, xscale = 6, yscale = 2)) 69 | #' 70 | #' # Rotation 71 | #' ggplot() + 72 | #' geom_rose(aes(n = 2, d = 1, c = 0, rotation = pi / 4)) 73 | #' 74 | #' # Multiple roses 75 | #' ggplot() + 76 | #' geom_rose(aes(n = 5:1, d = 1:5, c = 0, x0 = 1:5 * 3)) 77 | #' 78 | #' ggplot() + 79 | #' geom_rose(aes(n = 5, d = 4, c = 4), fill = "white") 80 | NULL 81 | 82 | #' @rdname ggshapes-extensions 83 | #' @format NULL 84 | #' @usage NULL 85 | #' @importFrom ggplot2 ggproto Stat aes 86 | #' @export 87 | StatRose <- ggproto('StatRose', Stat, 88 | compute_layer = function(self, data, params, layout) { 89 | if (is.null(data)) return(data) 90 | if (is.null(data$x0)) data$x0 <- 0 91 | if (is.null(data$y0)) data$y0 <- 0 92 | if (is.null(data$xscale)) data$xscale <- 1 93 | if (is.null(data$yscale)) data$yscale <- 1 94 | if (is.null(data$rotation)) data$rotation <- 0 95 | data$group <- seq_len(nrow(data)) 96 | 97 | data <- tidyr::nest(data, n, d, c, x0, y0, xscale, yscale, rotation) 98 | data$data <- lapply(data$data, rose_calc, params = params) 99 | tidyr::unnest(data) 100 | }, 101 | required_aes = c('n', 'd', 'c'), 102 | default_aes = aes(x0 = 0, y0 = 0, xscale = 1, yscale = 1, rotation = 0), 103 | extra_params = c('n_points', 'na.rm') 104 | ) 105 | 106 | rose_calc <- function(data, params) { 107 | k <- data$n / data$d 108 | theta <- seq(from = 0, to = 2 * pi * data$d, length.out = params$n_points) 109 | 110 | out <- data.frame( 111 | x = data$x0 + data$xscale * (cos(k * theta) + data$c) * cos(theta) / (1 + data$c), 112 | y = data$y0 + data$yscale * (cos(k * theta) + data$c) * sin(theta) / (1 + data$c) 113 | ) 114 | 115 | rotate_df(out, data$rotation) 116 | } 117 | 118 | 119 | #' @rdname geom_rose 120 | #' @importFrom ggplot2 layer 121 | #' @export 122 | stat_rose <- function(mapping = NULL, data = NULL, geom = "rose", 123 | position = "identity", n_points = 360, na.rm = FALSE, 124 | show.legend = NA, inherit.aes = TRUE, ...) { 125 | layer( 126 | stat = StatRose, data = data, mapping = mapping, geom = geom, 127 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 128 | params = list(na.rm = na.rm, n_points = n_points, ...) 129 | ) 130 | } 131 | 132 | #' @rdname geom_rose 133 | #' @importFrom ggplot2 layer 134 | #' @export 135 | geom_rose <- function(mapping = NULL, data = NULL, stat = "rose", 136 | position = "identity", n_points = 360, na.rm = FALSE, 137 | show.legend = NA, inherit.aes = TRUE, ...) { 138 | layer(data = data, mapping = mapping, stat = stat, geom = GeomShape, 139 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 140 | params = list(n_points = n_points, na.rm = na.rm, ...)) 141 | } 142 | -------------------------------------------------------------------------------- /R/shape.R: -------------------------------------------------------------------------------- 1 | #' @rdname ggshapes-extensions 2 | #' @format NULL 3 | #' @usage NULL 4 | #' @export 5 | GeomShape <- ggproto('GeomShape', GeomPolygon, 6 | default_aes = list( 7 | colour = 'black', 8 | fill = NA, 9 | size = 0.5, 10 | linetype = 1, 11 | alpha = NA 12 | ) 13 | ) 14 | -------------------------------------------------------------------------------- /R/star.R: -------------------------------------------------------------------------------- 1 | #' Draw a n pointed regular star 2 | #' 3 | #' This geom allows you to draw the star curve. 4 | #' 5 | #' @section Aesthetics: 6 | #' geom_arc understand the following aesthetics (required aesthetics are in 7 | #' bold): 8 | #' 9 | #' - **n_tips** 10 | #' - r_min 11 | #' - r_max 12 | #' - offset 13 | #' - x0 14 | #' - y0 15 | #' - xscale 16 | #' - yscale 17 | #' - rotation 18 | #' - color 19 | #' - fill 20 | #' - size 21 | #' - linetype 22 | #' - alpha 23 | #' - lineend 24 | #' 25 | #' @section Computed variables: 26 | #' 27 | #' \describe{ 28 | #' \item{x, y}{The coordinates for the points along the star curve} 29 | #' } 30 | #' 31 | #' @inheritParams ggplot2::geom_path 32 | #' @inheritParams ggplot2::stat_identity 33 | #' 34 | #' @param n_points The number of points to sample along the curve. 35 | #' 36 | #' @author Emil Hvitfeldt 37 | #' 38 | #' @name geom_star 39 | #' @rdname geom_star 40 | #' 41 | #' @examples 42 | #' # Changing number of tips 43 | #' ggplot() + 44 | #' geom_star(aes(n_tips = 5)) 45 | #' 46 | #' ggplot() + 47 | #' geom_star(aes(n_tips = 11)) 48 | #' 49 | #' # changing radei 50 | #' ggplot() + 51 | #' geom_star(aes(r_min = 0.2, r_max = 1, n_tips = 5)) 52 | #' 53 | #' ggplot() + 54 | #' geom_star(aes(r_min = 0.7, r_max = 1, n_tips = 5)) 55 | #' 56 | #' # rescaling 57 | #' ggplot() + 58 | #' geom_star(aes( n_tips = 5, xscale = 4, yscale = 2)) 59 | #' 60 | #' # Rotation 61 | #' ggplot() + 62 | #' geom_star(aes(n_tips = 5, rotation = pi / 4)) 63 | #' 64 | #' # Playing witn offset parameter 65 | #' ggplot() + 66 | #' geom_star(aes(n_tips = 5, offset = 0)) 67 | #' 68 | #' ggplot() + 69 | #' geom_star(aes(n_tips = 5, offset = 1)) 70 | #' 71 | #' ggplot() + 72 | #' geom_star(aes(n_tips = 11, offset = 5)) 73 | #' 74 | #' # Multiple stars 75 | #' ggplot() + 76 | #' geom_star(aes(n_tips = c(3, 5, 7), 77 | #' x0 = c(1, 4, 7), 78 | #' y0 = c(1, 4, 7))) 79 | #' 80 | #' # Regular polygons comes up as a special example when 81 | #' # r_max = r_min / cos(pi / n_tips) 82 | #' ggplot() + 83 | #' geom_star(aes(r_min = 0.5, r_max = 0.5 / cos(pi / 5), n_tips = 5)) 84 | NULL 85 | 86 | #' @rdname ggshapes-extensions 87 | #' @format NULL 88 | #' @usage NULL 89 | #' @importFrom ggplot2 ggproto Stat aes 90 | #' @export 91 | StatStar <- ggproto('StatStar', Stat, 92 | compute_layer = function(self, data, params, layout) { 93 | if (is.null(data)) return(data) 94 | if (is.null(data$x0)) data$x0 <- 0 95 | if (is.null(data$y0)) data$y0 <- 0 96 | if (is.null(data$xscale)) data$xscale <- 1 97 | if (is.null(data$yscale)) data$yscale <- 1 98 | if (is.null(data$offset)) data$offset <- 0.5 99 | if (is.null(data$r_max)) data$r_max <- 1 100 | if (is.null(data$r_min)) data$r_min <- 0.5 101 | if (is.null(data$rotation)) data$rotation <- 0 102 | data$group <- seq_len(nrow(data)) 103 | 104 | data <- tidyr::nest(data, r_min, r_max, n_tips, offset, x0, y0, xscale, yscale, rotation) 105 | data$data <- lapply(data$data, star_calc, params = params) 106 | tidyr::unnest(data) 107 | }, 108 | required_aes = c('n_tips'), 109 | default_aes = aes(x0 = 0, y0 = 0, offset = 0.5, xscale = 1, yscale = 1, 110 | r_max = 1, r_min = 0.5, rotation = 0), 111 | extra_params = c('n_points', 'na.rm') 112 | ) 113 | 114 | star_calc <- function(data, params) { 115 | theta <- seq(0, 2 * pi, length.out = data$n_tips + 1) + pi / 2 116 | theta_s <-seq(0, 2 * pi, length.out = data$n_tips + 1)[-1] + pi / 2 - 117 | pi / data$n_tips * 2 * data$offset 118 | 119 | out <- data.frame( 120 | x = data$x0 + data$xscale * weave(data$r_max * cos(theta), data$r_min * cos(theta_s)), 121 | y = data$y0 + data$yscale * weave(data$r_max * sin(theta), data$r_min * sin(theta_s)) 122 | ) 123 | 124 | rotate_df(out, data$rotation) 125 | } 126 | 127 | #' @rdname geom_star 128 | #' @importFrom ggplot2 layer 129 | #' @export 130 | stat_star <- function(mapping = NULL, data = NULL, geom = "star", 131 | position = "identity", n_points = 360, na.rm = FALSE, show.legend = NA, 132 | inherit.aes = TRUE, ...) { 133 | layer( 134 | stat = StatStar, data = data, mapping = mapping, geom = geom, 135 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 136 | params = list(na.rm = na.rm, n_points = n_points, ...) 137 | ) 138 | } 139 | 140 | #' @rdname geom_star 141 | #' @importFrom ggplot2 layer 142 | #' @export 143 | geom_star <- function(mapping = NULL, data = NULL, stat = "star", 144 | position = "identity", n_points = 360, na.rm = FALSE, 145 | show.legend = NA, inherit.aes = TRUE, ...) { 146 | layer(data = data, mapping = mapping, stat = stat, geom = GeomShape, 147 | position = position, show.legend = show.legend, inherit.aes = inherit.aes, 148 | params = list(n_points = n_points, na.rm = na.rm, ...)) 149 | } 150 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | 16 | 17 | # ggshapes 18 | 19 | 20 | [![Travis build status](https://travis-ci.org/EmilHvitfeldt/ggshapes.svg?branch=master)](https://travis-ci.org/EmilHvitfeldt/ggshapes) 21 | 22 | 23 | The goal of ggshapes is to add more shapes such and stars and other curves to ggplot2 the same way [ggforce](https://github.com/thomasp85/ggforce) adds regular polygons and circles. 24 | 25 | ## Installation 26 | 27 | You can install the released version of ggshapes from [CRAN](https://CRAN.R-project.org) with: 28 | 29 | ``` r 30 | # Not released yet 31 | install.packages("ggshapes") 32 | ``` 33 | 34 | And the development version from [GitHub](https://github.com/) with: 35 | 36 | ``` r 37 | # install.packages("devtools") 38 | devtools::install_github("EmilHvitfeldt/ggshapes") 39 | ``` 40 | 41 | ## Examples 42 | 43 | ggshapes provides many closed curves, one of which is the simple [rose](https://en.wikipedia.org/wiki/Rose_(mathematics)) curve. 44 | 45 | ```{r example} 46 | library(ggshapes) 47 | ggplot() + 48 | geom_rose(aes(n = 2, d = 1, c = 0)) 49 | ``` 50 | 51 | Each of these geoms comes with some tuning parameters that result in widely different curves so you should play around. 52 | 53 | ```{r} 54 | data <- data.frame(a = rep(1:6, times = 6), 55 | b = rep(1:6, each = 6), 56 | delta = 1) 57 | 58 | ggplot(data) + 59 | geom_lissajous(aes(a = a, b = b, delta = delta)) + 60 | facet_grid(a ~ b) + 61 | labs(title = "lissajous curves at varying values of a and b", x = "b", y = "a") + 62 | theme_minimal() + 63 | theme(axis.ticks.y = element_blank(), 64 | axis.text.y = element_blank(), 65 | axis.ticks.x = element_blank(), 66 | axis.text.x = element_blank()) 67 | ``` 68 | 69 | ggshapes doesn't natively work with [gganimate](https://github.com/thomasp85/gganimate) but gifs can be hacked together using [gifski](https://ropensci.org/technotes/2018/07/23/gifski-release/). 70 | 71 | ```{r, eval=FALSE} 72 | library(gifski) 73 | makeplot <- function(){ 74 | data <- expand.grid(tips = 2:10, time = seq(0, pi * 2, length.out = 50)[-1]) 75 | 76 | datalist <- split(data, data$time) 77 | lapply(datalist, function(data){ 78 | p <- ggplot(data) + 79 | geom_star(aes(n_tips = tips, rotation = time)) + 80 | coord_fixed() + 81 | theme_void() + 82 | xlim(-1, 1) + 83 | ylim(-1, 1) + 84 | facet_wrap(~tips) 85 | print(p) 86 | }) 87 | } 88 | 89 | gif_file <- save_gif(makeplot(), width = 800, height = 800, res = 200, delay = 0.01, gif_file = "man/example.gif") 90 | ``` 91 | 92 | ![](man/example.gif) 93 | 94 | ## Design choices 95 | 96 | All the geoms that produces closed curves (under certain choice of parameters) comes with a couple of geom specifit tuning parameters (`n`, `d` and `c` for `geom_star()`) and some shared aesthetics 97 | 98 | - x0 99 | - y0 100 | - xscale 101 | - yscale 102 | - rotation 103 | 104 | which denote the x and y coordinate of the center, the x and y scaling of the curve and its rotation in radians. By defaults the geoms produces curves bounded between -1 and 1, centered around (0, 0). Rotation is not applied by default. If rotation and scaling is applied then the curve will not be bounded anymore (as it retains its scale). 105 | 106 | ```{r} 107 | ggplot() + 108 | geom_rect(aes(xmin = -1, ymin = -1, xmax = 1, ymax = 1), fill = NA, color = "red", size = 1) + 109 | geom_lissajous(aes(a = 5, b = 4, delta = 2)) + 110 | theme_minimal() + 111 | coord_fixed() + 112 | labs(title = "The curve is bounded by the square going from (-1, -1) to (1, 1)") 113 | ``` 114 | 115 | ```{r} 116 | ggplot() + 117 | geom_rect(aes(xmin = -1, ymin = -1, xmax = 1, ymax = 1), fill = NA, color = "red", size = 1) + 118 | geom_lissajous(aes(a = 5, b = 4, delta = 2, rotation = pi / 7)) + 119 | theme_minimal() + 120 | coord_fixed() + 121 | labs(title = "Rotation will leave the curve at the same size") 122 | ``` 123 | 124 | ## Inspiration 125 | 126 | The original inspiration for this package came from the post [film flowers](http://bl.ocks.org/sxywu/raw/d612c6c653fb8b4d7ff3d422be164a5d/) by [Shirley Wu](https://twitter.com/sxywu) which drove me to the realization that such visualizations are quite the hassle to do in ggplot2 right now. 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # ggshapes 5 | 6 | 7 | 8 | [![Travis build 9 | status](https://travis-ci.org/EmilHvitfeldt/ggshapes.svg?branch=master)](https://travis-ci.org/EmilHvitfeldt/ggshapes) 10 | 11 | 12 | The goal of ggshapes is to add more shapes such and stars and other 13 | curves to ggplot2 the same way 14 | [ggforce](https://github.com/thomasp85/ggforce) adds regular polygons 15 | and circles. 16 | 17 | ## Installation 18 | 19 | You can install the released version of ggshapes from 20 | [CRAN](https://CRAN.R-project.org) with: 21 | 22 | ``` r 23 | # Not released yet 24 | install.packages("ggshapes") 25 | ``` 26 | 27 | And the development version from [GitHub](https://github.com/) with: 28 | 29 | ``` r 30 | # install.packages("devtools") 31 | devtools::install_github("EmilHvitfeldt/ggshapes") 32 | ``` 33 | 34 | ## Examples 35 | 36 | ggshapes provides many closed curves, one of which is the simple 37 | [rose](https://en.wikipedia.org/wiki/Rose_\(mathematics\)) curve. 38 | 39 | ``` r 40 | library(ggshapes) 41 | #> Loading required package: ggplot2 42 | ggplot() + 43 | geom_rose(aes(n = 2, d = 1, c = 0)) 44 | ``` 45 | 46 | 47 | 48 | Each of these geoms comes with some tuning parameters that result in 49 | widely different curves so you should play around. 50 | 51 | ``` r 52 | data <- data.frame(a = rep(1:6, times = 6), 53 | b = rep(1:6, each = 6), 54 | delta = 1) 55 | 56 | ggplot(data) + 57 | geom_lissajous(aes(a = a, b = b, delta = delta)) + 58 | facet_grid(a ~ b) + 59 | labs(title = "lissajous curves at varying values of a and b", x = "b", y = "a") + 60 | theme_minimal() + 61 | theme(axis.ticks.y = element_blank(), 62 | axis.text.y = element_blank(), 63 | axis.ticks.x = element_blank(), 64 | axis.text.x = element_blank()) 65 | ``` 66 | 67 | 68 | 69 | ggshapes doesn’t natively work with 70 | [gganimate](https://github.com/thomasp85/gganimate) but gifs can be 71 | hacked together using 72 | [gifski](https://ropensci.org/technotes/2018/07/23/gifski-release/). 73 | 74 | ``` r 75 | library(gifski) 76 | makeplot <- function(){ 77 | data <- expand.grid(tips = 2:10, time = seq(0, pi * 2, length.out = 50)[-1]) 78 | 79 | datalist <- split(data, data$time) 80 | lapply(datalist, function(data){ 81 | p <- ggplot(data) + 82 | geom_star(aes(n_tips = tips, rotation = time)) + 83 | coord_fixed() + 84 | theme_void() + 85 | xlim(-1, 1) + 86 | ylim(-1, 1) + 87 | facet_wrap(~tips) 88 | print(p) 89 | }) 90 | } 91 | 92 | gif_file <- save_gif(makeplot(), width = 800, height = 800, res = 200, delay = 0.01, gif_file = "man/example.gif") 93 | ``` 94 | 95 | ![](man/example.gif) 96 | 97 | ## Design choices 98 | 99 | All the geoms that produces closed curves (under certain choice of 100 | parameters) comes with a couple of geom specifit tuning parameters (`n`, 101 | `d` and `c` for `geom_star()`) and some shared aesthetics 102 | 103 | - x0 104 | - y0 105 | - xscale 106 | - yscale 107 | - rotation 108 | 109 | which denote the x and y coordinate of the center, the x and y scaling 110 | of the curve and its rotation in radians. By defaults the geoms produces 111 | curves bounded between -1 and 1, centered around (0, 0). Rotation is not 112 | applied by default. If rotation and scaling is applied then the curve 113 | will not be bounded anymore (as it retains its scale). 114 | 115 | ``` r 116 | ggplot() + 117 | geom_rect(aes(xmin = -1, ymin = -1, xmax = 1, ymax = 1), fill = NA, color = "red", size = 1) + 118 | geom_lissajous(aes(a = 5, b = 4, delta = 2)) + 119 | theme_minimal() + 120 | coord_fixed() + 121 | labs(title = "The curve is bounded by the square going from (-1, -1) to (1, 1)") 122 | ``` 123 | 124 | 125 | 126 | ``` r 127 | ggplot() + 128 | geom_rect(aes(xmin = -1, ymin = -1, xmax = 1, ymax = 1), fill = NA, color = "red", size = 1) + 129 | geom_lissajous(aes(a = 5, b = 4, delta = 2, rotation = pi / 7)) + 130 | theme_minimal() + 131 | coord_fixed() + 132 | labs(title = "Rotation will leave the curve at the same size") 133 | ``` 134 | 135 | 136 | 137 | ## Inspiration 138 | 139 | The original inspiration for this package came from the post [film 140 | flowers](http://bl.ocks.org/sxywu/raw/d612c6c653fb8b4d7ff3d422be164a5d/) 141 | by [Shirley Wu](https://twitter.com/sxywu) which drove me to the 142 | realization that such visualizations are quite the hassle to do in 143 | ggplot2 right now. 144 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | development: 2 | mode: auto 3 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | 3 | * local: darwin15.6.0-3.5.2 4 | * travis: 3.1, 3.2, 3.3, oldrel, release, devel 5 | * r-hub: windows-x86_64-devel, ubuntu-gcc-release, fedora-clang-devel 6 | * win-builder: windows-x86_64-devel 7 | 8 | ## R CMD check results 9 | 10 | 0 errors | 0 warnings | 1 note 11 | 12 | * This is a new release. 13 | -------------------------------------------------------------------------------- /ggshapes.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /man/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/example.gif -------------------------------------------------------------------------------- /man/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/figures/README-example-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/figures/README-unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/figures/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmilHvitfeldt/ggshapes/f9cd15572fe7c05b6b408f4f384610725338bd94/man/figures/README-unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /man/geom_epitrochoid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epitrochoid.R 3 | \name{geom_epitrochoid} 4 | \alias{geom_epitrochoid} 5 | \alias{stat_epitrochoid} 6 | \title{Draw a rose or Epitrochoid curve} 7 | \usage{ 8 | stat_epitrochoid(mapping = NULL, data = NULL, geom = "epitrochoid", 9 | position = "identity", n_points = 360, na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_epitrochoid(mapping = NULL, data = NULL, stat = "epitrochoid", 13 | position = "identity", n_points = 360, na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 18 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 19 | default), it is combined with the default mapping at the top level of the 20 | plot. You must supply \code{mapping} if there is no plot mapping.} 21 | 22 | \item{data}{The data to be displayed in this layer. There are three 23 | options: 24 | 25 | If \code{NULL}, the default, the data is inherited from the plot 26 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 27 | 28 | A \code{data.frame}, or other object, will override the plot 29 | data. All objects will be fortified to produce a data frame. See 30 | \code{\link[=fortify]{fortify()}} for which variables will be created. 31 | 32 | A \code{function} will be called with a single argument, 33 | the plot data. The return value must be a \code{data.frame}, and 34 | will be used as the layer data.} 35 | 36 | \item{geom}{The geometric object to use display the data} 37 | 38 | \item{position}{Position adjustment, either as a string, or the result of 39 | a call to a position adjustment function.} 40 | 41 | \item{n_points}{The number of points to sample along the curve.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{show.legend}{logical. Should this layer be included in the legends? 47 | \code{NA}, the default, includes if any aesthetics are mapped. 48 | \code{FALSE} never includes, and \code{TRUE} always includes. 49 | It can also be a named logical vector to finely select the aesthetics to 50 | display.} 51 | 52 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 53 | rather than combining with them. This is most useful for helper functions 54 | that define both data and aesthetics and shouldn't inherit behaviour from 55 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 56 | 57 | \item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}. These are 58 | often aesthetics, used to set an aesthetic to a fixed value, like 59 | \code{colour = "red"} or \code{size = 3}. They may also be parameters 60 | to the paired geom/stat.} 61 | 62 | \item{stat}{The statistical transformation to use on the data for this 63 | layer, as a string.} 64 | } 65 | \description{ 66 | This geom allows you to draw the epitrochoid curve. A epitrochoid is a 67 | curve traced by a point attached to a circle of radius r_min rolling around 68 | the outside of a fixed circle of radius r_max, where the point is at a 69 | distance h from the center of the interior circle. h is the same as r_min 70 | by default. 71 | } 72 | \details{ 73 | To unscale the curve, please set xscale and yscale to r_max + r_min + h. 74 | 75 | The curve follows the the parameterized form 76 | 77 | \deqn{x = (r_max + r_min) cos(\theta) - h * cos(\frac{r_max + r_min}{r_min} \theta)} 78 | \deqn{x = (r_max + r_min) sin(\theta) - h * sin(\frac{r_max + r_min}{r_min} \theta)} 79 | 80 | these curves are closed when the radion \eqn{a / b} is rational. delta have 81 | been scaled to be in the interval [0, 1]. 82 | } 83 | \section{Aesthetics}{ 84 | 85 | geom_arc understand the following aesthetics (required aesthetics are in 86 | bold): 87 | 88 | - **r_max** 89 | - **r_min** 90 | - h 91 | - x0 92 | - y0 93 | - xscale 94 | - yscale 95 | - rotation 96 | - color 97 | - fill 98 | - size 99 | - linetype 100 | - alpha 101 | - lineend 102 | } 103 | 104 | \section{Computed variables}{ 105 | 106 | 107 | \describe{ 108 | \item{x, y}{The coordinates for the points along the rose curve} 109 | } 110 | } 111 | 112 | \examples{ 113 | 114 | # When h is missing a hypocycloid is generated 115 | ggplot() + 116 | geom_epitrochoid(aes(r_max = 4, r_min = 1)) 117 | 118 | ggplot() + 119 | geom_epitrochoid(aes(r_max = 8, r_min = 1)) 120 | 121 | ggplot() + 122 | geom_epitrochoid(aes(r_max = c(4, 6, 8), r_min = 1)) 123 | 124 | # specifying h 125 | ggplot() + 126 | geom_epitrochoid(aes(r_max = 4, r_min = 1, h = 4)) 127 | 128 | ggplot() + 129 | geom_epitrochoid(aes(r_max = 4, r_min = 3, h = 20 / 13)) 130 | 131 | # Changing the horizontal and vertical scale 132 | 133 | ggplot() + 134 | geom_epitrochoid(aes(r_max = 4, r_min = 3, xscale = 10, yscale = 3)) 135 | 136 | # Rotating shape 137 | ggplot() + 138 | geom_epitrochoid(aes(r_max = 4, r_min = 3, rotation = pi / 4)) 139 | 140 | # When things go wild 141 | ggplot(expand.grid(seq(4, 20, by = 2), c(1, 3, 5, 9))) + 142 | geom_epitrochoid(aes(r_max = Var1, r_min = Var2, color = Var1, 143 | xscale = Var1 + Var2, yscale = Var1 + Var2)) + 144 | coord_fixed() + 145 | theme_minimal() + 146 | scale_color_viridis_c(option = "B") + 147 | guides(color = "none") + 148 | facet_wrap(~ Var2) 149 | } 150 | \references{ 151 | \url{http://mathworld.wolfram.com/Epitrochoid.html} 152 | \url{http://xahlee.info/SpecialPlaneCurves_dir/Epitrochoid_dir/epitrochoid.html} 153 | } 154 | \seealso{ 155 | [geom_hypotrochoid()] 156 | } 157 | \author{ 158 | Emil Hvitfeldt 159 | } 160 | -------------------------------------------------------------------------------- /man/geom_hypotrochoid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hypotrochoid.R 3 | \name{geom_hypotrochoid} 4 | \alias{geom_hypotrochoid} 5 | \alias{stat_hypotrochoid} 6 | \title{Draw a rose or Hypotrochoid curve} 7 | \usage{ 8 | stat_hypotrochoid(mapping = NULL, data = NULL, geom = "hypotrochoid", 9 | position = "identity", n_points = 360, na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_hypotrochoid(mapping = NULL, data = NULL, stat = "hypotrochoid", 13 | position = "identity", n_points = 360, na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 18 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 19 | default), it is combined with the default mapping at the top level of the 20 | plot. You must supply \code{mapping} if there is no plot mapping.} 21 | 22 | \item{data}{The data to be displayed in this layer. There are three 23 | options: 24 | 25 | If \code{NULL}, the default, the data is inherited from the plot 26 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 27 | 28 | A \code{data.frame}, or other object, will override the plot 29 | data. All objects will be fortified to produce a data frame. See 30 | \code{\link[=fortify]{fortify()}} for which variables will be created. 31 | 32 | A \code{function} will be called with a single argument, 33 | the plot data. The return value must be a \code{data.frame}, and 34 | will be used as the layer data.} 35 | 36 | \item{geom}{The geometric object to use display the data} 37 | 38 | \item{position}{Position adjustment, either as a string, or the result of 39 | a call to a position adjustment function.} 40 | 41 | \item{n_points}{The number of points to sample along the curve.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{show.legend}{logical. Should this layer be included in the legends? 47 | \code{NA}, the default, includes if any aesthetics are mapped. 48 | \code{FALSE} never includes, and \code{TRUE} always includes. 49 | It can also be a named logical vector to finely select the aesthetics to 50 | display.} 51 | 52 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 53 | rather than combining with them. This is most useful for helper functions 54 | that define both data and aesthetics and shouldn't inherit behaviour from 55 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 56 | 57 | \item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}. These are 58 | often aesthetics, used to set an aesthetic to a fixed value, like 59 | \code{colour = "red"} or \code{size = 3}. They may also be parameters 60 | to the paired geom/stat.} 61 | 62 | \item{stat}{The statistical transformation to use on the data for this 63 | layer, as a string.} 64 | } 65 | \description{ 66 | This geom allows you to draw the hypotrochoid curve. A hypotrochoid is a 67 | curve traced by a point attached to a circle of radius r_min rolling around 68 | the inside of a fixed circle of radius r_max, where the point is at a 69 | distance h from the center of the interior circle. 70 | } 71 | \details{ 72 | To unscale the curve, please set xscale and yscale to abs(r_max - r_min) + h. 73 | 74 | The curve follows the the parameterized form 75 | 76 | \deqn{x = (r_max - r_min) cos(\theta) + h * cos(\frac{r_max - r_min}{r_min} \theta)} 77 | \deqn{x = (r_max - r_min) sin(\theta) + h * sin(\frac{r_max - r_min}{r_min} \theta)} 78 | 79 | these curves are closed when the radion \eqn{a / b} is rational. delta have 80 | been scaled to be in the interval [0, 1]. 81 | } 82 | \section{Aesthetics}{ 83 | 84 | geom_arc understand the following aesthetics (required aesthetics are in 85 | bold): 86 | 87 | - **r_max** 88 | - **r_min** 89 | - h 90 | - x0 91 | - y0 92 | - xscale 93 | - yscale 94 | - rotation 95 | - color 96 | - fill 97 | - size 98 | - linetype 99 | - alpha 100 | - lineend 101 | } 102 | 103 | \section{Computed variables}{ 104 | 105 | 106 | \describe{ 107 | \item{x, y}{The coordinates for the points along the rose curve} 108 | } 109 | } 110 | 111 | \examples{ 112 | 113 | # When h is missing a hypocycloid is generated 114 | ggplot() + 115 | geom_hypotrochoid(aes(r_max = 4, r_min = 1)) 116 | 117 | ggplot() + 118 | geom_hypotrochoid(aes(r_max = 8, r_min = 1)) 119 | 120 | ggplot() + 121 | geom_hypotrochoid(aes(r_max = c(4, 6, 8), r_min = 1)) 122 | 123 | # specifying h 124 | ggplot() + 125 | geom_hypotrochoid(aes(r_max = 4, r_min = 9, h = 4)) 126 | 127 | ggplot() + 128 | geom_hypotrochoid(aes(r_max = 4, r_min = 3, h = 20 / 13)) 129 | 130 | # changing rotation 131 | ggplot() + 132 | geom_hypotrochoid(aes(r_max = 4, r_min = 1, rotation = pi / 4)) 133 | 134 | # When things go wild 135 | ggplot(expand.grid(seq(4, 20, by = 2), c(1, 3, 5, 9))) + 136 | geom_hypotrochoid(aes(r_max = Var1, r_min = Var2, color = Var1, 137 | xscale = abs(Var1 - Var2) + Var2, 138 | yscale = abs(Var1 - Var2) + Var2)) + 139 | coord_fixed() + 140 | theme_minimal() + 141 | scale_color_viridis_c(option = "B") + 142 | guides(color = "none") + 143 | facet_wrap(~ Var2) 144 | } 145 | \references{ 146 | \url{https://en.wikipedia.org/wiki/Hypocycloid} 147 | \url{http://xahlee.info/SpecialPlaneCurves_dir/Hypotrochoid_dir/hypotrochoid.html} 148 | } 149 | \seealso{ 150 | [geom_epitrochoid()] 151 | } 152 | \author{ 153 | Emil Hvitfeldt 154 | } 155 | -------------------------------------------------------------------------------- /man/geom_lissajous.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lissajous.R 3 | \name{geom_lissajous} 4 | \alias{geom_lissajous} 5 | \alias{stat_lissajous} 6 | \title{Draw a rose or lissajous curve} 7 | \usage{ 8 | stat_lissajous(mapping = NULL, data = NULL, geom = "lissajous", 9 | position = "identity", n_points = 360, na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_lissajous(mapping = NULL, data = NULL, stat = "lissajous", 13 | position = "identity", n_points = 360, na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 18 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 19 | default), it is combined with the default mapping at the top level of the 20 | plot. You must supply \code{mapping} if there is no plot mapping.} 21 | 22 | \item{data}{The data to be displayed in this layer. There are three 23 | options: 24 | 25 | If \code{NULL}, the default, the data is inherited from the plot 26 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 27 | 28 | A \code{data.frame}, or other object, will override the plot 29 | data. All objects will be fortified to produce a data frame. See 30 | \code{\link[=fortify]{fortify()}} for which variables will be created. 31 | 32 | A \code{function} will be called with a single argument, 33 | the plot data. The return value must be a \code{data.frame}, and 34 | will be used as the layer data.} 35 | 36 | \item{geom}{The geometric object to use display the data} 37 | 38 | \item{position}{Position adjustment, either as a string, or the result of 39 | a call to a position adjustment function.} 40 | 41 | \item{n_points}{The number of points to sample along the curve.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{show.legend}{logical. Should this layer be included in the legends? 47 | \code{NA}, the default, includes if any aesthetics are mapped. 48 | \code{FALSE} never includes, and \code{TRUE} always includes. 49 | It can also be a named logical vector to finely select the aesthetics to 50 | display.} 51 | 52 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 53 | rather than combining with them. This is most useful for helper functions 54 | that define both data and aesthetics and shouldn't inherit behaviour from 55 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 56 | 57 | \item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}. These are 58 | often aesthetics, used to set an aesthetic to a fixed value, like 59 | \code{colour = "red"} or \code{size = 3}. They may also be parameters 60 | to the paired geom/stat.} 61 | 62 | \item{stat}{The statistical transformation to use on the data for this 63 | layer, as a string.} 64 | } 65 | \description{ 66 | This geom allows you to draw the lissajous curve. 67 | } 68 | \details{ 69 | The curve follows the the parameterized form 70 | 71 | \deqn{x = sin(a\theta + \delta)} 72 | \deqn{y = sin(b\theta)} 73 | 74 | these curves are closed when the radion \eqn{a / b} is rational. delta have 75 | been scaled to be in the interval [0, 1]. 76 | } 77 | \section{Aesthetics}{ 78 | 79 | geom_arc understand the following aesthetics (required aesthetics are in 80 | bold): 81 | 82 | - **a** 83 | - **b** 84 | - **delta** 85 | - x0 86 | - y0 87 | - xscale 88 | - yscale 89 | - rotation 90 | - color 91 | - fill 92 | - size 93 | - linetype 94 | - alpha 95 | - lineend 96 | } 97 | 98 | \section{Computed variables}{ 99 | 100 | 101 | \describe{ 102 | \item{x, y}{The coordinates for the points along the rose curve} 103 | } 104 | } 105 | 106 | \examples{ 107 | ggplot() + 108 | geom_lissajous(aes(a = 5, b = 4, delta = 2)) 109 | 110 | ggplot() + 111 | geom_lissajous(aes(a = 2, b = 3, delta = 1)) 112 | 113 | ggplot() + 114 | geom_lissajous(aes(a = 1:3, b = 3, delta = 1, x0 = c(1, 4, 7))) 115 | 116 | # Scaling shapes 117 | ggplot() + 118 | geom_lissajous(aes(a = 2, b = 3, delta = 1, xscale = 5, yscale = 2)) 119 | 120 | # Rotation shapes 121 | ggplot() + 122 | geom_lissajous(aes(a = 2, b = 3, delta = 1, rotation = pi / 4)) 123 | 124 | } 125 | \references{ 126 | \url{https://en.wikipedia.org/wiki/Lissajous_curve} 127 | } 128 | \author{ 129 | Emil Hvitfeldt 130 | } 131 | -------------------------------------------------------------------------------- /man/geom_rose.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rose.R 3 | \name{geom_rose} 4 | \alias{geom_rose} 5 | \alias{stat_rose} 6 | \title{Draw a rose or rhodonea curve} 7 | \usage{ 8 | stat_rose(mapping = NULL, data = NULL, geom = "rose", 9 | position = "identity", n_points = 360, na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_rose(mapping = NULL, data = NULL, stat = "rose", 13 | position = "identity", n_points = 360, na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 18 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 19 | default), it is combined with the default mapping at the top level of the 20 | plot. You must supply \code{mapping} if there is no plot mapping.} 21 | 22 | \item{data}{The data to be displayed in this layer. There are three 23 | options: 24 | 25 | If \code{NULL}, the default, the data is inherited from the plot 26 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 27 | 28 | A \code{data.frame}, or other object, will override the plot 29 | data. All objects will be fortified to produce a data frame. See 30 | \code{\link[=fortify]{fortify()}} for which variables will be created. 31 | 32 | A \code{function} will be called with a single argument, 33 | the plot data. The return value must be a \code{data.frame}, and 34 | will be used as the layer data.} 35 | 36 | \item{geom}{The geometric object to use display the data} 37 | 38 | \item{position}{Position adjustment, either as a string, or the result of 39 | a call to a position adjustment function.} 40 | 41 | \item{n_points}{The number of points to sample along the curve.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{show.legend}{logical. Should this layer be included in the legends? 47 | \code{NA}, the default, includes if any aesthetics are mapped. 48 | \code{FALSE} never includes, and \code{TRUE} always includes. 49 | It can also be a named logical vector to finely select the aesthetics to 50 | display.} 51 | 52 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 53 | rather than combining with them. This is most useful for helper functions 54 | that define both data and aesthetics and shouldn't inherit behaviour from 55 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 56 | 57 | \item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}. These are 58 | often aesthetics, used to set an aesthetic to a fixed value, like 59 | \code{colour = "red"} or \code{size = 3}. They may also be parameters 60 | to the paired geom/stat.} 61 | 62 | \item{stat}{The statistical transformation to use on the data for this 63 | layer, as a string.} 64 | } 65 | \description{ 66 | This geom allows you to draw mathematical roses. A rose is a sinusoid 67 | plotted in polar coordinates. 68 | } 69 | \details{ 70 | the shape follows the following parameterized form 71 | 72 | \deqn{x = (cos(k\theta) + c)cos(\theta)} 73 | \deqn{y = (cos(k\theta) + c)sin(\theta)} 74 | 75 | where 76 | 77 | \deqn{k = n / d} 78 | 79 | the rose will be a closed loop when k is rational. this can easily be 80 | achived by keeping n and d whole numbers. c is the internal offset parameter 81 | changing how much the flower spreads out. 82 | } 83 | \section{Aesthetics}{ 84 | 85 | geom_arc understand the following aesthetics (required aesthetics are in 86 | bold): 87 | 88 | - **n** 89 | - **d** 90 | - **c** 91 | - x0 92 | - y0 93 | - xscale 94 | - yscale 95 | - rotation 96 | - color 97 | - fill 98 | - size 99 | - linetype 100 | - alpha 101 | - lineend 102 | } 103 | 104 | \section{Computed variables}{ 105 | 106 | 107 | \describe{ 108 | \item{x, y}{The coordinates for the points along the rose curve} 109 | } 110 | } 111 | 112 | \examples{ 113 | 114 | ggplot() + 115 | geom_rose(aes(n = 2, d = 1, c = 0)) 116 | 117 | ggplot() + 118 | geom_rose(aes(n = 2, d = 8, c = 0)) 119 | 120 | ggplot() + 121 | geom_rose(aes(n = 5, d = 4, c = 4)) 122 | 123 | # Rescaling 124 | ggplot() + 125 | geom_rose(aes(n = 5, d = 4, c = 4, xscale = 6, yscale = 2)) 126 | 127 | # Rotation 128 | ggplot() + 129 | geom_rose(aes(n = 2, d = 1, c = 0, rotation = pi / 4)) 130 | 131 | # Multiple roses 132 | ggplot() + 133 | geom_rose(aes(n = 5:1, d = 1:5, c = 0, x0 = 1:5 * 3)) 134 | 135 | ggplot() + 136 | geom_rose(aes(n = 5, d = 4, c = 4), fill = "white") 137 | } 138 | \references{ 139 | \url{https://en.wikipedia.org/wiki/Rose_(mathematics)} 140 | } 141 | \author{ 142 | Emil Hvitfeldt 143 | } 144 | -------------------------------------------------------------------------------- /man/geom_star.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/star.R 3 | \name{geom_star} 4 | \alias{geom_star} 5 | \alias{stat_star} 6 | \title{Draw a n pointed regular star} 7 | \usage{ 8 | stat_star(mapping = NULL, data = NULL, geom = "star", 9 | position = "identity", n_points = 360, na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_star(mapping = NULL, data = NULL, stat = "star", 13 | position = "identity", n_points = 360, na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or 18 | \code{\link[=aes_]{aes_()}}. If specified and \code{inherit.aes = TRUE} (the 19 | default), it is combined with the default mapping at the top level of the 20 | plot. You must supply \code{mapping} if there is no plot mapping.} 21 | 22 | \item{data}{The data to be displayed in this layer. There are three 23 | options: 24 | 25 | If \code{NULL}, the default, the data is inherited from the plot 26 | data as specified in the call to \code{\link[=ggplot]{ggplot()}}. 27 | 28 | A \code{data.frame}, or other object, will override the plot 29 | data. All objects will be fortified to produce a data frame. See 30 | \code{\link[=fortify]{fortify()}} for which variables will be created. 31 | 32 | A \code{function} will be called with a single argument, 33 | the plot data. The return value must be a \code{data.frame}, and 34 | will be used as the layer data.} 35 | 36 | \item{geom}{The geometric object to use display the data} 37 | 38 | \item{position}{Position adjustment, either as a string, or the result of 39 | a call to a position adjustment function.} 40 | 41 | \item{n_points}{The number of points to sample along the curve.} 42 | 43 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 44 | a warning. If \code{TRUE}, missing values are silently removed.} 45 | 46 | \item{show.legend}{logical. Should this layer be included in the legends? 47 | \code{NA}, the default, includes if any aesthetics are mapped. 48 | \code{FALSE} never includes, and \code{TRUE} always includes. 49 | It can also be a named logical vector to finely select the aesthetics to 50 | display.} 51 | 52 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 53 | rather than combining with them. This is most useful for helper functions 54 | that define both data and aesthetics and shouldn't inherit behaviour from 55 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 56 | 57 | \item{...}{Other arguments passed on to \code{\link[=layer]{layer()}}. These are 58 | often aesthetics, used to set an aesthetic to a fixed value, like 59 | \code{colour = "red"} or \code{size = 3}. They may also be parameters 60 | to the paired geom/stat.} 61 | 62 | \item{stat}{The statistical transformation to use on the data for this 63 | layer, as a string.} 64 | } 65 | \description{ 66 | This geom allows you to draw the star curve. 67 | } 68 | \section{Aesthetics}{ 69 | 70 | geom_arc understand the following aesthetics (required aesthetics are in 71 | bold): 72 | 73 | - **n_tips** 74 | - r_min 75 | - r_max 76 | - offset 77 | - x0 78 | - y0 79 | - xscale 80 | - yscale 81 | - rotation 82 | - color 83 | - fill 84 | - size 85 | - linetype 86 | - alpha 87 | - lineend 88 | } 89 | 90 | \section{Computed variables}{ 91 | 92 | 93 | \describe{ 94 | \item{x, y}{The coordinates for the points along the star curve} 95 | } 96 | } 97 | 98 | \examples{ 99 | # Changing number of tips 100 | ggplot() + 101 | geom_star(aes(n_tips = 5)) 102 | 103 | ggplot() + 104 | geom_star(aes(n_tips = 11)) 105 | 106 | # changing radei 107 | ggplot() + 108 | geom_star(aes(r_min = 0.2, r_max = 1, n_tips = 5)) 109 | 110 | ggplot() + 111 | geom_star(aes(r_min = 0.7, r_max = 1, n_tips = 5)) 112 | 113 | # rescaling 114 | ggplot() + 115 | geom_star(aes( n_tips = 5, xscale = 4, yscale = 2)) 116 | 117 | # Rotation 118 | ggplot() + 119 | geom_star(aes(n_tips = 5, rotation = pi / 4)) 120 | 121 | # Playing witn offset parameter 122 | ggplot() + 123 | geom_star(aes(n_tips = 5, offset = 0)) 124 | 125 | ggplot() + 126 | geom_star(aes(n_tips = 5, offset = 1)) 127 | 128 | ggplot() + 129 | geom_star(aes(n_tips = 11, offset = 5)) 130 | 131 | # Multiple stars 132 | ggplot() + 133 | geom_star(aes(n_tips = c(3, 5, 7), 134 | x0 = c(1, 4, 7), 135 | y0 = c(1, 4, 7))) 136 | 137 | # Regular polygons comes up as a special example when 138 | # r_max = r_min / cos(pi / n_tips) 139 | ggplot() + 140 | geom_star(aes(r_min = 0.5, r_max = 0.5 / cos(pi / 5), n_tips = 5)) 141 | } 142 | \author{ 143 | Emil Hvitfeldt 144 | } 145 | -------------------------------------------------------------------------------- /man/ggshapes-extensions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/epitrochoid.R, R/ggpronto-classes.R, 3 | % R/hypotrochoid.R, R/lissajous.R, R/rose.R, R/shape.R, R/star.R 4 | \docType{data} 5 | \name{StatEpitrochoid} 6 | \alias{StatEpitrochoid} 7 | \alias{ggshapes-extensions} 8 | \alias{StatHypotrochoid} 9 | \alias{StatLissajous} 10 | \alias{StatRose} 11 | \alias{GeomShape} 12 | \alias{StatStar} 13 | \title{ggshapes extensions to ggplot2} 14 | \description{ 15 | ggshapes makes heavy use of the ggproto class system to extend the 16 | functionality of ggplot2. In general the actual classes should be of little 17 | interest to users as the standard ggplot2 api of using geom_* and stat_* 18 | functions for building up the plot is encouraged. 19 | } 20 | \keyword{datasets} 21 | -------------------------------------------------------------------------------- /man/rotate_df.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/aaa.R 3 | \name{rotate_df} 4 | \alias{rotate_df} 5 | \title{Rotates a parametric data.frame} 6 | \usage{ 7 | rotate_df(df, theta) 8 | } 9 | \arguments{ 10 | \item{df}{a data frame with two columns x and y} 11 | 12 | \item{theta}{a numeric denoting the amount of rotation} 13 | } 14 | \value{ 15 | a data frame with two columns x and y 16 | } 17 | \description{ 18 | Rotates a parametric data.frame 19 | } 20 | -------------------------------------------------------------------------------- /man/weave.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/aaa.R 3 | \name{weave} 4 | \alias{weave} 5 | \title{Weaves two vectors together using alternating indecies} 6 | \usage{ 7 | weave(a, b) 8 | } 9 | \arguments{ 10 | \item{a}{Vector} 11 | 12 | \item{b}{Vector} 13 | } 14 | \value{ 15 | A vector 16 | } 17 | \description{ 18 | Weaves two vectors together using alternating indecies 19 | } 20 | --------------------------------------------------------------------------------