Рассчитать полную абсолютную кривизну по координатам в R - PullRequest
0 голосов
/ 29 апреля 2018

Учитывая набор координат, соответствующих замкнутой фигуре, я хочу вычислить полную абсолютную кривизну , которая требует вычисления кривизны для каждой точки, взятия абсолютного значения и суммирования их. Достаточно просто.

Я использовал ответ на этот вопрос , чтобы вычислить кривизну из матрицы координат x y (xymat) и получить то, что я думал, будет полной абсолютной кривизной:

sum(abs(predict(smooth.spline(xymat), deriv = 2)$y))

Проблема в том, что полная абсолютная кривизна имеет минимальное значение 2 * пи и является точно такой же, как для кругов, но этот код оценивается до значений, меньших 2 * пи:

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))

Возвращает 1.311098 вместо ожидаемого значения 6.283185.

Если я изменю параметр df с smooth.spline на 3, как в предыдущем ответе, возвращаемое значение будет 3.944053, все еще не доходя до 2 * pi (значение df smooth.spline, рассчитанное для себя, было 2.472213) .

Есть ли лучший способ для расчета кривизны? smooth.spline параметризован длиной дуги или будет ли это (каким-то образом) спасать этот расчет?

1 Ответ

0 голосов
/ 29 апреля 2018

Хорошо, несколько вещей, прежде чем мы начнем. Вы используете градусы в вашем seq, что даст вам неверные результаты (от 0 до 360 градусов). Вы можете проверить, что это неправильно, взяв cos(360) в R, который не равен 1. Это объясняется в документации для функций триггера в Подробно .

Итак, давайте изменим вашу функцию на эту

xymat <- map_df(data.frame(degrees=seq(0,2*pi,length=360)), 
         function(theta) data.frame(x = sin(theta), y = cos(theta)))

Если вы наметите это, это действительно будет выглядеть как круг.

Давайте на самом деле ограничим это нижней половиной круга. Если вы проведете сплайн через это, не понимая симметрию и не глядя на график, есть вероятность, что вы получите горизонтальную линию через круг.

Почему? потому что сплайн не знает, что он симметричен выше и ниже y = 0. Сплайн пытается подогнать функцию, которая объясняет «данные», а не прослеживать дугу. Разбивает разницу между двумя симметричными наборами точек вокруг y = 0.

Если мы ограничим сплайн нижней половиной круга, мы можем использовать значения y от 1 до -1, например:

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 * пи.

Это не идеально, но у сплайнов есть проблемы с краевыми эффектами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...