https://github.com/cran/spatstat
Tip revision: 3aca716ce2576a0dab83f08052acd47afed8ee6a authored by Adrian Baddeley on 29 February 2012, 00:00:00 UTC
version 1.25-4
version 1.25-4
Tip revision: 3aca716
lineardisc.R
#
#
# disc.R
#
# $Revision: 1.12 $ $Date: 2011/07/26 08:14:35 $
#
# Compute the disc of radius r in a linear network
#
#
lineardisc <- function(L, x=locator(1), r, plotit=TRUE,
cols=c("blue", "red", "green")) {
# L is the linear network (object of class "linnet")
# x is the centre point of the disc
# r is the radius of the disc
#
stopifnot(inherits(L, "linnet"))
lines <- L$lines
vertices <- L$vertices
lengths <- lengths.psp(lines)
win <- L$window
#
# project x to nearest segment
if(missing(x))
x <- clickppp(1, win, add=TRUE)
else
x <- as.ppp(x, win)
pro <- project2segment(x, lines)
# which segment?
startsegment <- pro$mapXY
# parametric position of x along this segment
startfraction <- pro$tp
# vertices at each end of this segment
A <- L$from[startsegment]
B <- L$to[startsegment]
# distances from x to A and B
dxA <- startfraction * lengths[startsegment]
dxB <- (1-startfraction) * lengths[startsegment]
# is r large enough to reach both A and B?
startfilled <- (max(dxA, dxB) <= r)
# compute vector of shortest path distances from x to each vertex j,
# going through A:
dxAv <- dxA + L$dpath[A,]
# going through B:
dxBv <- dxB + L$dpath[B,]
# going either through A or through B:
dxv <- pmin(dxAv, dxBv)
# Thus dxv[j] is the shortest path distance from x to vertex j.
#
# Determine which vertices are inside the disc of radius r
covered <- (dxv <= r)
# Thus covered[j] is TRUE if the j-th vertex is inside the disc.
#
# Determine which line segments are completely inside the disc
#
from <- L$from
to <- L$to
# ( a line segment is inside the disc if the shortest distance
# from x to one of its endpoints, plus the length of the segment,
# is less than r ....
allinside <- (dxv[from] + lengths <= r) | (dxv[to] + lengths <= r)
# ... or alternatively, if the sum of the
# two residual distances exceeds the length of the segment )
residfrom <- pmax(0, r - dxv[from])
residto <- pmax(0, r - dxv[to])
allinside <- allinside | (residfrom + residto >= lengths)
# start segment is special
allinside[startsegment] <- startfilled
# Thus allinside[k] is TRUE if the k-th segment is inside the disc
# Collect all these segments
disclines <- lines[allinside]
#
# Determine which line segments cross the boundary of the disc
boundary <- (covered[from] | covered[to]) & !allinside
# For each of these, calculate the remaining distance at each end
resid.from <- ifelse(boundary, pmax(r - dxv[from], 0), 0)
resid.to <- ifelse(boundary, pmax(r - dxv[to], 0), 0)
# Where the remaining distance is nonzero, create segment and endpoint
okfrom <- (resid.from > 0)
okfrom[startsegment] <- FALSE
if(any(okfrom)) {
v0 <- vertices[from[okfrom]]
v1 <- vertices[to[okfrom]]
tp <- (resid.from/lengths)[okfrom]
vfrom <- ppp((1-tp)*v0$x + tp*v1$x,
(1-tp)*v0$y + tp*v1$y,
window=win)
extralinesfrom <- as.psp(from=v0, to=vfrom)
} else vfrom <- extralinesfrom <- NULL
#
okto <- (resid.to > 0)
okto[startsegment] <- FALSE
if(any(okto)) {
v0 <- vertices[to[okto]]
v1 <- vertices[from[okto]]
tp <- (resid.to/lengths)[okto]
vto <- ppp((1-tp)*v0$x + tp*v1$x,
(1-tp)*v0$y + tp*v1$y,
window=win)
extralinesto <- as.psp(from=v0, to=vto)
} else vto <- extralinesto <- NULL
#
# deal with special case where start segment is not fully covered
if(!startfilled) {
vA <- vertices[A]
vB <- vertices[B]
rfrac <- r/lengths[startsegment]
tleft <- pmax(startfraction-rfrac, 0)
tright <- pmin(startfraction+rfrac, 1)
vleft <- ppp((1-tleft) * vA$x + tleft * vB$x,
(1-tleft) * vA$y + tleft * vB$y,
window=win)
vright <- ppp((1-tright) * vA$x + tright * vB$x,
(1-tright) * vA$y + tright * vB$y,
window=win)
startline <- as.psp(from=vleft, to=vright)
startends <- superimpose(if(!covered[A]) vleft else NULL,
if(!covered[B]) vright else NULL)
} else startline <- startends <- NULL
#
# combine all lines
disclines <- superimpose(disclines,
extralinesfrom, extralinesto, startline,
W=win, check=FALSE)
# combine all disc endpoints
discends <- superimpose(vfrom, vto, vertices[dxv == r], startends,
W=win, check=FALSE)
#
if(plotit) {
points(x, col=cols[1], pch=16)
plot(disclines, add=TRUE, col=cols[2], lwd=2)
plot(discends, add=TRUE, col=cols[3], pch=16)
}
return(list(lines=disclines, endpoints=discends))
}
countends <- function(L, x=locator(1), r) {
# L is the linear network (object of class "linnet")
# x is the centre point of the disc
# r is the radius of the disc
#
stopifnot(inherits(L, "linnet"))
lines <- L$lines
vertices <- L$vertices
lengths <- lengths.psp(lines)
dpath <- L$dpath
win <- L$window
nv <- vertices$n
ns <- lines$n
# get x
if(missing(x))
x <- clickppp(1, win, add=TRUE)
else
x <- as.ppp(x, win)
#
np <- npoints(x)
if(length(r) != np)
stop("Length of vector r does not match number of points in x")
# project x to nearest segment
pro <- project2segment(x, lines)
# which segment?
startsegment <- pro$mapXY
# parametric position of x along this segment
startfraction <- pro$tp
# convert indices to C
seg0 <- startsegment - 1
from0 <- L$from - 1
to0 <- L$to - 1
zz <- .C("countends",
np = as.integer(np),
f = as.double(startfraction),
seg = as.integer(seg0),
r = as.double(r),
nv = as.integer(vertices$n),
xv = as.double(vertices$x),
yv = as.double(vertices$y),
ns = as.integer(ns),
from = as.integer(from0),
to = as.integer(to0),
dpath = as.double(dpath),
lengths = as.double(lengths),
nendpoints = as.integer(integer(np)),
PACKAGE="spatstat")
zz$nendpoints
}