Nothing
#'
#' lintessmakers.R
#'
#' Creation of linear tessellations
#' and intersections between lintess objects
#'
#' $Revision: 1.7 $ $Date: 2023/12/01 19:53:54 $
#'
divide.linnet <- local({
#' Divide a linear network into tiles demarcated by
#' the points of a point pattern
divide.linnet <- function(X) {
stopifnot(is.lpp(X))
L <- as.linnet(X)
coo <- coords(X)
#' add identifiers of endpoints
coo$from <- L$from[coo$seg]
coo$to <- L$to[coo$seg]
#' group data by segment, sort by increasing 'tp'
coo <- coo[with(coo, order(seg, tp)), , drop=FALSE]
bits <- split(coo, coo$seg)
#' expand as a sequence of intervals
bits <- lapply(bits, expanddata)
#' reassemble as data frame
df <- Reduce(rbind, bits)
#' find all undivided segments
other <- setdiff(seq_len(nsegments(L)), unique(coo$seg))
#' add a single line for each undivided segment
if(length(other) > 0)
df <- rbind(df, data.frame(seg=other, t0=0, t1=1,
from=L$from[other], to=L$to[other]))
#' We now have a tessellation
#' Sort again
df <- df[with(df, order(seg, t0)), , drop=FALSE]
#' Now identify connected components
#' Two intervals are connected if they share an endpoint
#' that is a vertex of the network.
nvert <- nvertices(L)
nbits <- nrow(df)
iedge <- jedge <- integer(0)
for(iv in seq_len(nvert)) {
joined <- with(df, which(from == iv | to == iv))
njoin <- length(joined)
if(njoin > 1)
iedge <- c(iedge, joined[-njoin])
jedge <- c(jedge, joined[-1L])
}
lab0 <- cocoEngine(nbits, iedge - 1L, jedge - 1L)
lab <- lab0 + 1L
lab <- as.integer(factor(lab))
df <- df[,c("seg", "t0", "t1")]
df$tile <- lab
return(lintess(L, df))
}
expanddata <- function(z) {
df <- with(z,
data.frame(seg=c(seg[1L], seg),
t0 = c(0, tp),
t1 = c(tp, 1),
from=NA_integer_,
to=NA_integer_))
df$from[1L] <- z$from[1L]
df$to[nrow(df)] <- z$to[1L]
return(df)
}
divide.linnet
})
intersect.lintess <- function(X, Y) {
## common refinement of two tessellations on linear network
if(is.tess(X)) {
## X is a 2-dimensional tessellation
## Y should contain linear network information
L <- as.linnet(Y)
## find tessellation on L induced by X
X <- traceTessLinnet(X, L)
if(is.linnet(Y)) return(X)
}
if(is.tess(Y)) {
## Y is a 2-dimensional tessellation
## X should contain linear network information
L <- as.linnet(X)
## find tessellation on L induced by Y
Y <- traceTessLinnet(Y, L)
if(is.linnet(X)) return(Y)
}
verifyclass(X, "lintess")
verifyclass(Y, "lintess")
if(!identical(as.linnet(X), as.linnet(Y)))
stop("X and Y must be defined on the same linear network")
L <- as.linnet(X)
ns <- nsegments(L)
marX <- marks(X)
marY <- marks(Y)
X <- X$df
Y <- Y$df
XY <- data.frame(seg=integer(0), t0=numeric(0), t1=numeric(0),
tile=character(0))
for(seg in seq_len(ns)) {
xx <- X[X$seg == seg, , drop=FALSE]
yy <- Y[Y$seg == seg, , drop=FALSE]
nxx <- nrow(xx)
nyy <- nrow(yy)
if(nxx > 0 && nyy > 0) {
for(i in 1:nxx) {
xxi <- xx[i,,drop=FALSE]
xr <- with(xxi, c(t0, t1))
for(j in 1:nyy) {
yyj <- yy[j,,drop=FALSE]
yr <- with(yyj, c(t0, t1))
zz <- intersect.ranges(xr, yr, fatal=FALSE)
if(!is.null(zz)) {
XY <- rbind(XY,
data.frame(seg=seg, t0=zz[1], t1=zz[2],
tile=paste0(xxi$tile, ":", yyj$tile)))
}
}
}
}
}
out <- lintess(L, XY)
if(!is.null(marX) || !is.null(marY)) {
## associate marks with TILES
XYtiles <- levels(out$df$tile)
posstiles <- outer(levels(X$tile), levels(Y$tile), paste, sep=":")
m <- match(XYtiles, as.character(posstiles))
if(anyNA(m)) stop("Internal error in matching tile labels")
xid <- as.integer(row(posstiles))[m]
yid <- as.integer(col(posstiles))[m]
marXid <- marksubset(marX, xid)
marYid <- marksubset(marY, yid)
if(is.null(marX)) {
marks(out) <- marYid
} else if(is.null(marY)) {
marks(out) <- marXid
} else {
if(identical(ncol(marX), 1L)) colnames(marXid) <- "marksX"
if(identical(ncol(marY), 1L)) colnames(marYid) <- "marksY"
marks(out) <- data.frame(marksX=marXid, marksY=marYid)
}
}
return(out)
}
traceTessLinnet <- function(A, L) {
## linear tessellation on network L induced by 2D tessellation A
stopifnot(is.tess(A))
stopifnot(is.linnet(L))
til <- solapply(tiles(A), as.polygonal)
ntil <- length(til)
if(A$type == "image" && ntil > 1) {
## ensure disjoint
tcum <- til[[1L]]
for(i in 2:ntil) {
til.i <- til[[i]]
if(!is.empty(til.i)) {
til[[i]] <- setminus.owin(til.i, tcum)
tcum <- union.owin(tcum, til.i)
}
}
}
## extract all edges of tiles
edg <- do.call(superimpose.psp, unname(solapply(til, edges)))
## extract segments on network
lin <- L$lines
## determine crossing points
xing <- as.lpp(unique(crossing.psp(edg, lin)), L=L)
## induce tessellation
D <- divide.linnet(xing)
df <- D$df
## create test points in the middle of each piece of segment
dfmid <- with(df, data.frame(seg=seg, tp=(t0+t1)/2))
Xmid <- lpp(dfmid, L)
## classify each test point in tessellation A
ind <- tileindex(as.ppp(Xmid), Z=A)
tn <- tilenames(A)
if(anyNA(ind)) {
## add a tile
tn <- c(tn, "<OTHER>")
ind[is.na(ind)] <- length(tn)
}
## create linear tessellation data
dfnew <- df
dfnew$tile <- factor(ind, levels=1:length(tn), labels=tn)
## return
Z <- lintess(L, dfnew)
return(Z)
}
chop.linnet <- function(X, L) {
X <- as.linnet(X)
verifyclass(L, "infline")
## convert infinite lines to segments
LS <- clip.infline(L, Frame(X))
linemap <- marks(LS) # line which generated each segment
## extract segments of network
XS <- as.psp(X)
## find crossing points (remembering provenance)
Y <- crossing.psp(LS, XS, fatal=FALSE, details=TRUE)
## initialise tessellation
Tess <- lintess(X)
if(is.null(Y) || npoints(Y) == 0)
return(Tess)
## extract info about network
V <- vertices(X)
startvertex <- X$from
nXS <- nsegments(XS)
segseq <- seq_len(nXS)
## allocate vertices to halfplanes defined by lines
Vin <- whichhalfplane(L, V)
## group crossing-points by the infinite line that made them
M <- marks(Y) # column names: iA, tA, jB, tB
MM <- split(M, linemap[M$iA], drop=FALSE)
#' for each infinite line,
#' make the tessellation induced by this line
for(i in seq_along(MM)) {
Mi <- MM[[i]]
if(is.data.frame(Mi) && (ni <- nrow(Mi)) > 0) {
#' for each segment, determine which end is in lower left halfplane
startsinside <- Vin[i, startvertex ]
if(anyNA(startsinside))
browser()
#' find segments of X that are split, and position of split
jj <- Mi$jB
tt <- Mi$tB
ss <- startsinside[jj]
#' assemble data for these segments: 2 entries for each split segment
inside <- paste0(i, ifelse(ss, "-", "+"))
outside <- paste0(i, ifelse(ss, "+", "-"))
df <- data.frame(seg=rep(jj, 2),
t0=c(rep(0, ni), tt),
t1=c(tt, rep(1, ni)),
tile=c(inside, outside))
#' segments not split
otherseg <- segseq[-jj]
#' segments entirely inside
otherin <- startsinside[otherseg]
#' tack on
if(any(otherin))
df <- rbind(df,
data.frame(seg=otherseg[otherin],
t0=0, t1=1, tile=paste0(i, "-")))
if(any(!otherin))
df <- rbind(df,
data.frame(seg=otherseg[!otherin],
t0=0, t1=1, tile=paste0(i, "+")))
#' make it a tessellation
Tessi <- lintess(X, df)
#' intersect with existing
Tess <- intersect.lintess(Tess, Tessi)
}
}
return(Tess)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.