在 R 中计算二维样条曲线
Calculate a 2D spline curve in R
我正在尝试计算通过一系列 x-y 坐标的类似贝塞尔曲线的样条曲线。一个示例类似于 Matlab (example link) 中 cscvn
函数的以下输出:
我相信(不再维护)grid
包用于执行此操作(grid.xspline
功能?),但我无法安装该包的存档版本,并且找不到与我想要的完全一致的示例。
bezier
包看起来也很有前途,但是速度很慢,我也不太对劲:
library(bezier)
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
p <- cbind(x,y)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
plot(p, xlim=xlim, ylim=ylim)
text(p, labels=seq(n), pos=3)
bp <- pointsOnBezier(cbind(x,y), n=100)
lines(bp$points)
arrows(bp$points[nrow(bp$points)-1,1], bp$points[nrow(bp$points)-1,2],
bp$points[nrow(bp$points),1], bp$points[nrow(bp$points),2]
)
如您所见,它不通过任何点,除了结束值。
非常感谢您的指导!
这可能不是最好的方法,位 grid
当然不是不活动的。它作为默认包包含在 R 安装中。它是用于绘制 lattice 和 ggplot 等库的底层图形引擎。您不需要安装它,您应该能够加载它。以下是我如何翻译您的代码以使用 grid.xpline
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
library(grid)
grid.newpage()
pushViewport(viewport(xscale=xlim, yscale=ylim))
grid.points(x, y, pch=16, size=unit(2, "mm"),
default.units="native")
grid.text(seq(n), x,y, just=c("center","bottom"),
default.units="native")
grid.xspline(x, y, shape=c(0,rep(-1, 10-2),0), open=TRUE,
default.units="native")
popViewport()
这导致
请注意,网格非常漂亮 low-level,因此使用起来并不是特别容易,但它确实可以让您更好地控制绘图的内容和位置。
如果您想沿着曲线提取点而不是绘制曲线,请查看 ?xsplinePoints
帮助页面。
真的没必要用grid
。您可以从 graphics
包访问 xspline
。
根据您的代码和@mrflick 的 shape
:
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
p <- cbind(x,y)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
plot(p, xlim=xlim, ylim=ylim)
text(p, labels=seq(n), pos=3)
你只需要多一行:
xspline(x, y, shape = c(0,rep(-1, 10-2),0), border="red")
感谢所有为此提供帮助的人。我正在总结经验教训以及其他一些方面。
Catmull-Rom 样条与立方 B-spline
xspline
函数中的负形状值 return 一个 Catmull-Rom 类型的样条曲线,样条曲线通过 x-y 点。正值 return 三次 B 型样条。零值 return 一个尖角。如果给出单个形状值,则将其用于所有点。端点的形状始终被视为尖角(shape=0),其他值不影响端点处生成的样条:
# Catmull-Rom spline vs. cubic B-spline
plot(p, xlim=extendrange(x, f=0.2), ylim=extendrange(y, f=0.2))
text(p, labels=seq(n), pos=3)
# Catmull-Rom spline (-1)
xspline(p, shape = -1, border="red", lwd=2)
# Catmull-Rom spline (-0.5)
xspline(p, shape = -0.5, border="orange", lwd=2)
# cubic B-spline (0.5)
xspline(p, shape = 0.5, border="green", lwd=2)
# cubic B-spline (1)
xspline(p, shape = 1, border="blue", lwd=2)
legend("bottomright", ncol=2, legend=c(-1,-0.5), title="Catmull-Rom spline", col=c("red", "orange"), lty=1)
legend("topleft", ncol=2, legend=c(1, 0.5), title="cubic B-spline", col=c("blue", "green"), lty=1)
正在从 xspline
中提取结果用于外部绘图
这需要一些搜索,但技巧是将参数 draw=FALSE
应用于 xspline
。
# Extract xy values
plot(p, xlim=extendrange(x, f=0.1), ylim=extendrange(y, f=0.1))
text(p, labels=seq(n), pos=3)
spl <- xspline(x, y, shape = -0.5, draw=FALSE)
lines(spl)
arrows(x0=(spl$x[length(spl$x)-0.01*length(spl$x)]), y0=(spl$y[length(spl$y)-0.01*length(spl$y)]),
x1=(spl$x[length(spl$x)]), y1=(spl$y[length(spl$y)])
)
我正在尝试计算通过一系列 x-y 坐标的类似贝塞尔曲线的样条曲线。一个示例类似于 Matlab (example link) 中 cscvn
函数的以下输出:
我相信(不再维护)grid
包用于执行此操作(grid.xspline
功能?),但我无法安装该包的存档版本,并且找不到与我想要的完全一致的示例。
bezier
包看起来也很有前途,但是速度很慢,我也不太对劲:
library(bezier)
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
p <- cbind(x,y)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
plot(p, xlim=xlim, ylim=ylim)
text(p, labels=seq(n), pos=3)
bp <- pointsOnBezier(cbind(x,y), n=100)
lines(bp$points)
arrows(bp$points[nrow(bp$points)-1,1], bp$points[nrow(bp$points)-1,2],
bp$points[nrow(bp$points),1], bp$points[nrow(bp$points),2]
)
如您所见,它不通过任何点,除了结束值。
非常感谢您的指导!
这可能不是最好的方法,位 grid
当然不是不活动的。它作为默认包包含在 R 安装中。它是用于绘制 lattice 和 ggplot 等库的底层图形引擎。您不需要安装它,您应该能够加载它。以下是我如何翻译您的代码以使用 grid.xpline
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
library(grid)
grid.newpage()
pushViewport(viewport(xscale=xlim, yscale=ylim))
grid.points(x, y, pch=16, size=unit(2, "mm"),
default.units="native")
grid.text(seq(n), x,y, just=c("center","bottom"),
default.units="native")
grid.xspline(x, y, shape=c(0,rep(-1, 10-2),0), open=TRUE,
default.units="native")
popViewport()
这导致
请注意,网格非常漂亮 low-level,因此使用起来并不是特别容易,但它确实可以让您更好地控制绘图的内容和位置。
如果您想沿着曲线提取点而不是绘制曲线,请查看 ?xsplinePoints
帮助页面。
真的没必要用grid
。您可以从 graphics
包访问 xspline
。
根据您的代码和@mrflick 的 shape
:
set.seed(1)
n <- 10
x <- runif(n)
y <- runif(n)
p <- cbind(x,y)
xlim <- c(min(x) - 0.1*diff(range(x)), c(max(x) + 0.1*diff(range(x))))
ylim <- c(min(y) - 0.1*diff(range(y)), c(max(y) + 0.1*diff(range(y))))
plot(p, xlim=xlim, ylim=ylim)
text(p, labels=seq(n), pos=3)
你只需要多一行:
xspline(x, y, shape = c(0,rep(-1, 10-2),0), border="red")
感谢所有为此提供帮助的人。我正在总结经验教训以及其他一些方面。
Catmull-Rom 样条与立方 B-spline
xspline
函数中的负形状值 return 一个 Catmull-Rom 类型的样条曲线,样条曲线通过 x-y 点。正值 return 三次 B 型样条。零值 return 一个尖角。如果给出单个形状值,则将其用于所有点。端点的形状始终被视为尖角(shape=0),其他值不影响端点处生成的样条:
# Catmull-Rom spline vs. cubic B-spline
plot(p, xlim=extendrange(x, f=0.2), ylim=extendrange(y, f=0.2))
text(p, labels=seq(n), pos=3)
# Catmull-Rom spline (-1)
xspline(p, shape = -1, border="red", lwd=2)
# Catmull-Rom spline (-0.5)
xspline(p, shape = -0.5, border="orange", lwd=2)
# cubic B-spline (0.5)
xspline(p, shape = 0.5, border="green", lwd=2)
# cubic B-spline (1)
xspline(p, shape = 1, border="blue", lwd=2)
legend("bottomright", ncol=2, legend=c(-1,-0.5), title="Catmull-Rom spline", col=c("red", "orange"), lty=1)
legend("topleft", ncol=2, legend=c(1, 0.5), title="cubic B-spline", col=c("blue", "green"), lty=1)
正在从 xspline
中提取结果用于外部绘图
这需要一些搜索,但技巧是将参数 draw=FALSE
应用于 xspline
。
# Extract xy values
plot(p, xlim=extendrange(x, f=0.1), ylim=extendrange(y, f=0.1))
text(p, labels=seq(n), pos=3)
spl <- xspline(x, y, shape = -0.5, draw=FALSE)
lines(spl)
arrows(x0=(spl$x[length(spl$x)-0.01*length(spl$x)]), y0=(spl$y[length(spl$y)-0.01*length(spl$y)]),
x1=(spl$x[length(spl$x)]), y1=(spl$y[length(spl$y)])
)