Search code examples
roptimizationmathematical-optimization

how to calculate the radius of a trajectory with given 'x' and 'y' positions in R


I have trajectories of some moving objects in a data frame for example three trajectories were considered here as shown below:

> d1 <- data.frame(X1 = c(86.46, 79.88, 73.63, 67.63, 61.78, 56.05, 50.40, 44.80, 39.25, 33.79, 28.49, 23.40, 18.53, 13.84, 9.31, 5.04, 1.12), 
             Y1 = c(4.28, 5.49, 6.80, 8.16, 9.59, 11.18, 13.05, 15.28, 17.86, 20.81, 24.12, 27.75, 31.68, 35.87, 40.31, 44.92, 49.61))

> d2 <- data.frame(X2 = c(0.32, 4.00,  8.00, 12.31, 16.87, 21.64, 26.60, 31.75, 37.08, 42.62, 48.36, 54.33, 60.59, 67.25, 74.48, 82.42), 
             Y2 = c(57.55, 52.67, 47.98, 43.49, 39.24, 35.26, 31.59, 28.24, 25.19, 22.42, 19.92, 17.65, 15.55, 13.54, 11.54, 9.47))

> d3 <- data.frame(X3 = c(0.04, 1.76,  3.61, 5.63, 7.89, 10.42, 13.19, 16.14, 19.25, 22.61, 26.29, 30.35, 34.83, 39.71, 44.97, 50.58, 56.47, 62.56, 68.79, 75.19, 81.82),
             Y3 = c(58.34, 55.97, 53.49, 50.89, 48.15, 45.27, 42.35, 39.43, 36.50, 33.57, 30.66, 27.85, 25.18, 22.66, 20.27, 18.02, 15.94, 14.02, 12.22, 10.48, 8.83))


my.lists <- list(d1, d2, d3)

df12 <- do.call(qpcR:::cbind.na, my.lists) 

now I would like to calculate the radius of each trajectory in the df12 data frame. from each trajectory we can get useful parameters such as arc length and chord length as follows:

#for arc length
> library(geosphere) ## for calculating distance between successive points #step-1:

> d11 <-  data.frame(Distance = sqrt(diff(d1$X1)^2 + diff(d1$Y1)^2)) #step-2: 

> d11$csum1 <- ave(d11$Distance, FUN=cumsum) #step-3: 

#for chord length
> sqrt((d1[1,1]-d1[17,1])^2+(d1[1,2]-d1[17,2])^2)

is there any approach to calculate the radius of a trajectory?

thanks in advance


Solution

  • It is not completely clear what you mean with "radius of a trajectory". Here I assume you want to fit data points of a trajectory with a circle that runs through these points. We will look at your first example.

    library(pracma)
    x <- d1$X1; y <- d1$Y1              # data points
    res <- circlefit(x, y, fast=TRUE)   # "fitting a circle"
    res
    ## RMS error: 0.2696326 
    ## [1]  93.85894 123.25466 118.51384
    

    This computes a circle of radius r0 = 118.51384 and the center at (93.85894, 123.25466) with an RMS error of about 0.27. To visualize:

    x0 <- res[1]; y0 <- res[2]; r0 <- res[3]    # center and radius
    ts <- seq(0, 2*pi, length.out = 100)
    xs <- x0 + r0*cos(ts); ys <- y0 + r0*sin(ts)
    
    plot(xs, ys, type='l', col = "red", asp=1)
    points(x, y); grid()
    

    Do not use the fast = FALSE option in circlefit, the optimization process steered by optim() runs wild.

    You can also apply function CircleFitBy...() in package conicfit -- maybe that's even the better alternative. It depends also on what your preferred 'measure of fit' is.