R:将笛卡尔坐标转换为极坐标,然后计算距离原点的距离

时间:2013-05-03 03:36:45

标签: r coordinates simulation polar-coordinates cartesian-coordinates

我一直在寻找一种解决方案,将我所拥有的笛卡尔坐标(lat,long)转换为极坐标,以便于我想要运行的模拟,但我没有在这里找到任何问题或答案在R中执行此操作。有许多选项,包括Matlab中的内置函数cart2pol,但我的所有数据都在R中,我希望继续在此框架中工作。

问题:

我有来自标记数据的lat / long坐标,我想将它们转换为极坐标(意思是跳转大小和角度:http://en.wikipedia.org/wiki/Polar_coordinate_system),这样我就可以随机播放或引导它们(还没决定哪个)大约1000次,并计算每个模拟轨道从起点的直线距离。我有一个真正的轨道,我有兴趣通过模拟具有相同跳跃大小和转向角度的1,000个随机轨道来确定这种动物是否表现出场地亲和力,但是在完全不同的顺序和组合中。因此,我需要距离原点1000个直线距离来创建距离分布,然后将其与我的真实数据集的直线距离进行比较。

我很自在地进行自举,但是我在第一步停留,即将我的笛卡尔纬度/长坐标转换为极坐标(跳跃大小和转弯角度)。我知道在Matlab等其他程序中有内置函数可以做到这一点,但我找不到任何方法在R中做到这一点。我可以手动在for循环中手动完成,但是如果有一个包出来的话有更简单的方法,我更喜欢这样做。

理想情况下,我想将数据转换为极坐标,运行模拟,然后为每个随机轨道输出一个终点作为笛卡尔坐标,纬度/经度,这样我就可以计算行进的直线距离。

我没有发布任何样本数据,因为它只是一个lat和long坐标的两列数据框。

感谢您提供的任何帮助!如果在这个网站的某个地方或我错过的其他地方有一个简单的解释,请指出我的方向!我找不到任何东西。

干杯

7 个答案:

答案 0 :(得分:7)

对于相同单位的x-y坐标(例如米而不是纬度和经度),您可以使用此函数获取跳跃大小和转角(以度为单位)的数据框。

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)

enter image description here

答案 1 :(得分:2)

由于它非常简单,你可以编写自己的函数。 R:

中类似Matlab的cart2pol函数
cart2pol <- function(x, y)
{
  r <- sqrt(x^2 + y^2)
  t <- atan(y/x)

  c(r,t)
}

答案 2 :(得分:1)

我使用了Josh O'Brien的代码并得到了看似合理的跳跃和角度 - 它们很好地匹配粗略的距离和点之间的前进。然后我使用他的建议中的公式来创建一个函数来将极坐标转回笛卡尔坐标,并使用for循环将函数应用于所有极坐标的数据框。循环似乎工作,输出是正确的单位,但我不相信它输出的值对应于我的数据。所以要么我对我的公式做了错误的计算,要么就是其他事情发生了。更多详情如下:

这是我的lat长数据的头部:

> 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

当我将完整数据集绘制为值时,我得到了这个图: Lat-Long Plot

看起来与我使用R中的任何空间或映射包进行绘图完全相同。

然后我使用Josh的函数将我的数据转换为极坐标:

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值而不是千米或类似的值中计算距离。

所以,我在Josh的帮助和一些网络搜索中使用了这个功能:

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

这就是问题所在......来自N的x,y坐标逐渐变大 - 那里有一点变化,但如果向下滚动列表,y从0.39变为11.133,向后很少降低价值的步骤。这不是我的lat / long数据所做的,如果我正确计算了cart-&gt; pol和pol-&gt; cart,那么来自N的这些新值应该匹配我的lat / long数据,只是在不同的坐标系中。这就是N值的样子:

back-converted cartesian coordinates

完全不一样...... N中的最后一点是距离原点最远的点,而在我的纬度/经度数据中,最后一点实际上非常接近第一点,绝对不是最远点远。我认为问题必须在我从极坐标转换回笛卡尔坐标,但我不确定如何解决它......

非常感谢任何解决此问题的帮助!

干杯

答案 3 :(得分:1)

我认为您可以通过这种方式在 catesian 和 polar 之间进行转换:

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

答案 4 :(得分:0)

仅在学位

中的另一种选择
pol2car = function(angle, dist){
    co = dist*sin(angle)
    ca = dist*cos(angle)
    return(list(x=ca, y=co))
}
pol2car(angle = 45, dist = sqrt(2))

答案 5 :(得分:0)

我认为我编写的这段代码将转换为极坐标:

# 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

答案 6 :(得分:0)

cart2sph {pracma} 在二维和三维的笛卡尔坐标系、球坐标系、极坐标系和圆柱坐标系之间进行转换。