I'd like calculate (not plot) 2d spline paths in R. There's an old question on that topic that suggests xspline(): Calculate a 2D spline curve in R
xspline() somewhat works for my purpose, but has important limitations:
plot.new(), even if I don't want it to draw anythingReproducible example:
library(ggplot2)
# control points
x <- c(.1, .5, .7, .8)
y <- c(.9, .6, .5, .1)
plot.new() # necessary for xspline(); would be great if it could be avoided
# how do I set the number of interpolation points?
# how do I modify the exact path (beyond shape parameter)?
path <- xspline(x, y, shape = 1, draw = FALSE)
# plot path (black) and control points (blue) with ggplot
ggplot(data = NULL, aes(x, y)) +
geom_point(data = as.data.frame(path), size = 0.5) +
geom_point(data = data.frame(x, y), size = 2, color = "blue")

Created on 2021-08-14 by the reprex package (v2.0.0)
Are there any easily available alternatives to xspline()?
It's not clear from your example, but base R's spline function might meet your needs. We can wrap it in a function to make it easier to use the output:
f <- function(x, y, n, method = "natural") {
new_x <- seq(min(x), max(x), length.out = n)
data.frame(x = new_x, y = spline(x, y, n = n, method = method)$y)
}
So the co-ordinates for 10 evenly spaced points along the curve can be obtained like this:
f(x, y, 10)
#> x y
#> 1 0.1000000 0.9000000
#> 2 0.1777778 0.8042481
#> 3 0.2555556 0.7173182
#> 4 0.3333333 0.6480324
#> 5 0.4111111 0.6052126
#> 6 0.4888889 0.5976809
#> 7 0.5666667 0.6222222
#> 8 0.6444444 0.6013374
#> 9 0.7222222 0.4303155
#> 10 0.8000000 0.1000000
And we can show the shape of the curve like this:
ggplot(data = NULL, aes(x, y)) +
geom_point(data = f(x, y, 100), size = 0.5) +
geom_point(data = data.frame(x, y), size = 2, color = "blue")

You can change the method argument to get different shapes - the options are listed in ?spline
EDIT
To use spline on paths, simply create splines on x and y separately. These can be as a function of another variable t, or this can be left out if you want to assume equal time spacing on the path:
f2 <- function(x, y, t = seq_along(x), n, method = "natural") {
new_t <- seq(min(t), max(t), length.out = n)
new_x <- spline(t, x, xout = new_t, method = method)$y
new_y <- spline(t, y, xout = new_t, method = method)$y
data.frame(t = new_t, x = new_x, y = new_y)
}
x <- rnorm(10)
y <- rnorm(10)
ggplot(data = NULL, aes(x, y)) +
geom_point(data = f2(x, y, n = 1000), size = 0.5) +
geom_point(data = data.frame(x, y), size = 2, color = "blue")

Created on 2021-08-14 by the reprex package (v2.0.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With