Skip to content

Instantly share code, notes, and snippets.

@AndrewLJackson
Created July 18, 2017 09:56
Show Gist options
  • Save AndrewLJackson/413e3a2abd3519a6406c1cf66948d5a5 to your computer and use it in GitHub Desktop.
Save AndrewLJackson/413e3a2abd3519a6406c1cf66948d5a5 to your computer and use it in GitHub Desktop.
use chull to order points correctly for creating polygons.
theta <- seq(0, 2*pi, length = 360)
Z <- data.frame(x = cos(theta), y = sin(theta))
par(mfrow = c(2,2))
# points in order
plot(y~x, data = Z, type = "l", main = "Made in order", asp = 1)
# jumble the order
Z.j <- dplyr::sample_n(Z, size = nrow(Z))
plot(y~x, data = Z.j, type = "l", main = "jumbled", asp = 1)
# convert to polygon window
ch <- with(Z.j, chull(x, y))
# chull doesnt close the circle so need to add the first index on at the end
plot(y[c(ch, ch[1])]~x[c(ch, ch[1])], data = Z.j, type = "l", main = "Re-ordered", asp = 1)
# make a polygon in ggplot
library(ggplot2)
# i think geom_polygon doesnt need the first index repeated
ggplot(Z.j[ch,], aes(x,y)) + geom_polygon()
@markjholmes
Copy link

Stumbled across this today and it solved my problem - thank you ! Slightly expanded, ggplot-suitable version for when you have grouping variables below, in case it's useful:

library("tidyverse")

# adapted from here https://gist.github.com/AndrewLJackson/413e3a2abd3519a6406c1cf66948d5a5
order_chull <- function(dat, x, y, groups = NULL) {
    dat_split <- group_split(group_by(dat, across(all_of(groups))))
    ret <- bind_rows(lapply(dat_split, function(i) {
        ch <- chull(i[[x]], i[[y]])
        i[ch,]
        }))
    return(ret)
}

# no groups, yucky
ggplot(mtcars) +
	aes(x = wt, y = mpg) +
	geom_polygon()
	
# no groups, better
ggplot(order_chull(mtcars, "wt", "mpg")) +
	aes(x = wt, y = mpg) +
	geom_polygon()
	
# with groups, yucky
ggplot(mtcars) +
	aes(x = wt, y = mpg, fill = as.factor(cyl)) +
	geom_polygon()
	
# with groups, better
ggplot(order_chull(mtcars, "wt", "mpg", "cyl")) +
	aes(x = wt, y = mpg, fill = as.factor(cyl)) +
	geom_polygon()

# two groups, yucky
ggplot(mtcars) +
	aes(x = wt, y = mpg, fill = as.factor(cyl), color = as.factor(am)) +
	geom_polygon()

# two groups, better
ggplot(order_chull(mtcars, "wt", "mpg", c("cyl", "am"))) +
	aes(x = wt, y = mpg, fill = as.factor(cyl), color = as.factor(am)) +
	geom_polygon()

@AndrewLJackson
Copy link
Author

ah, that's really great, thanks Mark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment