R: преобразование декартовых координат в полярные координаты, а затем вычисление расстояния от начала координат

Я искал решение для преобразования декартовых координат (широта, долгота), которые у меня есть, в полярные координаты, чтобы облегчить моделирование, которое я хочу запустить, но я не нашел здесь никаких вопросов или ответов, чтобы сделать это в R. Есть несколько вариантов, в том числе встроенная функция cart2pol в Matlab, но все мои данные находятся в R, и я хотел бы продолжать комфортно работать в этой структуре.

Вопрос:

У меня есть координаты широты и долготы из данных тегов, и я хочу преобразовать их в полярные координаты (то есть размер и угол перехода: http://en.wikipedia.org/wiki/Polar_coordinate_system), чтобы затем я мог перетасовать или загрузить их (еще не решил, какой) около 1000 раз и вычислить расстояние по прямой для каждой моделируемой дорожки. с начальной точки. У меня есть точный след, и мне интересно определить, проявляет ли это животное сходство с местом, путем моделирования 1000 случайных следов с теми же размерами прыжков и углами поворота, но в совершенно разных порядках и комбинациях. Итак, мне нужно 1000 расстояний по прямой от начала координат, чтобы создать распределение расстояний, а затем сравнить это с расстоянием по прямой линии моего истинного набора данных.

Мне удобно выполнять начальную загрузку, но я застрял на самом первом этапе, который заключается в преобразовании моих декартовых координат широты и долготы в полярные координаты (размер прыжка и угол поворота). Я знаю, что есть встроенные функции для этого в других программах, таких как Matlab, но я не могу найти способ сделать это в R. Я мог бы сделать это вручную вручную в цикле for, но если есть пакет там или любым более простым способом, я бы предпочел это.

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

Я не публиковал никаких образцов данных, так как это был бы просто двухколоночный фрейм данных с координатами широты и долготы.

Спасибо за любую помощь, которую вы можете оказать! Если где-то на этом или другом сайте есть простое объяснение, которое я пропустил, укажите мне, пожалуйста, в этом направлении! Ничего не нашел.

Ваше здоровье


person stewart6    schedule 03.05.2013    source источник
comment
Вы имеете в виду cart2pol функцию Matlab?   -  person Nishanth    schedule 03.05.2013
comment
Вам может быть интересен пакет circular: cran.r-project. org / web / packages / круговой / круговой.pdf   -  person Ricardo Saporta    schedule 03.05.2013
comment
Да, cart2pol. Я посмотрю на круглую упаковку, спасибо!   -  person stewart6    schedule 03.05.2013
comment
Почему ответ не просто: r= sqrt(x^2+y^2)? (А если вы не знаете обратное преобразование, просто посмотрите Википедию или любой текст по координатной геометрии?)   -  person IRTFM    schedule 03.05.2013
comment
@ 42 В реальном мире оси наклонены и начало координат не 0,0   -  person skan    schedule 05.02.2016
comment
Тогда r= sqrt( (x-x0)^2+(y-y0)^2) ... результат должен быть неизменным относительно вращение. Но если вопрос действительно о расстоянии от поверхности Земли, то оно будет сильно варьироваться в зависимости от широты, потому что широта и долгота обычно не являются декартовыми. Если бы все это были данные, собранные в небольшом диапазоне широт, то вы могли бы применить простой поправочный коэффициент косинуса ко всем значениям долготы перед выполнением вычислений.   -  person IRTFM    schedule 05.02.2016


Ответы (7)


Для координат x-y, которые находятся в одних и тех же единицах измерения (например, в метрах, а не в градусах широты и градусах долготы), вы можете использовать эту функцию для получения data.frame размеров прыжков и углов поворота (в градусах).

getSteps <- function(x,y) {
    d <- diff(complex(real = x, imaginary = y))
    data.frame(size = Mod(d), 
               angle = c(NA, diff(Arg(d)) %% (2*pi)) * 360/(2*pi))
}

## Try it out   
set.seed(1)
x <- rnorm(10)
y <- rnorm(10)
getSteps(x, y)
#        size     angle
# 1 1.3838360        NA
# 2 1.4356900 278.93771
# 3 2.9066189 101.98625
# 4 3.5714584 144.00231
# 5 1.6404354 114.73369
# 6 1.3082132 135.76778
# 7 0.9922699  74.09479
# 8 0.2036045 141.67541
# 9 0.9100189 337.43632

## A plot helps check that this works
plot(x, y, type = "n", asp = 1)
text(x, y, labels = 1:10)

введите описание изображения здесь

person Josh O'Brien    schedule 03.05.2013
comment
Привет, Джош, это отлично сработало для преобразования моих точек широты и долготы в размеры и углы шагов. Координаты широты и долготы имеют примерно одинаковое расстояние между градусами на экваторе, поэтому они, по сути, находятся в одних и тех же единицах. Как бы вы преобразовали обратно в декартовы координаты из фрейма данных с размерами и углами поворота (т.е. после того, как я их рандомизировал?) - person stewart6; 03.05.2013
comment
@ stewart6 - Для обратного преобразования преобразуйте ваши углы из градусов обратно в радианы (разделив на 360/(2*pi), а затем используйте sin() и cos() для перехода от полярных координат к координатам xy. Я оставлю это как хорошее упражнение для вас;) Кроме того, если вы действительно не работаете около экватора, будьте осторожны и не предполагайте, что градусы широты и долготы эквивалентны. Там, где я живу, около 45 широты, градусы долготы составляют лишь около 70% длины градусов широты ... - person Josh O'Brien; 03.05.2013
comment
Привет, Джош! Сегодня утром я работал над внедрением вашего решения и мне удалось получить разумно выглядящие результаты, но я считаю, что по какой-то причине данные, которые оно выплевывает, неверны ... Я опубликовал более подробную информацию ниже. Буду признателен за любые предложения! - person stewart6; 03.05.2013

Поскольку это довольно просто, вы можете написать свою собственную функцию. Matlab-подобная функция cart2pol в R:

cart2pol <- function(x, y)
{
  r <- sqrt(x^2 + y^2)
  t <- atan(y/x)

  c(r,t)
}
person Nishanth    schedule 03.05.2013
comment
При этом не учитываются углы от 90 до 270 градусов (в вашем коде они будут ошибаться). - person Yossi Farjoun; 23.08.2013
comment
В реальном мире оси наклонены, а начало координат не 0,0 - person skan; 05.02.2016

Я использовал код Джоша О'Брайена и получил, казалось бы, разумные прыжки и углы - они довольно хорошо соответствуют приблизительному расстоянию и направлению между точками. Затем я использовал формулу из его предложений, чтобы создать функцию, возвращающую полярные координаты обратно в декартовы координаты, и цикл for, чтобы применить эту функцию к фрейму данных всех полярных координат. Кажется, что циклы работают, и выходные данные указаны в правильных единицах, но я не верю, что значения, которые он выводит, соответствуют моим данным. Так что либо я ошибся в расчетах с формулой, либо происходит что-то еще. Более подробная информация ниже:

Вот заголовок моих длинных данных:

> head(Tag1SSM[,3:4])
       lon       lat
1 130.7940 -2.647957
2 130.7873 -2.602994
3 130.7697 -2.565903
4 130.7579 -2.520757
5 130.6911 -2.704841
6 130.7301 -2.752182

Когда я рисую полный набор данных в виде значений, я получаю следующий график: График широты и долготы

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

Затем я использовал функцию Джоша для преобразования моих данных в полярные координаты:

x<-Tag1SSM$lon
y<-Tag1SSM$lat

getSteps <- function(x,y) {
  d <- diff(complex(real = x, imaginary = y))
  data.frame(size = Mod(d), 
             angle = c(NA, diff(Arg(d)) %% (2*pi)) * 360/(2*pi))
}

который соответствующим образом произвел следующие полярные координаты:

> polcoords<-getSteps(x,y)
> head(polcoords)
        size     angle
1 0.04545627        NA
2 0.04103718  16.88852
3 0.04667590 349.38153
4 0.19581350 145.35439
5 0.06130271  59.37629
6 0.01619242  31.86359

Опять же, они мне кажутся правильными и хорошо соответствуют реальным углам и относительным расстояниям между точками. Все идет нормально.

Теперь я хочу преобразовать их обратно в декартовы координаты и вычислить евклидово расстояние от начала координат. Они не обязательно должны быть в истинной широте / долготе, я просто сравниваю их между собой. Поэтому я рад, что начало координат установлено как (0,0) и расстояния, которые будут вычисляться в справочных значениях x, y, а не в километрах или что-то в этом роде.

Итак, я использовал эту функцию с помощью Джоша и немного поиска в Интернете:

polar2cart<-function(x,y,size,angle){

  #convert degrees to radians (dividing by 360/2*pi, or multiplying by pi/180)
  angle=angle*pi/180
  if(is.na(x)) {x=0} #this is for the purpose of the for loop below
  if(is.na(y)) {y=0}
  newx<-x+size*sin(angle)  ##X #this is how you convert back to cartesian coordinates
  newy<-y+size*cos(angle)  ##Y
  return(c("x"=newx,"y"=newy)) #output the new x and y coordinates
}

А затем подключил его к циклу for:

u<-polcoords$size
v<-polcoords$angle
n<-162 #I want 162 new coordinates, starting from 0
N<-cbind(rep(NA,163),rep(NA,163)) #need to make 163 rows, though, for i+1 command below— first row will be NA
for(i in 1:n){
  jump<-polar2cart(N[i,1],N[i,2],u[i+1],v[i+1]) #use polar2cart function above, jump from previous coordinate in N vector 
  N[i+1,1]<-jump[1] #N[1,] will be NA's which sets the starting point to 0,0—new coords are then calculated from each previous N entry
  N[i+1,2]<-jump[2]
  Dist<-sqrt((N[163,1]^2)+(N[163,2]^2)) 
}

А затем я могу взглянуть на N с моими новыми координатами, основанными на этих прыжках:

> N
               [,1]        [,2]
  [1,]           NA          NA
  [2,]  0.011921732  0.03926732
  [3,]  0.003320851  0.08514394
  [4,]  0.114640605 -0.07594871
  [5,]  0.167393509 -0.04472125
  [6,]  0.175941466 -0.03096891

Вот где проблема ... координаты x, y от N постепенно увеличиваются - там есть небольшие вариации, но если вы прокрутите список вниз, y изменится от 0,39 до 11,133, с очень небольшими шагами назад, чтобы уменьшить ценности. Это не то, что делают мои данные широты и долготы, и если я правильно рассчитал cart-> pol и pol-> cart, эти новые значения из N должны соответствовать моим данным широты и долготы, только в другой системе координат. Вот как выглядят значения N на графике:

декартовы координаты с обратным преобразованием

Совсем не то же самое ... Последняя точка в N - самая дальняя точка от начала координат, в то время как в моих данных широты / долготы последняя точка на самом деле довольно близко к первой точке и определенно не самая дальняя точка. Я думаю, что проблема должна быть в моем преобразовании из полярных координат обратно в декартовы координаты, но я не уверен, как это исправить ...

Любая помощь в решении этой проблемы будет принята с благодарностью!

Ваше здоровье

person stewart6    schedule 03.05.2013
comment
Хорошая работа. Извините, у меня мало времени, но вот что мне впервые приходит в голову. Я ожидал увидеть что-то вроде v <- cumsum(polcoords$angle) вместо v <- polcoords$angle (после выполнения v[is.na(v)] <- 0, чтобы избавиться от НА). В конце концов, направление каждого прыжка - это совокупность всех предыдущих углов поворота, и я не думаю, что ваш код еще это отражает. Некоторое время я не смогу больше на это смотреть, поэтому я надеюсь, что я просто случайно наткнулся на (единственную) ошибку. - person Josh O'Brien; 03.05.2013
comment
Еще одна идея - пока вы создаете этот код, вы можете поиграть с очень простым набором прыжков. Я бы, наверное, построил и использовал data.frame, состоящий из 4 прыжков под прямым углом и пары прямых прыжков. Это упростит понимание того, в чем заключается ошибка в нашем коде. - person Josh O'Brien; 04.05.2013
comment
Привет, Джош, спасибо за предложения. Я посмотрю, что я могу придумать, и опубликую здесь решение или другие проблемы. Ваша помощь очень ценится! - person stewart6; 05.05.2013

Я думаю, что этот код, который я написал, преобразуется в полярные координаты:

# example data
x<-runif(30)
y<-runif(30)
# center example around 0
x<-x-mean(x)
y<-y-mean(y)

# function to convert to polar coordinates
topolar<-function(x,y){

    # calculate angles 
    alphas<-atan(y/x)

    # correct angles per quadrant
    quad2<-which(x<0&y>0)
    quad3<-which(x<0&y<0)
    quad4<-which(x>0&y<0)
    alphas[quad2]<-alphas[quad2]+pi
    alphas[quad3]<-alphas[quad3]+pi
    alphas[quad4]<-alphas[quad4]+2*pi

    # calculate distances to 0,0
    r<-sqrt(x^2+y^2)

    # create output
    polar<-data.frame(alphas=alphas,r=r)

}

# call function
polar_out<-topolar(x,y)
# get out angles
the_angles<-polar_out$alphas
person Jintram    schedule 29.05.2019

Я думаю, что вы можете сделать преобразование между катезианским и полярным способом следующим образом:

polar2cart <- function(r, theta) {
  data.frame(x = r * cos(theta), y = r * sin(theta))
}

cart2polar <- function(x, y) {
  data.frame(r = sqrt(x^2 + y^2), theta = atan2(y, x))
}
person Eyayaw    schedule 24.12.2020

Другой вариант только по степени

pol2car = function(angle, dist){
    co = dist*sin(angle)
    ca = dist*cos(angle)
    return(list(x=ca, y=co))
}
pol2car(angle = 45, dist = sqrt(2))
person Edwin Torres    schedule 18.08.2016

cart2sph {pracma} Преобразование между декартовой, сферической, полярной и цилиндрической системами координат в двух и трех измерениях.

person LBV    schedule 26.03.2021