从 R 中的坐标计算总绝对曲率
Calculate total absolute curvature from coordinates in R
给定一个封闭形状对应的一组坐标,我想计算total absolute curvature,这需要计算每个点的曲率,取绝对值,然后求和。够简单了。
我使用 的答案从 x y 坐标矩阵 (xymat
) 计算曲率并得到我认为的总绝对曲率:
sum(abs(predict(smooth.spline(xymat), deriv = 2)$y))
问题是总绝对曲率的最小值为 2*pi,对于圆来说正是这个值,但是这段代码计算的值小于 2*pi:
library(purrr)
xymat <- map_df(data.frame(degrees=seq(0:360)),
function(theta) data.frame(x = sin(theta), y = cos(theta)))
sum(abs(predict(smooth.spline(xymat), deriv = 2)$y))
这个returns 1.311098
而不是6.283185
的预期值。
如果我把smooth.spline
的df
参数改成3,返回值是3.944053
,还是差2*pi(df值smooth.spline 自己计算出来的是 2.472213).
有没有更好的计算曲率的方法? smooth.spline
是按弧长参数化还是将其(以某种方式)合并以挽救此计算?
好的,在我们开始之前先说几件事。您在 seq
中使用的是度数,这会给您不正确的结果(0 到 360 度)。您可以通过在 R 中取 cos(360)
来检查这是否错误,这不是 1。这在 Details.[=20= 下的三角函数文档中进行了解释]
所以让我们把你的函数改成这个
xymat <- map_df(data.frame(degrees=seq(0,2*pi,length=360)),
function(theta) data.frame(x = sin(theta), y = cos(theta)))
如果你绘制这个,这确实看起来像一个圆圈。
让我们实际将其限制在圆的下半部分。如果你在不了解对称性并查看绘图的情况下将样条曲线穿过它,你很可能会得到一条穿过圆圈的水平线。
为什么?因为样条曲线不知道它在 y = 0 的上方和下方是对称的。样条曲线试图拟合解释 "data" 的函数,而不是追踪弧线。它拆分了 y = 0 周围两组对称点之间的差异。
如果我们将样条限制在圆的下半部分,我们可以使用介于 1 和 -1 之间的 y 值,如下所示:
lower.semicircle <- data.frame(predict(smooth.spline(xymat[91:270,], all.knots = T)))
让我们通过它拟合一条样条曲线。
lower.semicircle.pred<-data.frame(predict(smooth.spline(lower.semicircle, all.knots = T)))
注意 我在这里没有使用 deriv
函数。这是针对您链接到的 cars
示例中的另一个问题。你想要总的绝对曲率,他们正在研究曲率的变化率。
我们现在拥有的是使用样条曲线对下半圆的近似。现在你想要所有小连续点之间的距离,就像维基百科页面中的积分一样。
让我们使用距离矩阵计算所有小弧的距离。这从字面上计算了每个点到每个其他点之间的欧几里德距离。
all.pairwise.distances.in.the.spline.approx<-dist(lower.semicircle.pred, diag=F)
dist.matrix<-as.matrix(all.pairwise.distances.in.the.spline.approx)
seq.of.distances.you.want<-dist.matrix[row(dist.matrix) == col(dist.matrix) + 1]
最后一个对象是您需要求和的对象。
sum(seq.of.distances.you.want)
..下半圆的计算结果为 [1] 3.079
,大约是 2*pi 预期值的一半。
它并不完美,但样条曲线存在边缘效应问题。
给定一个封闭形状对应的一组坐标,我想计算total absolute curvature,这需要计算每个点的曲率,取绝对值,然后求和。够简单了。
我使用 xymat
) 计算曲率并得到我认为的总绝对曲率:
sum(abs(predict(smooth.spline(xymat), deriv = 2)$y))
问题是总绝对曲率的最小值为 2*pi,对于圆来说正是这个值,但是这段代码计算的值小于 2*pi:
library(purrr)
xymat <- map_df(data.frame(degrees=seq(0:360)),
function(theta) data.frame(x = sin(theta), y = cos(theta)))
sum(abs(predict(smooth.spline(xymat), deriv = 2)$y))
这个returns 1.311098
而不是6.283185
的预期值。
如果我把smooth.spline
的df
参数改成3,返回值是3.944053
,还是差2*pi(df值smooth.spline 自己计算出来的是 2.472213).
有没有更好的计算曲率的方法? smooth.spline
是按弧长参数化还是将其(以某种方式)合并以挽救此计算?
好的,在我们开始之前先说几件事。您在 seq
中使用的是度数,这会给您不正确的结果(0 到 360 度)。您可以通过在 R 中取 cos(360)
来检查这是否错误,这不是 1。这在 Details.[=20= 下的三角函数文档中进行了解释]
所以让我们把你的函数改成这个
xymat <- map_df(data.frame(degrees=seq(0,2*pi,length=360)),
function(theta) data.frame(x = sin(theta), y = cos(theta)))
如果你绘制这个,这确实看起来像一个圆圈。
让我们实际将其限制在圆的下半部分。如果你在不了解对称性并查看绘图的情况下将样条曲线穿过它,你很可能会得到一条穿过圆圈的水平线。
为什么?因为样条曲线不知道它在 y = 0 的上方和下方是对称的。样条曲线试图拟合解释 "data" 的函数,而不是追踪弧线。它拆分了 y = 0 周围两组对称点之间的差异。
如果我们将样条限制在圆的下半部分,我们可以使用介于 1 和 -1 之间的 y 值,如下所示:
lower.semicircle <- data.frame(predict(smooth.spline(xymat[91:270,], all.knots = T)))
让我们通过它拟合一条样条曲线。
lower.semicircle.pred<-data.frame(predict(smooth.spline(lower.semicircle, all.knots = T)))
注意 我在这里没有使用 deriv
函数。这是针对您链接到的 cars
示例中的另一个问题。你想要总的绝对曲率,他们正在研究曲率的变化率。
我们现在拥有的是使用样条曲线对下半圆的近似。现在你想要所有小连续点之间的距离,就像维基百科页面中的积分一样。
让我们使用距离矩阵计算所有小弧的距离。这从字面上计算了每个点到每个其他点之间的欧几里德距离。
all.pairwise.distances.in.the.spline.approx<-dist(lower.semicircle.pred, diag=F)
dist.matrix<-as.matrix(all.pairwise.distances.in.the.spline.approx)
seq.of.distances.you.want<-dist.matrix[row(dist.matrix) == col(dist.matrix) + 1]
最后一个对象是您需要求和的对象。
sum(seq.of.distances.you.want)
..下半圆的计算结果为 [1] 3.079
,大约是 2*pi 预期值的一半。
它并不完美,但样条曲线存在边缘效应问题。