Nothing
drape3d <- function(obj, ...)
UseMethod("drape3d")
drape3d.default <- function(obj, ...)
drape3d(as.mesh3d(obj), ...)
drape3d.mesh3d <- function(obj, x, y = NULL, z = NULL,
plot = TRUE, up = c(0, 0, 1), P = projectDown(up), ...)
{
# Takes segment number as input; returns
# NULL if in no triangle, otherwise matrix of projected locations and triangle numbers.
ztri <- function(i) {
p <- psegs[,i]
oo <- p[1] < TRI[1,1,] | p[1] > TRI[2,1,] |
p[2] < TRI[1,2,] | p[2] > TRI[2,2,]
result <- NULL
lam <- numeric(3)
for(j in which(!oo)) {
## get barycentric coords of p in projected triangle
v <- pverts[,obj$it[,j]] ## v[i,] vertices of projected triangle i
D <- (v[2,2]-v[2,3]) * (v[1,1]-v[1,3]) +
(v[1,3]-v[1,2]) * (v[2,1]-v[2,3])
if (D == 0) next
l <- (v[2,2]-v[2,3]) * (p[1] -v[1,3]) +
(v[1,3]-v[1,2]) * (p[2] -v[2,3])
lam[1] <- l/D
if (lam[1] < 0 || lam[1] > 1) next ## not in this triangle
l <- (v[2,3]-v[2,1]) * (p[1] -v[1,3]) +
(v[1,1]-v[1,3]) * (p[2] -v[2,3])
lam[2] <- l/D
if (lam[2] < 0 || lam[2] > 1) next ## not in this triangle
lam[3] <- 1-sum(lam[1:2])
if (lam[3] < 0 || lam[3] > 1) next ## not in this triangle
v <- matrix(verts[,obj$it[,j]], 3,3) ## Now v is vertices of original triangle
result <- rbind(result, c(v %*% lam, j))
}
result
}
op <- function(v)
v[if(v[1] > v[2]) c(2,1) else c(1,2)] ## orders pair
obj <- as.tmesh3d(obj)
verts <- obj$vb
segs <- xyz.coords(x, y, z, recycle=TRUE)
segs <- rbind(segs$x, segs$y, segs$z, 1)
if (length(dim(P)) != 2 || !all(dim(P) == 4))
stop("P should be a homogeneous coordinate matrix.")
P <- t(P) # The convention in rgl is row vectors on the left
# but we'll be using column vectors on the right
# Project the vertices, then get 1st two Euclidean coords
pverts <- P %*% verts
pverts <- pverts[1:2,]/rep(pverts[4,], each = 2)
# and switch verts to Euclidean:
verts <- verts[1:3,]/rep(verts[4,], each = 3)
psegs <- P %*% segs # projected segments
psegs <- psegs[1:2,]/rep(psegs[4,], each = 2)
## get unique point pairs making a triangle side
tri <- matrix(NA,nrow=3*ncol(obj$it),ncol=2)
n <- 0
for (j in seq_len(ncol(obj$it))) {
v <- obj$it[,j]
tri[n<-n+1,] <- v[c(1,2)]
tri[n<-n+1,] <- v[c(2,3)]
tri[n<-n+1,] <- v[c(3,1)]
}
TRI <- array(NA,c(2,2,ncol(obj$it)))
for(j in seq_len(ncol(obj$it))) {
v <- obj$it[,j] ## vertices of triangle
TRI[,,j] <- matrix(c(range(pverts[1,v]),range(pverts[2,v])),2,2)
}
## now TRI[,1,i] is x coord range for projected triangle i
## now TRI[,2,i] is y coord range for projected triangle i
result <- matrix(numeric(), ncol = 3)
p2 <- NA
p2tri <- NULL
for (i in seq_len(ncol(psegs))) {
p1 <- p2
p1tri <- p2tri
if (!length(p1tri))
zs <- NULL
else
zs <- cbind(p1tri, 0) # First point
p2 <- psegs[,i]
if (any(is.na(p2))) {
p2tri <- NULL
next
} else {
p2tri <- ztri(i)
zs <- rbind(zs, cbind(p2tri, 1)) # Last point
}
if (any(is.na(p1)))
next
## add middle points
p21 <- p2 - p1
s <- matrix(c(p1,p2),2,2) ## speedup: winnow futile intersection calcs
s <- t(apply(s,1,op))
## triangle seg x extent is all below or above line seg x extent
sx <- (pverts[1,tri[,1]] < s[1,1] & pverts[1,tri[,2]] < s[1,1]) |
(pverts[1,tri[,1]] > s[1,2] & pverts[1,tri[,2]] > s[1,2])
## triangle seg y extent is all below or above line seg y extent
sy <- (pverts[2,tri[,1]] < s[2,1] & pverts[2,tri[,2]] < s[2,1]) |
(pverts[2,tri[,1]] > s[2,2] & pverts[2,tri[,2]] > s[2,2])
for(j in which(!sx & !sy)) { ## possible intersections
p3 <- pverts[,tri[j,1]]
p4 <- pverts[,tri[j,2]]
p43 <- p4-p3
p31 <- p3-p1
D <- -p21[1]*p43[2] + p21[2]*p43[1]
if (D == 0) next ## parallel line segs
T1<- -p31[1]*p43[2] + p31[2]*p43[1]
t1 <- T1/D
if (t1 < 0 || t1 > 1) next ## not within p1 ... p2
T2<- p21[1]*p31[2] - p21[2]*p31[1]
t2 <- T2/D
if (t2 < 0 || t2 > 1) next ## not within p3 ... p4
v3 <- verts[,tri[j,1]]
v43 <- verts[,tri[j,2]] - v3
k <- (j+2)%/%3 # triangle number
zs <- rbind(zs, c(v3+t2*v43, k, t1))## t1 along line seg & point value
}
if (length(zs)) {
# Order by triangle to group them, then by t
# within triangle
o <- order(zs[,4], zs[,5])
zs <- zs[o, , drop = FALSE]
# Only keep cases that are on the same triangle
# Rounding may give us 1 or 3 intersections with a
# triangle; discard singletons, use first and last
# for triples.
k <- zs[,4]
dup <- duplicated(k)
nextdup <- c(dup[-1], FALSE)
keep <- xor(dup, nextdup) # The first or last for a triangle
zs <- zs[keep,,drop = FALSE]
# Order by t value
finish <- 2*seq_len(nrow(zs)/2)
start <- finish - 1
o <- order(zs[start, 5])
start <- start[o]
finish <- finish[o]
# Drop zero length segments
keep <- zs[start, 5] < zs[finish, 5]
start <- start[keep]
finish <- finish[keep]
both <- as.numeric(rbind(start, finish))
result <- rbind(result, zs[both, -(4:5), drop = FALSE])
}
}
if (plot)
segments3d(result, ...)
else
result
}
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.