4

Let's assume a line of segments of class SpatialLines of length len. This particular line starts at the upper left corner.

library(sp)
x <- structure(list(x = c(-7.23437435517476, 6.35937810318614, -5.86718660792582, 
                        7.96094089282062), y = c(7.08139459814975, 6.8633712983227, -7.61337581019376, 
                        -6.2180266913006)), .Names = c("x", "y"))

xline <- SpatialLines(list(Lines(Line(x), ID = 1)))
#len <- LineLength(as.matrix(data.frame(x)))
len <- LineLength(as.matrix(data.frame(coordinates(xline))))

plot(0,0, xlim = c(-10, 10), ylim = c(-10, 10), type = "n")
lines(xline)

find point on a line at desired distance from start

I would like to find a point on this line that is findme units away from the start of the line. For instance, if I were to look for a point that is 10 units along the line from the beginning, I would get a point near the node between first and second segment. Your input on a more robust solution most welcome.

I've tried to find it using spsample (see below), but this method is (too) unreliable and doesn't work for points the second half of the line.

# very approximate method, not very suitable
findme <- 11 # 11, 12 and 13 give same result
segs <- 1/(findme/xline.length)
xsam <- spsample(x = xline, n = segs, type = "regular", offset = 0)
points(xsam)
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
  • 1
    What is `xline.length`? Also, do you mean you want a point that is `findme` units along the path formed by the line? Or `findme` units as the crow flies? – Josh O'Brien Nov 13 '12 at 17:07
  • Sorry, `xline.length` is the total length of `xline` (I scrapped this approach and forgot to provide the `xline.length`). I want the point on that particular line. – Roman Luštrik Nov 13 '12 at 17:51

2 Answers2

4

The following steps will help you finding the coordinates.

General information of the lines:

library(np)

coord <- coordinates(xline)[[1]][[1]] 
nLines <- nrow(coord) - 1
#lengths <- sapply(seq_len(nLines), function(x) LineLength(coord[c(x, x + 1), ]))
lengths <- LineLength(coord, sum = FALSE)

Find the new coordinates:

findme <- 11 # the distance of the new coordinates

distances <- cumsum(lengths) - findme         # distances from the nodes
segment <- which(distances >= 0)[1]           # the segment of interest
distToNode <- distances[segment]
ratio <- distToNode / lengths[segment]
segCoord <- coord[c(segment, segment + 1), ]
newCoord <- (1 - ratio) * segCoord[2 , ] + ratio * segCoord[1 , ] 

Plot:

points(newCoord[1], newCoord[2])

enter image description here

Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
0

Could you:

  • Determine the order of the segments
  • Determine the length of each segment
  • Use the order and length to determine which segment the point is on
  • Subtract the start of the segment from the order * length (eg. if you know you're on the third segment, you'd subtract the length of the point where the third and second segments meet (which is just the sum of segment 1 and 2) from the start of the entire line). So, if you were trying to find the point at 7 units from the start of the line and the sum of segments 1 and 2 were 5, you'd be left with 2.
  • Then just use this method to deal with the only remaining segment to determine what the point is 2 units down that segment.

I'm sorry if this isn't the full solution. But maybe it'll give you an approach that is solvable.

Hope that helps...

Community
  • 1
  • 1
Homer6
  • 15,034
  • 11
  • 61
  • 81
  • Hehe, that's the method I'm trying to implement as we speak. :) – Roman Luštrik Nov 13 '12 at 17:52
  • Well.... the segment order is determined by your original set of (essentially) ordered pairs (x,y). Segment length calc is trivial. Now you know which segment contains your target distance. Use the point-slope method to find the coordinates of your desired distance. That should be simple enough :-) -- and pretty much what Sven did, I think. – Carl Witthoft Nov 13 '12 at 19:21