R: Converting cartesian coordinates to polar coordinates, and then calculating distance from origin

后端 未结 5 1770
梦如初夏
梦如初夏 2021-02-15 23:39

I\'ve been looking for a solution to convert cartesian coordinates (lat, long) that I have to polar coordinates in order to facilitate a simulation that I want to run, but I hav

相关标签:
5条回答
  • 2021-02-15 23:49

    I used Josh O'Brien's code and got what appear to be reasonable jumps and angles—they match up pretty well to eyeballing the rough distance and heading between points. I then used a formula from his suggestions to create a function to turn the polar coordinates back to cartesian coordinates, and a for loop to apply the function to the data frame of all of the polar coordinates. The loops appear to work, and the outputs are in the correct units, but I don't believe the values that it's outputting are corresponding to my data. So either I did a miscalculation with my formula, or there's something else going on. More details below:

    Here's the head of my lat long data:

    > 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
    

    When I plot the full dataset just as values, I get this plot: Lat-Long Plot

    which looks exactly the same as if I were to plot this using any spatial or mapping package in R.

    I then used Josh's function to convert my data to polar coordinates:

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

    which produced the following polar coordinates appropriately:

    > 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
    

    Again, these look right to me, and correspond well to the actual angles and relative distances between points. So far so good.

    Now I want to convert these back to cartesian coordinates and calculate a euclidian distance from the origin. These don't have to be in true lat/long, as I'm just comparing them amongst themselves. So I'm happy for the origin to be set as (0,0) and for distances to be calculated in reference x,y values instead of kilometers or something like that.

    So, I used this function with Josh's help and a bit of web searching:

    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
    }
    

    And then plugged it into this for loop:

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

    And then I can take a look at N, with my new coordinates based on those jumps:

    > 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
    

    This is where the problem is... the x,y coordinates from N get progressively larger—there's a bit of variation in there, but if you scroll down the list, y goes from 0.39 to 11.133, with very few backward steps to lower values. This isn't what my lat/long data do, and if I calculated the cart->pol and pol->cart properly, these new values from N should match my lat/long data, just in a different coordinate system. This is what the N values look like plotted:

    back-converted cartesian coordinates

    Not the same at all... The last point in N is the farthest point from the origin, while in my lat/long data, the last point is actually quite close to the first point, and definitely not the farthest point away. I think the issue must be in my conversion from polar coordinates back to cartesian coordinates, but I'm not sure how to fix it...

    Any help in solving this would be much appreciated!

    Cheers

    0 讨论(0)
  • 2021-02-15 23:59

    Since it is fairly straight forward, you can write your own function. Matlab-like cart2pol function in R:

    cart2pol <- function(x, y)
    {
      r <- sqrt(x^2 + y^2)
      t <- atan(y/x)
    
      c(r,t)
    }
    
    0 讨论(0)
  • 2021-02-16 00:01

    I think this code I wrote converts to polar coordinates:

    # 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
    
    0 讨论(0)
  • 2021-02-16 00:12

    For x-y coordinates that are in the same units (e.g. meters rather than degrees of latitude and degrees of longitude), you can use this function to get a data.frame of jump sizes and turning angles (in degrees).

    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

    0 讨论(0)
  • 2021-02-16 00:13

    I think you can do transformation bewteen catesian and polar this way:

    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))
    }
    
    0 讨论(0)
提交回复
热议问题