Skip to content
Prev 27069 / 29559 Next

Sampling random directional lines within a polygon

Had another idea which is now implemented...

Consider any segmented path of segments of lengths L_i at angles A_i. Its
endpoint will be the vector sum of those segments, ie at (x,y) = (sum(L_i
cos(A_i)), sum(L_i sin(A_i)).

To create a segmented path to a given (x,y), solve that expression for the
angles A_i. In R you can treat this as an optimisation problem - find a set
of angles A_i that minimise the distance of the end of the segmented path
from the target end point.

Here's some code that does that for a path from 0,0 to 0,1:

pathit <- function(segments){
    obj = function(angles){
        dxdy = dxdy(segments, angles)
        xerr = dxdy$dx-1
        yerr = dxdy$dy
        err = sqrt(xerr^2 + yerr^2)
        err
    }
    angles = runif(length(segments), 0 , 2*pi)
    optim(angles, obj)
}

dxdy = function(segments, angles){
    dx = sum(segments * cos(angles))
    dy = sum(segments * sin(angles))
    list(dx=dx, dy=dy)
}

plotsegs <- function(segments, angles){
    x = rep(NA, length(segments) +1)
    y = x
    x[1] = 0
    y[1] = 0
    for(i in 2:(length(segments)+1)){
        x[i] = x[i-1] + segments[i-1]*cos(angles[i-1])
        y[i] = y[i-1] + segments[i-1]*sin(angles[i-1])
    }
    cbind(x,y)
}

This is deliberately written naively for clarity.

To use, set the segment sizes, optimise, and then plot:

 s1 = c(.1,.3,.2,.1,.3,.3,.1)
 a1 = pathit(s1)
 plot(plotsegs(s1,a1$par),type="l")

which should show a path of seven segments from 0,0 to 0,1 - since the
initial starting values are random the model can find different solutions.
Run again for a different path.

To see what the space of paths looks like, do lots and overplot them:

  lots = lapply(1:1000, function(i)plotsegs(s1,pathit(s1)$par))
  plot(c(-.1,1.1),c(-1,1))
  p = lapply(lots, function(xy){lines(xy)})

this should show 1000 paths, and illustrates the "ellipse" of path
possibles that I mentioned in the previous email.

Sometimes the optimiser struggles to find a solution and so you should
probably test the output from optim for convergence and to make sure the
target function is close enough to zero for your purposes.  For the example
above most of the time the end point is about 1e-5  from (1,0) but for
harder problems such as s = rep(.1, 11) which only has 0.1 of extra "slack"
length, the error can be 0.02 and failed convergence. Possibly longer optim
runs would help or constraining the angles.

Anyway, interesting problem....

Barry







On Wed, Feb 6, 2019 at 8:23 PM Barry Rowlingson <b.rowlingson at gmail.com>
wrote: