geometry/ 0000755 0001762 0000144 00000000000 14751753072 012120 5 ustar ligges users geometry/tests/ 0000755 0001762 0000144 00000000000 13432270466 013256 5 ustar ligges users geometry/tests/testthat/ 0000755 0001762 0000144 00000000000 14751753072 015122 5 ustar ligges users geometry/tests/testthat/test-pol2cart.R 0000644 0001762 0000144 00000006145 13432317404 017744 0 ustar ligges users context("pol2cart")
test_that("pol2cart works correctly", {
t <- c(0, 0.5, 1)*pi
r <- 1
C <- pol2cart(t, r)
expect_equal(C[,"x"], c(1, 0, -1))
expect_equal(C[,"y"], c(0, 1, 0))
t <- c(0, 1, 1)*pi/4
r <- sqrt(2)*c(0, 1, 2)
C <- pol2cart(t, r)
expect_equal(C[,"x"], c(0, 1, 2))
expect_equal(C[,"y"], c(0, 1, 2))
t <- c(0, 1, 1)*pi/4
r <- sqrt(2)*c(0, 1, 2)
z <- c(0, 1, 2)
C <- pol2cart(t, r, z)
expect_equal(C[,"x"], c(0, 1, 2))
expect_equal(C[,"y"], c(0, 1, 2))
expect_equal(C[,"z"], z)
t <- 0
r <- c(0, 1, 2)
z <- c(0, 1, 2)
C <- pol2cart (t, r, z)
expect_equal (C[,"x"], c(0, 1, 2))
expect_equal (C[,"y"], c(0, 0, 0))
expect_equal (C[,"z"], z)
t <- c(1, 1, 1)*pi/4
r <- 1
z <- c(0, 1, 2)
C <- pol2cart (t, r, z)
expect_equal(C[,"x"], c(1, 1, 1)/sqrt(2))
expect_equal(C[,"y"], c(1, 1, 1)/sqrt(2))
expect_equal(C[,"z"], z)
t <- 0
r <- c(1, 2, 3)
z <- 1
C <- pol2cart (t, r, z)
expect_equal(C[,"x"], c(1, 2, 3))
expect_equal(C[,"y"], c(0, 0, 0)/sqrt (2))
expect_equal(C[,"z"], c(1, 1, 1))
P <- rbind(c(theta=0, r=0),
c(pi/4, sqrt(2)),
c(pi/4, 2*sqrt(2)))
C <- rbind(c(x=0, y=0),
c(1, 1),
c(2, 2))
expect_equal(pol2cart(P), C)
## %!test
## %! P <- c(0, 0, 0 pi/4, sqrt(2), 1 pi/4, 2*sqrt(2), 2)
## %! C <- c(0, 0, 0 1, 1, 1 2, 2, 2)
## %! expect_equal (pol2cart (P), C, sqrt (eps))
## %!test
## %! r <- ones (1, 1, 1, 2)
## %! r(1, 1, 1, 2) <- 2
## %! t <- pi/2 * r
## %! c(x, y) <- pol2cart (t, r)
## %! X <- zeros (1, 1, 1, 2)
## %! X(1, 1, 1, 2) <- -2
## %! Y <- zeros (1, 1, 1, 2)
## %! Y(1, 1, 1, 1) <- 1
## %! expect_equal (C[,"x"], X, 2*eps)
## %! expect_equal (C[,"y"], Y, 2*eps)
## %!test
## %! c(t, r, Z) <- meshgrid (c(0, pi/2), c(1, 2), c(0, 1))
## %! c(x, y, z) <- pol2cart (t, r, Z)
## %! X <- zeros(2, 2, 2)
## %! X(:, 1, 1) <- c(1 2)
## %! X(:, 1, 2) <- c(1 2)
## %! Y <- zeros(2, 2, 2)
## %! Y(:, 2, 1) <- c(1 2)
## %! Y(:, 2, 2) <- c(1 2)
## %! expect_equal (C[,"x"], X, eps)
## %! expect_equal (C[,"y"], Y, eps)
## %! expect_equal (z, Z)
## Test input validation
expect_error(pol2cart())
expect_error(pol2cart(1,2,3,4))
expect_error(pol2cart(list(1,2,3)), regexp="input must be matrix with 2 or 3 columns")
## %expect_error pol2cart (ones (3,3,2))
## %expect_error pol2cart (c(1))
## %expect_error pol2cart (c(1,2,3,4))
## %expect_error pol2cart ({1,2,3}, c(1,2,3))
## %expect_error pol2cart (c(1,2,3), {1,2,3})
## %expect_error pol2cart (ones (3,3,3), ones (3,2,3))
## %expect_error pol2cart ({1,2,3}, c(1,2,3), c(1,2,3))
## %expect_error pol2cart (c(1,2,3), {1,2,3}, c(1,2,3))
## %expect_error pol2cart (c(1,2,3), c(1,2,3), {1,2,3})
## %expect_error pol2cart (ones (3,3,3), 1, ones (3,2,3))
## %expect_error pol2cart (ones (3,3,3), ones (3,2,3), 1)
})
geometry/tests/testthat/test-tsearch-tsearchn-comparison.R 0000644 0001762 0000144 00000000735 14662314120 023621 0 ustar ligges users context("Comparison of tsearch and tsearchn")
test_that("tsearch and tsearchn give the same results", {
set.seed(1)
X <- runif(50)
Y <- runif(50)
T <- delaunayn(cbind(X, Y))
XI <- runif(1000)
YI <- runif(1000)
out <- tsearch(X, Y, T, XI, YI)
outn <- tsearchn(cbind(X, Y), T, cbind(XI, YI), fast=FALSE)
expect_equal(na.omit(out), na.omit(outn$idx))
out <- tsearch(X, Y, T, XI, YI, TRUE)
expect_equal(na.omit(outn$p), na.omit(out$p), tolerance=1e-12)
})
geometry/tests/testthat/test-convhulln.R 0000644 0001762 0000144 00000011077 14664417655 020247 0 ustar ligges users context("convhulln")
test_that("convhulln works on a cube", {
## Cube with unit length edges, centred on the origin
ps <- rbox(0, C=0.5)
ts <- convhulln(ps)
## Expect 12 facets, since faceted output is produced by default
expect_equal(nrow(ts), 12)
## When "FA" is specified area and volume should be returned
ts <- convhulln(ps, "FA")
expect_equal(length(ts), 4)
expect_equal(ts$area, 6)
expect_equal(ts$vol, 1)
## When "n" is specified normals should be returned
ts <- convhulln(ps, "n")
expect_equal(length(ts), 3)
## There are 12 normals, one for each facet. There are 6 *unique*
## normals, since for each face of the cube there are two triangular
## facets with the same normal
expect_equal(ts$normals,
rbind(c( 0, 0, -1, -0.5),
c( 0, 0, -1, -0.5),
c( 0, -1, 0, -0.5),
c( 0, -1, 0, -0.5),
c( 1, 0, 0, -0.5),
c( 1, 0, 0, -0.5),
c( -1, 0, 0, -0.5),
c( -1, 0, 0, -0.5),
c( 0, 1, 0, -0.5),
c( 0, 1, 0, -0.5),
c( 0, 0, 1, -0.5),
c( 0, 0, 1, -0.5)))
})
test_that("convhulln works on a cube with output.options", {
## Cube with unit length edges, centred on the origin
ps <- rbox(0, C=0.5)
ts <- convhulln(ps)
## Expect 12 facets, since faceted output is produced by default
expect_equal(nrow(ts), 12)
## When "FA" is specified area and volume should be returned
ts <- convhulln(ps, output.options="FA")
expect_equal(length(ts), 4)
expect_equal(ts$area, 6)
expect_equal(ts$vol, 1)
## When "n" is specified normals should be returned
ts <- convhulln(ps, output.options="n")
expect_equal(length(ts), 3)
## There are 12 normals, one for each facet. There are 6 *unique*
## normals, since for each face of the cube there are two triangular
## facets with the same normal
expect_equal(ts$normals,
rbind(c( 0, 0, -1, -0.5),
c( 0, 0, -1, -0.5),
c( 0, -1, 0, -0.5),
c( 0, -1, 0, -0.5),
c( 1, 0, 0, -0.5),
c( 1, 0, 0, -0.5),
c( -1, 0, 0, -0.5),
c( -1, 0, 0, -0.5),
c( 0, 1, 0, -0.5),
c( 0, 1, 0, -0.5),
c( 0, 0, 1, -0.5),
c( 0, 0, 1, -0.5)))
ts <- convhulln(ps, output.options=TRUE)
expect_equal(length(ts), 5)
})
test_that("convhulln can run on an example with 3000 points", {
set.seed(1)
ps <- matrix(rnorm(3000), ncol=3)
ps <- sqrt(3)*ps/drop(sqrt((ps^2) %*% rep(1,3)))
ts <- convhulln(ps)
expect_identical(nrow(ts), 1996L)
ts.full <- convhulln(ps, "FA")
expect_equal(ts.full$area, 37.47065, tolerance=0.001)
expect_equal(ts.full$vol, 21.50165, tolerance=0.001)
})
## Qhull 8.0.2 no longer complains about duplicated points being passed to qhullNewQhull
## test_that("convhulln throws an error with duplicated points", {
## load(file.path(system.file(package="geometry"), "extdata", "ordination.Rdata"))
## expect_error(out <- convhulln(ordination), "QH6114 qhull precision error: initial simplex is not convex")
## })
test_that("If the input matrix contains NAs, convhulln should return an error", {
ps <- matrix(rnorm(999), ncol=3)
ps <- sqrt(3)*ps/drop(sqrt((ps^2) %*% rep(1,3)))
ps <- rbind(ps, NA)
expect_error(convhulln(ps))
})
test_that("If there are not enough points to construct a simplex, an error is thrown", {
expect_error(convhulln(diag(4)))
})
test_that("Output to file works", {
## To prevent regression in package betapart
fname <- path.expand(file.path(tempdir(), "vert.txt"))
unlink(fname)
tr <- rbind(c(3,1),c(2,1),c(4,3),c(4,2))
convhulln(tr, paste0("Fx TO '", fname, "'"))
expect_true(file.exists(fname))
vert <- scan(fname, quiet=TRUE)
expect_equal(vert, c(4, 2, 1, 0, 3))
})
test_that("Output of non-triangulated facets works", {
X1 <- matrix(c( 1, 1, 1,
1, 1, -1,
1, -1, 1,
1, -1, -1,
-1, 1, 1,
-1, 1, -1,
-1, -1, 1,
-1, -1, -1,
3, 0, 0), ncol=3, byrow = TRUE)
ts1 <- convhulln(X1, return.non.triangulated.facets = TRUE)
tbl1 <- table(rowSums(!is.na(ts1)))
expect_equal(names(tbl1), c("3", "4"))
expect_equal(as.numeric(tbl1), c(4, 5))
})
geometry/tests/testthat/test-tsearch.R 0000644 0001762 0000144 00000013206 14664423323 017651 0 ustar ligges users context("tsearch")
test_that("tsearch gives the expected output", {
x <- c(-1, -1, 1)
y <- c(-1, 1, -1)
p <- cbind(x, y)
tri <- matrix(c(1, 2, 3), 1, 3)
## Should be in triangle #1
ts <- tsearch(x, y, tri, -1, -1)
expect_equal(ts, 1)
## Should be in triangle #1
ts <- tsearch(x, y, tri, 1, -1)
expect_equal(ts, 1)
## Should be in triangle #1
ts <- tsearch(x, y, tri, -1, 1)
expect_equal(ts, 1)
## Centroid
ts <- tsearch(x, y, tri, -1/3, -1/3)
expect_equal(ts, 1)
## Should be outside triangle #1, so should return NA
ts <- tsearch(x, y, tri, 1, 1)
expect_true(is.na(ts))
})
test_that("tsearch can deal with faulty input", {
x <- c(-1, -1, 1)
y <- c(-1, 1, -1)
p <- cbind(x, y)
tri <- matrix(c(1, 2, 3), 1, 3)
## NULLs and NAs
## expect_error(tsearch(x, y, tri, NA, NA))
expect_error(tsearch(x, y, NA, -1, 1))
expect_error(tsearch(NA, NA, tri, -1, 1))
expect_error(tsearch(x, y, tri, NULL, NULL))
expect_error(tsearch(x, y, NULL, -1, 1))
expect_error(tsearch(NULL, NULL, tri, -1, 1))
## Wrong number of columns
expect_error(tsearch(p, 0, tri, -1, 1))
## Non-integer triangulation
expect_error(tsearch(x, y, matrix(runif(15), 5, 3), -1, 1), regexp="does not have integer elements")
## Wrong number of columns in triangulation
expect_error(tsearch(x, y, matrix(1:4, 4, 2), -1, 1))
## Mismatch in x and y lengths
expect_error(tsearch(x, y[-1], tri, -1, 1))
## Mismatch in xi and yi lengths
expect_error(tsearch(x, y, tri, c(-1, 1), 1))
## A subtle one! This gives numeric(0) as the final arguments and
## should give idx with no elements and a 0x3 matrix for p
ps <- matrix(0, 0, 2)
expect_equal(tsearch(x, y, tri, ps[,1], ps[,2], bary=TRUE),
list(idx=integer(0), p=matrix(0, 0, 3)))
})
## See
## http://totologic.blogspot.co.uk/2014/01/accurate-point-in-triangle-test.html
## for inspiration for the test below
test_that("tsearch gives the expected output when computer precision problem arise", {
# ==== Hand made test ====
x1 <- 1/10
y1 <- 1/9
x2 <- 100/8
y2 <- 100/3
P <- rbind(c(x1, y1), c(x2, y2), c(100/4, 100/9), c(-100/8, 100/6))
# And a single point p(x, y) lying exactly on the segment [p1, p2] :
xi <- x1 + (3/7)*(x2 - x1)
yi <- y1 + (3/7)*(y2 - y1)
# Should always give triangle 2 since this is the lastest tested
tri1 <- rbind(1:3, c(1, 2, 4))
ts <- tsearch(P[,1], P[,2], tri1, xi, yi)
expect_equal(ts, 2)
tri2 <- rbind(c(1, 2, 4), 1:3)
ts <- tsearch(P[,1], P[,2], tri2, xi, yi)
expect_equal(ts, 2)
# The same but with only one triangle
P <- rbind(c(x1, y1), c(x2, y2), c(100/4, 100/9))
tri <- matrix(c(1, 2, 3), 1, 3)
ts <- tsearch(P[,1], P[,2], tri, xi, yi)
expect_equal(ts, 1)
tri <- matrix(c(3, 2, 1), 1, 3)
ts <- tsearch(P[,1], P[,2], tri, xi, yi)
expect_equal(ts, 1)
# The same but with the other triangle
P <- rbind(c(x2, y2), c(100/4, 100/9), c(-100/8, 100/6))
tri <- matrix(c(1, 2, 3), 1, 3)
ts <- tsearch(P[,1], P[,2], tri, xi, yi)
expect_equal(ts, 1)
tri <- matrix(c(3, 2, 1), 1, 3)
ts <- tsearch(P[,1], P[,2], tri, xi, yi)
expect_equal(ts, 1)
# Another test
x <- c(6.89, 7.15, 7.03)
y <- c(7.76, 7.75, 8.35)
tri <- matrix(c(1, 2, 3), 1, 3)
ts <- tsearch(x, y, tri, 7.125, 7.875)
expect_equal(ts, 1)
# ==== Test known to bug in former code ====
x <- c(278287.03, 278286.89, 278287.15, 278287.3)
y <- c(602248.35, 602247.76, 602247.75, 602248.35)
xi = 278287.125
yi = 602247.875
# Should always give triangle 2 but here it does not work
tri = rbind(c(3,1,4), c(3,1,2))
ts <- tsearch(x, y, tri, xi, yi)
expect_equal(ts, 2)
tri = rbind(c(1,2,3), c(1,3,4))
ts <- tsearch(x, y, tri, xi, yi)
expect_equal(ts, 1)
# This is because the buffer epsilon is 1.0e-12.
x <- c(278287.03, 278287.15, 278287.3)
y <- c(602248.35, 602247.75, 602248.35)
tri <- matrix(c(1, 2, 3), 1, 3)
ts <- tsearch(x, y, tri, xi, yi)
expect_true(is.na(ts))
#expect_equal(ts, 1) #With epsilon = 1.0e-10 it works.
})
test_that("no regression on Issue #39", {
## See https://github.com/davidcsterratt/geometry/issues/39
## vertices
P <- rbind(
c(373.8112, 4673.726), #31
c(222.9705, 4280.085), #32
c(291.0508, 4476.996), #42
c(553.4783, 4523.605), #43
c(222.6388, 4023.920), #44
c(445.2401, 4370.940), #48
c(81.54986, 4125.393)) #61
## I found this error on my system with Ubuntu 16.04, R 3.4.1 and
## `geometry_0.4.2`. `geometry_0.4.0` gave the same error). The error
## persists on Windows 10 with R 3.6.1.
## triangulation
T <- rbind(
c(3, 2, 6),
c(5, 2, 7),
c(4, 1, 3))
## data
data <- rbind(
c(221.6, 4171.8),
c(250.4, 4311.8),
c(496.6, 4516.2),
c(254.0, 4294.8),
c(199.4, 4072.6))
## With bug returns NA for datapoints 3 and 5
expect_equal(tsearch(P[,1], P[,2],T, data[,1], data[,2]), c(2, 1, 3, 1, 2))
data2 <- rbind(
c(221.6, 4171.8),
c(250.4, 4311.8),
c(496.6, 4516.2),
c(254.0, 4294.8),
c(199.4, 4072.0)) #note that only the Y coordinate of datapoint 5 was changed
expect_equal(tsearch(P[,1], P[,2],T, data2[,1], data2[,2]), c(2, 1, 3, 1, 2))
})
test_that("no regression on Issue #57", {
load(file.path(system.file(package="geometry"), "extdata", "issue57-tsearch.RData"))
dn <- delaunayn(P, options = "")
tri <- tsearch(P[, "XCoord"], P[, "YCoord"], dn, Pi[, "XCoord"], Pi[, "YCoord"], bary = T)
tri2 <- tsearch(P[, "XCoord"], P[, "YCoord"], dn, Pi[, "XCoord"], Pi[, "YCoord"], bary = T, method = "orig")
## trimesh(dn, P[,"XCoord"], P[, "YCoord"])
## points(P[,"XCoord"], P[,"YCoord"], col='red')
expect_equal(tri, tri2)
})
geometry/tests/testthat/test-polyarea.R 0000644 0001762 0000144 00000000505 14662314120 020022 0 ustar ligges users context("polyarea")
test_that("ployarea computes the area of two identical squares", {
x <- c(1, 1, 3, 3, 1)
y <- c(1, 3, 3, 1, 1)
expect_equal(polyarea(cbind(x, x), cbind(y, y)), c(4, 4))
expect_equal(polyarea(cbind(x, x), cbind(y, y), 1), c(4, 4))
expect_equal(polyarea(rbind(x, x), rbind(y, y), 2), c(4, 4))
})
geometry/tests/testthat/test-inhulln.R 0000644 0001762 0000144 00000002260 14662314120 017657 0 ustar ligges users context("inhulln")
test_that("inhulln gives the expected output", {
## Basic test
x <- c(-1, -1, 1)
y <- c(-1, 1, -1)
p <- cbind(x, y)
ch <- convhulln(p)
## Should be in hull
pin <- inhulln(ch, cbind(-0.5, -0.5))
expect_true(pin)
## Should be outside hull
pout <- inhulln(ch, cbind(1, 1))
expect_false(pout)
## Erroneous input is caught safely
expect_error(inhulln(1, 2), "Convex hull has no convhulln attribute")
expect_error(inhulln(ch, rbind(1, 1)), "Number of columns in test points p (1) not equal to dimension of hull (2).", fixed=TRUE)
expect_error(inhulln(ch, cbind(1, 1, 1)), "Number of columns in test points p (3) not equal to dimension of hull (2).", fixed=TRUE)
## Test cube
p <- rbox(n=0, D=3, C=1)
ch <- convhulln(p)
tp <- cbind(seq(-1.9, 1.9, by=0.2), 0, 0)
pin <- inhulln(ch, tp)
## Points on x-axis should be in box only between -1 and 1
expect_equal(pin, tp[,1] < 1 & tp[,1] > -1)
## Test hypercube
p <- rbox(n=0, D=4, C=1)
ch <- convhulln(p)
tp <- cbind(seq(-1.9, 1.9, by=0.2), 0, 0, 0)
pin <- inhulln(ch, tp)
## Points on x-axis should be in box only between -1 and 1
expect_equal(pin, tp[,1] < 1 & tp[,1] > -1)
})
geometry/tests/testthat/test-extprod3d.R 0000644 0001762 0000144 00000001431 13432317404 020123 0 ustar ligges users ## Based on Octave tests for cross.m
## http://hg.savannah.gnu.org/hgweb/octave/file/c2ef0eddf6bc/scripts/linear-algebra/cross.m
context("extprod3d")
test_that("extprod3d gives the expected output", {
x <- c(1, 0, 0)
y <- c(0, 1, 0)
r <- c(0, 0, 1)
expect_equal(extprod3d(x, y), r)
expect_equal(extprod3d(x, y, drop=FALSE), t(r))
x <- c(1, 2, 3)
y <- c(4, 5, 6)
r <- c((2*6-3*5), (3*4-1*6), (1*5-2*4))
expect_equal(extprod3d(x, y), r)
x <- rbind(c(1, 0, 0),
c(0, 1, 0),
c(0, 0, 1))
y <- rbind(c(0, 1, 0),
c(0, 0, 1),
c(1, 0, 0))
r <- rbind(c(0, 0, 1),
c(1, 0, 0),
c(0, 1, 0))
expect_equal(extprod3d(x, y), r)
##error extprod3d (0,0)
##error extprod3d ()
})
geometry/tests/testthat/test-halfspacen.R 0000644 0001762 0000144 00000005340 13432317404 020316 0 ustar ligges users context("halfspacen")
test_that("halfspacen works on a cube", {
## Cube with unit length edges, centred on the origin
ps <- rbox(0, C=0.5)
## Convex hull. When "n" is specified normals should be returned
ch <- convhulln(ps, "n")
## Intersections of half planes
## These points should be the same as the orginal points
pn <- halfspacen(ch$normals, c(0, 0, 0))
## Convex hull of these points should have same characteristics as original cube
ts <- convhulln(pn, "FA")
expect_equal(ts$area, 6)
expect_equal(ts$vol, 1)
## If the feasible point is outwith the normlas to the cube, an
## error should be thrown
expect_error(halfspacen(ch$normals, c(1, 1, 1)))
})
test_that("halfspacen works on a cube with non triangulated facets", {
## Cube with unit length edges, centred on the origin
ps <- rbox(0, C=0.5)
## Convex hull. When "n" is specified normals should be returned
ch <- convhulln(ps, "n", return.non.triangulated.facets=TRUE)
## Intersections of half planes
## These points should be the same as the orginal points
pn <- halfspacen(ch$normals, c(0, 0, 0))
## Convex hull of these points should have same characteristics as original cube
ts <- convhulln(pn, "FA")
expect_equal(ts$area, 6)
expect_equal(ts$vol, 1)
## If the feasible point is outwith the normlas to the cube, an
## error should be thrown
expect_error(halfspacen(ch$normals, c(1, 1, 1)))
})
test_that("halfspacen can compute volume of intersection of halfspaces", {
## Cube with unit length edges, centred on the origin
ps1 <- rbox(0, C=0.5)
## Cube with unit length edges, centred on the (0.5, 0.5, 0.5)
ps2 <- rbox(0, C=0.5) + 0.5
## Convex hulls with normals
ch1 <- convhulln(ps1, "n", return.non.triangulated.facets=TRUE)
ch2 <- convhulln(ps2, "n", return.non.triangulated.facets=TRUE)
## Intersection of merged halfspaces
pn <- halfspacen(rbind(ch1$normals, ch2$normals), c(0.25, 0.25, 0.25))
## Convex hull of these points should be cube with vertices at
## intersection of cubes, i.e. a cube of length 0.5
ts <- convhulln(pn, "FA")
expect_equal(ts$area, 6*0.5^2)
expect_equal(ts$vol, 1*0.5^3)
})
test_that("halfspacen can do the round trip on an example with 3000 points",
{
set.seed(1)
ps <- matrix(rnorm(3000), ncol=3)
ps <- sqrt(3)*ps/drop(sqrt((ps^2) %*% rep(1,3)))
ch <- convhulln(ps, "n FA")
pn <- halfspacen(ch$normals, c(0, 0, 0))
chn <- convhulln(pn, "n FA")
expect_equal(ch$area, chn$area)
expect_equal(ch$vol, chn$vol)
})
test_that("halfspacen throws an error when the feasible point is not clearly inside the halfspace",
{
load(file.path(system.file(package="geometry"), "extdata", "halfspacen.RData"))
expect_error(halfspacen(normals, fp), "QH6023 qhull input error")
})
geometry/tests/testthat/test-distmesh2d.R 0000644 0001762 0000144 00000001223 13432317404 020254 0 ustar ligges users context("distmesh2d")
test_that("distmesh2d can create a mesh on an ellipse", {
bbox <- 2*matrix(c(-1,1,-1/2,1/2),2,2)
## Ellipse
fd1 <- function(p,ra2=1/1.,rb2=1/2,xc2=0,yc2=0, ...){
if (!is.matrix(p))
p <- t(as.matrix(p))
return(sqrt(((p[,1]-xc2)/ra2)^2+((p[,2]-yc2)/rb2)^2)-1)
}
## Solve using distmesh2d()
fh <- function(p,...) rep(1,nrow(p))
## This is the original line, which throws a warning. New one does
## too, but runs faster p <-
## distmesh2d(fd=fd1,fh=fh,p=NULL,h0=0.05,bbox=bbox,maxiter=1000,
## plot=FALSE)
expect_warning(p <- distmesh2d(fd=fd1,fh=fh,p=NULL,h0=0.05,bbox=bbox,maxiter=10, plot=FALSE))
})
geometry/tests/testthat/test-cart2pol.R 0000644 0001762 0000144 00000005741 13432317404 017745 0 ustar ligges users context("cart2pol")
test_that("cart2pol works correctly", {
x <- c(0, 1, 2)
y <- 0
P <- cart2pol (x, y)
expect_equal (P[,"theta"], c(0, 0, 0))
expect_equal (P[,"r"], x)
x <- c(0, 1, 2)
y <- c(0, 1, 2)
P <- cart2pol(x, y)
expect_equal (P[,"theta"], c(0, pi/4, pi/4))
expect_equal (P[,"r"], sqrt (2)*c(0, 1, 2))
x <- c(0, 1, 2)
y <- c(0, 1, 2)
z <- c(0, 1, 2)
P <- cart2pol (x, y, z)
expect_equal (P[,"theta"], c(0, pi/4, pi/4))
expect_equal (P[,"r"], sqrt (2)*c(0, 1, 2))
expect_equal (P[,"z"], z)
x <- c(0, 1, 2)
y <- 0
z <- 0
P <- cart2pol (x, y, z)
expect_equal (P[,"theta"], c(0, 0, 0))
expect_equal (P[,"r"], x)
expect_equal (P[,"z"], c(0, 0, 0))
x <- 0
y <- c(0, 1, 2)
z <- 0
P <- cart2pol (x, y, z)
expect_equal (P[,"theta"], c(0, 1, 1)*pi/2)
expect_equal (P[,"r"], y)
expect_equal (P[,"z"], c(0, 0, 0))
x <- 0
y <- 0
z <- c(0, 1, 2)
P <- cart2pol (x, y, z)
expect_equal (P[,"theta"], c(0, 0, 0))
expect_equal (P[,"r"], c(0, 0, 0))
expect_equal (P[,"z"], z)
C <- rbind(c(x=0, y=0), c(1, 1), c( 2, 2))
P <- rbind(c(theta=0, r=0), c(pi/4, sqrt(2)), c(pi/4, 2*sqrt(2)))
expect_equal(cart2pol(C), P)
## %!test
## %! C <- c(0, 0, 0 1, 1, 1 2, 2, 2)
## %! P <- c(0, 0, 0 pi/4, sqrt(2), 1 pi/4, 2*sqrt(2), 2)
## %! expect_equal (cart2pol (C), P)
## %!test
## %! x <- zeros (1, 1, 1, 2)
## %! x(1, 1, 1, 2) <- sqrt (2)
## %! y <- x
## %! c(P[,"theta"], r) <- cart2pol (x, y)
## %! T <- zeros (1, 1, 1, 2)
## %! T(1, 1, 1, 2) <- pi/4
## %! R <- zeros (1, 1, 1, 2)
## %! R(1, 1, 1, 2) <- 2
## %! expect_equal (P[,"theta"], T)
## %! expect_equal (P[,"r"], R)
## %!test
## %! c(x, y, Z) <- meshgrid (c(0, 1), c(0, 1), c(0, 1))
## %! c(t, r, z) <- cart2pol (x, y, Z)
## %! T(:, :, 1) <- c(0, 0 pi/2, pi/4)
## %! T(:, :, 2) <- T(:, :, 1)
## %! R <- sqrt (x.^2 + y.^2)
## %! expect_equal (t, T)
## %! expect_equal (P[,"r"], R)
## %! expect_equal (z, Z)
## Test input validation
expect_error(cart2pol())
expect_error(cart2pol(1,2,3,4))
expect_error(cart2pol(list(1,2,3)), regexp="input must be matrix with 2 or 3 columns")
## expect_error cart2pol (ones (3,3,2))
## expect_error cart2pol (c(1))
## expect_error cart2pol (c(1,2,3,4))
## expect_error cart2pol ({1,2,3}, c(1,2,3))
## expect_error cart2pol (c(1,2,3), {1,2,3})
## expect_error cart2pol (ones (3,3,3), ones (3,2,3))
## expect_error cart2pol ({1,2,3}, c(1,2,3), c(1,2,3))
## expect_error cart2pol (c(1,2,3), {1,2,3}, c(1,2,3))
## expect_error cart2pol (c(1,2,3), c(1,2,3), {1,2,3})
## expect_error cart2pol (ones (3,3,3), 1, ones (3,2,3))
## expect_error cart2pol (ones (3,3,3), ones (3,2,3), 1)
})
geometry/tests/testthat/test-parallel.R 0000644 0001762 0000144 00000001256 14662314120 020006 0 ustar ligges users context("Interaction with parallel package")
library(parallel)
test_that("delaunayn can be called with mc.apply", {
## mc.cores must be 1 on Windows. Otherwise use only 2 cores to comply
## with CRAN guidelines.
mc.cores <- ifelse(Sys.info()[1] == "Windows", 1, 2)
## Set seed for replicability
set.seed(1)
## Create points and try standard Delaunay Triangulation
N <- 100000
P <- matrix(runif(2*N), N, 2)
T <- delaunayn(P)
expect_identical(nrow(T), 199966L)
## Now try out the parallel version.
Ts <- mclapply(list(P, P, P, P), delaunayn, mc.cores=mc.cores)
expect_length(Ts, 4)
expect_identical(nrow(Ts[[1]]), 199966L)
expect_identical(Ts[[1]], T)
})
geometry/tests/testthat/test-delaunayn.R 0000644 0001762 0000144 00000013046 14664554667 020222 0 ustar ligges users context("delaunayn")
test_that("delaunayn produces the correct output", {
## Create points that, when passed to Qhull with the Qt option,
## would give degenerate simplices - thanks to Bill Denney for
## example
ps <- as.matrix(rbind(data.frame(a=0, b=0, d=0),
merge(merge(data.frame(a=c(-1, 1)),
data.frame(b=c(-1, 1))),
data.frame(d=c(-1, 1)))))
ts <- delaunayn(ps)
expect_type(ts, "integer")
expect_identical(dim(ts), c(12L, 4L))
## With output.options=TRUE, there should be a trinagulation, areas and
## neighbours and the sum of the ares should be 8
ts.full <- delaunayn(ps, output.options=TRUE)
expect_equal(ts, ts.full$tri, check.attributes=FALSE)
expect_equal(length(ts.full$areas), nrow(ts.full$tri))
expect_equal(length(ts.full$neighbours), nrow(ts.full$tri))
expect_equal(sum(ts.full$area), 8)
## With full output, there should be a trinagulation, areas and
## neighbours and the sum of the ares should be 8
## full will be deprecated in a future version
ts.full <- delaunayn(ps, full=TRUE)
expect_equal(ts, ts.full$tri, check.attributes=FALSE)
expect_equal(length(ts.full$areas), nrow(ts.full$tri))
expect_equal(length(ts.full$neighbours), nrow(ts.full$tri))
expect_equal(sum(ts.full$area), 8)
## tsearchn shouldn't return a "degnerate simplex" error.
expect_silent(tsearchn(ps, ts, cbind(1, 2, 4)))
## If the input matrix contains NAs, delaunayn should return an error
ps <- rbind(ps, NA)
expect_error(delaunayn(ps))
})
test_that("In the case of just one triangle, delaunayn returns a matrix", {
pc <- rbind(c(0, 0), c(0, 1), c(1, 0))
pct <- delaunayn(pc)
expect_type(pct, "integer")
expect_identical(dim(pct), c(1L, 3L))
## With no options it should also produce a triangulation. This
## mirrors the behaviour of octave and matlab
pct <- delaunayn(pc, "")
expect_type(pct, "integer")
expect_identical(dim(pct), c(1L, 3L))
pct.full <- delaunayn(pc, output.options=TRUE)
expect_equal(pct.full$areas, 0.5)
})
test_that("In the case of a degenerate triangle, delaunayn returns a matrix with zero rows", {
pc <- rbind(c(0, 0), c(0, 1), c(0, 2))
pct <- delaunayn(pc)
expect_type(pct, "integer")
expect_identical(dim(pct), c(0L, 3L))
pct.full <- delaunayn(pc, output.options=TRUE)
expect_equal(length(pct.full$areas), 0)
expect_equal(length(pct.full$neighbours), 0)
})
test_that("In the case of just one tetrahaedron, delaunayn returns a matrix", {
pc <- rbind(c(0, 0, 0), c(0, 1, 0), c(1, 0, 0), c(0, 0, 1))
pct <- delaunayn(pc)
expect_type(pct, "integer")
expect_identical(dim(pct), c(1L, 4L))
pct.full <- delaunayn(pc, output.options=TRUE)
expect_equal(pct.full$areas, 1/6)
})
test_that("Output to file works", {
ps <- matrix(rnorm(3000), ncol=3)
ps <- sqrt(3)*ps/drop(sqrt((ps^2) %*% rep(1, 3)))
fname <- path.expand(file.path(tempdir(), "test1.txt"))
pst <- delaunayn(ps, paste0("QJ TO '", fname, "'"))
expect_true(file.exists(fname))
})
test_that("The QJ option can give degenerate simplices", {
## Create degenerate simplex - thanks to Bill Denney for example
ps <- as.matrix(rbind(data.frame(a=0, b=0, d=0),
merge(merge(data.frame(a=c(-1, 1)),
data.frame(b=c(-1, 1))),
data.frame(d=c(-1, 1)))))
## The QJ option leads to on simplex being very small
ts <- delaunayn(ps, "QJ")
expect_warning(tsearchn(ps, ts, cbind(1, 2, 4)))
})
test_that("A square is triangulated", {
## This doesn't work if the Qz option isn't supplied
square <- rbind(c(0, 0), c(0, 1), c(1, 0), c(1, 1))
expect_equal(delaunayn(square), rbind(c(4, 2, 1),
c(4, 3, 1)),
check.attributes=FALSE)
expect_error(delaunayn(square, ""), "QH6239 Qhull precision error: initial Delaunay input sites are cocircular or cospherical")
})
test_that("No regression on issue 11: All points in a box far from the origin are triangulated", {
## Generate set of randomly generated points in a 40 unit square,
## 250,000 from the origin
set.seed(2)
p <- geometry::rbox(4000, D=2, 20) + 250000
## Triangulate
t <- delaunayn(p)
## Count how many of the points aren't in the triangulation - should be zero
expect_equal(length(setdiff(seq(1,nrow(p)), unique(c(t[,1], t[,2], t[,3])))),
0)
## Plotting: in the plot below, untriangulated points appear in red
## Basted on Jean-Romain's example in https://github.com/davidcsterratt/geometry/issues/11
## x <- p[,1]
## y <- p[,2]
## plot(x, y, cex = 0.1, col = "red")
## trimesh(t, x, y, add = T)
})
test_that("No regression on issue 12: All points in a small box with different x and y distances to the origin are triangulated", {
## Generate set of randomly generated points in a 40 unit square,
## with x distance of 5E5 from the origin and y distance 5E6 from
## the orgin. Note that the mean x and y values relative to the
## width of the window are quite different to each other.
set.seed(2)
p <- geometry::rbox(4000, D=2, 20) + 5E5
p[,2] <- p[,2] + 5E6
## Expect warnings without the correct options
expect_warning(delaunayn(p), "points missing from triangulation")
expect_warning(delaunayn(p, options="Qt Qc Qz Qbb"), "points missing from triangulation")
expect_warning(delaunayn(p, options="Qt Qc Qz QbB"), "points missing from triangulation")
## Centring the points does allow triangulation
p.centred <- cbind(p[,1] - mean(p[,1]),
p[,2] - mean(p[,2]))
delaunayn(p.centred)
})
geometry/tests/testthat/test-cart2sph.R 0000644 0001762 0000144 00000003771 13432317404 017746 0 ustar ligges users context("cart2sph")
test_that("cart2sph works correctly", {
x <- c(0, 1, 2)
y <- c(0, 1, 2)
z <- c(0, 1, 2)
Ps <- cart2sph(x, y, z)
expect_equal(Ps[,"theta"], c(0, pi/4, pi/4))
expect_equal(Ps[,"phi"], c(0, 1, 1)*atan(sqrt(0.5)))
expect_equal(Ps[,"r"], c(0, 1, 2)*sqrt(3))
x <- 0
y <- c(0, 1, 2)
z <- c(0, 1, 2)
Ps <- cart2sph(x, y, z)
expect_equal(Ps[,"theta"], c(0, 1, 1)*pi/2)
expect_equal(Ps[,"phi"], c(0, 1, 1)*pi/4)
expect_equal(Ps[,"r"], c(0, 1, 2)*sqrt(2))
x <- c(0, 1, 2)
y <- 0
z <- c(0, 1, 2)
Ps <- cart2sph(x, y, z)
expect_equal(Ps[,"theta"], c(0, 0, 0))
expect_equal(Ps[,"phi"], c(0, 1, 1)*pi/4)
expect_equal(Ps[,"r"], c(0, 1, 2)*sqrt(2))
x <- c(0, 1, 2)
y <- c(0, 1, 2)
z <- 0
Ps <- cart2sph(x, y, z)
expect_equal(Ps[,"theta"], c(0, 1, 1)*pi/4)
expect_equal(Ps[,"phi"], c(0, 0, 0))
expect_equal(Ps[,"r"], c(0, 1, 2)*sqrt(2))
C <- rbind(c(0, 0, 0),
c(1, 0, 1),
c(2, 0, 2))
S <- rbind(c(theta=0, phi=0, r=0),
c(0, pi/4, sqrt(2)),
c(0, pi/4, 2*sqrt(2)))
expect_equal(cart2sph(C), S)
})
test_that("cart2sph error validation works correctly", {
expect_error(cart2sph())
expect_error(cart2sph(1,2))
expect_error(cart2sph(1,2,3,4))
expect_error(cart2sph(list(1, 2, 3)), regexp="input must be matrix with 3 columns")
expect_error(cart2sph(array(1, c(3,3,2))), regexp="matrix input must have 3 columns")
expect_error(cart2sph(cbind(1,2,3,4)), regexp=c("matrix input must have 3 columns"))
expect_error(cart2sph(list(1,2,3), c(1,2,3), c(1,2,3)), regexp="numeric arrays of the same size")
expect_error(cart2sph(c(1,2,3), list(1,2,3), c(1,2,3), regexp="numeric arrays of the same size"))
expect_error(cart2sph(c(1,2,3), c(1,2,3), list(1,2,3)), regexp="numeric arrays of the same size")
expect_error(cart2sph(array(1, c(3, 3, 3)), 1, array(1, c(3,3,2))), regexp="matrices of the same size")
expect_error(cart2sph(array(1, c(3, 3, 3)), array(1, c(3,3,2)), 1), regexp="matrices of the same size")
})
geometry/tests/testthat/test-tsearchn.R 0000644 0001762 0000144 00000010027 13525562746 020035 0 ustar ligges users context("tsearchn")
test_that("tsearchn gives the expected output", {
## Simple example
x <- c(-1, -1, 1)
y <- c(-1, 1, -1)
p <- cbind(x, y)
tri <- matrix(c(1, 2, 3), 1, 3)
## Should be in triangle #1
ts <- tsearchn(p, tri, cbind(-1, -1),fast=FALSE)
expect_equal(ts$idx, 1)
expect_equal(ts$p, cbind(1, 0, 0))
## Should be in triangle #1
ts <- tsearchn(p, tri, cbind(1, -1), fast=FALSE)
expect_equal(ts$idx, 1)
expect_equal(ts$p, cbind(0, 0, 1))
## Should be in triangle #1
ts <- tsearchn(p, tri, cbind(-1, 1), fast=FALSE)
expect_equal(ts$idx, 1)
expect_equal(ts$p, cbind(0, 1, 0))
## Centroid
ts <- tsearchn(p, tri, cbind(-1/3, -1/3), fast=FALSE)
expect_equal(ts$idx, 1)
expect_equal(ts$p, cbind(1/3, 1/3, 1/3))
## Should be outside triangle #1, so should return NA
ts <- tsearchn(p, tri, cbind(1, 1), fast=FALSE)
expect_true(is.na(ts$idx))
expect_true(all(is.na(ts$p)))
## Create a mesh with a zero-area element (degenerate simplex)
p <- cbind(c(-1, -1, 0, 1, 2),
c(-1, 1, 0, 0, 0))
tri <- rbind(c(1, 2, 3),
c(3, 4, 5))
## Look for one point in one of the simplices and a point outwith the
## simplices. This forces tsearchn to look in all simplices. It
## shouldn't fail on the degenerate simplex.
expect_warning(ts <- tsearchn(p, tri, rbind(c(-0.5, 0), c(3, 1)), fast=FALSE))
expect_equal(ts$idx, c(1, NA))
ts <- tsearchn(p, tri, rbind(c(-0.5, 0), c(3, 1)), fast=TRUE)
expect_equal(ts$idx, c(1, NA))
})
context("tsearchn_delaunayn")
test_that("tsearchn gives the expected output", {
## Erroneous input is caught safely. Force
## tsearchn_delaunayn to be called
tfake <- matrix(1:3, 1, 3)
class(tfake) <- "delaunayn"
expect_error(suppressWarnings(tsearchn(NA, tfake, matrix(1:2, 1, 2))), "Delaunay triangulation has no delaunayn attribute")
x <- cbind(c(-1, -1, 1),
c(-1, 1, -1))
dt <- delaunayn(x, output.options=TRUE)
## Should be in triangle #1
xi <- cbind(-1, 1)
expect_warning(ts <- tsearchn(NA, dt, xi))
expect_equal(ts$idx, 1)
expect_equal(bary2cart(x[dt$tri[ts$idx,],], ts$p), xi)
## Centroid
xi <- cbind(-1/3, -1/3)
expect_warning(ts <- tsearchn(NA, dt, xi))
expect_equal(ts$idx, 1)
expect_equal(ts$p, cbind(1/3, 1/3, 1/3))
## Should be outside triangle #1, so should return NA
xi <- cbind(1, 1)
expect_warning(ts <- tsearchn(NA, dt, xi))
expect_true(is.na(ts$idx))
expect_true(all(is.na(ts$p)))
## Check mutliple points work
xi <- rbind(c(-1, 1),
c(-1/3, -1/3))
expect_warning(ts <- tsearchn(NA, dt, xi))
expect_equal(ts$idx, c(1, 1))
expect_equal(do.call(rbind, lapply(1:2, function(i) {
bary2cart(x[dt$tri[ts$idx[i],],], ts$p[i,])
})), xi)
## Test against original version
p <- cbind(c(0, 0, 1, 1, 0.5),
c(0, 1, 1, 0, 0.5))
dt <- delaunayn(p, "FA") ## Interesting error, as default options are 'nixed
dt <- delaunayn(p, output.options=TRUE)
xi <- c(0.1, 0.5, 0.9, 0.5)
yi <- c(0.5, 0.9, 0.5, 0.1)
expect_warning(ts <- tsearchn(NA, dt, cbind(xi, yi)))
expect_equal(ts$idx,
tsearch(p[,1], p[,2], dt$tri, xi, yi, method="orig"))
## 3D test
x <- rbox(D=3, B=1)
dt <- delaunayn(x, output.options=TRUE)
xi <- rbind(c(0.5, 0.5, 0.5),
c(-0.5, -0.5, -0.5),
c(0.9, 0, 0))
expect_warning(ts <- tsearchn(NA, dt, xi))
expect_equal(do.call(rbind, lapply(1:3, function(i) {
bary2cart(x[dt$tri[ts$idx[i],],], ts$p[i,])
})), xi)
## 4D test
##
## This does not work yet. The "best" facet is not always the correct facet.
## x <- rbox(D=4, B=1)
## dt <- delaunayn(x, output.options=TRUE)
## xi <- rbind(c(0.5, 0.5, 0.5, 0.5),
## c(-0.49, -0.49, -0.49, -0.49),
## c(0.9, 0, 0, 0))
## ts <- tsearchn(dt, NA, xi)
## expect_equal(do.call(rbind, lapply(1:3, function(i) {
## bary2cart(x[dt$tri[ts$idx[i],],], ts$p[i,])
## })), xi)
## We don't need to test when creating a mesh with a zero-area
## element (degenerate simplex), as these shouldn't be produced by
## qhull.
})
geometry/tests/testthat/test-sph2cart.R 0000644 0001762 0000144 00000004473 13432317404 017746 0 ustar ligges users context("sph2cart")
test_that("sph2cart works correctly", {
t <- c(0, 0, 0)
p <- c(0, 0, 0)
r <- c(0, 1, 2)
C <- sph2cart (t, p, r)
expect_equal(C[,"x"], r)
expect_equal(C[,"y"], c(0, 0, 0))
expect_equal(C[,"z"], c(0, 0, 0))
t <- 0
p <- c(0, 0, 0)
r <- c(0, 1, 2)
C <- sph2cart(t, p, r)
expect_equal(C[,"x"], r)
expect_equal(C[,"y"], c(0, 0, 0))
expect_equal(C[,"z"], c(0, 0, 0))
t <- c(0, 0, 0)
p <- 0
r <- c(0, 1, 2)
C <- sph2cart (t, p, r)
expect_equal(C[,"x"], r)
expect_equal(C[,"y"], c(0, 0, 0))
expect_equal(C[,"z"], c(0, 0, 0))
t <- c(0, 0.5, 1)*pi
p <- c(0, 0, 0)
r <- 1
C <- sph2cart(t, p, r)
expect_equal(C[,"x"], c(1, 0, -1))
expect_equal(C[,"y"], c(0, 1, 0))
expect_equal(C[,"z"], c(0, 0, 0))
C <- sph2cart(c(0, 0, 0), 0, 1)
expect_equal(C[,"x"], c(1, 1, 1))
expect_equal(C[,"y"], c(0, 0, 0))
expect_equal(C[,"z"], c(0, 0, 0))
S <- rbind(c(0, 0, 1),
c(0.5*pi, 0, 1),
c(pi, 0, 1))
C <- rbind(c(x=1, y=0, z=0),
c(0, 1, 0),
c(-1, 0, 0))
expect_equal(sph2cart(S), C)
})
# FIXME: to implement
#! c(t, p, r) <- meshgrid (c(0, pi/2), c(0, pi/2), c(0, 1))
#! c(x, y, z) <- sph2cart (t, p, r)
#! X <- zeros(2, 2, 2)
#! X(1, 1, 2) <- 1
#! Y <- zeros(2, 2, 2)
#! Y(1, 2, 2) <- 1
#! Z <- zeros(2, 2, 2)
#! Z(2, :, 2) <- c(1 1)
#! expect_equal(x, X, eps)
#! expect_equal(y, Y, eps)
#! expect_equal(z, Z)
test_that("sph2cart error validation works correctly", {
expect_error(sph2cart())
expect_error(sph2cart(1,2))
expect_error(sph2cart(1,2,3,4))
expect_error(sph2cart(list(1, 2, 3)), regexp="input must be matrix with 3 columns")
expect_error(sph2cart(array(1, c(3,3,2))), regexp="matrix input must have 3 columns")
expect_error(sph2cart(cbind(1,2,3,4)), regexp=c("matrix input must have 3 columns"))
expect_error(sph2cart(list(1,2,3), c(1,2,3), c(1,2,3)), regexp="numeric arrays of the same size")
expect_error(sph2cart(c(1,2,3), list(1,2,3), c(1,2,3), regexp="numeric arrays of the same size"))
expect_error(sph2cart(c(1,2,3), c(1,2,3), list(1,2,3)), regexp="numeric arrays of the same size")
expect_error(sph2cart(array(1, c(3, 3, 3)), 1, array(1, c(3,3,2))), regexp="matrices of the same size")
expect_error(sph2cart(array(1, c(3, 3, 3)), array(1, c(3,3,2)), 1), regexp="matrices of the same size")
})
geometry/tests/testthat/test-intersectn.R 0000644 0001762 0000144 00000021311 13462263674 020400 0 ustar ligges users test_that("intersectn can run on overlapping triangles", {
## Make star of David from isosceles triangles of length 3
ps1 <- rbind(c(0, sqrt(3)),
c(3/2, -sqrt(3)/2),
c(-3/2, -sqrt(3)/2))
ps2 <- ps1
ps2[,2] <- -ps2[,2]
expect_equal(feasible.point(convhulln(ps1, output.options=TRUE),
convhulln(ps2, output.options=TRUE)),
c(0, 0))
is <- intersectn(ps1, ps2)
isa <- intersectn(ps1, ps2, autoscale=TRUE)
## Intersecting area is same as 6 isosceles triangles of length 1, which have
## area sqrt(3)/4
##
expect_equal(is$ch$vol, sqrt(3)/4*6)
expect_equal(isa$ch$vol, sqrt(3)/4*6)
## Another overlapping example
ps2 <- ps1
ps2[,2] <- ps2[,2]+2
is <- intersectn(ps1, ps2)
## Now make one element of feasible point negative
ps3 <- ps1
ps4 <- ps1
ps4[,2] <- -ps4[,2]
ps3[,2] <- ps3[,2] - 10
ps4[,2] <- ps4[,2] - 10
expect_equal(feasible.point(convhulln(ps3, output.options=TRUE),
convhulln(ps4, output.options=TRUE)),
c(0, -10))
expect_equal(intersectn(ps3, ps4)$ch$vol, sqrt(3)/4*6)
})
test_that("intersectn gives zero volume on non-overlapping triangles", {
ps1 <- rbind(c(0, sqrt(3)),
c(3/2, -sqrt(3)/2),
c(-3/2, -sqrt(3)/2))
ps2 <- ps1
ps2[,2] <- ps2[,2] + 3
expect_equal(feasible.point(convhulln(ps1, "n"), convhulln(ps2, "n")), NA)
is <- intersectn(ps1, ps2)
expect_equal(is$ch$vol, 0)
})
test_that("intersectn gives zero volume on non-overlapping triangles", {
ps1 <- rbind(c(0, sqrt(3)),
c(3/2, -sqrt(3)/2),
c(-3/2, -sqrt(3)/2))
ps2 <- ps1
ps2[,2] <- ps2[,2] + 3
expect_equal(feasible.point(convhulln(ps1, "n"), convhulln(ps2, "n")), NA)
is <- intersectn(ps1, ps2)
expect_equal(is$ch$vol, 0)
})
test_that("feasible.point works on a 3D example", {
## These tetrahedra do not overlap
ps1 <- rbind(c( 0.5000000, -0.5000000, 0.5000000),
c(-0.1018942, 0.1848312, -0.1260239),
c( 0.5000000, -0.5000000, -0.5000000),
c(-0.5000000, -0.5000000, -0.5000000))
ps2 <- rbind(c( 0.7581575, 0.6352585, 0.32876),
c( 1.0000000, 0.0000000, 1.00000),
c( 0.0000000, 0.0000000, 1.00000),
c( 1.0000000, 0.0000000, 0.00000))
expect_equal(feasible.point(convhulln(ps1, "n"), convhulln(ps2, "n")), NA)
})
test_that("intersectn can run on overlapping tetrahedra", {
## Make star of David from isocelese triangles of length 3
ps1 <- rbind(c(0, sqrt(3), 0),
c(3/2, -sqrt(3)/2, 0),
c(-3/2, -sqrt(3)/2, 0),
c(0, 0, 3*sqrt(2/3)))
ch1 <- convhulln(ps1, "FA")
expect_equal(ch1$vol, sqrt(2)/12*27)
ps2 <- ps1
## By shifting tetrahedron up by half of its height, we should make
## something with 1/8 of the volume
ps2[,3] <- ps2[,3] + 3/2*sqrt(2/3)
is <- intersectn(ps1, ps2)
expect_equal(is$ch$vol, sqrt(2)/12*27/8)
})
test_that("intersectn can run on tetrahedra with a common point", {
ps1 <- rbind(c(-0.4015654, -0.1084358, -0.3727391),
c( 0.2384763, 0.3896078, -0.4447473),
c( 0.5000000, -0.5000000, -0.5000000),
c(-0.5000000, -0.5000000, -0.5000000))
ps2 <- rbind(c(-0.1392469, 0.03303547, -0.2436112),
c( 0.3434195, -0.20338201, -0.4638141),
c(-0.5000000, 0.50000000, -0.5000000),
c(-0.5000000, -0.50000000, -0.5000000))
is <- intersectn(ps1, ps2)
})
test_that("intersectn can compute the volume of overlapping delaunay triangulations of boxes", {
## Volume of overlap should be 1/8
ps1 <- rbox(2, B=0.5, C=0.5)
ps2 <- rbox(2, B=0.5, C=0.5) + 0.5
dt1 <- delaunayn(ps1)
dt2 <- delaunayn(ps2)
vol <- 0
for (i in 1:nrow(dt1)) {
for (j in 1:nrow(dt2)) {
is <- intersectn(ps1[dt1[i,],], ps2[dt2[j,],])
vol <- vol + is$ch$vol
}
}
expect_equal(vol, 0.125, tol=0.0001)
})
test_that("intersectn can deal with some input that caused errors before fixing Issue #34", {
## Issue 34: https://github.com/davidcsterratt/geometry/issues/34
ps1 <- rbind(
c(500.9656357388012111187, 843268.9656357388012111, 5.5),
c(658.9656357388012111187, 843109.9656357388012111, 10.0),
c(576.9656357388012111187, 843174.9656357388012111, 2.0),
c(795.9656357388012111187, 843235.9656357388012111, 20.0))
ps2 <- rbind(
c(707.9656400000000076034, 843153.9656399999512359, 12.000000000000000000000),
c(645.6795799999999871943, 843166.4228499999735504, 10.200630000000000308091),
c(631.6632399999999734064, 843182.9680800000205636, 8.772800000000000153477),
c(707.9656400000000076034, 843153.9656399999512359, 12.000000000000000000000),
c(608.9447900000000117871, 843172.7368899999419227, 7.772330000000000183036),
c(607.9656400000000076034, 843173.9656399999512359, 7.669999999999999928946))
## Before Issue #34 was fixed this threw an error:
## Received error code 2 from qhull. Qhull error:
## qhull precision warning:
## The initial hull is narrow (cosine of min. angle is 1.0000000000000002).
## expect_error(intersectn(ps1, ps2, tol=1E-4, return.chs=FALSE, options="Tv"), ".*The initial hull is narrow.*")
## This threw an error in Rev aab45b7311b6
out <- intersectn(ps1, ps2, tol=1E-4, return.chs=FALSE)
})
test_that("intersectn works on rotated boxes", {
rot <- function(theta) {return(rbind(c(cos(theta), sin(theta)), c(-sin(theta), cos(theta))))}
## Area of octogan created by two squares at 45 deg to each other
sq <- rbox(C=1, D=2, n=0)
expect_equal(intersectn(sq%*%rot(pi/4), sq)$ch$vol, 8*(sqrt(2) - 1))
rot4 <- function(theta) {return(rbind(c(cos(theta), sin(theta), 0, 0), c(-sin(theta), cos(theta), 0, 0), c(0, 0, 1, 0), c(0, 0, 0 ,1)))}
## Area of hyperoctoid created by two hypercubes at 45 deg to each other
hc <- rbox(C=1, D=4, n=0)
expect_equal(intersectn(hc%*%rot4(pi/4), hc)$ch$vol, 4*8*(sqrt(2) - 1))
})
test_that("intersectn works in 4D", {
load(file.path(system.file(package="geometry"), "extdata", "intersectn4D.RData"))
chi <- convhulln(seti, output.options=TRUE)
chj <- convhulln(setj, output.options=TRUE)
chij <- intersectn(seti, setj)
chji <- intersectn(setj, seti)
expect_equal(chij$ch$vol, chji$ch$vol)
expect_true(chi$vol >= chij$ch$vol)
expect_equal(chj$vol, chij$ch$vol)
})
test_that("no regression on issue 35", {
## This gave an error in version 0.4.1
## See https://github.com/davidcsterratt/geometry/issues/35
load(file.path(system.file(package="geometry"), "extdata", "issue35-intersectn.RData"))
ch <- intersectn(seti, setj)
expect_true(ch$ch$vol > 0)
cha <- intersectn(seti, setj, autoscale=TRUE)
expect_true(cha$ch$vol > 0)
expect_equal(ch$ch$vol, cha$ch$vol)
})
test_that("no regression on issue 35", {
## This is an example that requires various combinations of flags to
## be provided to lpSolve::lp
##
## Also testing a scaled version, which was easier to fixed with the
## set of flags used originally.
## https://github.com/davidcsterratt/geometry/issues/35
load(file.path(system.file(package="geometry"), "extdata", "error_15_620.RData"))
ch <- intersectn(p1, p1)
expect_true(ch$ch$vol > 0)
cha <- intersectn(p1, p1, autoscale=TRUE)
expect_true(cha$ch$vol > 0)
expect_equal(ch$ch$vol, cha$ch$vol)
zfac <- 10
p1[,3] <- p1[,3]*zfac
p2[,3] <- p2[,3]*zfac
ch <- intersectn(p1, p1)
expect_true(ch$ch$vol > 0)
cha <- intersectn(p1, p1, autoscale=TRUE)
expect_true(cha$ch$vol > 0)
expect_equal(ch$ch$vol, cha$ch$vol)
})
test_that("intersectn doesn't crash on some input", {
## This is an example causes a crash if flag SCALE_GEOMETRIC (4) is
## given to lpSolve::lp in feasible.point()
load(file.path(system.file(package="geometry"), "extdata", "overlap260-5034.RData"))
ch <- intersectn(p1, p2)
cha <- intersectn(p1, p2, autoscale=TRUE)
expect_equal(ch$ch$vol, cha$ch$vol)
})
test_that("intersectn doesn't crash on input that causes a crash with scale=7 on some processors", {
## This is an example causes a crash on some processors if flag SCALE_CURTISREID (7) is
## given to lpSolve::lp in feasible.point()
load(file.path(system.file(package="geometry"), "extdata", "save-overlap32-176.RData"))
intersectn(p1, p2, tol=1E-3)
load(file.path(system.file(package="geometry"), "extdata", "save-overlap68-557.RData"))
intersectn(p1, p2, tol=1E-3)
})
test_that("intersectn doesn't crash on input that causes a crash with EQUILIBRIATE=1 on some processors", {
## This is an example causes a crash on some processors if flag
## EQUILIBRIATE is given to lpSolve::lp in feasible.point()
load(file.path(system.file(package="geometry"), "extdata", "save-overlap149-9428.RData"))
intersectn(p1, p2, tol=1E-3)
})
geometry/tests/testthat.R 0000644 0001762 0000144 00000000052 13432270466 015236 0 ustar ligges users library(testthat)
test_check("geometry")
geometry/tests/spelling.R 0000644 0001762 0000144 00000000241 13432270466 015213 0 ustar ligges users if(requireNamespace('spelling', quietly = TRUE))
spelling::spell_check_test(vignettes = TRUE, error = FALSE,
skip_on_cran = TRUE)
geometry/MD5 0000644 0001762 0000144 00000032216 14751753072 012434 0 ustar ligges users 9087749cf71bc7122189ca675372b1d9 *DESCRIPTION
068b549a6e5e2c90a18f87356b4f00a4 *NAMESPACE
eb31eec68df1b606d75f57adeb3ed912 *NEWS
d100f679b938110d96307291fce64c41 *R/RcppExports.R
9c6b34a4cc5fd5384ff9576db63347e0 *R/Unique.R
6676c6f07f0bcf0743181ad81a5b13bc *R/cart2pol.R
422a3c2ca63eb50396f478d6ba49c445 *R/cart2sph.R
89a8d43655515d1c3c79a2e962fe1ab0 *R/convhulln.R
8f98d65db1398d025604e04570125e7e *R/delaunayn.R
f67b6e054d55c085ef68f4fde78db0d8 *R/distmesh2d.R
58839184c5c9f16e927f689276f9521b *R/distmeshnd.R
f02e89ee5fbbee42592d159bb119ee29 *R/dotprod.R
53e68a5fd3ffa96307ac3eec3ed15241 *R/entry.value.R
75b95b74ee13f9fc9f74214416e2512c *R/extprod3d.R
13663e9698eeef3705b2cf444b55df42 *R/halfspacen.R
5f62c32fecf8cefacd30b5df31fde42f *R/inhulln.R
9a409fbef9b11d787e3b27b57d6b6dd5 *R/intersectn.R
c2917f4499966c4bff5722c3a20ee293 *R/matmax.R
7953e067c808a844a6c25661b1f1fb19 *R/matmin.R
8845a9403edba64246177b1dab548d13 *R/matorder.R
7e77a7bbe9672e5a0efb27c33d0e47b7 *R/matsort.R
7d2a5c12b42717a5ccdf00af6b2acd06 *R/mesh.dcircle.R
2c454daede65e5c6a297c26c0de3bdc8 *R/mesh.diff.R
c5a88a07fa0bb752e0b0fbc6a645e583 *R/mesh.drectangle.R
2ae969c5c662d5c4467ef4e7b6896fbd *R/mesh.dsphere.R
51f8458e619561296c18480dd9999be9 *R/mesh.hunif.R
019be320da1d80cd299776aba8e99e9e *R/mesh.intersect.R
4b471fb760c3b594a694cb8c8f2da59a *R/mesh.union.R
f5863ae2279fab13fcca746122d3fb46 *R/pol2cart.R
fcb8ec599d4463dc3e54287a670a1fab *R/polyarea.R
c12ac336deb0b3be98a34eedb85bb61c *R/qhull-options.R
1c1c60e6a45ddb705e6480e965ab73d9 *R/rbox.R
979d55326e8f9e1029e95bd5651dc207 *R/sph2cart.R
95f3f780f786fa8dd704c89a9a0a0398 *R/surf.tri.R
babfa6ca9e4b76b0353281b26426dfa0 *R/tetramesh.R
0255bc872693f2a7d519c67bf89217b2 *R/trimesh.R
d0a05bf107df68a7a13fdfc16f3ab4c1 *R/trisplinter.R
bd79225e1f0911ec27614d244b9df7a3 *R/tsearch.R
5bcde801b6cdd84aeb1d9fd51f5d2206 *build/vignette.rds
29a536ff14c26f87f9db8a06086d57eb *demo/00Index
2c2720d298e89a313a8963f5edc84fe6 *demo/intersectn.R
3128acf4b0156e6c2b2d1e8ed9e3fcac *inst/WORDLIST
af3ca7a8ec4eb7c3808e7e4b0e7b9d20 *inst/doc/LICENSE-NOTES
a17aa14b2581ee880ad40d5d1ad0c138 *inst/doc/MODIFIED.txt
74b4f6b9894c15d5da15f00fb59bcedb *inst/doc/qhull-eg.R
e4da12d940671662c95f27cc01da1ddb *inst/doc/qhull-eg.Rnw
525f6d48677f96b423db7c9f29812cf8 *inst/doc/qhull-eg.pdf
7f91e2f84c11dd41a932b6d03a63ae3d *inst/doc/qhull/Announce.txt
0c45b9e641ac0592e3eda32dac223b9a *inst/doc/qhull/COPYING.txt
1ad9811271fd30b546ff4f5d3d0e4cc6 *inst/doc/qhull/File_id.diz
916939bb1fee5b8ca7826fbcf7b53232 *inst/doc/qhull/README.txt
dfc60c06612b894244510f7efa338c08 *inst/doc/qhull/REGISTER.txt
4b18ce3564cef2b9954e0c13163abfbd *inst/doc/qhull/html/index.html
59e9b69f186c9e715192df9e146ebd21 *inst/doc/qhull/html/normal_voronoi_knauss_oesterle.jpg
5f502b6a0e08493f4ef5ced79ddb5a77 *inst/doc/qhull/html/qconvex.html
fbd0d63639d5aa801f85e37f75c5d392 *inst/doc/qhull/html/qdelau_f.html
28dd1530388b4de8badc95b12b1d9bef *inst/doc/qhull/html/qdelaun.html
bb51e7810cc49e5aff1b910bc3126713 *inst/doc/qhull/html/qh--4d.gif
687f459f95e958da6c3ff0c83cafcf46 *inst/doc/qhull/html/qh--cone.gif
dc51084bc7ba1f235c71d40c771ce9c8 *inst/doc/qhull/html/qh--dt.gif
829df3fbc9a3f36dbdb6389f768b5570 *inst/doc/qhull/html/qh--geom.gif
0587393a4591c5fbcd040af9a4f510c7 *inst/doc/qhull/html/qh--half.gif
0515fcc283b7dfeeaa7169218722880e *inst/doc/qhull/html/qh--rand.gif
012717a06d2274995a039dbc931d10aa *inst/doc/qhull/html/qh-code.html
ca6ae4c704d8be67d50b71ce137768a4 *inst/doc/qhull/html/qh-eg.html
378b30492679846a65c50da8d1bd9962 *inst/doc/qhull/html/qh-faq.html
189ccc476db023a2ef3d5f74a301842a *inst/doc/qhull/html/qh-get.html
c572d9a92948eb7f3333ff153c844b7f *inst/doc/qhull/html/qh-impre.html
8d37fbeae5ba5dc5f8d673ca589d07eb *inst/doc/qhull/html/qh-optc.html
14922021d64987023bb90e3b628eceff *inst/doc/qhull/html/qh-optf.html
eb0cb51f5497a0b57098213858fc665b *inst/doc/qhull/html/qh-optg.html
b7f55169f381cfab737188ded5aa3fa3 *inst/doc/qhull/html/qh-opto.html
e4c732d38d8389c55fa63955a7e644c8 *inst/doc/qhull/html/qh-optp.html
b5a6d0038f4522eb94b4b87804e1d2f9 *inst/doc/qhull/html/qh-optq.html
008e3a59ba0a8c98d4671f8a751f5e6e *inst/doc/qhull/html/qh-optt.html
30454c2fa7db3ea2a72bf72ded9d6447 *inst/doc/qhull/html/qh-quick.html
6aa82b4c2709dd98df2aff103fb944b5 *inst/doc/qhull/html/qhalf.html
e8992f5b2de07cbf48583e1f6b9ad5e9 *inst/doc/qhull/html/qhull-cpp.xml
35d88647a340615dcd1bd842a565475c *inst/doc/qhull/html/qhull.html
fc4b6d8b5abec935f14dd71369718e9f *inst/doc/qhull/html/qhull.man
5e213194265bc30a85ef692ac37d7836 *inst/doc/qhull/html/qhull.txt
8550cf46dbd89d8068969bf225600f16 *inst/doc/qhull/html/qvoron_f.html
f8369a8be58b5f738e7421e367881db2 *inst/doc/qhull/html/qvoronoi.html
03b90e4e5eb3ed77f57a3063694f801d *inst/doc/qhull/html/rbox.html
4cbad586d2136f611dbaf7f47128cc86 *inst/doc/qhull/html/rbox.man
61cd54c422366e1ef1db2babdb3daff9 *inst/doc/qhull/html/rbox.txt
b0e7f903d9fe9008ff87baabe3c57b64 *inst/doc/qhull/index.html
70edf8a33ab665ac8d181b0f0a7c5496 *inst/extdata/error_15_620.RData
ccb784cef19f015690156d6780ad1a6e *inst/extdata/halfspacen.RData
58ce4b940b18d18c73c8d6a2e9f911ef *inst/extdata/intersectn4D.RData
758b6dfb5a56d69ee98f6474793e1eba *inst/extdata/issue35-intersectn.RData
6d8d5e35f877f39179969b2e5a793841 *inst/extdata/issue57-tsearch.RData
f3bce9787d6a1583475c384de6041ca7 *inst/extdata/ordination.Rdata
4f62407c45fc0dbc915fc76e289f04eb *inst/extdata/overlap260-5034.RData
845b30a0f674ce6f53afda166c81c131 *inst/extdata/save-overlap149-9428.RData
bbb03765b5230d3f247478cc86c80379 *inst/extdata/save-overlap32-176.RData
c80140a229d66996a43c5bdaeba9ef7d *inst/extdata/save-overlap68-557.RData
120f155140c555c5b001863ccde95627 *man/Unique.Rd
07fe105f12d5ca8f759c262e2e957477 *man/bary2cart.Rd
970ab4a4e47777dfd940103ff2b23985 *man/cart2bary.Rd
0a8e16e3e143df04b6ef8875b9433a49 *man/cart2pol.Rd
b51e6d8148da25fac20a3c1d8fd05303 *man/cart2sph.Rd
9b80ae9a1b822833c73cfffd1aca77f4 *man/convhulln.Rd
b0d7fec3ad46a86f33a9f217a7a722f5 *man/delaunayn.Rd
ada20b0e85ad504dd3c5ac9f487b511a *man/distmesh2d.Rd
15bbc0b6a76439450d957b4130f19726 *man/distmeshnd.Rd
d0e930cee46465b667cc89e57beed520 *man/dot.Rd
afff3cc2ac7de8b6ceda27ef8431aaf2 *man/entry.value.Rd
6b4b104a8b8e185e0e15ab4e650c9a6d *man/extprod3d.Rd
a347008f8c0116f3634986d4c86e7b27 *man/feasible.point.Rd
593b6ddb499d3354dc486a1c4a0e6fe2 *man/halfspacen.Rd
c8fd1fadfa33cb0a7bb18e102719328c *man/inhulln.Rd
7fcb5537b976dba7490b46dba00f139b *man/intersectn.Rd
1c60bf8b2f2ade2f4d1c640c7bc5c4c9 *man/matmax.Rd
cb5183b698da11fa5690176793b1cfe9 *man/mesh.dcircle.Rd
4f11eee330ec96bd13383003e2648fa2 *man/mesh.diff.Rd
a187c0aed06dac008908a53d5d1b52f4 *man/mesh.drectangle.Rd
6289e1380af8c9da6901ae4e9b137dd9 *man/mesh.dsphere.Rd
b08538f269bdda5767085f1b3c31274e *man/mesh.hunif.Rd
16aadfcf20aa49101e47abcd754b0b60 *man/pol2cart.Rd
462775b2834730b47871d60a0bbb9be8 *man/polyarea.Rd
0c7bac3dc3ba975ac9fad2935e7b5d05 *man/rbox.Rd
d90c27c663cc7691a3b918d061903a71 *man/sph2cart.Rd
41c20ea09b7956e3f5d8cbf777305b37 *man/surf.tri.Rd
2d672ec9d2497f941103d4ae5d3034e9 *man/tetramesh.Rd
b51abc8a985602501e0c3816b2218e0a *man/to.mesh3d.Rd
fa42ae047747c7605cbe6e0298cde115 *man/trimesh.Rd
8e2cbb2206ba988c4dde2298573ac198 *man/tsearch.Rd
b61620430d94896c9caba6fc026c08e6 *man/tsearchn.Rd
bf9376b598a1adace8c07e6fc5a3e76f *src/Makevars
016587028ca03860d1055fecfbc2f8e3 *src/QuadTree.cpp
142aeeb7f52a33ab71d3e5075e2e388c *src/QuadTree.h
0ac63fec329ebed7be67d5e5e92a89b2 *src/Rconvhulln.c
0f03f1357a95a4b83dcf1146fc351d59 *src/RcppExports.cpp
e25e79ab57d6d2f9c968feaf8bde820b *src/Rdelaunayn.c
b6287f38e608ad7c37adf9f48e5f106f *src/Rgeometry.c
8acf1c1bc44b83391141acfc86110efe *src/Rgeometry.h
3fe2e4e7a286bfa60915c8ad39e71ceb *src/Rhalfspacen.c
eb79fb47cc16340b0e261d45c0cd5409 *src/Rinhulln.c
09a5802c8f61d9e73e1809e30190107a *src/Rtsearch.cpp
552312654c3fc22ca2911a61936d5a77 *src/Rtsearch_orig.c
132f1ddd370877642193ac318285c63a *src/Rtsearchn.c
876c09adad390e33d27f72fbb6dc520d *src/geom2_r.c
b5bfc1b056f16945579951686dc2c428 *src/geom_r.c
cfde24c128897c30273de690cfb8ad20 *src/geom_r.h
023f4e70e66fe514f68d6a5ffab2201f *src/geometry_init.c
37a6859600a9ea0f040ccf9e15a9ecc4 *src/global_r.c
d04d6bb90395474fc978ce7cc6e13915 *src/io_r.c
ebd7597c25e31f815e819da068e9914f *src/io_r.h
b6910ea39f0797da7489f4421c9b88ea *src/libqhull_r.c
a14a634963717e60cba5b904939388d0 *src/libqhull_r.h
8275d12edcabef504d1a39db3680bd09 *src/mem_r.c
61b477889f291ecfc36e9d4d3f9fa8d7 *src/mem_r.h
746094f172d5e194a3b6c857a554e397 *src/merge_r.c
905850f71545d3b4d2d3d0811035eb3d *src/merge_r.h
3e5c51d6c3a002eb661060b51be47fef *src/poly2_r.c
f28a42b955f615484659d25f4d40bc72 *src/poly_r.c
73b0c0b388910469d2faae58a39ebca6 *src/poly_r.h
52fcd7e36336fd312c022fce2c45edf5 *src/qhull_ra.h
09c81cd16e87e5db473438003ccd848b *src/qset_r.c
10c15020e692682c0a5dcbd0d78c2cc0 *src/qset_r.h
f498e0602fba35e60a1080f3918b99c4 *src/random_r.c
a1fe43bed99882c8c850ea6f0ae15ecd *src/random_r.h
f38529b9bb49238666b5b7ab044e4b49 *src/rboxlib_r.c
f4651d79b4ad50819541cf9092f793f6 *src/stat_r.c
ee0baf81125db01bf0bc29f4c2a3c33f *src/stat_r.h
27987c9ca25ddb728b7de06abeffd039 *src/user_r.c
560946c6d1a20ac71211e1d76f3b5f78 *src/user_r.h
d18307a2d9a08ae0518527cbb782d901 *src/usermem_r.c
61cd83f3c0639f8e6933f5a15b6c229c *src/userprintf_r.c
cc32478b6848d9938c0c5c2832e4869b *src/userprintf_rbox_r.c
0622a97a2aaa3c342f09636052c2d7f5 *tests/spelling.R
56604df63c661b6ff144cbaa297a33ea *tests/testthat.R
bb752ab1be8abd752e160eb4f6447da4 *tests/testthat/test-cart2pol.R
ff43d4c55f592fdaf2f7448d7e4f8c0c *tests/testthat/test-cart2sph.R
6656a757cfa9231683e457e9fdb2a336 *tests/testthat/test-convhulln.R
a1c6b576e28d85965c6bc2a956de7048 *tests/testthat/test-delaunayn.R
2cb0f78866e8c8721a7b480e30fb6716 *tests/testthat/test-distmesh2d.R
039e347fe28ddf0ccbd4f2cb8a475a55 *tests/testthat/test-extprod3d.R
97b50a3013ad39c4c9ab324aa169e785 *tests/testthat/test-halfspacen.R
e2c95479bf74aa684ecbba9bbe7043d6 *tests/testthat/test-inhulln.R
7c5dbfcf2f9bad68a5c3349374e9441a *tests/testthat/test-intersectn.R
f31602e6034e476ca45ae37dc1174c88 *tests/testthat/test-parallel.R
f281e943e2b03f9779a928d579d1c212 *tests/testthat/test-pol2cart.R
2d4dfa8755e18a70a0684185285cb0f2 *tests/testthat/test-polyarea.R
17a871068bdea2a3060b7453d747ab74 *tests/testthat/test-sph2cart.R
97b23669d29291f045958d43f72caeb5 *tests/testthat/test-tsearch-tsearchn-comparison.R
7caf7a903cd201929495683eedd3a69a *tests/testthat/test-tsearch.R
3a847edb84b447e6cd7f6c52e141230e *tests/testthat/test-tsearchn.R
af3ca7a8ec4eb7c3808e7e4b0e7b9d20 *vignettes/LICENSE-NOTES
a17aa14b2581ee880ad40d5d1ad0c138 *vignettes/MODIFIED.txt
68a2cd14c4b008ba087a727ca09b5bc4 *vignettes/qhull-eg-002.pdf
d58115b01fb59320488283b1e5bdca89 *vignettes/qhull-eg-004.pdf
e4da12d940671662c95f27cc01da1ddb *vignettes/qhull-eg.Rnw
7f91e2f84c11dd41a932b6d03a63ae3d *vignettes/qhull/Announce.txt
0c45b9e641ac0592e3eda32dac223b9a *vignettes/qhull/COPYING.txt
1ad9811271fd30b546ff4f5d3d0e4cc6 *vignettes/qhull/File_id.diz
916939bb1fee5b8ca7826fbcf7b53232 *vignettes/qhull/README.txt
dfc60c06612b894244510f7efa338c08 *vignettes/qhull/REGISTER.txt
4b18ce3564cef2b9954e0c13163abfbd *vignettes/qhull/html/index.html
59e9b69f186c9e715192df9e146ebd21 *vignettes/qhull/html/normal_voronoi_knauss_oesterle.jpg
5f502b6a0e08493f4ef5ced79ddb5a77 *vignettes/qhull/html/qconvex.html
fbd0d63639d5aa801f85e37f75c5d392 *vignettes/qhull/html/qdelau_f.html
28dd1530388b4de8badc95b12b1d9bef *vignettes/qhull/html/qdelaun.html
bb51e7810cc49e5aff1b910bc3126713 *vignettes/qhull/html/qh--4d.gif
687f459f95e958da6c3ff0c83cafcf46 *vignettes/qhull/html/qh--cone.gif
dc51084bc7ba1f235c71d40c771ce9c8 *vignettes/qhull/html/qh--dt.gif
829df3fbc9a3f36dbdb6389f768b5570 *vignettes/qhull/html/qh--geom.gif
0587393a4591c5fbcd040af9a4f510c7 *vignettes/qhull/html/qh--half.gif
0515fcc283b7dfeeaa7169218722880e *vignettes/qhull/html/qh--rand.gif
012717a06d2274995a039dbc931d10aa *vignettes/qhull/html/qh-code.html
ca6ae4c704d8be67d50b71ce137768a4 *vignettes/qhull/html/qh-eg.html
378b30492679846a65c50da8d1bd9962 *vignettes/qhull/html/qh-faq.html
189ccc476db023a2ef3d5f74a301842a *vignettes/qhull/html/qh-get.html
c572d9a92948eb7f3333ff153c844b7f *vignettes/qhull/html/qh-impre.html
8d37fbeae5ba5dc5f8d673ca589d07eb *vignettes/qhull/html/qh-optc.html
14922021d64987023bb90e3b628eceff *vignettes/qhull/html/qh-optf.html
eb0cb51f5497a0b57098213858fc665b *vignettes/qhull/html/qh-optg.html
b7f55169f381cfab737188ded5aa3fa3 *vignettes/qhull/html/qh-opto.html
e4c732d38d8389c55fa63955a7e644c8 *vignettes/qhull/html/qh-optp.html
b5a6d0038f4522eb94b4b87804e1d2f9 *vignettes/qhull/html/qh-optq.html
008e3a59ba0a8c98d4671f8a751f5e6e *vignettes/qhull/html/qh-optt.html
30454c2fa7db3ea2a72bf72ded9d6447 *vignettes/qhull/html/qh-quick.html
6aa82b4c2709dd98df2aff103fb944b5 *vignettes/qhull/html/qhalf.html
e8992f5b2de07cbf48583e1f6b9ad5e9 *vignettes/qhull/html/qhull-cpp.xml
35d88647a340615dcd1bd842a565475c *vignettes/qhull/html/qhull.html
fc4b6d8b5abec935f14dd71369718e9f *vignettes/qhull/html/qhull.man
5e213194265bc30a85ef692ac37d7836 *vignettes/qhull/html/qhull.txt
8550cf46dbd89d8068969bf225600f16 *vignettes/qhull/html/qvoron_f.html
f8369a8be58b5f738e7421e367881db2 *vignettes/qhull/html/qvoronoi.html
03b90e4e5eb3ed77f57a3063694f801d *vignettes/qhull/html/rbox.html
4cbad586d2136f611dbaf7f47128cc86 *vignettes/qhull/html/rbox.man
61cd54c422366e1ef1db2babdb3daff9 *vignettes/qhull/html/rbox.txt
b0e7f903d9fe9008ff87baabe3c57b64 *vignettes/qhull/index.html
geometry/R/ 0000755 0001762 0000144 00000000000 14744661717 012327 5 ustar ligges users geometry/R/sph2cart.R 0000644 0001762 0000144 00000005244 13433536400 014165 0 ustar ligges users ## Copyright (C) 2017 David Sterratt
## Copyright (C) 2000-2017 Kai Habel
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it){
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for (more details.){
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING. If not, see
## .
##' Transform spherical coordinates to Cartesian coordinates
##'
##' The inputs \code{theta}, \code{phi}, and \code{r} must be the same
##' shape, or scalar. If called with a single matrix argument then
##' each row of \code{S} represents the spherical coordinate
##' (\code{theta}, \code{phi}, \code{r}).
##'
##' @param theta describes the angle relative to the positive x-axis.
##' @param phi is the angle relative to the xy-plane.
##' @param r is the distance to the origin \code{(0, 0, 0)}.
##'
##' If only a single return argument is requested then return a matrix
##' \code{C} where each row represents one Cartesian coordinate
##' (\code{x}, \code{y}, \code{z}).
##' @seealso \code{\link{cart2sph}}, \code{\link{pol2cart}}, \code{\link{cart2pol}}
##' @author Kai Habel
##' @author David Sterratt
##' @export
sph2cart <- function(theta, phi=NULL, r=NULL) {
if ((is.null(phi) & !is.null(r)) |
(is.null(r) & !is.null(phi))) {
stop("There should be 3 arguments (theta, phi, r) or one argument (theta)")
}
if (is.null(phi) & is.null(r)) {
if (!(is.numeric(theta))) {
stop("input must be matrix with 3 columns [theta, phi, r]")
}
if (!(is.matrix(theta) & (ncol(theta) == 3))) {
stop("matrix input must have 3 columns [theta, phi, r]")
}
r <- theta[,3]
phi <- theta[,2]
theta <- theta[,1]
} else {
if (!is.numeric(theta) | !is.numeric(phi) | !is.numeric (r))
stop("theta, phi, r must be numeric arrays of the same size, or scalar")
if ( !(((length(theta) == length(phi)) | (length(theta) == 1) | (length(phi) == 1)) &
((length(theta) == length(r)) | (length(theta) == 1) | (length(r) == 1)) &
((length(phi) == length(r)) | (length(phi) == 1) | (length(r) == 1)))) {
stop("theta, phi, r must be matrices of the same size, or scalar")
}
}
x <- r*cos(phi)*cos(theta)
y <- r*cos(phi)*sin(theta)
z <- r*sin(phi)
return(cbind(x, y, z))
}
geometry/R/mesh.intersect.R 0000644 0001762 0000144 00000000145 13432317337 015372 0 ustar ligges users "mesh.intersect" <-
function (p, regionA, regionB, ...)
matmax(regionA(p, ...), regionB(p, ...))
geometry/R/RcppExports.R 0000644 0001762 0000144 00000000477 14744661717 014753 0 ustar ligges users # Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' @importFrom Rcpp sourceCpp
C_tsearch <- function(x, y, elem, xi, yi, bary = FALSE, eps = 1.0e-12) {
.Call('_geometry_C_tsearch', PACKAGE = 'geometry', x, y, elem, xi, yi, bary, eps)
}
geometry/R/halfspacen.R 0000644 0001762 0000144 00000007005 14662314120 014536 0 ustar ligges users ##' Compute halfspace intersection about a point
##'
##' @param p An \eqn{M}-by-\eqn{N+1} matrix. Each row of \code{p}
##' represents a halfspace by a \eqn{N}-dimensional normal to a
##' hyperplane and the offset of the hyperplane.
##' @param fp A \dQuote{feasible} point that is within the space
##' contained within all the halfspaces.
##' @param options String containing extra options, separated by
##' spaces, for the underlying Qhull command; see Qhull
##' documentation at \url{../doc/qhull/html/qhalf.html}.
##'
##' @return A \eqn{N}-column matrix containing the intersection
##' points of the hyperplanes \url{../doc/qhull/html/qhalf.html}.
##'
##' @author David Sterratt
##' @note \code{halfspacen} was introduced in geometry 0.4.0, and is
##' still under development. It is worth checking results for
##' unexpected behaviour.
##' @seealso \code{\link{convhulln}}
##' @references \cite{Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T.,
##' \dQuote{The Quickhull algorithm for convex hulls,} \emph{ACM
##' Trans. on Mathematical Software,} Dec 1996.}
##'
##' \url{http://www.qhull.org}
##' @examples
##' p <- rbox(0, C=0.5) # Generate points on a unit cube centered around the origin
##' ch <- convhulln(p, "n") # Generate convex hull, including normals to facets, with "n" option
##' # Intersections of half planes
##' # These points should be the same as the orginal points
##' pn <- halfspacen(ch$normals, c(0, 0, 0))
##'
##' @export
##' @useDynLib geometry
halfspacen <- function (p, fp, options = "Tv") {
tmp_stdout <- tempfile("Rf")
tmp_stderr <- tempfile("Rf")
on.exit(c(tmp_stdout, tmp_stderr))
## Input sanitisation
options <- paste(options, collapse=" ")
## Coerce the input to be matrix
if (is.data.frame(p)) {
p <- as.matrix(p)
}
## Make sure we have real-valued input
storage.mode(p) <- "double"
## We need to check for NAs in the input, as these will crash the C
## code.
if (any(is.na(p))) {
stop("The first argument should not contain any NAs")
}
## Check dimensions
if (ncol(p) - 1 != length(as.vector(fp))) {
stop("Dimension of hyperspace is ", ncol(p) - 1, " but dimension of fixed point is ", length(as.vector(fp)))
}
## In geometry 0.4.0, we tried to get around halspacen fails because
## of similar hyperplanes, by removing the most similar ones (i.e.
## those that had very acute angles to one another). However, this
## was ugly and turned out to unreliable , so it has been removed in
## geometry 0.4.1 and above. Users are recommended to supply the
## QJ option in
## The fixed point is passed as an option
out <- tryCatch(.Call("C_halfspacen", p,
as.character(paste(options, paste0("H",paste(fp, collapse=",")))),
tmp_stdout, tmp_stderr,
PACKAGE="geometry"),
error=function(e) {
if (grepl("^Received error code 2 from qhull.", e$message)) {
e$message <- paste(e$message, "\nTry calling halfspacen with options=\"Tv QJ\"")
}
return(e)
})
if (inherits(out, "error")) {
stop(out$message)
}
return(out)
}
## If there is an error, it could be because of two very similar halfspaces.
## n1 = ch1$normals[1,1:3]
## n2 = ch2$normals[1,1:3]
## d1 = ch1$normals[1,4]
## d2 = ch2$normals[1,4]
## solve(rbind(n1, n2, extprod3d(n1, n2)), c(d1, d2, 0))
## sqrt(sum(solve(rbind(n1, n2, extprod3d(n1, n2)), c(-d1, -d2, 0))^2))
## dot(n1+ n2, extprod3d(n1, n2))
geometry/R/matsort.R 0000644 0001762 0000144 00000001140 13432317337 014124 0 ustar ligges users "matsort" <-
function (...) {
x = cbind(...)
if(!is.numeric(x))
stop("Input should by numeric.")
res = array(dim = c(nrow(x), 0))
if (!is.matrix(drop(x)))
return(x)
else if (ncol(x) > 30)
return(t(apply(x, 1, sort)))
else while (is.matrix(drop(x))) {
imc = max.col(x)
x = t(x)
imx = nrow(x) * (1:ncol(x) - 1) + imc
xmax = x[imx]
x = t(matrix(x[-imx], ncol = ncol(x)))
res = cbind(res, xmax)
}
res = cbind(res, x)
colnames(res) = NULL
rownames(res) = NULL
return(res)
}
geometry/R/tsearch.R 0000644 0001762 0000144 00000030366 14662314120 014071 0 ustar ligges users ##' Search for the enclosing Delaunay convex hull
##'
##' For \code{t <- delaunay(cbind(x, y))}, where \code{(x, y)} is a 2D set of
##' points, \code{tsearch(x, y, t, xi, yi)} finds the index in \code{t}
##' containing the points \code{(xi, yi)}. For points outside the convex hull
##' the index is \code{NA}.
##'
##' @param x X-coordinates of triangulation points
##' @param y Y-coordinates of triangulation points
##' @param t Triangulation, e.g. produced by \code{t <-
##' delaunayn(cbind(x, y))}
##' @param xi X-coordinates of points to test
##' @param yi Y-coordinates of points to test
##' @param bary If \code{TRUE} return barycentric coordinates as well
##' as index of triangle.
##' @param method One of \code{"quadtree"} or \code{"orig"}. The
##' Quadtree algorithm is much faster and new from version
##' 0.4.0. The \code{orig} option uses the tsearch algorithm adapted
##' from Octave code. Its use is deprecated and it may be removed
##' from a future version of the package.
##' @return If \code{bary} is \code{FALSE}, the index in \code{t} containing the points
##' \code{(xi, yi)}. For points outside the convex hull the index is \code{NA}.
##' If \code{bary} is \code{TRUE}, a list containing:
##' \describe{
##' \item{list("idx")}{the index in \code{t} containing the points \code{(xi, yi)}}
##' \item{list("p")}{a 3-column matrix containing the barycentric coordinates with
##' respect to the enclosing triangle of each point \code{(xi, yi)}.}
##' }
##' @author Jean-Romain Roussel (Quadtree algorithm), David Sterratt (Octave-based implementation)
##' @note The original Octave function is Copyright (C) 2007-2012
##' David Bateman
##' @seealso \code{\link{tsearchn}}, \code{\link{delaunayn}}
##' @export
tsearch <- function(x, y, t, xi, yi, bary=FALSE, method="quadtree") {
xtxt = deparse(substitute(x))
ytxt = deparse(substitute(y))
xitxt = deparse(substitute(xi))
yitxt = deparse(substitute(yi))
ttxt = deparse(substitute(t))
if (!is.vector(x)) {stop(paste(xtxt, "is not a vector"))}
if (!is.vector(y)) {stop(paste(ytxt, "is not a vector"))}
if (!is.matrix(t)) {stop(paste(ttxt, "is not a matrix"))}
if (!is.vector(xi)) {stop(paste(xitxt, "is not a vector"))}
if (!is.vector(yi)) {stop(paste(yitxt, "is not a vector"))}
if (length(x) != length(y)) {
stop(paste(xtxt, "is not same length as", ytxt))
}
if (length(xi) != length(yi)) {
stop(paste(xitxt, "is not same length as", yitxt))
}
if (ncol(t) != 3) {
stop(paste(ttxt, "does not have three columns"))
}
if (any(as.integer(t) != t)) {
stop(paste(ttxt, "does not have integer elements"))
}
if (length(x) == 0) {stop(paste(xtxt, "is empty"))}
if (length(y) == 0) {stop(paste(ytxt, "is empty"))}
if (any(is.na(x))) {stop(paste(xtxt, "contains NAs"))}
if (any(is.na(y))) {stop(paste(ytxt, "contains NAs"))}
if (length(x) < 3 | length(y) < 3) {
stop("A triangulation should have at least 3 points")
}
storage.mode(t) <- "integer"
if (max(t) > length(x)) {
stop(paste(ttxt, "has indexes greater than the number of points"))
}
if (min(t) <= 0) {
stop(paste(ttxt, "has indexes which refer to non-existing points"))
}
if (length(xi) == 0 | length(yi) == 0) {
if (!bary)
return (integer(0))
else
return (list(idx = integer(0), p = matrix(0,0,3)))
}
if (method == "quadtree") {
out <- C_tsearch(x, y, t, xi, yi, bary)
} else {
out <- .Call("C_tsearch_orig", x, y, t, xi, yi, bary, PACKAGE="geometry")
}
if (bary) {
names(out) <- c("idx", "p")
}
return(out)
}
##' Search for the enclosing Delaunay convex hull
##'
##' For \code{t = delaunayn(x)}, where \code{x} is a set of points in \eqn{N}
##' dimensions, \code{tsearchn(x, t, xi)} finds the index in \code{t}
##' containing the points \code{xi}. For points outside the convex hull,
##' \code{idx} is \code{NA}. \code{tsearchn} also returns the barycentric
##' coordinates \code{p} of the enclosing triangles.
##'
##' If \code{x} is \code{NA} and the \code{t} is a
##' \code{delaunayn} object produced by
##' \code{\link{delaunayn}} with the \code{full} option, then use the
##' Qhull library to perform the search. Please note that this is
##' experimental in geometry version 0.4.0 and is only partly tested
##' for 3D hulls, and does not yet work for hulls of 4 dimensions and
##' above.
##'
##' @param x An \eqn{N}-column matrix, in which each row represents a
##' point in \eqn{N}-dimensional space.
##' @param t A matrix with \eqn{N+1} columns. A row of \code{t}
##' contains indices into \code{x} of the vertices of an
##' \eqn{N}-dimensional simplex. \code{t} is usually the output of
##' delaunayn.
##' @param xi An \eqn{M}-by-\eqn{N} matrix. The rows of \code{xi}
##' represent \eqn{M} points in \eqn{N}-dimensional space whose
##' positions in the mesh are being sought.
##' @param ... Additional arguments
##' @return A list containing:
##' \describe{
##' \item{\code{idx}}{An \eqn{M}-long vector containing the indices
##' of the row of \code{t} in which each point in \code{xi} is found.}
##' \item{\code{p}}{An \eqn{M}-by-\eqn{N+1} matrix containing the
##' barycentric coordinates with respect to the enclosing simplex
##' of each point in \code{xi}.}}
##' @author David Sterratt
##' @note Based on the Octave function Copyright (C) 2007-2012 David
##' Bateman.
##' @seealso \code{\link{tsearch}}, \code{\link{delaunayn}}
##' @export
tsearchn <- function(x, t, xi, ...) {
if (any(is.na(x)) && inherits(t, "delaunayn")) {
return(tsearchn_delaunayn(t, xi))
}
fast <- TRUE
if (!is.null(list(...)$fast) & is.logical(list(...)$fast))
fast <- list(...)$fast
## Check input
if (!is.matrix(x)) {stop(paste(deparse(substitute(x)), "is not a matrix"))}
if (!is.matrix(t)) {stop(paste(deparse(substitute(t)), "is not a matrix"))}
if (!is.matrix(xi)) {stop(paste(deparse(substitute(xi)), "is not a matrix"))}
n <- dim(x)[2] # Number of dimensions
if (n==2 && fast) {
return(tsearch(x[,1], x[,2], t, xi[,1], xi[,2], bary=TRUE))
}
nt <- dim(t)[1] # Number of simplexes
m <- dim(x)[1] # Number of points in simplex grid
mi <- dim(xi)[1] # Number of points to search for
## If there are no points to search for, return an empty index
## vector and an empty coordinate matrix
if (mi==0) {
return(list(idx=c(), p=matrix(0, 0, n + 1)))
}
idx <- rep(NA, mi)
p <- matrix(NA, mi, n + 1)
## Indicies of points that still need to be searched for
ni <- 1:mi
degenerate.simplices <- c()
## Go through each simplex in turn
for (i in 1:nt) {
## Only calculate the Barycentric coordinates for points that have not
## already been found in a simplex.
b <- suppressWarnings(cart2bary(x[t[i,],], xi[ni,,drop=FALSE]))
if (is.null(b)) {
degenerate.simplices <- c(degenerate.simplices, i)
} else {
## Our points xi are in the current triangle if (all(b >= 0) &&
## all (b <= 1)). However as we impose that sum(b,2) == 1 we only
## need to test all(b>=0). Note that we need to add a small margin
## for rounding errors
intri <- apply(b >= -1e-12, 1, all)
## Set the simplex indicies of the points that have been found to
## this simplex
idx[ni[intri]] <- i
## Set the baryocentric coordinates of the points that have been found
p[ni[intri],] <- b[intri,]
## Remove these points from the search list
ni <- ni[!intri]
## If there are no more points to search for, give up
if (length(ni) == 0) { break }
}
}
if (length(degenerate.simplices) > 0) {
warning(paste("Degenerate simplices:", toString(degenerate.simplices)))
}
return(list(idx=idx, p=p))
}
##' Conversion of Cartesian to Barycentric coordinates.
##'
##' Given the Cartesian coordinates of one or more points, compute
##' the barycentric coordinates of these points with respect to a
##' simplex.
##'
##' Given a reference simplex in \eqn{N} dimensions represented by a
##' \eqn{N+1}-by-\eqn{N} matrix an arbitrary point \eqn{P} in
##' Cartesian coordinates, represented by a 1-by-\eqn{N} row vector, can be
##' written as
##' \deqn{P = \beta X}
##' where \eqn{\beta} is an \eqn{N+1} vector of the barycentric coordinates.
##' A criterion on \eqn{\beta} is that
##' \deqn{\sum_i\beta_i = 1}
##' Now partition the simplex into its first \eqn{N} rows \eqn{X_N} and
##' its \eqn{N+1}th row \eqn{X_{N+1}}. Partition the barycentric
##' coordinates into the first \eqn{N} columns \eqn{\beta_N} and the
##' \eqn{N+1}th column \eqn{\beta_{N+1}}. This allows us to write
##' \deqn{P_{N+1} - X_{N+1} = \beta_N X_N + \beta_{N+1} X_{N+1} - X_{N+1}}
##' which can be written
##' \deqn{P_{N+1} - X_{N+1} = \beta_N(X_N - 1_N X_{N+1})}
##' where \eqn{1_N} is an \eqn{N}-by-1 matrix of ones. We can then solve
##' for \eqn{\beta_N}:
##' \deqn{\beta_N = (P_{N+1} - X_{N+1})(X_N - 1_N X_{N+1})^{-1}}
##' and compute
##' \deqn{\beta_{N+1} = 1 - \sum_{i=1}^N\beta_i}
##' This can be generalised for multiple values of
##' \eqn{P}, one per row.
##'
##' @param X Reference simplex in \eqn{N} dimensions represented by a
##' \eqn{N+1}-by-\eqn{N} matrix
##' @param P \eqn{M}-by-\eqn{N} matrix in which each row is the Cartesian
##' coordinates of a point.
##' @return \eqn{M}-by-\eqn{N+1} matrix in which each row is the
##' barycentric coordinates of corresponding row of \code{P}. If the
##' simplex is degenerate a warning is issued and the function returns
##' \code{NULL}.
##' @author David Sterratt
##' @note Based on the Octave function by David Bateman.
##' @examples
##' ## Define simplex in 2D (i.e. a triangle)
##' X <- rbind(c(0, 0),
##' c(0, 1),
##' c(1, 0))
##' ## Cartesian coordinates of points
##' P <- rbind(c(0.5, 0.5),
##' c(0.1, 0.8))
##' ## Plot triangle and points
##' trimesh(rbind(1:3), X)
##' text(X[,1], X[,2], 1:3) # Label vertices
##' points(P)
##' cart2bary(X, P)
##' @seealso \code{\link{bary2cart}}
##' @export
cart2bary <- function(X, P) {
M <- nrow(P)
N <- ncol(P)
if (ncol(X) != N) {
stop("Simplex X must have same number of columns as point matrix P")
}
if (nrow(X) != (N+1)) {
stop("Simplex X must have N columns and N+1 rows")
}
X1 <- X[1:N,] - (matrix(1,N,1) %*% X[N+1,,drop=FALSE])
if (rcond(X1) < .Machine$double.eps) {
warning("Degenerate simplex")
return(NULL)
}
Beta <- (P - matrix(X[N+1,], M, N, byrow=TRUE)) %*% solve(X1)
Beta <- cbind(Beta, 1 - apply(Beta, 1, sum))
return(Beta)
}
##' Conversion of Barycentric to Cartesian coordinates
##'
##' Given the barycentric coordinates of one or more points with
##' respect to a simplex, compute the Cartesian coordinates of these
##' points.
##'
##' @param X Reference simplex in \eqn{N} dimensions represented by a
##' \eqn{N+1}-by-\eqn{N} matrix
##' @param Beta \eqn{M} points in barycentric coordinates with
##' respect to the simplex \code{X} represented by a
##' \eqn{M}-by-\eqn{N+1} matrix
##' @return \eqn{M}-by-\eqn{N} matrix in which each row is the
##' Cartesian coordinates of corresponding row of \code{Beta}
##' @examples
##' ## Define simplex in 2D (i.e. a triangle)
##' X <- rbind(c(0, 0),
##' c(0, 1),
##' c(1, 0))
##' ## Cartesian cooridinates of points
##' beta <- rbind(c(0, 0.5, 0.5),
##' c(0.1, 0.8, 0.1))
##' ## Plot triangle and points
##' trimesh(rbind(1:3), X)
##' text(X[,1], X[,2], 1:3) # Label vertices
##' P <- bary2cart(X, beta)
##' points(P)
##' @seealso \code{\link{cart2bary}}
##' @author David Sterratt
##' @export
bary2cart <- function(X, Beta) {
return(Beta %*% X)
}
tsearchn_delaunayn <- function(t, xi) {
warning("tsearchn using the Qhull library is currently an experimental feature. It has been tested somewhat for 3D triangulations, but it does not work reliably for 4D triangulations. See https://github.com/davidcsterratt/geometry/issues/6")
ts <- .Call("C_tsearchn", t, xi)
p <- do.call(rbind,
lapply(1:nrow(xi), function(i) {
cart2bary(ts$P[t$tri[ts$idx[i],],], xi[i,,drop=FALSE])
}))
## C_tsearchn will return the *best* facet. Need to check it is
## actually in the triangulation
outwith_facet_inds <- which(apply(p < 0, 1, any))
idx <- ts$idx
idx[outwith_facet_inds] <- NA
p[outwith_facet_inds,] <- NA
return(list(idx=idx, p=p, P=ts$P))
}
geometry/R/dotprod.R 0000644 0001762 0000144 00000002246 13432317337 014116 0 ustar ligges users ##' If \code{x} and \code{y} are matrices, calculate the dot-product
##' along the first non-singleton dimension. If the optional argument
##' \code{d} is given, calculate the dot-product along this
##' dimension.
##'
##' @title Compute the dot product of two vectors
##' @param x Matrix of vectors
##' @param y Matrix of vectors
##' @param d Dimension along which to calculate the dot product
##' @return Vector with length of \code{d}th dimension
##' @author David Sterratt
##' @keywords arith math array
##' @export
dot <- function(x, y, d=NULL) {
if (is.vector(x))
x <- matrix(x, ncol = 1)
if (is.vector(y))
y <- matrix(y, ncol = 1)
ndim <- length(dim(x))
## Determine dimension along which to sum
if (is.null(d)) {
di <- which(dim(x) > 1)
if (length(di == 0)) {
d <- 1
} else {
d <- di[1]
}
}
## Check size of d
if (d > ndim) {
stop("d is larger than the number of dimensions of the data")
}
## Use rowSums and colSums as they are more efficient than apply
if (ndim == 2) {
if (d == 2) {
return(rowSums(x*y))
}
if (d == 1) {
return(colSums(x*y))
}
}
return(apply(x*y, d, sum))
}
geometry/R/trisplinter.R 0000644 0001762 0000144 00000000463 13432317337 015021 0 ustar ligges users "trisplinter" <-
function(T,p,threshold=sqrt(.Machine$double.eps)){
rownorm2 = function(x) drop(sqrt((x^2)%*%c(1,1)))
d1 = p[T[,1],] - p[T[,2],]
d2 = p[T[,2],] - p[T[,3],]
d1 = d1 / rownorm2(d1)
d2 = d2 / rownorm2(d2)
ar = d1[,1]*d2[,2] - d1[,2]*d2[,1]
return(abs(ar) < threshold)
}
geometry/R/mesh.dcircle.R 0000644 0001762 0000144 00000002201 13432317337 014772 0 ustar ligges users ##' Signed distance from points \code{p} to boundary of circle to
##' allow easy definition of regions in \code{\link{distmesh2d}}.
##'
##' @title Circle distance function
##' @param p A matrix with 2 columns (3 in \code{mesh.dsphere}), each row
##' representing a point in the plane.
##' @param radius radius of circle
##' @param ... additional arguments (not used)
##' @return A vector of length \code{nrow(p)} containing the signed
##' distances to the circle
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @seealso \code{\link{distmesh2d}}, \code{\link{mesh.drectangle}},
##' \code{\link{mesh.diff}}, \code{\link{mesh.intersect}},
##' \code{\link{mesh.union}}
##' @references \url{http://persson.berkeley.edu/distmesh/}
##'
##' \cite{P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB. SIAM
##' Review, Volume 46 (2), pp. 329-345, June 2004}
##' @keywords arith math
##' @examples
##'
##' example(distmesh2d)
##' @export
mesh.dcircle <- function (p, radius = 1, ...) {
if (!is.matrix(p))
p <- t(as.matrix(p))
return(sqrt((p^2) %*% c(1, 1)) - radius)
}
geometry/R/mesh.hunif.R 0000644 0001762 0000144 00000001363 13432317337 014506 0 ustar ligges users ##' Uniform desired edge length function of position to allow easy
##' definition of regions when passed as the \code{fh} argument of
##' \code{\link{distmesh2d}} or \code{\link{distmeshnd}}.
##'
##' @title Uniform desired edge length
##' @param p A \code{n}-by-\code{m} matrix, each row representing a
##' point in an \code{m}-dimensional space.
##' @param ... additional arguments (not used)
##' @return Vector of ones of length \code{n}.
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @seealso \code{\link{distmesh2d}} and \code{\link{distmeshnd}}.
##' @export
mesh.hunif <- function (p, ...) {
if (!is.matrix(p))
stop("Input `p' should be matrix.")
return(rep(1, nrow(p)))
}
geometry/R/extprod3d.R 0000644 0001762 0000144 00000002357 14664604470 014367 0 ustar ligges users ##' Compute external- or \sQuote{cross}- product of 3D vectors.
##'
##' Computes the external product
##' \deqn{ \left(x_2 y_3 - x_3 y_2,\;
##' x_3 y_1 - x_1 y_3,\;
##' x_1 y_2 - x_2 y_1 \right) }{
##' (x2 * y3 - x3 * y2,
##' x3 * y1 - x1 * y3,
##' x1 * y2 - x2 * y1) }
##' of the 3D vectors in \bold{x} and \bold{y}.
##'
##' @param x \code{n}-by-3 matrix. Each row is one \bold{x}-vector
##' @param y \code{n}-by-3 matrix. Each row is one \bold{y}-vector
##' @param drop logical. If \code{TRUE} and if the inputs are one row
##' matrices or vectors, then delete the dimensions of the array
##' returned.
##' @return If \code{n} is greater than 1 or \code{drop} is
##' \code{FALSE}, \code{n}-by-3 matrix; if \code{n} is 1 and
##' \code{drop} is \code{TRUE}, a vector of length 3.
##' @author Raoul Grasman
##' @keywords arith math array
##' @seealso \code{\link[base]{drop}}
##' @export
extprod3d <-function (x, y, drop=TRUE)
{
x = matrix(x, ncol = 3)
y = matrix(y, ncol = 3)
z = cbind(x[, 2] * y[, 3] - x[, 3] * y[, 2],
x[, 3] * y[, 1] - x[, 1] * y[, 3],
x[, 1] * y[, 2] - x[, 2] * y[, 1])
if (drop) {
return(drop(z))
}
return(z)
}
geometry/R/distmesh2d.R 0000644 0001762 0000144 00000022733 14662314120 014505 0 ustar ligges users ##' A simple mesh generator for non-convex regions
##'
##' An unstructured simplex requires a choice of mesh points (vertex nodes) and
##' a triangulation. This is a simple and short algorithm that improves the
##' quality of a mesh by relocating the mesh points according to a relaxation
##' scheme of forces in a truss structure. The topology of the truss is reset
##' using Delaunay triangulation. A (sufficiently smooth) user supplied signed
##' distance function (\code{fd}) indicates if a given node is inside or
##' outside the region. Points outside the region are projected back to the
##' boundary.
##'
##' This is an implementation of original Matlab software of Per-Olof Persson.
##'
##' Excerpt (modified) from the reference below:
##'
##' \sQuote{The algorithm is based on a mechanical analogy between a triangular
##' mesh and a 2D truss structure. In the physical model, the edges of the
##' Delaunay triangles of a set of points correspond to bars of a truss. Each
##' bar has a force-displacement relationship \eqn{f(\ell, \ell_{0})}{F(L,L0)}
##' depending on its current length \eqn{\ell}{L} and its unextended length
##' \eqn{\ell_{0}}{L0}.}
##'
##' \sQuote{External forces on the structure come at the boundaries, on which
##' external forces have normal orientations. These external forces are just
##' large enough to prevent nodes from moving outside the boundary. The
##' position of the nodes are the unknowns, and are found by solving for a
##' static force equilibrium. The hope is that (when \code{fh = function(p)
##' return(rep(1,nrow(p)))}), the lengths of all the bars at equilibrium will
##' be nearly equal, giving a well-shaped triangular mesh.}
##'
##' See the references below for all details. Also, see the comments in the
##' source file.
##'
##' @param fd Vectorized signed distance function, for example
##' \code{\link{mesh.dcircle}} or \code{\link{mesh.diff}}, accepting
##' an \code{n}-by-\code{2} matrix, where \code{n} is arbitrary, as
##' the first argument.
##' @param fh Vectorized function, for example
##' \code{\link{mesh.hunif}}, that returns desired edge length as a
##' function of position. Accepts an \code{n}-by-\code{2} matrix,
##' where \code{n} is arbitrary, as its first argument.
##' @param h0 Initial distance between mesh nodes. (Ignored of
##' \code{p} is supplied)
##' @param bbox Bounding box \code{cbind(c(xmin,xmax), c(ymin,ymax))}
##' @param p An \code{n}-by-\code{2} matrix. The rows of \code{p}
##' represent locations of starting mesh nodes.
##' @param pfix \code{nfix}-by-2 matrix with fixed node positions.
##' @param \dots parameters to be passed to \code{fd} and/or \code{fh}
##' @param dptol Algorithm stops when all node movements are smaller
##' than \code{dptol}
##' @param ttol Controls how far the points can move (relatively)
##' before a retriangulation with \code{\link{delaunayn}}.
##' @param Fscale \dQuote{Internal pressure} in the edges.
##' @param deltat Size of the time step in Euler's method.
##' @param geps Tolerance in the geometry evaluations.
##' @param deps Stepsize \eqn{\Delta x} in numerical derivative
##' computation for distance function.
##' @param maxiter Maximum iterations.
##' @param plot logical. If \code{TRUE} (default), the mesh is
##' plotted as it is generated.
##' @return \code{n}-by-\code{2} matrix with node positions.
##' @section Wishlist : \itemize{ \item Implement in C/Fortran
##' \item Implement an \code{n}D version as provided in the Matlab
##' package \item Translate other functions of the Matlab package }
##' @author Raoul Grasman
##' @seealso \code{\link[interp]{tri.mesh}}, \code{\link{delaunayn}},
##' \code{\link{mesh.dcircle}}, \code{\link{mesh.drectangle}},
##' \code{\link{mesh.diff}}, \code{\link{mesh.union}},
##' \code{\link{mesh.intersect}}
##' @references \url{http://persson.berkeley.edu/distmesh/}
##'
##' \cite{P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB. SIAM
##' Review, Volume 46 (2), pp. 329-345, June 2004}
##' @keywords math optimize dplot graphs
##' @examples
##'
##' # examples distmesh2d
##' fd <- function(p, ...) sqrt((p^2)%*%c(1,1)) - 1
##' # also predefined as `mesh.dcircle'
##' fh <- function(p,...) rep(1,nrow(p))
##' bbox <- matrix(c(-1,1,-1,1),2,2)
##' p <- distmesh2d(fd,fh,0.2,bbox, maxiter=100)
##' # this may take a while:
##' # press Esc to get result of current iteration
##'
##' # example with non-convex region
##' fd <- function(p, ...) mesh.diff(p , mesh.drectangle, mesh.dcircle, radius=.3)
##' # fd defines difference of square and circle
##'
##' p <- distmesh2d(fd,fh,0.05,bbox,radius=0.3,maxiter=4)
##' p <- distmesh2d(fd,fh,0.05,bbox,radius=0.3, maxiter=10)
##' # continue on previous mesh
##' @export
distmesh2d <- function(fd, fh, h0, bbox, p=NULL, pfix=array(0,dim=c(0,2)), ...,
dptol=0.001, ttol=0.1, Fscale=1.2, deltat=0.2,
geps=0.001*h0, deps=sqrt(.Machine$double.eps)*h0,
maxiter=1000, plot=TRUE)
{
rownorm2 = function(x) drop(sqrt((x^2)%*%c(1, 1)))
if(any(apply(bbox, 2, diff)==0))
stop("Supplied bounding box has zero area.")
if(is.null(p)) {
#%1 generate initial grid
y = seq(bbox[1, 2],bbox[2, 2], by=h0*sqrt(3)/2)
x = seq(bbox[1, 1], bbox[2, 1], by=h0)
x = matrix(x,length(y),length(x),byrow=TRUE)
x[seq(2,length(y),by=2),] = x[seq(2,length(y),by=2),] + h0/2
p = cbind(c(x),y)
#%2 remove nodes outside boundary specified by fd (points evaluated negative are
# considered to lie inside the boundary)
p = p[fd(p, ...) < geps,]
}
## For density control
nfix <- nrow(pfix)
count <- 0
densityctrlfreq <- 30
count2 <- 0
r0 = 1 / fh(p, ...)^2 # acceptance probability
p = rbind(pfix, p[stats::runif(nrow(p)) ttol) {
pold = p
T = delaunayn(p) # generate a Delaunay triangulation
pmid = (p[T[, 1],] + p[T[, 2],] + p[T[, 3],])/3 # calculate average of node locations as centers
T = T[fd(pmid, ...) < (-geps), 1:3] # remove triangles with center outside region
#%4 describe edges by uniqe pairs of nodes
#bars = unique(rbind(T[, -1],T[, -2],T[, -3]), MARGIN=1);
#bars = bars[order(bars[, 1],bars[, 2]),];
bars = rbind(T[, -3], T[, -2], T[, -1]) # select unique edges
#too slow: bars = unique(matsort(bars), MARGIN=1)
bars = Unique(matsort(bars)) # order the edges according to the node indices
#%5 Graphical display
if (plot)
trimesh(T, p, asp=1) # a la Matlab
}
#%6 compute force F on the basis of edge lenghts
barvec = p[bars[, 1],] - p[bars[, 2],] # bar vectors
L = rownorm2(barvec) # their lengths
# calculate desired lengths L0 by use of fh
hbars = fh((p[bars[, 1],] + p[bars[, 2],])/2, ...)
L0 = hbars * Fscale * sqrt(sum(L^2)/sum(hbars^2))
######################################################
# Original Matlab code
# % Density control - remove points that are too close
# if mod(count,densityctrlfreq)==0 & any(L0>2*L)
# p(setdiff(reshape(bars(L0>2*L,:),[],1),1:nfix),:)=[];
# N=size(p,1); pold=inf;
# continue;
# end
######################################################
# R translation
# Density control - remove points that are too close
tmp1 <- (count %% densityctrlfreq)
tmp2 <- any(L0 > (2*L))
if (tmp1 == 0 & tmp2) {
count2 <- count2 + 1
# reshape(bars(L0>2*L,:),[],1)
tmp3 <- c(bars[L0 > (2*L),])
up <- which(duplicated(tmp3) == TRUE, arr.ind=TRUE)
p <- p[-up,]
N <- length(p[,1])
pold <- 1/.Machine$double.eps
}
######################################################
F = drop(L0 - L)
F[F < 0] = 0
Fvec = barvec * (F/L)
Ftot = matrix(0, N, 2)
ii = bars[, c(1, 1, 2, 2)]
jj = rep(1, length(F)) %o% c(1, 2, 1, 2)
s = c(cbind(Fvec, -Fvec))
ns = length(s)
Ftot[1:(2*N)] = rowsum(s, ii[1:ns] + ns*(jj[1:ns] - 1)) # sum all forces on each node
if (nrow(pfix) > 0) Ftot[1:nrow(pfix),] = 0 # Force = 0 at fixed points
p = p + deltat*Ftot;
#%7 excercise normal force at boundary: move overshoot points to nearest boundary point
d = fd(p);
ix= d > 0; # find points outside
dgradx= (fd(cbind(p[ix, 1]+deps, p[ix, 2]),...) - d[ix])/deps; # Numerical
dgrady= (fd(cbind(p[ix, 1], p[ix, 2]+deps),...) - d[ix])/deps; # gradient
p[ix,] = p[ix,] - cbind(d[ix]*dgradx, d[ix]*dgrady); # Project back to boundary
#%8 test for convergence
if(max(rownorm2(deltat*Ftot[d < (-geps),])/h0) < dptol | iter>=maxiter) break;
iter = iter + 1
}
message(sprintf("Number of density control ops = %d",count2))
message(sprintf("Number of iterations = %d",iter))
if (iter >= maxiter)
warning(" Maximum iterations reached. Relaxation process not \n completed")
return(p)
}
geometry/R/matorder.R 0000644 0001762 0000144 00000000270 13432317337 014253 0 ustar ligges users "matorder" <-
function (...)
{
x = cbind(...)
if(!is.numeric(x))
stop("Input should be numeric.")
do.call("order", lapply(1:ncol(x), function(i) x[, i]))
}
geometry/R/mesh.diff.R 0000644 0001762 0000144 00000002741 13432317337 014306 0 ustar ligges users ##' Compute the signed distances from points \code{p} to a region
##' defined by the difference, union or intersection of regions
##' specified by the functions \code{regionA} and \code{regionB}.
##' \code{regionA} and \code{regionB} must accept a matrix \code{p}
##' with 2 columns as their first argument, and must return a vector
##' of length \code{nrow(p)} containing the signed distances of the
##' supplied points in \code{p} to their respective regions.
##'
##' @title Difference, union and intersection operation on two regions
##' @return A vector of length \code{nrow(p)} containing the signed
##' distances to the boundary of the region.
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @param p A matrix with 2 columns (3 in \code{mesh.dsphere}), each row
##' representing a point in the plane.
##' @param regionA vectorized function describing region A in the
##' union / intersection / difference
##' @param regionB vectorized function describing region B in the
##' union / intersection / difference
##' @param ... additional arguments passed to \code{regionA} and
##' \code{regionB}
##' @aliases mesh.diff mesh.union mesh.intersect
##' @seealso \code{\link{distmesh2d}}, \code{\link{mesh.dcircle}},
##' \code{\link{mesh.drectangle}} \code{\link{mesh.dsphere}}
##' @export mesh.diff mesh.union mesh.intersect
mesh.diff <-function (p, regionA, regionB, ...) {
return(matmax(regionA(p, ...), -regionB(p, ...)))
}
geometry/R/intersectn.R 0000644 0001762 0000144 00000026327 13476414562 014635 0 ustar ligges users ##' Compute convex hull of intersection of two sets of points
##' @param ps1 First set of points
##' @param ps2 Second set of points
##' @param tol Tolerance used to determine if a feasible point lies
##' within the convex hulls of both points and to round off the
##' points generated by the halfspace intersection, which sometimes
##' produces points very close together.
##' @param return.chs If \code{TRUE} (default) return the convex hulls
##' of the first and second sets of points, as well as the convex
##' hull of the intersection.
##' @param options Options passed to \code{\link{halfspacen}}. By
##' default this is \code{Tv}.
##' @param fp Coordinates of feasible point, i.e. a point known to lie
##' in the hulls of \code{ps1} and \code{ps2}. The feasible point is
##' required for \code{\link{halfspacen}} to find the intersection.
##' \code{intersectn} tries to find the feasible point automatically
##' using the linear program in \code{\link{feasible.point}}, but
##' currently the linear program fails on some examples where there
##' is an obvious solution. This option overrides the automatic
##' search for a feasible point
##' @param autoscale \emph{Experimental in v0.4.2} Automatically scale
##' the points to lie in a sensible numeric range. May help to
##' correct some numerical issues.
##' @return List containing named elements: \code{ch1}, the convex
##' hull of the first set of points, with volumes, areas and normals
##' (see \code{\link{convhulln}}; \code{ch2}, the convex hull of the
##' first set of points, with volumes, areas and normals; \code{ps},
##' the intersection points of convex hulls \code{ch1} and
##' \code{ch2}; and \code{ch}, the convex hull of the intersection
##' points, with volumes, areas and normals.
##' @export
##' @examples
##' # Two overlapping boxes
##' ps1 <- rbox(0, C=0.5)
##' ps2 <- rbox(0, C=0.5) + 0.5
##' out <- intersectn(ps1, ps2)
##' message("Volume of 1st convex hull: ", out$ch1$vol)
##' message("Volume of 2nd convex hull: ", out$ch2$vol)
##' message("Volume of intersection convex hull: ", out$ch$vol)
##' @author David Sterratt
##' @note \code{intersectn} was introduced in geometry 0.4.0, and is
##' still under development. It is worth checking results for
##' unexpected behaviour.
##' @seealso \code{\link{convhulln}}, \code{\link{halfspacen}},
##' \code{\link{inhulln}}, \code{\link{feasible.point}}
##' @importFrom utils packageDescription
intersectn <- function(ps1, ps2, tol=0, return.chs=TRUE, options="Tv",
fp=NULL, autoscale=FALSE) {
distinct <-
any(apply(ps1, 2, min) > apply(ps2, 2, max)) ||
any(apply(ps1, 2, max) < apply(ps2, 2, min))
if (distinct & !return.chs) {
return(list(ch=list(vol=0)))
}
ch1 <- convhulln(ps1, "n FA")
ch2 <- convhulln(ps2, "n FA")
if (distinct) {
return(list(ch1=ch1, ch2=ch2, ch=list(vol=0)))
}
ch1s <- ch1
ch2s <- ch2
if (autoscale) {
pmean <- colMeans(rbind(ps1, ps2))
ch1s <- convhulln(t(t(ps1) - pmean), "n FA")
ch2s <- convhulln(t(t(ps2) - pmean), "n FA")
if (!is.null(fp)) {
fp <- fp - pmean
}
}
## Find feasible point in which points could overlap
if (is.null(fp)) {
fp <-tryCatch(feasible.point(ch1s, ch2s, tol=tol),
error=function(e){
stop("feasible.point() failed with error ",
e$message, "\n",
"If you can find a feasible point (i.e. point that lies in both hulls)\n",
"for this input, supply this with the \"fp\" option.\n",
"Otherwise, report bug, including inputs to intersectn() at\n",
utils::packageDescription("geometry", fields="BugReports"), "\n",
"or to ",
utils::packageDescription("geometry", fields="Maintainer"))
})
if (all(is.na(fp))) {
if (return.chs) {
return(list(ch1=ch1, ch2=ch2, ch=list(vol=0)))
}
return(list(ch=list(vol=0)))
}
} else {
## fp supplied
if (!is.numeric(fp)) {
stop("fp should be numeric")
}
if (length(fp) != ncol(ps1)) {
stop("fp should have same dimension as ps1 and ps2")
}
}
## Find intersections of halfspaces about feasible point. Catch error
## (code QH6023) when fixed point is not in intersection, due to
## precision issue.
ps <- tryCatch(halfspacen(rbind(ch1s$normals, ch2s$normals), fp, options=options),
error=function(e) {
if (grepl("QH6023", e$message)) {
return(NA)
}
errmess <- e$message
if (!grepl("QJ", options)) {
errmess <- paste(errmess, "\nTry calling intersectn with options=\"Tv QJ\"")
}
stop(errmess)
})
if (all(is.na(ps)) || is.null(ps)) {
if (return.chs) {
return(list(ch1=ch1, ch2=ch2, ch=list(vol=0)))
}
return(list(ch=list(vol=0)))
}
if (autoscale) {
ps <- t(t(ps) + pmean)
}
## Occasionally the halfspace creates points very close together. We
## can impose a tolerance to merge them
if (tol != 0) {
ps <- round(ps, ceiling(-log10(abs(tol/2))))
ps <- ps[!duplicated(ps),]
}
ch <- convhulln(ps, "n FA")
## Check for gross volume errors
if ((ch$vol > ch1$vol * (1 + 1E-4))) {
warning("Volume of final intersection hull is bigger than first of the original hulls\n",
"ch1 vol = ", ch1$vol, "\n",
"ch vol = ", ch$vol, "\n",
"Returning ch1")
ch <- ch1
}
if ((ch$vol > ch2$vol * (1 + 1E-4))) {
warning("Volume of final intersection hull is bigger than first of the original hulls\n",
"ch2 vol = ", ch2$vol, "\n",
"ch vol = ", ch$vol, "\n",
"Returning ch2")
ch <- ch2
}
if (return.chs) {
out <- list(ch1=ch1, ch2=ch2, ps=ps, ch=ch)
class(out) <- "intersectn"
return(out)
}
return(list(ch=ch))
}
##' Find point in intersection of convex hulls
##'
##' Find point that lies somewhere in interesction of two convex
##' hulls. If such a point does not exist, return \code{NA}. The
##' feasible point is found using a linear program similar to the one
##' suggested at \url{../doc/qhull/html/qhalf.html#notes}
##'
##' @param ch1 First convex hull with normals
##' @param ch2 Second convex hull with normals
##' @param tol The point must be at least this far within the facets
##' of both convex hulls
##' @export
feasible.point <- function(ch1, ch2, tol=0) {
N <- ncol(ch1$p) # Number of dimensions
M <- nrow(ch1$normals) + nrow(ch2$normals) # Total number of normals
## Find the point that bounds all points from below. Becuase
## lpSolve::lp() implicitly gives solutions in the positive
## quadrant, we need to subtract p0 from the search point, and then
## add it to the optimised solution. This will ensure that solutions
## not in the positive quadrant are found.
p0 <- apply(rbind(ch1$p, ch2$p), 2, min)
objective.in <- c(rep(0, N), 1)
const.mat <- rbind(cbind(ch1$normals[,-(N + 1)], 1),
cbind(ch2$normals[,-(N + 1)], 1),
c(rep(0, N), -1))
## p0 is incorporated into the matrix here
const.rhs <- -c(const.mat[1:M, 1:N] %*% cbind(p0) +
c(ch1$normals[,N + 1], ch2$normals[,N + 1]),
tol)
const.dir <- c(rep("<", length(const.rhs)))
## Scaling: The scale option of lpSolve::lp() determines options
## used for scaling, and is crucial to avoid errors in some edge
## cases. For list of options, see:
## http://lpsolve.sourceforge.net/5.1/set_scaling.htm
## http://lpsolve.sourceforge.net/5.1/scaling.htm
## See also https://github.com/davidcsterratt/geometry/issues/35
##
## After testing on 10,000+ examples, it appears that to get
## maxiumum coverage, in some cases multiple combinations of options
## need to be tried. This code cycles through options, starting with
## the combinations most likely to work.
## DYNUPDATE == 0 may also work, but DYNUPDATE == 1 may work better
## for some 4D examples
DYNUPDATE <- 1
## Both options may help
for (POWER2 in 0:1) {
## Both options may help
for (QUADRATIC in 0:1) {
## 1 (SCALE_EXTREME) and 3 (SCALE_EXTREME) didn't work well in
## tests
##
## 4 (SCALE_GEOMETRIC) on one example (included in tests) caused
## some sort of infinite loop or race condition leading to the
## process up 100%
##
## 2 (SCALE_RANGE) and 7 (SCALE_CURTISREID) seem to work OK for
## most cases. SCALE_CURTISREID (with the 5.6.13 version of
## lpSolve, at least) has caused some sort of infinite loop or
## race condition leading to the process up 100% on 2 out of
## millions of intersections computed on some processors, hence
## it is put as the second option.
for (MAIN in c(2, 7)) {
## Both options may help
for (LOGARITHMIC in 0:1) {
## Equilibriate seemed to help for some cases, but caused a
## crash in the example of inst/extdata
EQUILIBRIATE <- 0
scale <-
MAIN +
QUADRATIC * 8 +
LOGARITHMIC * 16 +
POWER2 * 32 +
EQUILIBRIATE * 64 +
DYNUPDATE * 256
opt <- lpSolve::lp(direction = "max",
objective.in,
const.mat,
const.dir,
const.rhs,
scale=scale)
## See http://lpsolve.sourceforge.net/5.5/solve.htm for status codes
## Infeasible solution
if (opt$status == 2) return(NA)
## Optimal
if (opt$status == 0) return(opt$solution[1:N] + p0)
}
}
}
}
## Debugging output
if (!is.null(getOption("geometry.debug"))) {
opt <- linprog::writeMps("feasible-point.mps",
cvec=objective.in,
bvec=const.rhs,
Amat=const.mat, "Feasible point")
writeLines(gsub("_ ", "_", readLines("feasible-point-tmp.mps")), "feasible-point.mps")
message("Debugging output saved to feasible-point.mps\n",
"Test on command line by running\n",
" lp_solve -max -fmps feasible-point.mps")
}
stop("lpSolve::lp() returned error code ", opt$status, "\n",
"See http://lpsolve.sourceforge.net/5.5/solve.htm for explanation of errors.\n",
"Rescaling your problem may help")
}
##' @method plot intersectn
##' @export
plot.intersectn <- function(x, y, ...) {
args <- list(...)
add <- FALSE
if ("add" %in% names(args)) {
add <- args$add
args$add <- NULL
}
xlim <- ylim <- NULL
if ("xlim" %in% names(args)) {
xlim <- args$xlim
args$xlim <- NULL
}
if ("ylim" %in% names(args)) {
ylim <- args$ylim
args$xlim <- NULL
}
if (ncol(x$p) == 2) {
if (!add) {
p <- rbind(x$ch1$p, x$ch2$p)
if (is.null(xlim)) xlim <- range(p[,1])
if (is.null(ylim)) ylim <- range(p[,2])
plot.new()
do.call(plot.window, c(list(xlim=xlim, ylim=ylim), args))
}
plot(x$ch1, add=TRUE, lty=2)
plot(x$ch2, add=TRUE, lty=2)
plot(x$ch, add=TRUE, lwd=2)
}
}
geometry/R/Unique.R 0000644 0001762 0000144 00000002347 13432317337 013713 0 ustar ligges users ##' Extract Unique Rows
##'
##' \sQuote{Unique} returns a vector, data frame or array like 'x' but with
##' duplicate elements removed.
##'
##'
##' @param X Numerical matrix.
##' @param rows.are.sets If \sQuote{\code{TRUE}}, rows are treated as sets -
##' i.e., to define uniqueness, the order of the rows does not matter.
##' @return Matrix of the same number of columns as \code{x}, with the unique
##' rows in \code{x} sorted according to the columns of \code{x}. If
##' \code{rows.are.sets = TRUE} the rows are also sorted.
##' @note \sQuote{\code{Unique}} is (under circumstances) much quicker than the
##' more generic base function \sQuote{\code{unique}}.
##' @author Raoul Grasman
##' @keywords arith math array
##' @examples
##'
##' # `Unique' is faster than `unique'
##' x = matrix(sample(1:(4*8),4*8),ncol=4)
##' y = x[sample(1:nrow(x),3000,TRUE), ]
##' gc(); system.time(unique(y))
##' gc(); system.time(Unique(y))
##'
##' #
##' z = Unique(y)
##' x[matorder(x),]
##' z[matorder(z),]
##'
##' @export
"Unique" <-
function (X, rows.are.sets = FALSE)
{
if (rows.are.sets)
X = matsort(X)
X = X[matorder(X), ]
dX = apply(X, 2, diff)
uniq = c(TRUE, ((dX^2) %*% rep(1, ncol(dX))) > 0)
X = X[uniq, ]
return(X)
}
geometry/R/polyarea.R 0000644 0001762 0000144 00000003754 13511174150 014254 0 ustar ligges users ## Copyright (C) 1999, 2006, 2007, 2009 David M. Doolin
## bugs and limitations:
## Probably ought to be an optional check to make sure that
## traversing the vertices doesn't make any sides cross
## (Is simple closed curve the technical definition of this?).
##' Determines area of a polygon by triangle method. The variables
##' \code{x} and \code{y} define the vertex pairs, and must therefore
##' have the same shape. They can be either vectors or arrays. If
##' they are arrays then the columns of \code{x} and \code{y} are
##' treated separately and an area returned for each.
##'
##' If the optional \code{dim} argument is given, then \code{polyarea}
##' works along this dimension of the arrays \code{x} and \code{y}.
##'
##' @title Determines area of a polygon by triangle method.
##' @param x X coordinates of vertices.
##' @param y Y coordinates of vertices.
##' @param d Dimension of array to work along.
##' @return Area(s) of polygon(s).
##' @author David Sterratt based on the octave sources by David M. Doolin
##' @export
##' @importFrom magic shift ashift
##' @examples
##' x <- c(1, 1, 3, 3, 1)
##' y <- c(1, 3, 3, 1, 1)
##' polyarea(x, y)
##' polyarea(cbind(x, x), cbind(y, y)) ## c(4, 4)
##' polyarea(cbind(x, x), cbind(y, y), 1) ## c(4, 4)
##' polyarea(rbind(x, x), rbind(y, y), 2) ## c(4, 4)
polyarea <- function(x, y, d=1) {
if (is.vector(x) & is.vector(y)) {
if (length(x) == length(y)) {
a <- abs(sum(x*(shift(y, -1) - shift(y, 1))))/2
} else {
stop("x and y must have the same shape")
}
} else {
if (is.array(x) & is.array(y)) {
if (length(dim(x)) != 2) {
stop("Arrays must have two dimensions.")
}
if (all(dim(x) == dim(y))) {
v <- c(0, 0)
v[d] <- 1
a <- abs(apply(x*(ashift(y, -v) - ashift(y, v)), 3 - d, sum))/2
} else {
stop("x and y must have the same shape")
}
} else {
stop("x and y must be of same type")
}
}
names(a) <- NULL
return(a)
}
geometry/R/matmax.R 0000644 0001762 0000144 00000002463 13432317337 013733 0 ustar ligges users ##' Row-wise matrix functions
##'
##' Compute maximum or minimum of each row, or sort each row of a matrix, or a
##' set of (equal length) vectors.
##'
##'
##' @aliases matmax matmin matsort matorder
##' @param \dots A numeric matrix or a set of numeric vectors (that are
##' column-wise bind together into a matrix with \code{cbind}).
##' @return \code{matmin} and \code{matmax} return a vector of length
##' \code{nrow(cbind(...))}. \code{matsort} returns a matrix of dimension
##' \code{dim(cbind(...))} with in each row of \code{cbind(...)} sorted.
##' \code{matsort(x)} is a lot faster than, e.g., \code{t(apply(x,1,sort))},
##' if \code{x} is tall (i.e., \code{nrow(x)}>>\code{ncol(x)} and
##' \code{ncol(x)}<30. If \code{ncol(x)}>30 then \code{matsort} simply calls
##' `\code{t(apply(x,1,sort))}'. \code{matorder} returns a permutation which
##' rearranges its first argument into ascending order, breaking ties by
##' further arguments.
##' @author Raoul Grasman
##' @keywords array arith
##' @examples
##'
##' example(Unique)
##'
##' @export matmax matmin matsort matorder
"matmax" <-
function (...)
{
x = cbind(...)
if(!is.numeric(x))
stop("Input should by numeric.")
if (!is.matrix(drop(x)))
x = t(x)
x[1:nrow(x) + nrow(x) * (max.col(x) - 1)]
}
geometry/R/mesh.dsphere.R 0000644 0001762 0000144 00000002024 13432317337 015022 0 ustar ligges users ##' Signed distance from points \code{p} to boundary of sphere to
##' allow easy definition of regions in \code{\link{distmeshnd}}.
##'
##' @title Sphere distance function
##' @param p A matrix with 2 columns (3 in \code{mesh.dsphere}), each row
##' representing a point in the plane.
##' @param radius radius of sphere
##' @param ... additional arguments (not used)
##' @return A vector of length \code{nrow(p)} containing the signed
##' distances to the sphere
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @seealso \code{\link{distmeshnd}}
##' @references \url{http://persson.berkeley.edu/distmesh/}
##'
##' \cite{P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB. SIAM
##' Review, Volume 46 (2), pp. 329-345, June 2004}
##' @keywords arith math
##' @examples
##'
##' example(distmeshnd)
##' @export
"mesh.dsphere" <-
function (p, radius = 1, ...)
{
if (!is.matrix(p))
p = t(as.matrix(p))
sqrt((p^2) %*% rep(1, ncol(p))) - radius
}
geometry/R/surf.tri.R 0000644 0001762 0000144 00000011472 14662314120 014211 0 ustar ligges users ##' Find surface triangles from tetrahedral mesh
##'
##' Find surface triangles from tetrahedral mesh typically obtained
##' with \code{\link{delaunayn}}.
##'
##' \code{surf.tri} and \code{\link{convhulln}} serve a similar purpose in 3D,
##' but \code{surf.tri} also works for non-convex meshes obtained e.g. with
##' \code{\link{distmeshnd}}. It also does not produce currently unavoidable
##' diagnostic output on the console as \code{convhulln} does at the Rterm
##' console--i.e., \code{surf.tri} is silent.
##'
##' @param p An \code{n}-by-\code{3} matrix. The rows of \code{p} represent
##' \code{n} points in \code{dim}-dimensional space.
##' @param t Matrix with 4 columns, interpreted as output of
##' \code{\link{delaunayn}}.
##' @return An \code{m}-by-\code{3} index matrix of which each row defines a
##' triangle. The indices refer to the rows in \code{p}.
##' @note \code{surf.tri} was based on Matlab code for mesh of Per-Olof Persson
##' (\url{http://persson.berkeley.edu/distmesh/}).
##' @author Raoul Grasman
##' @seealso \code{\link[interp]{tri.mesh}}, \code{\link{convhulln}},
##' \code{\link{surf.tri}}, \code{\link{distmesh2d}}
##' @keywords math optimize dplot
##' @examples
##'
##' \dontrun{
##' # more extensive example of surf.tri
##'
##' # url's of publically available data:
##' data1.url = "http://neuroimage.usc.edu/USCPhantom/mesh_data.bin"
##' data2.url = "http://neuroimage.usc.edu/USCPhantom/CT_PCS_trans.bin"
##'
##' meshdata = R.matlab::readMat(url(data1.url))
##' elec = R.matlab::readMat(url(data2.url))$eeg.ct2pcs/1000
##' brain = meshdata$mesh.brain[,c(1,3,2)]
##' scalp = meshdata$mesh.scalp[,c(1,3,2)]
##' skull = meshdata$mesh.skull[,c(1,3,2)]
##' tbr = t(surf.tri(brain, delaunayn(brain)))
##' tsk = t(surf.tri(skull, delaunayn(skull)))
##' tsc = t(surf.tri(scalp, delaunayn(scalp)))
##' rgl::triangles3d(brain[tbr,1], brain[tbr,2], brain[tbr,3],col="gray")
##' rgl::triangles3d(skull[tsk,1], skull[tsk,2], skull[tsk,3],col="white", alpha=0.3)
##' rgl::triangles3d(scalp[tsc,1], scalp[tsc,2], scalp[tsc,3],col="#a53900", alpha=0.6)
##' rgl::view3d(-40,30,.4,zoom=.03)
##' lx = c(-.025,.025); ly = -c(.02,.02);
##' rgl::spheres3d(elec[,1],elec[,3],elec[,2],radius=.0025,col='gray')
##' rgl::spheres3d( lx, ly,.11,radius=.015,col="white")
##' rgl::spheres3d( lx, ly,.116,radius=.015*.7,col="brown")
##' rgl::spheres3d( lx, ly,.124,radius=.015*.25,col="black")
##' }
##'
##' @export
"surf.tri" <-
function(p,t){
# original by Per-Olof Persson (c) 2005 for MATLAB
# ported to R and modified for efficiency by Raoul Grasman (c) 2005
# construct all faces
faces = rbind(t[,-4], t[,-3], t[,-2], t[,-1]);
node4 = rbind(t[, 4], t[, 3], t[, 2], t[, 1]);
# #original translated from MATLAB:
# # select the faces that occur only once --> these are the surface boundary faces
# faces = t(apply(faces,1,sort)); # sort each row
# foo = apply(faces,1,function(x) do.call("paste",as.list(x,sep=" "))); # makes a string from each row
# vec = table(foo); # tabulates the number of occurences of each string
# ix = sapply(names(vec[vec==1]),function(b) which(b==foo)) # obtain indices of faces with single occurence
# tri = faces[ix,];
# node4 = node4[ix];
# we wish to achieve
# > faces = t(apply(faces,1,sort));
# but this is much too slow, we therefore use max.col and the fact
# that there are only 3 columns in faces
i.max = 3*(1:nrow(faces)-1) + max.col(faces)
i.min = 3*(1:nrow(faces)-1) + max.col(-faces)
faces = t(faces)
faces = cbind(faces[i.min], faces[-c(i.max,i.min)], faces[i.max])
ix = order(faces[,1], faces[,2], faces[,3])
# Next, we wish to detect duplicated rows in faces, that is,
# > qx = duplicated(faces[ix,],MARGIN=1) # logical indicating duplicates
# but this is also much to slow, we therefore use the fact that
# faces[ix,] has the duplicate rows ordered beneath each other
# and the fact that each row occurs exactly once or twice
fo = apply(faces[ix,],2,diff)
dup = (abs(fo) %*% rep(1,3)) == 0 # a row of only zeros indicates duplicate
dup = c(FALSE,dup) # first is never a duplicate
qx = diff(dup)==0 # only zero if two consecutive elems are not duplicates
qx = c(qx, !dup[length(dup)]) # last row is either non-duplicate or should not be selected
tri = faces[ix[qx],] # ix[qx] are indices of singly occuring faces
node4 = node4[ix[qx]]
# compute face orientations
v1 = p[tri[,2],] - p[tri[,1],]; # edge vectors
v2 = p[tri[,3],] - p[tri[,1],];
v3 = p[node4,] - p[tri[,1],];
ix = which( apply(extprod3d(v1,v2) * v3, 1, sum) > 0 )
tri[ix,c(2,3)] = tri[ix,c(3,2)]
rownames(tri) = NULL
tri
}
geometry/R/mesh.drectangle.R 0000644 0001762 0000144 00000003270 13432317337 015504 0 ustar ligges users ##' Signed distance from points \code{p} to boundary of rectangle to
##' allow easy definition of regions in \code{\link{distmesh2d}}.
##'
##' @title Rectangle distance function
##' @param p A matrix with 2 columns, each row representing a point in
##' the plane.
##' @param x1 lower left corner of rectangle
##' @param y1 lower left corner of rectangle
##' @param x2 upper right corner of rectangle
##' @param y2 upper right corner of rectangle
##' @param \dots additional arguments (not used)
##' @return a vector of length \code{nrow(p)} containing the signed distances
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @seealso \code{\link{distmesh2d}}, \code{\link{mesh.drectangle}},
##' \code{\link{mesh.diff}}, \code{\link{mesh.intersect}},
##' \code{\link{mesh.union}}
##' @references \url{http://persson.berkeley.edu/distmesh/}
##'
##' \cite{P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB. SIAM
##' Review, Volume 46 (2), pp. 329-345, June 2004}
##' @keywords arith math
##' @examples
##' example(distmesh2d)
##' @export
mesh.drectangle <- function (p, x1 = -1/2, y1 = -1/2, x2 = 1/2, y2 = 1/2, ...) {
if (!is.matrix(p))
p = t(as.matrix(p))
d1 = y1 - p[, 2]
d2 = -y2 + p[, 2]
d3 = x1 - p[, 1]
d4 = -x2 + p[, 1]
d5 = sqrt(d1^2 + d3^2)
d6 = sqrt(d1^2 + d4^2)
d7 = sqrt(d2^2 + d3^2)
d8 = sqrt(d2^2 + d4^2)
matmin = function(...) apply(cbind(...), 1, min)
d = -matmin(matmin(matmin(-d1, -d2), -d3), -d4)
ix = d1 > 0 & d3 > 0
d[ix] = d5[ix]
ix = d1 > 0 & d4 > 0
d[ix] = d6[ix]
ix = d2 > 0 & d3 > 0
d[ix] = d7[ix]
ix = d2 > 0 & d4 > 0
d[ix] = d8[ix]
return(d)
}
geometry/R/convhulln.R 0000644 0001762 0000144 00000021474 14664576025 014470 0 ustar ligges users ##' Compute smallest convex hull that encloses a set of points
##'
##' Returns information about the smallest convex complex of a set of
##' input points in \eqn{N}-dimensional space (the convex hull of the
##' points). By default, indices to points forming the facets of the
##' hull are returned; optionally normals to the facets and the
##' generalised surface area and volume can be returned. This function
##' interfaces the \href{http://www.qhull.org}{Qhull} library.
##'
##' @param p An \eqn{M}-by-\eqn{N} matrix. The rows of \code{p}
##' represent \eqn{M} points in \eqn{N}-dimensional space.
##'
##' @param options String containing extra options for the underlying
##' Qhull command; see details below and Qhull documentation at
##' \url{../doc/qhull/html/qconvex.html#synopsis}.
##'
##' @param output.options String containing Qhull options to generate
##' extra output. Currently \code{n} (normals) and \code{FA}
##' (generalised areas and volumes) are supported; see
##' \sQuote{Value} for details. If \code{output.options} is
##' \code{TRUE}, select all supported options.
##'
##' @param return.non.triangulated.facets logical defining whether the
##' output facets should be triangulated; \code{FALSE} by default.
##'
##' @return By default (\code{return.non.triangulated.facets} is
##' \code{FALSE}), return an \eqn{M}-by-\eqn{N} matrix in which each
##' row contains the indices of the points in \code{p} forming an
##' \eqn{N-1}-dimensional facet. e.g In 3 dimensions, there are 3
##' indices in each row describing the vertices of 2-dimensional
##' triangles.
##'
##' If \code{return.non.triangulated.facets} is \code{TRUE} then the
##' number of columns equals the maximum number of vertices in a
##' facet, and each row defines a polygon corresponding to a facet
##' of the convex hull with its vertices followed by \code{NA}s
##' until the end of the row.
##'
##' If the \code{output.options} or \code{options} argument contains
##' \code{FA} or \code{n}, return a list with class \code{convhulln}
##' comprising the named elements:
##' \describe{
##' \item{\code{p}}{The points passed to \code{convnhulln}}
##' \item{\code{hull}}{The convex hull, represented as a matrix indexing \code{p}, as
##' described above}
##' \item{\code{area}}{If \code{FA} is specified, the generalised area of
##' the hull. This is the surface area of a 3D hull or the length of
##' the perimeter of a 2D hull.
##' See \url{../doc/qhull/html/qh-optf.html#FA}.}
##' \item{\code{vol}}{If \code{FA} is specified, the generalised volume of
##' the hull. This is volume of a 3D hull or the area of a 2D hull.
##' See \url{../doc/qhull/html/qh-optf.html#FA}. }
##' \item{\code{normals}}{If \code{n} is specified, this is a matrix
##' hyperplane normals with offsets. See \url{../doc/qhull/html/qh-opto.html#n}.}
##' }
##'
##' @note This function was originally a port of the
##' \href{https://octave.org/}{Octave} convhulln function written
##' by Kai Habel.
##'
##' See further notes in \code{\link{delaunayn}}.
##'
##' @author Raoul Grasman, Robert B. Gramacy, Pavlo Mozharovskyi and
##' David Sterratt \email{david.c.sterratt@@ed.ac.uk}
##' @seealso \code{\link{intersectn}}, \code{\link{delaunayn}},
##' \code{\link{surf.tri}}, \code{\link[interp]{convex.hull}}
##' @references \cite{Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T.,
##' \dQuote{The Quickhull algorithm for convex hulls,} \emph{ACM
##' Trans. on Mathematical Software,} Dec 1996.}
##'
##' \url{http://www.qhull.org}
##' @keywords math dplot graphs
##' @examples
##' ## Points in a sphere
##' ps <- matrix(rnorm(3000), ncol=3)
##' ps <- sqrt(3)*ps/drop(sqrt((ps^2) %*% rep(1, 3)))
##' ts.surf <- t(convhulln(ps)) # see the qhull documentations for the options
##' \dontrun{
##' rgl::triangles3d(ps[ts.surf,1],ps[ts.surf,2],ps[ts.surf,3],col="blue",alpha=.2)
##' for(i in 1:(8*360)) rgl::view3d(i/8)
##' }
##'
##' ## Square
##' pq <- rbox(0, C=0.5, D=2)
##' # Return indices only
##' convhulln(pq)
##' # Return convhulln object with normals, generalised area and volume
##' ch <- convhulln(pq, output.options=TRUE)
##' plot(ch)
##'
##' ## Cube
##' pc <- rbox(0, C=0.5, D=3)
##' # Return indices of triangles on surface
##' convhulln(pc)
##' # Return indices of squares on surface
##' convhulln(pc, return.non.triangulated.facets=TRUE)
##' @export
##' @useDynLib geometry
convhulln <- function (p, options = "Tv", output.options=NULL, return.non.triangulated.facets = FALSE) {
tmp_stdout <- tempfile("Rf")
tmp_stderr <- tempfile("Rf")
on.exit(unlink(c(tmp_stdout, tmp_stderr)))
## Combine and check options
options <- tryCatch(qhull.options(options, output.options, supported_output.options <- c("n", "FA")), error=function(e) {stop(e)})
## Coerce the input to be matrix
if (is.data.frame(p)) {
p <- as.matrix(p)
}
## Make sure we have real-valued input
storage.mode(p) <- "double"
## We need to check for NAs in the input, as these will crash the C
## code.
if (any(is.na(p))) {
stop("The first argument should not contain any NAs")
}
if (!return.non.triangulated.facets){
## It is essential that delaunayn is called with either the QJ or Qt
## option. Otherwise it may return a non-triangulated structure, i.e
## one with more than dim+1 points per structure, where dim is the
## dimension in which the points p reside.
if (!grepl("Qt", options) & !grepl("QJ", options)) {
options <- paste(options, "Qt")
}
}
out <- tryCatch(
.Call("C_convhulln", p, as.character(options), as.integer(return.non.triangulated.facets), tmp_stdout, tmp_stderr, PACKAGE="geometry"),
error=function(e) {
message = e$message
if (grepl("QH6271", e$message)) {
message("You may be able to avoid the following error by adding \"Qbb\" to the \"options\" argument of convhulln()
For example: options=\"", options, " Qbb\"
If this does not work, please add to the issue at
https://github.com/davidcsterratt/geometry/issues/58
")
}
stop(e)
})
# Remove NULL elements
out[which(sapply(out, is.null))] <- NULL
if (is.null(out$area) & is.null(out$vol) & is.null(out$normals)) {
attr(out$hull, "convhulln") <- attr(out, "convhulln")
return(out$hull)
}
class(out) <- "convhulln"
out$p <- p
return(out)
}
##' @importFrom graphics plot
##' @method plot convhulln
##' @export
plot.convhulln <- function(x, y, ...) {
if (ncol(x$p) < 2 || ncol(x$p) > 3)
stop("Only 2D and 3D convhullns can be plotted")
args <- list(...)
add <- FALSE
if ("add" %in% names(args)) {
add <- args$add
args$add <- NULL
}
if (ncol(x$p) == 2) {
if (!add) {
plot(x$p[,1], x$p[,2], ...)
}
m <- x$hull
p <- x$p
do.call(segments, c(list(p[m[,1],1],p[m[,1],2],p[m[,2],1],p[m[,2],2]),
args))
}
if (ncol(x$p) == 3) {
if(requireNamespace("rgl") == FALSE)
stop("The rgl package is required for tetramesh")
if (!add) rgl::clear3d()
if (ncol(x$hull) == 3) {
do.call(rgl::triangles3d,
c(list(x$p[t(x$hull),1], x$p[t(x$hull),2], x$p[t(x$hull),3]),
args))
} else {
stop("At present only convhullns with triangulated facets can be plotted")
}
}
}
##' Convert convhulln object to RGL mesh
##'
##' @param x \code{\link{convhulln}} object
##' @param ... Arguments to \code{\link[rgl]{qmesh3d}} or
##' \code{\link[rgl]{tmesh3d}}
##' @return \code{\link[rgl]{mesh3d}} object, which can be displayed
##' in RGL with \code{\link[rgl]{dot3d}}, \code{\link[rgl]{wire3d}}
##' or \code{\link[rgl]{shade3d}}
##'
##' @seealso \code{\link[rgl]{as.mesh3d}}
##' @export
to.mesh3d <- function(x, ...) UseMethod("to.mesh3d")
##' @importFrom graphics plot
##' @method to.mesh3d convhulln
##' @export
to.mesh3d.convhulln <- function(x, ...) {
if(requireNamespace("rgl") == FALSE)
stop("The rgl package is required for as.mesh.convhulln")
if (ncol(x$p) != 3) {
stop("Only convex hulls of points in 3D can be turned into meshes")
}
if (ncol(x$hull) == 4) {
stop("At present only convhulls with triangulated facets can be converted to mesh3d")
## return(rgl::qmesh3d(t(x$p), t(x$hull), homogeneous=FALSE, ...))
}
if (ncol(x$hull) == 3) {
return(rgl::tmesh3d(t(x$p), t(x$hull), homogeneous=FALSE, ...))
}
stop("Facets of hull must be triangles or quadrilaterals")
}
## LocalWords: dQuote Qhull param itemize Kai Habel delaunayn Pavlo
## LocalWords: Grasman Gramacy Mozharovskyi Sterratt seealso tri ps
## LocalWords: interp distmesh intersectn Dobkin Huhdanpaa emph Tv
## LocalWords: Quickhull ACM dplot convhulln qhull rnorm ncol sqrt
## LocalWords: dontrun useDynLib tmp_stdout tmp_stderr tempdir sanitisation NAs na
## LocalWords: QJ grepl importFrom convhulls args requireNamespace
## LocalWords: rgl tetramesh eqn href sQuote hyperplane rbox
## LocalWords: convulln convhullns
geometry/R/distmeshnd.R 0000644 0001762 0000144 00000017063 14662314120 014601 0 ustar ligges users ##' A simple mesh generator for non-convex regions in n-D space
##'
##' An unstructured simplex requires a choice of mesh points (vertex nodes) and
##' a triangulation. This is a simple and short algorithm that improves the
##' quality of a mesh by relocating the mesh points according to a relaxation
##' scheme of forces in a truss structure. The topology of the truss is reset
##' using Delaunay triangulation. A (sufficiently smooth) user supplied signed
##' distance function (\code{fd}) indicates if a given node is inside or
##' outside the region. Points outside the region are projected back to the
##' boundary.
##'
##' This is an implementation of original Matlab software of Per-Olof Persson.
##'
##' Excerpt (modified) from the reference below:
##'
##' \sQuote{The algorithm is based on a mechanical analogy between a triangular
##' mesh and a n-D truss structure. In the physical model, the edges of the
##' Delaunay triangles of a set of points correspond to bars of a truss. Each
##' bar has a force-displacement relationship \eqn{f(\ell, \ell_{0})}{F(L,L0)}
##' depending on its current length \eqn{\ell}{L} and its unextended length
##' \eqn{\ell_{0}}{L0}.}
##'
##' \sQuote{External forces on the structure come at the boundaries, on which
##' external forces have normal orientations. These external forces are just
##' large enough to prevent nodes from moving outside the boundary. The
##' position of the nodes are the unknowns, and are found by solving for a
##' static force equilibrium. The hope is that (when \code{fh = function(p)
##' return(rep(1,nrow(p)))}), the lengths of all the bars at equilibrium will
##' be nearly equal, giving a well-shaped triangular mesh.}
##'
##' See the references below for all details. Also, see the comments in the
##' source file of \code{distmesh2d}.
##'
##' @param fdist Vectorized signed distance function, for example
##' \code{\link{mesh.dsphere}}, accepting an \code{m}-by-\code{n}
##' matrix, where \code{m} is arbitrary, as the first argument.
##' @param fh Vectorized function, for example \code{\link{mesh.hunif}},
##' that returns desired edge length as a function of position.
##' Accepts an \code{m}-by-\code{n} matrix, where \code{n} is
##' arbitrary, as its first argument.
##' @param h Initial distance between mesh nodes.
##' @param box \code{2}-by-\code{n} matrix that specifies the bounding box.
##' (See \link{distmesh2d} for an example.)
##' @param pfix \code{nfix}-by-2 matrix with fixed node positions.
##' @param \dots parameters that are passed to \code{fdist} and \code{fh}
##' @param ptol Algorithm stops when all node movements are smaller than
##' \code{dptol}
##' @param ttol Controls how far the points can move (relatively) before a
##' retriangulation with \code{\link{delaunayn}}.
##' @param deltat Size of the time step in Euler's method.
##' @param geps Tolerance in the geometry evaluations.
##' @param deps Stepsize \eqn{\Delta x} in numerical derivative computation for
##' distance function.
##' @return \code{m}-by-\code{n} matrix with node positions.
##' @section Wishlist : \itemize{ \item Implement in C/Fortran \item Translate
##' other functions of the Matlab package }
##' @author Raoul Grasman; translated from original Matlab sources of Per-Olof
##' Persson.
##' @seealso \code{\link{distmesh2d}}, \code{\link[interp]{tri.mesh}},
##' \code{\link{delaunayn}}, \code{\link{mesh.dsphere}},
##' \code{\link{mesh.hunif}},\cr \code{\link{mesh.diff}},
##' \code{\link{mesh.union}}, \code{\link{mesh.intersect}}
##' @references \url{http://persson.berkeley.edu/distmesh/}
##'
##' \cite{P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB. SIAM
##' Review, Volume 46 (2), pp. 329-345, June 2004}
##' @keywords math optimize dplot graphs
##' @examples
##'
##' \dontrun{
##' # examples distmeshnd
##' require(rgl)
##'
##' fd = function(p, ...) sqrt((p^2)%*%c(1,1,1)) - 1
##' # also predefined as `mesh.dsphere'
##' fh = function(p,...) rep(1,nrow(p))
##' # also predefined as `mesh.hunif'
##' bbox = matrix(c(-1,1),2,3)
##' p = distmeshnd(fd,fh,0.2,bbox, maxiter=100)
##' # this may take a while:
##' # press Esc to get result of current iteration
##' }
##'
##' @export
"distmeshnd" <-
function (fdist, fh, h, box, pfix = array(dim = c(0, ncol(box))),
..., ptol = 0.001, ttol = 0.1, deltat = 0.1, geps = 0.1 *
h, deps = sqrt(.Machine$double.eps) * h)
{
# %DISTMESHND N-D Mesh Generator using Distance Functions.
dim = ncol(as.matrix(box))
L0mult = 1 + 0.4/2^(dim - 1)
rownorm2 = function(x) drop(sqrt((x^2) %*% rep(1, ncol(x))))
# %1. Create initial distribution in bounding box
if (dim == 1) {
p = seq(box[1], box[2], by = h)
}
else {
cbox = lapply(1:dim, function(ii) seq(box[1, ii], box[2,
ii], by = h))
p = do.call("expand.grid", cbox)
p = as.matrix(p)
}
# %2. Remove points outside the region, apply the rejection method
p = p[fdist(p, ...) < geps, ]
r0 = fh(p, ...)
p = rbind(pfix, p[stats::runif(nrow(p)) < min(r0)^dim/r0^dim, ])
N = nrow(p)
if (N <= dim + 1)
stop("Not enough starting points inside boundary (is h0 too large?).")
on.exit(return(invisible(p)))
message("Press esc if the mesh seems fine but the algorithm hasn't converged.")
utils::flush.console()
count = 0
p0 = 1/.Machine$double.eps
# mimick Matlab call ``localpairs=nchoosek(1:dim+1,2)'':
localpairs = as.matrix(expand.grid(1:(dim + 1), 1:(dim + 1)))
localpairs = localpairs[lower.tri(matrix(TRUE, dim + 1, dim + 1)), 2:1]
while (TRUE) {
if (max(rownorm2(p - p0)) > ttol * h) {
# %3. Retriangulation by Delaunay:
p0 = p
t = delaunayn(p)
pmid = matrix(0, nrow(t), dim)
for (ii in 1:(dim + 1)) pmid = pmid + p[t[, ii],
]/(dim + 1)
t = t[fdist(pmid, ...) < (-geps), ]
pair = array(dim = c(0, 2))
for (ii in 1:nrow(localpairs)) {
pair = rbind(pair, t[, localpairs[ii, ]])
}
# %4. Describe each edge by a unique pair of nodes
pair = Unique(pair, TRUE); # base-function `unique' is way too slow
if (dim == 2) {
trimesh(t, p[, 1:2])
}
else if (dim == 3) {
if (count%%5 == 0) {
tetramesh(t, p)
}
}
else {
message("Retriangulation #", 15)
utils::flush.console()
}
count = count + 1
}
bars = p[pair[, 1], ] - p[pair[, 2], ]
L = rownorm2(bars)
L0 = fh((p[pair[, 1], ] + p[pair[, 2], ])/2, ...)
L0 = L0 * L0mult * (sum(L^dim)/sum(L0^dim))^(1/dim)
F = L0 - L
F[F < 0] = 0
Fbar = cbind(bars, -bars) * matrix(F/L, nrow = nrow(bars),
ncol = 2 * dim)
ii = pair[, t(matrix(1:2, 2, dim))]
jj = rep(1, nrow(pair)) %o% c(1:dim, 1:dim)
s = c(Fbar)
ns = length(s)
dp = matrix(0, N, dim)
dp[1:(dim * N)] = rowsum(s, ii[1:ns] + ns * (jj[1:ns] -
1))
if (nrow(pfix) > 0)
dp[1:nrow(pfix), ] = 0
p = p + deltat * dp
d = fdist(p, ...)
ix = d > 0
gradd = matrix(0, sum(ix), dim)
for (ii in 1:dim) {
a = rep(0, dim)
a[ii] = deps
d1x = fdist(p[ix, ] + rep(1, sum(ix)) %o% a, ...)
gradd[, ii] = (d1x - d[ix])/deps
}
p[ix, ] = p[ix, ] - (d[ix] %o% rep(1, dim)) * gradd
maxdp = max(deltat * rownorm2(dp[d < (-geps), ]))
if (maxdp < ptol * h)
break
}
}
geometry/R/qhull-options.R 0000644 0001762 0000144 00000001755 14662314120 015256 0 ustar ligges users qhull.options <- function(options, output.options, supported_output.options, full=FALSE) {
if (full) {
if (!is.null(output.options)) {
stop("full and output.options should not be specified together")
}
output.options = TRUE
## Enable message in 0.4.1
## Turn to warning in 0.4.7
message("delaunayn: \"full\" option is deprecated; adding \"Fa\" and \"Fn\" to options.
Please update your code to use \"output.options=TRUE\" or set \"output.options\" to a
string containing desired QHull options.")
}
if (is.null(output.options)) {
output.options <- ""
}
if (is.logical(output.options)) {
if (output.options) {
output.options <- paste(supported_output.options, collapse=" ")
} else {
output.options <- ""
}
}
if (!is.character(output.options)) {
stop("output.options must be a string, logical or NULL")
}
## Input sanitisation
options <- paste(options, output.options, collapse=" ")
return(options)
}
geometry/R/cart2sph.R 0000644 0001762 0000144 00000005117 14662314120 014162 0 ustar ligges users ## Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2009, 2017 Kai Habel
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or (at
## your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING. If not, see
## .
## This file has been adapted for R by David C Sterratt
##' Transform Cartesian to spherical coordinates
##'
##' If called with a single matrix argument then each row of \code{c}
##' represents the Cartesian coordinate (\code{x}, \code{y}, \code{z}).
##'
##' @param x x-coordinates or matrix with three columns
##' @param y y-coordinates (optional, if \code{x}) is a matrix
##' @param z z-coordinates (optional, if \code{x}) is a matrix
##' @return Matrix with columns:
##' \item{\code{theta}}{the angle relative to the positive x-axis}
##' \item{\code{phi}}{the angle relative to the xy-plane}
##' \item{\code{r}}{the distance to the origin \code{(0, 0, 0)}}
##' @seealso \code{\link{sph2cart}}, \code{\link{cart2pol}},
##' \code{\link{pol2cart}}
##' @author Kai Habel
##' @author David Sterratt
##' @export
cart2sph <- function(x, y=NULL, z=NULL) {
if ((is.null(y) & !is.null(z)) |
(is.null(z) & !is.null(y))) {
stop("There should be 3 arguments (x, y, z) or one argument (x)")
}
if (is.null(y) & is.null(z)) {
if (!(is.numeric(x))) {
stop("input must be matrix with 3 columns [x, y, z]")
}
if (!(is.matrix(x) & ncol(x) == 3)) {
stop("matrix input must have 3 columns [x, y, z]")
}
z <- x[,3]
y <- x[,2]
x <- x[,1]
} else {
if (!is.numeric(x) | !is.numeric(y) | !is.numeric (z))
stop("x, y, z must be numeric arrays of the same size, or scalar")
if ( !(((length(x) == length(y)) | (length(x) == 1) | (length(y) == 1)) &
((length(x) == length(z)) | (length(x) == 1) | (length(z) == 1)) &
((length(y) == length(z)) | (length(y) == 1) | (length(z) == 1)))) {
stop("x, y, z must be matrices of the same size, or scalar")
}
}
theta <- atan2(y, x)
phi <- atan2(z, sqrt(x^2 + y^2))
r <- sqrt(x^2 + y^2 + z^2)
return(cbind(theta, phi, r))
}
geometry/R/mesh.union.R 0000644 0001762 0000144 00000000141 13432317337 014516 0 ustar ligges users "mesh.union" <-
function (p, regionA, regionB, ...)
matmin(regionA(p, ...), regionB(p, ...))
geometry/R/trimesh.R 0000644 0001762 0000144 00000003267 13432317337 014122 0 ustar ligges users ##' \code{trimesh(T, p)} displays the triangles defined in the m-by-3
##' matrix \code{T} and points \code{p} as a mesh. Each row of
##' \code{T} specifies a triangle by giving the 3 indices of its
##' points in \code{X}.
##'
##' @title Display triangles mesh (2D)
##' @param T T is a \code{m}-by-3 matrix. A row of \code{T} contains
##' indices into \code{X} of the vertices of a triangle. \code{T} is
##' usually the output of \code{\link{delaunayn}}.
##' @param p A vector or a matrix.
##' @param p2 if \code{p} is not a matrix \code{p} and \code{p2} are bind to a
##' matrix with \code{cbind}.
##' @param add Add to existing plot in current active device?
##' @param axis Draw axes?
##' @param boxed Plot box?
##' @param \dots Parameters to the rendering device. See the \link[rgl]{rgl}
##' package.
##' @author Raoul Grasman
##' @seealso \code{\link{tetramesh}}, \code{\link[rgl]{rgl}},
##' \code{\link{delaunayn}}, \code{\link{convhulln}},
##' \code{\link{surf.tri}}
##' @keywords hplot
##' @examples
##' #example trimesh
##' p = cbind(x=rnorm(30), y=rnorm(30))
##' tt = delaunayn(p)
##' trimesh(tt,p)
##' @export
##' @importFrom graphics box plot.new plot.window segments
trimesh <- function(T, p, p2, add=FALSE, axis=FALSE, boxed=FALSE, ...){
if(!is.matrix(p)){
p = cbind(p,p2) # automatically generates error if p2 not present
}
xlim = range(p[,1])
ylim = range(p[,2])
if(!add){
plot.new()
plot.window(xlim, ylim, ...)
}
if(boxed){
box()
}
if(axis) {
axis(1)
axis(2)
}
m = rbind(T[,-1], T[, -2], T[, -3])
segments(p[m[,1],1],p[m[,1],2],p[m[,2],1],p[m[,2],2], ...)
return(invisible(list(T = T, p = p)))
}
geometry/R/cart2pol.R 0000644 0001762 0000144 00000005571 13433536400 014170 0 ustar ligges users ## Copyright (C) 2000-2017 Kai Habel
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING. If not, see
## .
## This file has been adapted for R by David C Sterratt
##' Transform Cartesian coordinates to polar or cylindrical coordinates.
##'
##' The inputs \code{x}, \code{y} (, and \code{z}) must be the same shape, or
##' scalar. If called with a single matrix argument then each row of \code{C}
##' represents the Cartesian coordinate (\code{x}, \code{y} (, \code{z})).
##'
##' @param x x-coordinates or matrix with three columns
##' @param y y-coordinates (optional, if \code{x}) is a matrix
##' @param z z-coordinates (optional, if \code{x}) is a matrix
##' @return A matrix \code{P} where each row represents one
##' polar/(cylindrical) coordinate (\code{theta}, \code{r}, (,
##' \code{z})).
##' @seealso \code{\link{pol2cart}}, \code{\link{cart2sph}},
##' \code{\link{sph2cart}}
##' @author Kai Habel
##' @author David Sterratt
##' @export
cart2pol <- function(x, y=NULL, z=NULL) {
if (is.null(y) & is.null(z)) {
if (!(is.numeric(x))) {
stop("input must be matrix with 2 or 3 columns")
}
if (!(is.numeric (x) & is.matrix (x)
& (ncol(x) == 2 | ncol(x) == 3))) {
stop("matrix input must have 2 or 3 columns [X, Y (, Z)]");
}
if (ncol(x) == 3) {
z <- x[,3]
}
y <- x[,2]
x <- x[,1]
} else {
if (is.null(z)) {
if (!is.numeric (x) | !is.numeric (y)) {
stop("X, Y must be numeric arrays of the same size, or scalar")
}
if ( !((length(x) == length(y)) | (length(x) == 1) | (length(y) == 1))) {
stop("X, Y must be numeric arrays of the same size, or scalar")
}
} else {
if (! is.numeric (x) | ! is.numeric (y) | ! is.numeric (z)) {
stop("X, Y, Z must be numeric arrays of the same size, or scalar")
}
if ( !(((length(x) == length(y)) | (length(x) == 1) | (length(y) == 1)) &
((length(x) == length(z)) | (length(x) == 1) | (length(z) == 1)) &
((length(y) == length(z)) | (length(y) == 1) | (length(z) == 1)))) {
stop("x, y, z must be matrices of the same size, or scalar")
}
}
}
theta <- atan2 (y, x)
r <- sqrt(x^2 + y^2)
if (is.null(z)) {
return(cbind(theta=theta, r=r))
}
return(cbind(theta=theta, r=r, z=z))
}
geometry/R/rbox.R 0000644 0001762 0000144 00000001342 13432317337 013411 0 ustar ligges users ##' Default is corners of a hypercube.
##' @title Generate various point distributions
##' @param n number of random points in hypercube
##' @param D number of dimensions of hypercube
##' @param B bounding box coordinate - faces will be \code{-B} and \code{B} from origin
##' @param C add a unit hypercube to the output - faces will be \code{-C} and \code{C} from origin
##' @return Matrix of points
##' @author David Sterratt
##' @export
rbox <- function(n=3000, D=3, B=0.5, C=NA) {
P <- matrix(0, 0, D)
if (!is.na(C)) {
P <- rbind(P,
as.matrix(do.call(expand.grid, rep(list(c(-C, C)), D))))
}
if (n > 0) {
P <- rbind(P,
matrix(stats::runif(n=n*D, min=-B, max=B), n, D))
}
return(P)
}
geometry/R/pol2cart.R 0000644 0001762 0000144 00000005675 13433536400 014175 0 ustar ligges users ## Copyright (C) 2000-2017 Kai Habel
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING. If not, see
## .
## This file has been adapted for R by David C Sterratt
##' Transform polar or cylindrical coordinates to Cartesian coordinates.
##'
##' The inputs \code{theta}, \code{r}, (and \code{z}) must be the same shape, or
##' scalar. If called with a single matrix argument then each row of \code{P}
##' represents the polar/(cylindrical) coordinate (\code{theta}, \code{r}
##' (, \code{z})).
##'
##' @param theta describes the angle relative to the positive x-axis.
##' @param r is the distance to the z-axis (0, 0, z).
##' @param z (optional) is the z-coordinate
##' @return a matrix \code{C} where each row represents one Cartesian
##' coordinate (\code{x}, \code{y} (, \code{z})).
##' @seealso \code{\link{cart2pol}}, \code{\link{sph2cart}},
##' \code{\link{cart2sph}}
##' @author Kai Habel
##' @author David Sterratt
##' @export
pol2cart <- function(theta, r=NULL, z=NULL) {
if (is.null(r) & is.null(z)) {
if (!(is.numeric(theta))) {
stop("input must be matrix with 2 or 3 columns")
}
if (!(is.numeric (theta) & is.matrix (theta)
& (ncol(theta) == 2 | ncol(theta) == 3))) {
stop("matrix input must have 2 or 3 columns [THETA, R (, Z)]");
}
if (ncol(theta) == 3) {
z <- theta[,3]
}
r <- theta[,2]
theta <- theta[,1]
} else {
if (is.null(z)) {
if (!is.numeric (theta) | !is.numeric (r)) {
stop("THETA, R must be numeric arrays of the same size, or scalar")
}
if ( !((length(theta) == length(r)) | (length(theta) == 1) | (length(r) == 1))) {
stop("THETA, Y must be numeric arrays of the same size, or scalar")
}
} else {
if (! is.numeric (theta) | ! is.numeric (r) | ! is.numeric (z)) {
stop("THETA, R, Z must be numeric arrays of the same size, or scalar")
}
if ( !(((length(theta) == length(r)) | (length(theta) == 1) | (length(r) == 1)) &
((length(theta) == length(z)) | (length(theta) == 1) | (length(z) == 1)) &
((length(r) == length(z)) | (length(r) == 1) | (length(z) == 1)))) {
stop("theta, r, z must be matrices of the same size, or scalar")
}
}
}
x <- r*cos(theta)
y <- r*sin(theta)
if (is.null(z)) {
return(cbind(x=x, y=y))
}
return(cbind(x=x, y=y, z=z))
}
geometry/R/entry.value.R 0000644 0001762 0000144 00000004031 13433536400 014704 0 ustar ligges users ##' Retrieve or set a list of array element values
##'
##' \code{entry.value} retrieves or sets the values in an array \code{a} at the
##' positions indicated by the rows of a matrix \code{idx}.
##'
##'
##' @aliases entry.value entry.value<-
##' @param a An array.
##' @param idx Numerical matrix with the same number of columns as the number
##' of dimensions of \code{a}. Each row indices a cell in \code{a} of which
##' the value is to be retrieved or set.
##' @param value An array of length \code{nrow(idx)}.
##' @return \code{entry.value(a,idx)} returns a vector of values at the
##' indicated cells. \code{entry.value(a,idx) <- val} changes the indicated
##' cells of \code{a} to \code{val}.
##' @author Raoul Grasman
##' @keywords arith math array
##' @examples
##'
##' a = array(1:(4^4),c(4,4,4,4))
##' entry.value(a,cbind(1:4,1:4,1:4,1:4))
##' entry.value(a,cbind(1:4,1:4,1:4,1:4)) <- 0
##'
##' entry.value(a, as.matrix(expand.grid(1:4,1:4,1:4,1:4)))
##' # same as `c(a[1:4,1:4,1:4,1:4])' which is same as `c(a)'
##'
##' @export entry.value entry.value<-
"entry.value" <-
function (a, idx)
{
if (!is.array(a))
stop("First argument `", deparse(substitute(a)), "' should be an array.")
if (!is.matrix(idx))
stop("Second argument `", substitute(idx), "' should be a matrix.")
n <- length(dim(a))
if (n != ncol(idx))
stop("Number of columns in", deparse(substitute(idx)),
"is incompatible is dimension of", deparse(substitute(a)))
a[(idx - 1) %*% c(1, cumprod(dim(a))[-n]) + 1]
}
"entry.value<-" <-
function (a, idx, value)
{
if (!is.array(a))
stop("First argument `", deparse(substitute(a)), "' should be an array.")
if (!is.matrix(idx))
stop("Second argument `", substitute(idx), "' should be a matrix.")
n <- length(dim(a))
if (n != ncol(idx))
stop("Number of columns in", deparse(substitute(idx)),
"is incompatible is dimension of", deparse(substitute(a)))
a[(idx - 1) %*% c(1, cumprod(dim(a))[-n]) + 1] <- value
return(a)
}
geometry/R/tetramesh.R 0000644 0001762 0000144 00000003564 14662314120 014434 0 ustar ligges users ##' \code{tetramesh(T, X, col)} uses the \link[rgl]{rgl} package to
##' display the tetrahedrons defined in the m-by-4 matrix T as mesh.
##' Each row of \code{T} specifies a tetrahedron by giving the 4
##' indices of its points in \code{X}.
##'
##' @title Render tetrahedron mesh (3D)
##' @param T T is a \code{m}-by-3 matrix in trimesh and \code{m}-by-4 in
##' tetramesh. A row of \code{T} contains indices into \code{X} of the vertices
##' of a triangle/tetrahedron. \code{T} is usually the output of delaunayn.
##' @param X X is an n-by-2/n-by-3 matrix. The rows of X represent \code{n}
##' points in 2D/3D space.
##' @param col The tetrahedron colour. See rgl documentation for details.
##' @param clear Should the current rendering device be cleared?
##' @param \dots Parameters to the rendering device. See the \link[rgl]{rgl}
##' package.
##' @author Raoul Grasman
##' @seealso \code{\link{trimesh}}, \code{\link[rgl]{rgl}}, \code{\link{delaunayn}},
##' \code{\link{convhulln}}, \code{\link{surf.tri}}
##' @keywords hplot
##' @examples
##' \dontrun{
##' # example delaunayn
##' d = c(-1,1)
##' pc = as.matrix(rbind(expand.grid(d,d,d),0))
##' tc = delaunayn(pc)
##'
##' # example tetramesh
##' clr = rep(1,3) %o% (1:nrow(tc)+1)
##' rgl::view3d(60,fov=20)
##' rgl::light3d(270,60)
##' tetramesh(tc,pc,alpha=0.7,col=clr)
##' }
##' @export
tetramesh <- function (T, X, col = grDevices::heat.colors(nrow(T)), clear = TRUE, ...) {
if(requireNamespace("rgl") == FALSE)
stop("the rgl package is required for tetramesh")
if (!is.numeric(T) | !is.numeric(T))
stop("`T' and `X' should both be numeric.")
if (ncol(T) != 4)
stop("Expect first arg `T' to have 4 columns.")
if (ncol(X) != 3)
stop("Expect second arg `X' to have 3 columns.")
t = t(rbind(T[, -1], T[, -2], T[, -3], T[, -4]))
if (clear)
rgl::clear3d()
rgl::triangles3d(X[t, 1], X[t, 2], X[t, 3], col = col, ...)
}
geometry/R/matmin.R 0000644 0001762 0000144 00000000331 13432317337 013721 0 ustar ligges users "matmin" <-
function (...)
{
x = cbind(...)
if(!is.numeric(x))
stop("Input should by numeric.")
if (!is.matrix(drop(x)))
x = t(x)
x[1:nrow(x) + nrow(x) * (max.col(-x) - 1)]
}
geometry/R/inhulln.R 0000644 0001762 0000144 00000002615 14227215261 014110 0 ustar ligges users ##' Test if points lie in convex hull
##'
##' Tests if a set of points lies within a convex hull, returning a
##' boolean vector in which each element is \code{TRUE} if the
##' corresponding point lies within the hull and \code{FALSE} if it
##' lies outwith the hull or on one of its facets.
##'
##' @param ch Convex hull produced using \code{\link{convhulln}}
##' @param p An \eqn{M}-by-\eqn{N} matrix of points to test. The rows
##' of \code{p} represent \eqn{M} points in \eqn{N}-dimensional
##' space.
##' @return A boolean vector with \eqn{M} elements
##' @author David Sterratt
##' @note \code{inhulln} was introduced in geometry 0.4.0, and is
##' still under development. It is worth checking results for
##' unexpected behaviour.
##' @seealso \code{\link{convhulln}}, \code{point.in.polygon} in \pkg{sp}
##' @export
##' @examples
##' p <- cbind(c(-1, -1, 1), c(-1, 1, -1))
##' ch <- convhulln(p)
##' ## First point should be in the hull; last two outside
##' inhulln(ch, rbind(c(-0.5, -0.5),
##' c( 1 , 1),
##' c(10 , 0)))
##'
##' ## Test hypercube
##' p <- rbox(D=4, B=1)
##' ch <- convhulln(p)
##' tp <- cbind(seq(-1.9, 1.9, by=0.2), 0, 0, 0)
##' pin <- inhulln(ch, tp)
##' ## Points on x-axis should be in box only betw,een -1 and 1
##' pin == (tp[,1] < 1 & tp[,1] > -1)
inhulln <- function(ch, p) {
return(.Call("C_inhulln", ch, p, PACKAGE="geometry"))
}
geometry/R/delaunayn.R 0000644 0001762 0000144 00000020526 14664554667 014445 0 ustar ligges users ##' Delaunay triangulation in N dimensions
##'
##' The Delaunay triangulation is a tessellation of the convex hull of
##' the points such that no \eqn{N}-sphere defined by the \eqn{N}-
##' triangles contains any other points from the set.
##'
##' @param p An \eqn{M}-by-\eqn{N} matrix whose rows represent \eqn{M}
##' points in \eqn{N}-dimensional space.
##'
##' @param options String containing extra control options for the
##' underlying Qhull command; see the Qhull documentation
##' (\url{../doc/qhull/html/qdelaun.html}) for the available
##' options.
##'
##' The \code{Qbb} option is always passed to Qhull. The remaining
##' default options are \code{Qcc Qc Qt Qz} for \eqn{N<4} and
##' \code{Qcc Qc Qt Qx} for \eqn{N>=4}. If neither of the \code{QJ}
##' or \code{Qt} options are supplied, the \code{Qt} option is
##' passed to Qhull. The \code{Qt} option ensures all Delaunay
##' regions are simplical (e.g., triangles in 2D). See
##' \url{../doc/qhull/html/qdelaun.html} for more details. Contrary
##' to the Qhull documentation, no degenerate (zero area) regions
##' are returned with the \code{Qt} option since the R function
##' removes them from the triangulation.
##'
##' \emph{If \code{options} is specified, the default options are
##' overridden.} It is recommended to use \code{output.options} for
##' options controlling the outputs.
##'
##' @param output.options String containing Qhull options to control
##' output. Currently \code{Fn} (neighbours) and \code{Fa} (areas)
##' are supported. Causes an object of return value for details. If
##' \code{output.options} is \code{TRUE}, select all supported
##' options.
##'
##' @param full Deprecated and will be removed in a future release.
##' Adds options \code{Fa} and \code{Fn}.
##'
##' @return If \code{output.options} is \code{NULL} (the default),
##' return the Delaunay triangulation as a matrix with \eqn{M} rows
##' and \eqn{N+1} columns in which each row contains a set of
##' indices to the input points \code{p}. Thus each row describes a
##' simplex of dimension \eqn{N}, e.g. a triangle in 2D or a
##' tetrahedron in 3D.
##'
##' If the \code{output.options} argument is \code{TRUE} or is a
##' string containing \code{Fn} or \code{Fa}, return a list with
##' class \code{delaunayn} comprising the named elements:
##' \describe{
##' \item{\code{tri}}{The Delaunay triangulation described above}
##' \item{\code{areas}}{If \code{TRUE} or if \code{Fa} is specified, an
##' \eqn{M}-dimensional vector containing the generalised area of
##' each simplex (e.g. in 2D the areas of triangles; in 3D the volumes
##' of tetrahedra). See \url{../doc/qhull/html/qh-optf.html#Fa}.}
##' \item{\code{neighbours}}{If \code{TRUE} or if \code{Fn} is specified,
##' a list of neighbours of each simplex. Note that a negative number
##' corresponds to "facet" (="edge" in 2D or "face" in 3D) that has no
##' neighbour, as will be the case for some simplices on the boundary
##' of the triangulation.
##' See \url{../doc/qhull/html/qh-optf.html#Fn}}
##' }
##'
##' @note This function interfaces the Qhull library and is a port
##' from Octave (\url{https://octave.org/}) to R. Qhull computes
##' convex hulls, Delaunay triangulations, halfspace intersections
##' about a point, Voronoi diagrams, furthest-site Delaunay
##' triangulations, and furthest-site Voronoi diagrams. It runs in
##' 2D, 3D, 4D, and higher dimensions. It implements the
##' Quickhull algorithm for computing the convex hull. Qhull handles
##' round-off errors from floating point arithmetic. It computes
##' volumes, surface areas, and approximations to the convex
##' hull. See the Qhull documentation included in this distribution
##' (the doc directory \url{../doc/qhull/index.html}).
##'
##' Qhull does not support constrained Delaunay triangulations, triangulation
##' of non-convex surfaces, mesh generation of non-convex objects, or
##' medium-sized inputs in 9D and higher. A rudimentary algorithm for mesh
##' generation in non-convex regions using Delaunay triangulation is
##' implemented in \link{distmesh2d} (currently only 2D).
##' @author Raoul Grasman and Robert B. Gramacy; based on the
##' corresponding Octave sources of Kai Habel.
##' @seealso \code{\link[interp]{tri.mesh}}, \code{\link{convhulln}},
##' \code{\link{surf.tri}}, \code{\link{distmesh2d}}
##' @references \cite{Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T.,
##' \dQuote{The Quickhull algorithm for convex hulls,} \emph{ACM Trans. on
##' Mathematical Software,} Dec 1996.}
##'
##' \url{http://www.qhull.org}
##' @keywords math dplot graphs
##' @examples
##'
##' # example delaunayn
##' d <- c(-1,1)
##' pc <- as.matrix(rbind(expand.grid(d,d,d),0))
##' tc <- delaunayn(pc)
##'
##' # example tetramesh
##' \dontrun{
##' rgl::view3d(60)
##' rgl::light3d(120,60)
##' tetramesh(tc,pc, alpha=0.9)
##' }
##'
##' tc1 <- delaunayn(pc, output.options="Fa")
##' ## sum of generalised areas is total volume of cube
##' sum(tc1$areas)
##'
##' @export
##' @useDynLib geometry
delaunayn <-
function(p, options=NULL, output.options=NULL, full=FALSE) {
tmp_stdout <- tempfile("Rf")
tmp_stderr <- tempfile("Rf")
on.exit(unlink(c(tmp_stdout, tmp_stderr)))
## Coerce the input to be matrix
if (is.data.frame(p)) {
p <- as.matrix(p)
}
## Make sure we have real-valued input
storage.mode(p) <- "double"
## We need to check for NAs in the input, as these will crash the C
## code.
if (any(is.na(p))) {
stop("The first argument should not contain any NAs")
}
## Default options
defult.options <- "Qt Qc Qx"
if (ncol(p) < 4) {
default.options <- "Qt Qc Qz"
}
if (is.null(options)) {
options <- default.options
}
## Combine and check options
options <- tryCatch(qhull.options(options, output.options, supported_output.options <- c("Fa", "Fn"), full=full), error=function(e) {stop(e)})
## It is essential that delaunayn is called with either the QJ or Qt
## option. Otherwise it may return a non-triangulated structure, i.e
## one with more than dim+1 points per structure, where dim is the
## dimension in which the points p reside.
if (!grepl("Qt", options) & !grepl("QJ", options)) {
options <- paste(options, "Qt")
}
out <- .Call("C_delaunayn", p, as.character(options), tmp_stdout, tmp_stderr, PACKAGE="geometry")
## Check for points missing from triangulation, but not in the case
## of a degenerate trianguation (zero rows in output)
if (nrow(out$tri) > 0) {
missing.points <- length(setdiff(seq(1,nrow(p)), unique(as.vector(out$tri))))
if (missing.points > 0) {
warning(paste0(missing.points, " points missing from triangulation.
It is possible that setting the 'options' argument of delaunayn may help.
For example:
options = \"", default.options, " Qbb\"
options = \"", default.options, " QbB\"
If these options do not work, try shifting the centre of the points
to the origin by subtracting the mean coordinates from every point."))
}
}
# Remove NULL elements
out[which(sapply(out, is.null))] <- NULL
if (is.null(out$areas) & is.null(out$neighbours)) {
attr(out$tri, "delaunayn") <- attr(out$tri, "delaunayn")
return(out$tri)
}
class(out) <- "delaunayn"
out$p <- p
return(out)
}
##' @importFrom graphics plot
##' @method plot delaunayn
##' @export
plot.delaunayn <- function(x, y, ...) {
if (ncol(x$p) < 2 || ncol(x$p) > 3)
stop("Only 2D and 3D convhullns can be plotted")
args <- list(...)
add <- FALSE
if ("add" %in% names(args)) {
add <- args$add
args$add <- NULL
}
if (ncol(x$p) == 2) {
if (!add) {
plot(x$p[,1], x$p[,2], ...)
}
m <- Unique(rbind(x$tri[,1:2],
x$tri[,2:3],
x$tri[,c(1,3)]))
p <- x$p
do.call(segments, c(list(p[m[,1],1],p[m[,1],2],p[m[,2],1],p[m[,2],2]),
args))
}
if (ncol(x$p) == 3) {
do.call(tetramesh, c(list(x$tri, x$p),
args))
}
}
## LocalWords: param Qhull Fn delaunayn Qbb Qcc Qc Qz Qx QJ itemize
## LocalWords: tri Voronoi Quickhull distmesh Grasman Gramacy Kai
## LocalWords: Habel seealso interp convhulln Dobkin Huhdanpaa ACM
## LocalWords: dQuote emph dplot pc tc tetramesh dontrun useDynLib
# LocalWords: eqn url math tmp stdout tempfile stderr unlink NAs na
# LocalWords: tryCatch qhull grepl sapply attr importFrom convhullns
# LocalWords: args rbind
geometry/demo/ 0000755 0001762 0000144 00000000000 13430240556 013033 5 ustar ligges users geometry/demo/00Index 0000644 0001762 0000144 00000000077 13300625475 014174 0 ustar ligges users intersectn Demonstration of intersection of 2D convex hulls
geometry/demo/intersectn.R 0000644 0001762 0000144 00000001353 13430240556 015336 0 ustar ligges users library(geometry)
## 2D example
ps1 <- rbind(c(0, sqrt(3)),
c(3/2, -sqrt(3)/2),
c(-3/2, -sqrt(3)/2))
ps2 <- ps1
ps2[,2] <- -ps2[,2]
is <- intersectn(ps1, ps2)
plot(is, asp=1)
## 3D example
ps1a <- rbox(2, C=0.5)
dt1a <- delaunayn(ps1a)
ps1b <- rbox(2, C=0.5) + 2
dt1b <- delaunayn(ps1b)
ps1 <- rbind(ps1a, ps1b)
dt1 <- rbind(dt1a, dt1b + nrow(ps1a))
tetramesh(dt1, ps1, alpha=0.5, col="yellow")
ps2 <- rbox(2, C=0.5) + 0.5
dt2 <- delaunayn(ps2)
tetramesh(dt2, ps2, alpha=0.5, col="red", clear=FALSE)
vol <- 0
for (i in 1:nrow(dt1)) {
for (j in 1:nrow(dt2)) {
is <- intersectn(ps1[dt1[i,],], ps2[dt2[j,],])
vol <- vol + is$ch$vol
}
}
message(paste("Volume of overlap should be 0.125. It is:", vol))
geometry/NEWS 0000644 0001762 0000144 00000050540 14751717775 012635 0 ustar ligges users CHANGES IN VERSION 0.5.2 - Released 2025/02/08
BUG FIX
* Issue #75: More sanitiser issues
https://github.com/davidcsterratt/geometry/issues/76
This update resolves another issue with memory sanitisation observed
when compiling in an UBSAN environment. Thanks to Brian Ripley for
running the tests and reporting the error, and Tomas Kalibera for
suggesting and testing the fix.
CHANGES IN VERSION 0.5.1 - Released 2025/01/09
BUG FIX
* Issue #75: Sanitiser issues
https://github.com/davidcsterratt/geometry/issues/75
This update resolves issues with memory sanitisation observed when
compiling in an UBSAN environment. Thanks to Brian Ripley for
running the tests and reporting the error, and Tomas Kalibera for
providing the fix.
CHANGES IN VERSION 0.5.0 - Released 2024/08/31
CODE IMPROVEMENTS
* Issue #37: Incorporate Qhull 8.0.2
https://github.com/davidcsterratt/geometry/issues/37
This update of Qhull resolves or addresses a number of issues (#11,
#12) relating to points spanning a small distance compared to their
mean distance to the origin
MINOR API CHANGE
* Issue #12: QH6227 impossible to triangulate a dataset far from the origin
https://github.com/davidcsterratt/geometry/issues/12
This particular error was fixed by the fix for #37, but some points
were still missing from the triangulation, when the points are far
from the origin. Delaunayn now throws a warning about points missing
from the triangulation, and suggests passing options to deluanayn
that may help, or centering the input data before passing it to
delaunayn. Thanks to Jean-Romain the orignal report, and C. B.
Barber for extensive advice on Qhull.
BUG FIXES
* Fix for Issue #71: noRemap CRAN chack
https://github.com/davidcsterratt/geometry/issues/71
Thanks to the CRAN maintainers for reporting this and Jean-Romain
Roussel for providing the fix.
* Fix for Issue #11: Wrong triangulation for a specific dataset
https://github.com/davidcsterratt/geometry/issues/11
Thanks to Jean-Romain the report and C. B. Barber for help debugging
* Fix for Issues #57 and #46: tsearch fails on points far from the origin
https://github.com/davidcsterratt/geometry/issues/57
https://github.com/davidcsterratt/geometry/issues/46
Thanks to Wayne Jones for the report and Jean-Romain for the fix
* Issue #58: convhulln() receives QH6271 qhull precision error
https://github.com/davidcsterratt/geometry/issues/58
convhulln() now issues advice about options to avoid this error.
Thanks to GitHub user Huangmp1996 for the report
CHANGES IN VERSION 0.4.7 - Released 2023/02/03
BUG FIXES
* Fix for Issue #67: Compiled code should not call sprintf()
https://github.com/davidcsterratt/geometry/issues/67
Thanks to the CRAN maintainers for reporting this. Update uses
snprintf() function.
* PR #64: Replace rgl.* with *3d
https://github.com/davidcsterratt/geometry/pull/64
Thanks to Duncan Murdoch for replacing rgl.* functions with *3d functions
* Issue #60: Negative neighbour IDs reported by delaunayn
https://github.com/davidcsterratt/geometry/issues/60
Provide documentation to explain that the Qhull "Fn" option returns
negative IDs.
API CHANGE
* Issue #29: Make behaviour of convhulln() and delaunayn() more consistent
https://github.com/davidcsterratt/geometry/issues/29
Issue message to indicate full option to delaunayn is dprecated
NEW FEATURE
* Issue #29: Make behaviour of convhulln() and delaunayn() more consistent
https://github.com/davidcsterratt/geometry/issues/29
plot.delaunayn() to plot triangulations
CHANGES IN VERSION 0.4.6.1 - Released 2022/07/04
BUG FIXES
* Fix for Issue #66: Replace the tripack package with the interp
package
https://github.com/davidcsterratt/geometry/issues/66 The
Thanks to the CRAN maintainers for replacing references to the
suggested tripack package with interp
CHANGES IN VERSION 0.4.6 - Released 2022/04/18
BUG FIXES
* PR #49: Update tests for testthat v3 compatibility
https://github.com/davidcsterratt/geometry/pull/49
Thanks to Hugo Gruson for providing the pull request
* PR #50: Reorder documentation lines
https://github.com/davidcsterratt/geometry/pull/50
Thanks to Hugo Gruson for providing the pull request
* PR #54: Fix typo
https://github.com/davidcsterratt/geometry/pull/54
Thanks to Hugh Gruson for providing the pull request
OTHER CHANGES
* Fix for Issue #61: Legacy macros need replaced
https://github.com/davidcsterratt/geometry/issues/61
Thanks to the Brian Ripley and the CRAN team for the alert
CHANGES IN VERSION 0.4.5 - Released 2019/12/02
BUG FIX
* Fix for Issue #47: Install failure with gcc 10
https://github.com/davidcsterratt/geometry/issues/47
Thanks to Brian Ripley for pointing this out
CHANGES IN VERSION 0.4.4 - Released 2019/08/27
BUG FIX
* Fix for Issue #45: LTO error
https://github.com/davidcsterratt/retistruct/issues/45
Thanks to Brian Ripley for pointing this out and providing the fix
CHANGES IN VERSION 0.4.3 - Released 2019/08/21
BUG FIXES
* Fix for Issue #39: tsearchn() returns NA for some points within
triangle
https://github.com/davidcsterratt/geometry/issues/39
tsearchn() failed (=return NA) for some points that lie within the
triangulation. Thanks to Jan Lause (https://github.com/jlause) for
reporting the bug and Jean-Romain Roussel for providing the fix.
* Fix for Issue #40: memory misuse in src/Rtsearchn.c
https://github.com/davidcsterratt/geometry/issues/40
In src/Rtsearchn.c 'idmap' was allocated with max_facet_id elements
but then a value to idmap[max_facet_id] was assigned, which was one
element beyond the end of that allocation, potentially clobbering
the memory allocation system.
Thanks to Bill Dunlap (https://github.com/BillDunlap) for reporting
this, and the suggested fix.
* Fix for Issue #44: R_tmpnam()/free() causes crash in TERR
https://github.com/davidcsterratt/geometry/issues/44
Because TERR
(https://docs.tibco.com/products/tibco-enterprise-runtime-for-r) is
not compiled with gcc (it uses either the Intel or Microsoft C++
compiler) on Windows, calling free() in a package's DLL for memory
allocated with malloc() in TERR's own DLL causes a crash. The R API
function R_tmpnam() causes this problem in the geometry package.
Thanks to Bill Dunlap (https://github.com/BillDunlap) for reporting
this, and the suggested fix.
ENHANCEMENT
* Fix for Issue #42: Improve error reporting from Qhull
https://github.com/davidcsterratt/geometry/issues/42
Full error from Qhull is now returned, rather than just the first
two lines.
CHANGES IN VERSION 0.4.2 - Released 2019/07/05
BUG FIX
* Fix for Issue #35: intersectn() reports zero volume for some
overlapping 4D hulls
https://github.com/davidcsterratt/geometry/issues/35
intersectn() failed on a particular example. Modifying the scale
option given to lpSolve::lp in feasible.point() has fixed this
problem. feasible.point() also now returns the lpSolve::lp() error
message when it fails, rather than failing silently as before.
Thanks to Maxime Logez for reporting the bug and Sam Buttrey,
lpSolve maintainer, for insights into lpSolve.
CHANGES IN VERSION 0.4.1 - Released 2019/03/27
BUG FIXES
* Fix for Issue #34: intersectn() fails when overlapping region is not
in positive quadrant
https://github.com/davidcsterratt/geometry/issues/34
intersectn() would return no intersecting hull for input hulls
whose overlapping region did not overlap with the postive quadrant
(i.e. the region where all coordinates are non-negative). Thanks to
Maxime Logez for reporting the bug.
* Fix for Issue #33: nonsensical results from intersectn() in 4D
https://github.com/davidcsterratt/geometry/issues/33
intersectn() gave demonstrably wrong results in some cases. This was
Because of some heuristic (non-Qhull) code in halfspacen which was
designed to get round cases in which Qhull fails with options "Tv"
because the hull is very narrow. The solution is to remove the
heuristic method, and also to fix Issue #34 (above). Before Issue
#34 was fixed, it was found that adding the "QJ" option could also
help, and this is now suggested in the error message about narrow
hulls. Thanks to Maxime Logez for reporting the bug and supplying a
reproducible example, now included in tests.
CHANGES IN VERSION 0.4.0 - Released 2019/02/18
LICENSE CHANGES
* Following requests by the CRAN maintainers and disucssion on the
r-package-devel email list, the entire package is now released under
GPL (>= 3).
https://github.com/davidcsterratt/geometry/issues/27
API CHANGES
* Default options to delaunayn have been changed
https://github.com/davidcsterratt/geometry/issues/4
The Qc and Qz or Qx options have been added as defaults, making the
default options "Qbb Qc Qt Qz" for 3 dimensions or less and "Qbb Qc
Qt Qx" for 4 or more dimensions. This brings the R implementation
into line with Octave, and very similar to matlab and
scipy.spatial.Delaunayn .
* New argument "output.options" for convhulln() and delaunayn().
https://github.com/davidcsterratt/geometry/issues/29
Qhull options which affect output should be put in this string,
e.g. delaunayn(ps, output.options="Fn Fa")
* The "full" option to delaunayn() is deprecated
https://github.com/davidcsterratt/geometry/issues/29
Use output.options=TRUE instead. In geometry 0.4.0 using "full" does
not give a message or warning; this will happen in future versions
* distmesh2d() has a plot option
https://github.com/davidcsterratt/geometry/issues/15
The new plot option (TRUE by default) allows plotting to during mesh
generation to be suspended, which is useful for running tests. The
use of cat() has been replaced by message(), meaning messages can be
supressed, for example during tests.
* extprod3d() has a "drop" option
https://github.com/davidcsterratt/geometry/issues/16
Setting drop=FALSE guarantees that the output of extprod3d() is an
array rather than a vector, even when presented with two vectors.
NEW FUNCTIONS
* New function inhulln() to test if points are in a hull
https://github.com/davidcsterratt/geometry/issues/1
* New function halfspacen() to compute intersection points of
halfspaces about an interior point
https://github.com/davidcsterratt/geometry/issues/25
* New function intersectn() to compute intersection of convex hulls of
two sets of points
https://github.com/davidcsterratt/geometry/issues/26
* Functions cart2sph, sph2cart, cart2pol, pol2cart ported from Octave
https://github.com/davidcsterratt/geometry/issues/14
NEW FEATURES
* convhulln() can produce non-triangulated output
https://github.com/davidcsterratt/geometry/issues/22
Thanks to Pavlo Mozharovskyi for pushing code to achive this
* delaunayn() and convhulln() throw Qhull error messages when Qhull fails
https://github.com/davidcsterratt/geometry/issues/28
BUG FIXES
* Fix for Issue #6072: distmesh2d - convergence problem
(https://r-forge.r-project.org/tracker/?func=detail&atid=4552&aid=6072&group_id=1149)
Some parts of the original Matlab implementation of distmesh2d were
omitted during the translation to R. The effect is not obvious on
some problems, except for long convergence times due to excessive
iterations - some do not converge at all. Graham Griffiths made
changes to the code which appears to have fixed the problem as
example problems now appear to run significantly faster - even
faster than those I have run using Matlab. Graham's example code is now included in a test.
Thanks to Graham Griffiths for reporting this problem and supplying the fix.
* Fix for Issue #30: Move qhull docs to vignettes
https://github.com/davidcsterratt/geometry/issues/30
This is a change in response to the way R deals with inst/doc, which
broke the included Qhull docs.
CODE IMPROVEMENTS
* The 2D tsearch C code has been replaced by a much more efficient
QuadTree algorithm written in C++ by Jean-Romain Roussel. The
speedup with uniformly distribued mesh points and search points is
of the order of 40x. Many thanks to Jean-Romain for the
contribution.
https://github.com/davidcsterratt/geometry/issues/9
https://github.com/davidcsterratt/geometry/pull/8
* The new reentrant Qhull library (current version v7.2.1) is used,
as a precursor to allowing Qhull objects to be returned and operated
on
https://github.com/davidcsterratt/geometry/issues/3
* convhulln() now returns a pointer to the qhull object representing
the hull.
https://github.com/davidcsterratt/geometry/issues/2
This is used in the inhull() implementation
* delaunayn() now returns a pointer to the qhull object representing
the triangulation
https://github.com/davidcsterratt/geometry/issues/7
* tsearchn() can take an delaunay object, which should give fast
performance
https://github.com/davidcsterratt/geometry/issues/6
NOTE: This feature is experimental and has only been tested
on 3D triangulations
* Test added for polyarea()
Thanks to Toby Hocking for suggesting adding one
CHANGES IN VERSION 0.3-6 - Released 2015/09/04
CODE IMPROVEMENTS
* As per CRAN policies, the title in the DESCRIPTION file is now in title
case.
BUG FIXES
* Fix for Issue #5738: segfault when run from directory lacking write
permission
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5738&group_id=1149&atid=4552)
Using "." as a temporary directory can cause problems if it is not
writeable. Now the geometry package uses tempdir(), which R should
guarantee to exist.
Thanks to Laura Riggi for reporting this problem.
* Put Robert B. Gramacy back in the author list, after he was
accidentally omitted when changing to the Authors@R format on
2014/10/29 (version 0.3-5).
Thanks to Robert B. Gramacy for reporting this, and apologies for
the error.
CHANGES IN VERSION 0.3-5 - Released 2014/11/06
API CHANGES
* The default Qhull option to the delaunayn() function is now "Qt"
rather than "QJ" and degenerate (zero-area) simplices are removed
from the triangulation, so that all simplicies are non-degenerate.
This is a follow-up to issue #2009: delaunayn can return degenerate
simplicies by default
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1993&group_id=1149&atid=4552). Thanks
to Rolf Turner for alerting me to the issue.
* delaunayn() now throws an error if the number of points is less than
the number of dimensions + 1.
FEATURES
* delaunayn() with the "full" option also returns the areas of
facets. This is a byproduct of the API change above.
BUG FIXES
* Fix for Issue #2789: inline functions min/max generate linker error
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2789&group_id=1149&atid=4552)
Thanks to Bernd Bischl for reporting the problem and suggesting the
fix.
* Partial Fix for Issue #5738: segfault when run from directory
lacking write permission
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5738&group_id=1149&atid=4552)
An error is now thrown, rather than a segfault. The underlying
problem still needs to be dealth with.
DOCUMENTATION IMPROVEMENTS
* The meanings of "area" and "vol" in the convhulln return value have
been clarified. Thanks to Michael Cole for raising the issue.
* The documentation of "cart2bary" and "bary2cart" has been corrected
and improved. Thanks to Francisco Mendoza Torres for raising the issue.
* HTML documentation has been for validation errors with HTML tidy.
Thanks to Kurt Hornik and the CRAN maintainers for alerting me to
the problem.
CODE IMPROVEMENTS
* Tests are now all done using the testthat framework.
* There is now a test to make sure output to file works. Thanks to
Brian Ripley for identifying the problem while testing the pacakge
for CRAN.
CHANGES IN VERSION 0.3-4 - Released 2014/03/04
BUG FIXES
* Fix for Issue #5406: Compilation flags in Makevars
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5406&group_id=1149&atid=4552)
Thanks to Kurt Hornik and the CRAN maintainers for alerting me to
the problem.
CHANGES IN VERSION 0.3-3 - Released 2013/04/18
BUG FIXES
* The License has been changed to GPL (>= 3) + file LICENSE and the
LICENSE file made clearer. Thanks to Kurt Hornik and the CRAN
maintainers for alerting me to the problem and helping with a
solution.
* Fix for Issue #1993: Error in solve.default in
tsearchn
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1993&group_id=1149&atid=4552)
Thanks to Bill Denny for reporting this and suggesting a way forward
with a fix. Thanks to John Drake for alerting me to the recurrence
of the problem and Jon Clayden on the R-devel list for pointing out
the correct way of testing for ill-conditioned matrices.
* Fix for Issue #2009: delaunayn can return degenerate simplicies by
default
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1993&group_id=1149&atid=4552)
This is a follow-on of #1993, so thanks to Bill Denny for
highlighting the issue.
* Fix for Issue #2007: Qt option given to Qhull
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2007&group_id=1149&atid=4552)
* The use of the multicore package in tests has been replaced by use
of the parallel package. Thanks to Kurk Hornik for pointing this
out.
* Removed non-API call to R_TempDir. Thanks to Kurk Hornik for
pointing this out.
CHANGES IN VERSION 0.3-2 - Released 2012/05/12
BUG FIXES
* Fix for Issue #1968: convhulln crash with T0 option
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1968&group_id=1149&atid=4552)
Thanks to Thomas Kirschstein, Oskar Knapik and Uwe Ligges for
reporting this and to Duncan Murdoch for help on the r-devel mailing
list.
* Fix for Issue #1983: NA in an input to delaunayn crashes R
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1983&group_id=1149&atid=4552)
Thanks to Bill Denny for reporting this and suggestiong a way
forward with a fix.
CHANGES IN VERSION 0.3-1 - Released 2012/05/01
BUG FIXES
* Fix for Issue #1964: R crashes when using convhulln/delaunayn
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1964&group_id=1149&atid=4552).
Thanks to Thomas Kirschstein, Oskar Knapik and Paolo Piras for
reporting this.
CHANGES IN VERSION 0.3-0 - Released 2012/04/17
NEW FEATURES
* New function dot() to compute dot product. Syntax is shared with
Octave dot() function.
* New function polyarea() to compute area of polygons. Syntax is shared with
Octave polyarea() function.
BUG FIXES
* Fix for Issue #1578: convhulln crashes when running 2 instances of
R in the same directory: output to qhull_out.txt removed
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1578&group_id=1149&atid=4552).
Thanks to Francois Rousset and Bernd Bischl for reporting this.
* Fix for Issue #1923: Compilation on Windows 64 doesn't work (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1923&group_id=1149&atid=4552)
* Fix for Issue #1924: Silent operation is not supported (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1924&group_id=1149&atid=4552)
Thanks to Raphael Leblois for reporting this.
* Fix for Issue #1930: delaunayn should always return a matrix (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1930&group_id=1149&atid=4552)
* Fix for Issue #1915: geometry segfaults during tests (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1915&group_id=1149&atid=4552)
* Fix for Issue #1947: convhulln crash when Qhull error reported
(https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1947&group_id=1149&atid=4552).
Thanks to Petr Savicky for reporting this.
OTHER CHANGES
* Updated to qhull version 2011.2.
* The default qhull option "QJ" for delaunayn() has been replaced by
"Qt". One or other option is always provided to the qhull code (see
https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1915&group_id=1149&atid=4552).
* Documentation improvements.
* Added some tests.
CHANGES IN VERSION 0.2-0 - Released 2011/09/09
NEW FEATURES
* The tsearch and tsearchn functions have been ported from
Octave. These functions have the same syntax as the Octave
versions, though it also possible to get tsearch to output
barycentric coordinates. tsearch only works for 2D simplexes
(i.e. triangles), but is fast because it is written in C. By
default, tsearchn uses the fast tsearch function when presented
with 2D data.
NEW MAINTAINER
* David Sterratt has taken over from Bobby Gramacy. Thank-you to
Bobby for his work on the package.
geometry/vignettes/ 0000755 0001762 0000144 00000000000 14751720222 014117 5 ustar ligges users geometry/vignettes/qhull-eg.Rnw 0000644 0001762 0000144 00000006033 13431000557 016323 0 ustar ligges users %\VignetteIndexEntry{Qhull examples}
\documentclass{article}
\usepackage{Sweave}
\SweaveOpts{echo=TRUE}
\usepackage{hyperref}
\usepackage[british]{babel}
\title{Qhull examples}
\author{David C. Sterratt}
\begin{document}
\maketitle
This document presents examples of the \texttt{geometry} package
functions which implement functions using the
\href{http://www.qhull.org}{Qhull library}.
\section{Convex hulls in 2D}
\label{qhull-eg:sec:convex-hull-2d}
\subsection{Calling \texttt{convhulln} with one argument}
\label{qhull-eg:sec:call-convh-with}
With one argument, convhulln returns the indices of the points of the
convex hull.
<<>>=
library(geometry)
ps <-matrix(rnorm(30), , 2)
ch <- convhulln(ps)
head(ch)
@
\subsection{Calling \texttt{convhulln} with \texttt{options}}
\label{qhull-eg:sec:call-convh-with}
We can supply Qhull options to \texttt{convhulln}; in this case it
returns an object of class \texttt{convhulln} which is also a list.
For example \texttt{FA} returns the generalised \texttt{area} and
\texttt{vol}ume. Confusingly in 2D the generalised area is the length
of the perimeter, and the generalised volume is the area.
<<>>=
ps <-matrix(rnorm(30), , 2)
ch <- convhulln(ps, options="FA")
print(ch$area)
print(ch$vol)
@
A \texttt{convhulln} object can also be plotted.
<>=
plot(ch)
@
We can also find the normals to the ``facets'' of the convex hull:
<<>>=
ch <- convhulln(ps, options="n")
head(ch$normals)
@
Here the first two columns and the $x$ and $y$ direction of the normal,
and the third column defines the position at which the face intersects
that normal.
\subsection{Testing if points are inside a convex hull with \texttt{inhulln}}
\label{qhull-eg:sec:testing-if-points}
The function \texttt{inhulln} can be used to test if points are inside
a convex hull. Here the function \texttt{rbox} is a handy way to
create points at random locations.
<>=
tp <- rbox(n=200, D=2, B=4)
in_ch <- inhulln(ch, tp)
plot(tp[!in_ch,], col="gray")
points(tp[in_ch,], col="red")
plot(ch, add=TRUE)
@
\section{Delaunay triangulation in 2D}
\label{qhull-eg:sec:dela-triang-2d}
\subsection{Calling \texttt{delaunayn} with one argument}
\label{qhull-eg:sec:call-delaunayn-with}
With one argument, a set of points, \texttt{delaunayn} returns the
indices of the points at each vertex of each triangle in the triangulation.
<>=
ps <- rbox(n=10, D=2)
dt <- delaunayn(ps)
head(dt)
trimesh(dt, ps)
points(ps)
@
\subsection{Calling \texttt{delaunayn} with \texttt{options}}
\label{qhull-eg:sec:call-dela-with}
We can supply Qhull options to \texttt{delaunayn}; in this case it
returns an object of class \texttt{delaunayn} which is also a list.
For example \texttt{Fa} returns the generalised \texttt{area} of each
triangle. In 2D the generalised area is the actual area; in 3D it
would be the volume.
<<>>=
dt2 <- delaunayn(ps, options="Fa")
print(dt2$areas)
dt2 <- delaunayn(ps, options="Fn")
print(dt2$neighbours)
@
\end{document}
% LocalWords: Qhull convhulln ps rnorm ume inhulln rbox tp gray dt
% LocalWords: delaunayn trimesh Fn
geometry/vignettes/qhull/ 0000755 0001762 0000144 00000000000 14751753072 015255 5 ustar ligges users geometry/vignettes/qhull/REGISTER.txt 0000644 0001762 0000144 00000001676 13431000556 017236 0 ustar ligges users Dear Qhull User
We would like to find out how you are using our software. Think of
Qhull as a new kind of shareware: you share your science and successes
with us, and we share our software and support with you.
If you use Qhull, please send us a note telling
us what you are doing with it.
We need to know:
(1) What you are working on - an abstract of your work would be
fine.
(2) How Qhull has helped you, for example, by increasing your
productivity or allowing you to do things you could not do
before. If Qhull had a direct bearing on your work, please
tell us about this.
We encourage you to cite Qhull in your publications.
To cite Qhull, please use
Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull
algorithm for convex hulls," ACM Trans. on Mathematical Software,
22(4):469-483, Dec 1996, http://www.qhull.org.
Please send e-mail to
bradb@shore.net
Thank you!
geometry/vignettes/qhull/File_id.diz 0000644 0001762 0000144 00000000631 13431000556 017302 0 ustar ligges users Qhull 2015.2 - Qhull computes convex hulls,
Delaunay triangulations, halfspace inter-
sections about a point, Voronoi diagrams,
furthest-site Delaunay triangulations, and
furthest-site Voronoi diagrams. Qhull
works with 2-d, 3-d, 4-d, 5-d, and higher
dimensions. It computes volumes, surface
areas, and approximations. It runs in a
command window under Windows 95/NT/XP/7.
www.qhull.org, freeware.
geometry/vignettes/qhull/README.txt 0000644 0001762 0000144 00000052531 13431000556 016743 0 ustar ligges users Name
qhull, rbox 2015.2 2016/01/18
Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection
Documentation:
html/index.htm
Available from:
(git@github.com:qhull/qhull.git)
News and a paper:
Version 1 (simplicial only):
Purpose
Qhull is a general dimension convex hull program that reads a set
of points from stdin, and outputs the smallest convex set that contains
the points to stdout. It also generates Delaunay triangulations, Voronoi
diagrams, furthest-site Voronoi diagrams, and halfspace intersections
about a point.
Rbox is a useful tool in generating input for Qhull; it generates
hypercubes, diamonds, cones, circles, simplices, spirals,
lattices, and random points.
Qhull produces graphical output for Geomview. This helps with
understanding the output.
Environment requirements
Qhull and rbox should run on all 32-bit and 64-bit computers. Use
an ANSI C or C++ compiler to compile the program. The software is
self-contained. It comes with examples and test scripts.
Qhull's C++ interface uses the STL. The C++ test program uses QTestLib
from the Qt Framework. Qhull's C++ interface may change without
notice. Eventually, it will move into the qhull shared library.
Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt
before using or distributing Qhull.
To cite Qhull, please use
Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull
algorithm for convex hulls," ACM Trans. on Mathematical Software,
22(4):469-483, Dec 1996, http://www.qhull.org.
To modify Qhull, particularly the C++ interface
Qhull is on GitHub
(http://github.com/qhull/qhull, git@github.com:qhull/qhull.git)
For internal documentation, see html/qh-code.htm
To install Qhull
Qhull is precompiled for Windows 32-bit, otherwise it needs compilation.
Qhull includes Makefiles for gcc and other targets, CMakeLists.txt for CMake,
.sln/.vcproj/.vcxproj files for Microsoft Visual Studio, and .pro files
for Qt Creator. It compiles under Windows with mingw.
Install and build instructions follow.
See the end of this document for a list of distributed files.
-----------------
Installing Qhull on Windows 10, 8, 7 (32- or 64-bit), Windows XP, and Windows NT
The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe,
qhalf.exe, qvoronoi.exe, testqset.exe, user_eg*.exe, documentation files,
and source files. Qhull.exe and user-eg3.exe are compiled with the reentrant
library while the other executables use the non-reentrant library.
To install Qhull:
- Unzip the files into a directory (e.g., named 'qhull')
- Click on QHULL-GO or open a command window into Qhull's bin directory.
- Test with 'rbox D4 | qhull'
To uninstall Qhull
- Delete the qhull directory
To learn about Qhull:
- Execute 'qconvex' for a synopsis and examples.
- Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points.
- Execute 'rbox 10 | qconvex i TO file' to write results to 'file'.
- Browse the documentation: qhull\html\index.htm
- If an error occurs, Windows sends the error to stdout instead of stderr.
Use 'TO xxx' to send normal output to xxx
To improve the command window
- Double-click the window bar to increase the size of the window
- Right-click the window bar
- Select Properties
- Check QuickEdit Mode
Select text with right-click or Enter
Paste text with right-click
- Change Font to Lucinda Console
- Change Layout to Screen Buffer Height 999, Window Size Height 55
- Change Colors to Screen Background White, Screen Text Black
- Click OK
- Select 'Modify shortcut that started this window', then OK
If you use qhull a lot, install a bash shell such as
MSYS (www.mingw.org/wiki/msys), Road Bash (www.qhull.org/bash),
or Cygwin (www.cygwin.com).
-----------------
Installing Qhull on Unix with gcc
To build Qhull, static libraries, shared library, and C++ interface
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- make
- export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
The Makefiles may be edited for other compilers.
If 'testqset' exits with an error, qhull is broken
A simple Makefile for Qhull is in src/libqhull and src/libqhull_r.
To build the Qhull executables and libqhullstatic
- Extract Qhull from qhull...tgz or qhull...zip
- cd src/libqhull_r # cd src/libqhull
- make
-----------------
Installing Qhull with CMake 2.6 or later
See CMakeLists.txt for examples and further build instructions
To build Qhull, static libraries, shared library, and C++ interface
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- cd build
- cmake --help # List build generators
- make -G "" .. && cmake ..
- cmake ..
- make
- make install
The ".." is important. It refers to the parent directory (i.e., qhull/)
On Windows, CMake installs to C:/Program Files/qhull. 64-bit generators
have a "Win64" tag.
If creating a qhull package, please include a pkg-config file based on build/qhull*.pc.in
If cmake fails with "No CMAKE_C_COMPILER could be found"
- cmake was not able to find the build environment specified by -G "..."
-----------------
Installing Qhull with Qt
To build Qhull, including its C++ test (qhulltest)
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Load src/qhull-all.pro into QtCreator
- Build
-------------------
Working with Qhull's C++ interface
See html/qh-code.htm#cpp for calling Qhull from C++ programs
See html/qh-code.htm#reentrant for converting from Qhull-2012
Examples of using the C++ interface
user_eg3_r.cpp
qhulltest/*_test.cpp
Qhull's C++ interface is likely to change. Stay current with GitHub.
To clone Qhull's next branch from http://github.com/qhull/qhull
git init
git clone git@github.com:qhull/qhull.git
cd qhull
git checkout next
...
git pull origin next
Compile qhullcpp and libqhullstatic_r with the same compiler. Both libraries
use the C routines setjmp() and longjmp() for error handling. They must
be compiled with the same compiler.
-------------------
Calling Qhull from C programs
See html/qh-code.htm#library for calling Qhull from C programs
See html/qh-code.htm#reentrant for converting from Qhull-2012
Warning: You will need to understand Qhull's data structures and read the
code. Most users will find it easier to call Qhull as an external command.
The new, reentrant 'C' code (src/libqhull_r), passes a pointer to qhT
to most Qhull routines. This allows multiple instances of Qhull to run
at the same time. It simplifies the C++ interface.
The non-reentrant 'C' code (src/libqhull) looks unusual. It refers to
Qhull's global data structure, qhT, through a 'qh' macro (e.g., 'qh ferr').
This allows the same code to use static memory or heap memory.
If qh_QHpointer is defined, qh_qh is a pointer to an allocated qhT;
otherwise qh_qh is a global static data structure of type qhT.
------------------
Compiling Qhull with Microsoft Visual C++
To compile 32-bit Qhull with Microsoft Visual C++ 2010 and later
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Load solution build/qhull-32.sln
- Build target 'Win32'
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012)
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
To compile 64-bit Qhull with Microsoft Visual C++ 2010 and later
- 64-bit Qhull has larger data structures due to 64-bit pointers
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Load solution build/qhull-64.sln
- Build target 'Win32'
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/5.2.0/5.2.0/msvc2012_64)
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
To compile Qhull with Microsoft Visual C++ 2005 (vcproj files)
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Load solution build/qhull.sln
- Build target 'win32' (not 'x64')
- Project qhulltest requires Qt for DevStudio (http://www.qt.io)
Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/4.7.4)
If QTDIR is incorrect, precompile will fail with 'Can not locate the file specified'
-----------------
Compiling Qhull with Qt Creator
Qt (http://www.qt.io) is a C++ framework for Windows, Linux, and Macintosh
Qhull uses QTestLib to test qhull's C++ interface (see src/qhulltest/)
To compile Qhull with Qt Creator
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Download the Qt SDK
- Start Qt Creator
- Load src/qhull-all.pro
- Build
-----------------
Compiling Qhull with mingw on Windows
To compile Qhull with MINGW
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Install Road Bash (http://www.qhull.org/bash)
or install MSYS (http://www.mingw.org/wiki/msys)
- Install MINGW-w64 (http://sourceforge.net/projects/mingw-w64).
Mingw is included with Qt SDK.
- make
-----------------
Compiling Qhull with cygwin on Windows
To compile Qhull with cygwin
- Download and extract Qhull (either GitHub, .tgz file, or .zip file)
- Install cygwin (http://www.cygwin.com)
- Include packages for gcc, make, ar, and ln
- make
-----------------
Compiling from Makfile without gcc
The file, qhull-src.tgz, contains documentation and source files for
qhull and rbox.
To unpack the tgz file
- tar zxf qhull-src.tgz
- cd qhull
- Use qhull/Makefile
Simpler Makefiles are qhull/src/libqhull/Makefile and qhull/src/libqhull_r/Makefile
Compiling qhull and rbox with Makefile
- in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines
- the defaults are gcc and enscript
- CCOPTS1 should include the ANSI flag. It defines __STDC__
- in user.h, check the definitions of qh_SECticks and qh_CPUclock.
- use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour
- type: make
- this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a libqhull_r.a
- type: make doc
- this prints the man page
- See also qhull/html/index.htm
- if your compiler reports many errors, it is probably not a ANSI C compiler
- you will need to set the -ansi switch or find another compiler
- if your compiler warns about missing prototypes for fprintf() etc.
- this is ok, your compiler should have these in stdio.h
- if your compiler warns about missing prototypes for memset() etc.
- include memory.h in qhull_a.h
- if your compiler reports "global.c: storage size of 'qh_qh' isn't known"
- delete the initializer "={0}" in global.c, stat.c and mem.c
- if your compiler warns about "stat.c: improper initializer"
- this is ok, the initializer is not used
- if you have trouble building libqhull.a with 'ar'
- try 'make -f Makefile.txt qhullx'
- if the code compiles, the qhull test case will automatically execute
- if an error occurs, there's an incompatibility between machines
- If you can, try a different compiler
- You can turn off the Qhull memory manager with qh_NOmem in mem.h
- You can turn off compiler optimization (-O2 in Makefile)
- If you find the source of the problem, please let us know
- to install the programs and their man pages:
- define MANDIR and BINDIR
- type 'make install'
- if you have Geomview (www.geomview.org)
- try 'rbox 100 | qconvex G >a' and load 'a' into Geomview
- run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm)
------------------
Compiling on other machines and compilers
Qhull may compile with Borland C++ 5.0 bcc32. A Makefile is included.
Execute 'cd src/libqhull; make -f Mborland'. If you use the Borland IDE, set
the ANSI option in Options:Project:Compiler:Source:Language-compliance.
Qhull may compile with Borland C++ 4.02 for Win32 and DOS Power Pack.
Use 'cd src/libqhull; make -f Mborland -D_DPMI'. Qhull 1.0 compiles with
Borland C++ 4.02. For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c".
Use the same options for Qhull 1.0. [D. Zwick]
If you have troubles with the memory manager, you can turn it off by
defining qh_NOmem in mem.h.
-----------------
Distributed files
README.txt // Instructions for installing Qhull
REGISTER.txt // Qhull registration
COPYING.txt // Copyright notice
QHULL-GO.lnk // Windows icon for eg/qhull-go.bat
Announce.txt // Announcement
CMakeLists.txt // CMake build file (2.6 or later)
CMakeModules/CheckLFS.cmake // enables Large File Support in cmake
File_id.diz // Package descriptor
index.htm // Home page
Makefile // Makefile for gcc and other compilers
qhull*.md5sum // md5sum for all files
bin/* // Qhull executables and dll (.zip only)
build/qhull*.pc.in // pkg-config templates for qhull_r, qhull, and qhull_p
build/qhull-32.sln // 32-bit DevStudio solution and project files (2010 and later)
build/*-32.vcxproj
build/qhull-64.sln // 64-bit DevStudio solution and project files (2010 and later)
build/*-64.vcxproj
build/qhull.sln // DevStudio solution and project files (2005 and 2009)
build/*.vcproj
eg/* // Test scripts and geomview files from q_eg
html/index.htm // Manual
html/qh-faq.htm // Frequently asked questions
html/qh-get.htm // Download page
html/qhull-cpp.xml // C++ style notes as a Road FAQ (www.qhull.org/road)
src/Changes.txt // Change history for Qhull and rbox
src/qhull-all.pro // Qt project
eg/
q_eg // shell script for Geomview examples (eg.01.cube)
q_egtest // shell script for Geomview test examples
q_test // shell script to test qhull
q_test-ok.txt // output from q_test
qhulltest-ok.txt // output from qhulltest (Qt only)
make-vcproj.sh // bash shell script to create vcproj and vcxprog files
qhull-zip.sh // bash shell script for distribution files
rbox consists of (bin, html):
rbox.exe // Win32 executable (.zip only)
rbox.htm // html manual
rbox.man // Unix man page
rbox.txt
qhull consists of (bin, html):
qconvex.exe // Win32 executables and dlls (.zip download only)
qhull.exe // Built with the reentrant library (about 2% slower)
qdelaunay.exe
qhalf.exe
qvoronoi.exe
qhull_r.dll
qhull-go.bat // command window
qconvex.htm // html manual
qdelaun.htm
qdelau_f.htm
qhalf.htm
qvoronoi.htm
qvoron_f.htm
qh-eg.htm
qh-code.htm
qh-impre.htm
index.htm
qh-opt*.htm
qh-quick.htm
qh--*.gif // images for manual
normal_voronoi_knauss_oesterle.jpg
qhull.man // Unix man page
qhull.txt
bin/
msvcr80.dll // Visual C++ redistributable file (.zip download only)
src/
qhull/unix.c // Qhull and rbox applications using non-reentrant libqhullstatic.a
rbox/rbox.c
qconvex/qconvex.c
qhalf/qhalf.c
qdelaunay/qdelaunay.c
qvoronoi/qvoronoi.c
qhull/unix_r.c // Qhull and rbox applications using reentrant libqhullstatic_r.a
rbox/rbox_r.c
qconvex/qconvex_r.c // Qhull applications built with reentrant libqhull_r/Makefile
qhalf/qhalf_r.c
qdelaunay/qdelaun_r.c
qvoronoi/qvoronoi_r.c
user_eg/user_eg_r.c // example of using qhull_r.dll from a user program
user_eg2/user_eg2_r.c // example of using libqhullstatic_r.a from a user program
user_eg3/user_eg3_r.cpp // example of Qhull's C++ interface libqhullcpp with libqhullstatic_r.a
qhulltest/qhulltest.cpp // Test of Qhull's C++ interface using Qt's QTestLib
qhull-*.pri // Include files for Qt projects
testqset_r/testqset_r.c // Test of reentrant qset_r.c and mem_r.c
testqset/testqset.c // Test of non-rentrant qset.c and mem.c
src/libqhull
libqhull.pro // Qt project for non-rentrant, shared library (qhull.dll)
index.htm // design documentation for libqhull
qh-*.htm
qhull-exports.def // Export Definition file for Visual C++
Makefile // Simple gcc Makefile for qhull and libqhullstatic.a
Mborland // Makefile for Borland C++ 5.0
libqhull.h // header file for qhull
user.h // header file of user definable constants
libqhull.c // Quickhull algorithm with partitioning
user.c // user re-definable functions
usermem.c
userprintf.c
userprintf_rbox.c
qhull_a.h // include files for libqhull/*.c
geom.c // geometric routines
geom2.c
geom.h
global.c // global variables
io.c // input-output routines
io.h
mem.c // memory routines, this is stand-alone code
mem.h
merge.c // merging of non-convex facets
merge.h
poly.c // polyhedron routines
poly2.c
poly.h
qset.c // set routines, this only depends on mem.c
qset.h
random.c // utilities w/ Park & Miller's random number generator
random.h
rboxlib.c // point set generator for rbox
stat.c // statistics
stat.h
src/libqhull_r
libqhull_r.pro // Qt project for rentrant, shared library (qhull_r.dll)
index.htm // design documentation for libqhull_r
qh-*_r.htm
qhull-exports_r.def // Export Definition file for Visual C++
Makefile // Simple gcc Makefile for qhull and libqhullstatic.a
libqhull_r.h // header file for qhull
user_r.h // header file of user definable constants
libqhull_r.c // Quickhull algorithm wi_r.hpartitioning
user_r.c // user re-definable functions
usermem.c
userprintf.c
userprintf_rbox.c
qhull_ra.h // include files for libqhull/*_r.c
geom_r.c // geometric routines
geom2.c
geom_r.h
global_r.c // global variables
io_r.c // input-output routines
io_r.h
mem_r.c // memory routines, this is stand-alone code
mem.h
merge_r.c // merging of non-convex facets
merge.h
poly_r.c // polyhedron routines
poly2.c
poly_r.h
qset_r.c // set routines, this only depends on mem_r.c
qset.h
random_r.c // utilities w/ Park & Miller's random number generator
random.h
rboxlib_r.c // point set generator for rbox
stat_r.c // statistics
stat.h
src/libqhullcpp/
libqhullcpp.pro // Qt project for renentrant, static C++ library
Qhull.cpp // Calls libqhull_r.c from C++
Qhull.h
qt-qhull.cpp // Supporting methods for Qt
Coordinates.cpp // input classes
Coordinates.h
PointCoordinates.cpp
PointCoordinates.h
RboxPoints.cpp // call rboxlib.c from C++
RboxPoints.h
QhullFacet.cpp // data structure classes
QhullFacet.h
QhullHyperplane.cpp
QhullHyperplane.h
QhullPoint.cpp
QhullPoint.h
QhullQh.cpp
QhullRidge.cpp
QhullRidge.h
QhullVertex.cpp
QhullVertex.h
QhullFacetList.cpp // collection classes
QhullFacetList.h
QhullFacetSet.cpp
QhullFacetSet.h
QhullIterator.h
QhullLinkedList.h
QhullPoints.cpp
QhullPoints.h
QhullPointSet.cpp
QhullPointSet.h
QhullSet.cpp
QhullSet.h
QhullSets.h
QhullVertexSet.cpp
QhullVertexSet.h
functionObjects.h // supporting classes
QhullError.cpp
QhullError.h
QhullQh.cpp
QhullQh.h
QhullStat.cpp
QhullStat.h
RoadError.cpp // Supporting base classes
RoadError.h
RoadLogEvent.cpp
RoadLogEvent.h
usermem_r-cpp.cpp // Optional override for qh_exit() to throw an error
src/libqhullstatic/
libqhullstatic.pro // Qt project for non-reentrant, static library
src/libqhullstatic_r/
libqhullstatic_r.pro // Qt project for reentrant, static library
src/qhulltest/
qhulltest.pro // Qt project for test of C++ interface
Coordinates_test.cpp // Test of each class
PointCoordinates_test.cpp
Qhull_test.cpp
QhullFacet_test.cpp
QhullFacetList_test.cpp
QhullFacetSet_test.cpp
QhullHyperplane_test.cpp
QhullLinkedList_test.cpp
QhullPoint_test.cpp
QhullPoints_test.cpp
QhullPointSet_test.cpp
QhullRidge_test.cpp
QhullSet_test.cpp
QhullVertex_test.cpp
QhullVertexSet_test.cpp
RboxPoints_test.cpp
RoadTest.cpp // Run multiple test files with QTestLib
RoadTest.h
-----------------
Authors:
C. Bradford Barber Hannu Huhdanpaa (Version 1.0)
bradb@shore.net hannu@qhull.org
Qhull 1.0 and 2.0 were developed under NSF grants NSF/DMS-8920161
and NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard
University. If you find Qhull useful, please let us know.
geometry/vignettes/qhull/html/ 0000755 0001762 0000144 00000000000 14664417655 016230 5 ustar ligges users geometry/vignettes/qhull/html/qconvex.html 0000644 0001762 0000144 00000066201 14664417655 020606 0 ustar ligges users
qconvex -- convex hull
Up:
Home page for Qhull (local)
Up: Qhull manual: contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
To: synopsis
input outputs
controls graphics
notes conventions
options
qconvex -- convex hull
The convex hull of a set of points is the smallest convex set
containing the points. See the detailed introduction by O'Rourke
['94]. See Description of Qhull and How Qhull adds a point.
- Example: rbox 10 D3 | qconvex s o TO result
- Compute the 3-d convex hull of 10 random points. Write a
summary to the console and the points and facets to
'result'.
-
- Example: rbox c | qconvex n
- Print the normals for each facet of a cube.
-
- Example: rbox c | qconvex i Qt
- Print the triangulated facets of a cube.
-
- Example: rbox y 500 W0 | qconvex
- Compute the convex hull of a simplex with 500
points on its surface.
-
- Example: rbox x W1e-12 1000 | qconvex
QR0
- Compute the convex hull of 1000 points near the
surface of a randomly rotated simplex. Report
the maximum thickness of a facet.
-
- Example: rbox 1000 s | qconvex s FA
- Compute the convex hull of 1000 cospherical
points. Verify the results and print a summary
with the total area and volume.
-
- Example: rbox d D12 | qconvex QR0 FA
- Compute the convex hull of a 12-d diamond.
Randomly rotate the input. Note the large number
of facets and the small volume.
-
- Example: rbox c D7 | qconvex FA TF1000
- Compute the convex hull of the 7-d hypercube.
Report on progress every 1000 facets. Computing
the convex hull of the 9-d hypercube takes too
much time and space.
-
- Example: rbox c d D2 | qconvex Qc s f Fx | more
- Dump all fields of all facets for a square and a
diamond. Also print a summary and a list of
vertices. Note the coplanar points.
-
Except for rbox, all of the qhull programs compute a convex hull.
By default, Qhull merges coplanar facets. For example, the convex
hull of a cube's vertices has six facets.
If you use 'Qt' (triangulated output),
all facets will be simplicial (e.g., triangles in 2-d). For the cube
example, it will have 12 facets. Some facets may be
degenerate and have zero area.
If you use 'QJ' (joggled input),
all facets will be simplicial. The corresponding vertices will be
slightly perturbed and identical points will be joggled apart.
Joggled input is less accurate that triangulated
output.See Merged facets or joggled input.
The output for 4-d convex hulls may be confusing if the convex
hull contains non-simplicial facets (e.g., a hypercube). See
Why
are there extra points in a 4-d or higher convex hull?
The 'qconvex' program is equivalent to
'qhull'. It disables the following Qhull
options: d v H Qbb Qf Qg Qm
Qr Qu Qv Qx Qz TR E V Fp Gt Q0,etc.
Copyright © 1995-2020 C.B. Barber
qconvex -- compute the convex hull.
input (stdin): dimension, number of points, point coordinates
comments start with a non-numeric character
options:
Qt - triangulated output
QJ - joggled input instead of merged facets
Tv - verify result: structure, convexity, and point inclusion
. - concise list of all options
- - one-line description of each option
-? - this message
-V - version
output options (subset):
s - summary of results (default)
i - vertices incident to each facet
n - normals with offsets
p - vertex coordinates (if 'Qc', includes coplanar points)
FA - report total area and volume
FS - total area and volume
Fx - extreme points (convex hull vertices)
G - Geomview output (2-d, 3-d, and 4-d)
m - Mathematica output (2-d and 3-d)
o - OFF format (dim, n, points, facets)
QVn - print facets that include point n, -n if not
TI file - input file, may be enclosed in single quotes
TO file - output file, may be enclosed in single quotes
examples:
rbox c D2 | qconvex s n rbox c D2 | qconvex i
rbox c D2 | qconvex o rbox 1000 s | qconvex s Tv FA
rbox c d D2 | qconvex s Qc Fx rbox y 1000 W0 | qconvex Qc s n
rbox y 1000 W0 | qconvex s QJ rbox d G1 D12 | qconvex QR0 FA Pp
rbox c D7 | qconvex FA TF1000
The input data on stdin consists of:
- dimension
- number of points
- point coordinates
Use I/O redirection (e.g., qconvex < data.txt), a pipe (e.g., rbox 10 | qconvex),
or the 'TI' option (e.g., qconvex TI data.txt).
Comments start with a non-numeric character. Error reporting is
simpler if there is one point per line. Dimension
and number of points may be reversed.
Here is the input for computing the convex
hull of the unit cube. The output is the normals, one
per facet.
rbox c > data
3 RBOX c
8
-0.5 -0.5 -0.5
-0.5 -0.5 0.5
-0.5 0.5 -0.5
-0.5 0.5 0.5
0.5 -0.5 -0.5
0.5 -0.5 0.5
0.5 0.5 -0.5
0.5 0.5 0.5
qconvex s n < data
Convex hull of 8 points in 3-d:
Number of vertices: 8
Number of facets: 6
Number of non-simplicial facets: 6
Statistics for: RBOX c | QCONVEX s n
Number of points processed: 8
Number of hyperplanes created: 11
Number of distance tests for qhull: 35
Number of merged facets: 6
Number of distance tests for merging: 84
CPU seconds to compute hull (after input): 0.081
4
6
0 0 -1 -0.5
0 -1 0 -0.5
1 0 0 -0.5
-1 0 0 -0.5
0 1 0 -0.5
0 0 1 -0.5
These options control the output of qconvex. They may be used
individually or together.
-
- Vertices
- Fx
- list extreme points (i.e., vertices). The first line is the number of
extreme points. Each point is listed, one per line. The cube example
has eight vertices. In 2-d, extreme points are in counter-clockwise order.
- Fv
- list vertices for each facet. The first line is the number of facets.
Each remaining line starts with the number of vertices. For the cube example,
each facet has four vertices.
- i
- list vertices for each facet. The first line is the number of facets. The
remaining lines list the vertices for each facet. The facets are oriented.
In 4-d and higher, triangulate non-simplicial facets by adding an extra point.
-
-
- Coordinates
- o
- print vertices and facets of the convex hull in OFF format. The
first line is the dimension. The second line is the number of
vertices, facets, and ridges. The vertex
coordinates are next, followed by the facets. Each facet starts with
the number of vertices. Simplicial and 3-d facets are oriented. The cube
example has four vertices per facet.
- Ft
- print a triangulation of the convex hull in OFF format. The first line
is the dimension. The second line is the number of vertices and added points,
followed by the number of facets and the number of ridges.
The vertex coordinates are next, followed by the centrum coordinates. There is
one centrum for each non-simplicial facet.
The cube example has six centrums, one per square.
Each facet starts with the number of vertices or centrums.
In the cube example, each facet uses two vertices and one centrum.
- p
- print vertex coordinates. The first line is the dimension and the second
line is the number of vertices. The following lines are the coordinates of each
vertex. The cube example has eight vertices.
- Qc p
- print coordinates of vertices and coplanar points. The first line is the dimension.
The second line is the number of vertices and coplanar points. The coordinates
are next, one line per point. Use 'Qc Qi p'
to print the coordinates of all points.
-
-
- Facets
- Fn
- list neighboring facets for each facet. The first line is the
number of facets. Each remaining line starts with the number of
neighboring facets. The cube example has four neighbors per facet.
- FN
- list neighboring facets for each point. The first line is the
total number of points. Each remaining line starts with the number of
neighboring facets. Each vertex of the cube example has three neighboring
facets. Use 'Qc Qi FN'
to include coplanar and interior points.
- Fa
- print area for each facet. The first line is the number of facets.
Facet area follows, one line per facet. For the cube example, each facet has area one.
- FI
- list facet IDs. The first line is the number of
facets. The IDs follow, one per line.
-
-
- Coplanar and interior points
- Fc
- list coplanar points for each facet. The first line is the number
of facets. The remaining lines start with the number of coplanar points.
A coplanar point is assigned to one facet.
- Qi Fc
- list interior points for each facet. The first line is the number
of facets. The remaining lines start with the number of interior points.
A coplanar point is assigned to one facet.
- FP
- print distance to nearest vertex for coplanar points. The first line is the
number of coplanar points. Each remaining line starts with the point ID of
a vertex, followed by the point ID of a coplanar point, its facet, and distance.
Use 'Qc Qi
FP' for coplanar and interior points.
-
-
- Hyperplanes
- n
- print hyperplane for each facet. The first line is the dimension. The
second line is the number of facets. Each remaining line is the hyperplane's
coefficients followed by its offset.
- Fo
- print outer plane for each facet. The output plane is above all points.
The first line is the dimension. The
second line is the number of facets. Each remaining line is the outer plane's
coefficients followed by its offset.
- Fi
- print inner plane for each facet. The inner plane of a facet is
below its vertices.
The first line is the dimension. The
second line is the number of facets. Each remaining line is the inner plane's
coefficients followed by its offset.
-
-
- General
- s
- print summary for the convex hull. Use 'Fs' and 'FS' if you need numeric data.
- FA
- compute total area and volume for 's' and 'FS'
- m
- Mathematica output for the convex hull in 2-d or 3-d.
- FM
- Maple output for the convex hull in 2-d or 3-d.
- G
- Geomview output for the convex hull in 2-d, 3-d, or 4-d.
-
-
- Scaling and rotation
- Qbk:n
- scale k'th coordinate to lower bound.
- QBk:n
- scale k'th coordinate to upper bound.
- QbB
- scale input to unit cube centered at the origin.
- QRn
- randomly rotate the input with a random seed of n. If n=0, the
seed is the time. If n=-1, use time for the random seed, but do
not rotate the input.
- Qbk:0Bk:0
- remove k'th coordinate from input. This computes the
convex hull in one lower dimension.
These options provide additional control:
- Qt
- triangulated output. Qhull triangulates non-simplicial facets. It may produce
degenerate facets of zero area.
- QJ
- joggle the input instead of merging facets. This guarantees simplicial facets
(e.g., triangles in 3-d). It is less accurate than triangulated output ('Qt').
- Qc
- keep coplanar points
- Qi
- keep interior points
- f
- facet dump. Print the data structure for each facet.
- QVn
- select facets containing point n as a vertex,
- QGn
- select facets that are visible from point n
(marked 'good'). Use -n for the remainder.
- PDk:0
- select facets with a negative coordinate for dimension k
- TFn
- report progress after constructing n facets
- Tv
- verify result
- TI file
- input data from file. The filename may not use spaces or quotes.
- TO file
- output results to file. Use single quotes if the filename
contains spaces (e.g., TO 'file with spaces.txt'
- Qs
- search all points for the initial simplex. If Qhull can
not construct an initial simplex, it reports a
descriptive message. Usually, the point set is degenerate and one
or more dimensions should be removed ('Qbk:0Bk:0').
If not, use option 'Qs'. It performs an exhaustive search for the
best initial simplex. This is expensive is high dimensions.
Display 2-d, 3-d, and 4-d convex hulls with Geomview ('G').
Display 2-d and 3-d convex hulls with Mathematica ('m').
To view 4-d convex hulls in 3-d, use 'Pd0d1d2d3' to select the positive
octant and 'GrD2' to drop dimension
2.
Qhull always computes a convex hull. The
convex hull may be used for other geometric structures. The
general technique is to transform the structure into an
equivalent convex hull problem. For example, the Delaunay
triangulation is equivalent to the convex hull of the input sites
after lifting the points to a paraboloid.
The following terminology is used for convex hulls in Qhull.
See Qhull's data structures.
- point - d coordinates
- vertex - extreme point of the input set
- ridge - d-1 vertices between two
neighboring facets
- hyperplane - halfspace defined by a unit normal
and offset
- coplanar point - a nearly incident point to a
hyperplane
- centrum - a point on the hyperplane for testing
convexity
- facet - a facet with vertices, ridges, coplanar
points, neighboring facets, and hyperplane
- simplicial facet - a facet with d
vertices, d ridges, and d neighbors
- non-simplicial facet - a facet with more than d
vertices
- good facet - a facet selected by 'QVn', etc.
qconvex -- compute the convex hull
http://www.qhull.org
input (stdin):
first lines: dimension and number of points (or vice-versa).
other lines: point coordinates, best if one point per line
comments: start with a non-numeric character
options:
Qc - keep coplanar points with nearest facet
Qi - keep interior points with nearest facet
QJ - joggled input instead of merged facets
Qt - triangulated output
Qhull control options:
Qa - allow input with fewer or more points than coordinates
Qbk:n - scale coord k so that low bound is n
QBk:n - scale coord k so that upper bound is n (QBk is 0.5)
QbB - scale input to unit cube centered at the origin
Qbk:0Bk:0 - remove k-th coordinate from input
QJn - randomly joggle input in range [-n,n]
QRn - random rotation (n=seed, n=0 time, n=-1 time/no rotate)
Qs - search all points for the initial simplex
Qhull extra options:
QGn - good facet if visible from point n, -n for not visible
QVn - good facet if it includes point n, -n if not
Qw - allow option warnings
Q12 - allow wide facets and wide dupridge
Q14 - merge pinched vertices that create a dupridge
T options:
TFn - report summary when n or more facets created
TI file - input file, may be enclosed in single quotes
TO file - output file, may be enclosed in single quotes
Ts - statistics
Tv - verify result: structure, convexity, and in-circle test
Tz - send all output to stdout
Trace options:
T4 - trace at level n, 4=all, 5=mem/gauss, -1= events
Ta - annotate output with message codes
TAn - stop qhull after adding n vertices
TCn - stop qhull after building cone for point n
TVn - stop qhull after adding point n, -n for before
Tc - check frequently during execution
Tf - flush each qh_fprintf for debugging segfaults
TPn - turn on tracing when point n added to hull
TMn - turn on tracing at merge n
TWn - trace merge facets when width > n
Precision options:
Cn - radius of centrum (roundoff added). Merge facets if non-convex
An - cosine of maximum angle. Merge facets if cosine > n or non-convex
C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge
Rn - randomly perturb computations by a factor of [1-n,1+n]
Un - max distance below plane for a new, coplanar point
Wn - min facet width for outside point (before roundoff)
Output formats (may be combined; if none, produces a summary to stdout):
f - facet dump
G - Geomview output (see below)
i - vertices incident to each facet
m - Mathematica output (2-d and 3-d)
n - normals with offsets
o - OFF file format (dim, points and facets)
p - point coordinates
s - summary (stderr)
More formats:
Fa - area for each facet
FA - compute total area and volume for option 's'
Fc - count plus coplanar points for each facet
use 'Qc' (default) for coplanar and 'Qi' for interior
FC - centrum for each facet
Fd - use cdd format for input (homogeneous with offset first)
FD - use cdd format for numeric output (offset first)
FF - facet dump without ridges
Fi - inner plane for each facet
FI - ID for each facet
Fm - merge count for each facet (511 max)
FM - Maple output (2-d and 3-d)
Fn - count plus neighboring facets for each facet
FN - count plus neighboring facets for each point
Fo - outer plane (or max_outside) for each facet
FO - options and precision constants
FP - nearest vertex for each coplanar point
FQ - command used for qconvex
Fs - summary: #int (8), dimension, #points, tot vertices, tot facets,
output: #vertices, #facets, #coplanars, #nonsimplicial
#real (2), max outer plane, min vertex
FS - sizes: #int (0)
#real (2) tot area, tot volume
Ft - triangulation with centrums for non-simplicial facets (OFF format)
Fv - count plus vertices for each facet
FV - average of vertices (a feasible point for 'H')
Fx - extreme points (in order for 2-d)
Geomview output (2-d, 3-d, and 4-d)
Ga - all points as dots
Gp - coplanar points and vertices as radii
Gv - vertices as spheres
Gc - centrums
GDn - drop dimension n in 3-d and 4-d output
Gh - hyperplane intersections
Gi - inner planes only
Gn - no planes
Go - outer planes only
Gr - ridges
Print options:
PAn - keep n largest facets by area
Pdk:n - drop facet if normal[k] <= n (default 0.0)
PDk:n - drop facet if normal[k] >= n
PFn - keep facets whose area is at least n
Pg - print good facets (needs 'QGn' or 'QVn')
PG - print neighbors of good facets
PMn - keep n facets with most merges
Po - force output. If error, output neighborhood of facet
Pp - do not report precision problems
. - list of all options
- - one line descriptions of all options
-? - help with examples
-V - version
Up: Home page for Qhull (local)
Up: Qhull manual: contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
To: synopsis
input outputs
controls graphics
notes conventions
options
The Geometry Center
Home Page
Comments to: qhull@qhull.org
Created: Sept. 25, 1995 --- Last modified: see top
geometry/vignettes/qhull/html/qh-get.html 0000644 0001762 0000144 00000013527 14664417655 020313 0 ustar ligges users
Qhull Downloads
Up: Qhull Home Page (www.qhull.org)
Qhull Downloads
- Qhull Home Page
Qhull
computes the convex hull, Delaunay triangulation, Voronoi diagram, halfspace
intersection about a point, furthest-site Delaunay
triangulation, and furthest-site Voronoi diagram. It
runs in 2-d, 3-d, 4-d, and higher dimensions. It
implements the Quickhull algorithm for computing the
convex hull. Qhull handles roundoff errors from floating
point arithmetic. It can approximate a convex hull.
Visit Qhull News
for news, bug reports, change history, and users.
If you use Qhull 2003.1 or 2009.1, please upgrade or apply
poly.c-qh_gethash.patch.
- Download:
Qhull 2020.2 for Windows 10, 8, 7, XP, and NT (3.3 MB,
readme,
md5sum,
contents)
Type: console programs for Windows (32- or 64-bit)
Includes 32-bit executables, documentation, and sources files. It runs in a
command window. Qhull may be compiled for 64-bits.
- GitHub Qhull (git@github.com:qhull/qhull.git)
Type: git repository for Qhull. See current Changes.txt
Includes documentation, source files, C++ interface, and test programs. It builds with gcc, mingw,
CMake, DevStudio, and Qt Creator.
- Download: Qhull 2020.2 for Unix (1.3 MB,
readme,
md5sum,
contents)
Type: C/C++ source code for 32-bit and 64-bit architectures.
Includes documentation, source files, Makefiles, CMakeLists.txt, DevStudio projects, and Qt projects.
Includes C++ support.
Download and search sites for pre-built packages include
- The Quickhull algorithm for convex hulls (PDF, 307K)
Type: PDF on ACM Digital Library (from this page only)
Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T.,
"The Quickhull algorithm for convex hulls," ACM
Transactions on Mathematical Software, 22(4):469-483, Dec 1996 [abstract].
- Download:
Qhull version 1.0 (92K)
Type: C source code for
32-bit architectures
Version 1.0 is a fifth the size of version 2.4. It
computes convex hulls and Delaunay triangulations. If a
precision error occurs, it stops with an error message.
It reports an initialization error for inputs made with
0/1 coordinates.
Version 1.0 compiles on a PC with Borland C++ 4.02 for
Win32 and DOS Power Pack. The options for rbox are
"bcc32 -WX -w- -O2-e -erbox -lc rbox.c". The
options for qhull are the same. [D. Zwick]
- Sept. 3, 2020 22:14 EDT md5sum for Qhull 2020.2 downloads
4f68ebb4700849a548b332de500d42e9 *qhull-2020.2/qhull-2020.2-zip.md5sum
ed767244864488d5e9a22dfa788663a9 *qhull-2020.2/qhull-2020-src-8.0.2-tgz.md5sum
7ed0bcce474bf12f6fbb5b4093760f3d *qhull-2020.2.zip
295f7332269a38279478f555cc185296 *qhull-2020-src-8.0.2.tgz
Up: Qhull Home Page (www.qhull.org)
The Geometry Center Home Page
Comments to: qhull@qhull.org
geometry/vignettes/qhull/html/qh--cone.gif 0000644 0001762 0000144 00000005602 13431000556 020304 0 ustar ligges users GIF87ad d ç [~.TopPZ OXa>Uj3.OšP*$?C1Lk5k4'#?9$k)KTRn(7+-aV_"/*&%Z—@‹®˜K\!£µ©JZ W‘=:5€¨ÅÊÇQƒ7]/F@(Y()]/D_¤½)$&Kb>2;<}M7%,'X{-NY zvsUu*$j(f2?…S=Q"9-\N…:?€I^œCÕ×Ö]œB\šAOz1L[!<6^caþþþqpmüüü¶µ´_‚0úúúT^"öööS\!ôôôñòñ86Oq*1.$ìììPBCK$4''´Á¸T¤VÛÜÛF†EO†:PœR’‘W.OšQ(%M–Oª¯®k5?9LX >9&!608&U3+j>=}IU_"L`#E-“Ÿ—$!ðïïT‹;QBG˜cZ{-2i*b>P‡:3-2-O™P6%ikj3Q($q ‚MY $j)put(D\01#:{O]œC%.;B/)*"+{~{M5R\!QZ %FK33<520[éêê@G3PD{7àâá%k)LSS€Š†Mq,-a.6/21.]›B$#Xz[<=>9$g+<7Ls.ÿÿÿHPýýý_ƒ0Z*F?÷÷÷DŒ^I.óóóQt,#TQM4=ííí;$$G˜dQBA‚GCH;{K3=)&Q*&8[1/GŽP*H˜˜–T£VS£Ub0:)QŸSN™PEd#ÒÓÒ'34Uw,>8¢¦¦Ne%\ZT'&U^"¿¿¿ ::9s;!d*ÇÏÊE•a=~L0+)* Ô , d d þ e H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—‰„Ú“%-s_ù
Æ&˜5Mâ"#[ uÄ-[º4S’ "ÍE’¤NUª«rá"Ш—P:zõª:u„¶v¶#ˆ©gËV=‹Im 6RÚf$Bª„Õ¿€ÿfÕÚÕ™Þ‹I^ü·DšSø:\1‰ ƘWýÙìçO/`”%î…9sç?§‘
ب¹VçÂ6«ÓæÛ\аvØéõlÙr©Ö¾½ÙMZ».!·*íàgë·àfÍµä ‰îœ{lᄈþ'[Cáv„¤J«—ô
¤dÓP 0ù|AnëÕOúÅÿ—¦‹P°ö
N~êAÒ©L3ßjö€
‚™±°à)B2ŸnöÙlÍ}âU“hâ¨8°I€Qa"ÞèU% bâ8 ƒÖGFs þ&œ\«hrã/§À¢£†k˜—\(Æ(¤Œy"*Úè¸âõ±fiböÍ)þ²‰h éà€»}fiœb!§hƒ&šRðUh漉Y ‰|’È)d¢’æ¡ÇáaKLåçb“òÉ ƒ4sЇ¢‰†ƒ-Rææ£}ÓŒ¤”~¢@˜‘ªäy^þPN$tsUñÉ·* Bd™¥‰6yØv²>×Ýb(€k®qÄÑŠ¯¬îÈ¥^ UìŒÀá°¬©4;‹’¿jÓÀâ8Ö—C¢ŒÂ%»Í6;ŽŽÑ»gPø’Njê qTÐ,‡º‹Â$Å„úþ…€¿þ& °Àq€ó„¦h6@APQÒpcÚö;ˆLÜlŸ‚¢k¬ÑCMÀ0ü1$Œzë TT`rÀLx°²¦\”Wӧئk4Uä`JšjI¼PÇ*½âÒ.½îl% cŠ)˜ÒŒTD
µ Ph¹/q£îµF«ƒCØ`ƒÝŒ fCªþ¯Úp±Æ½+‘ÉÛ´+I#u×rä/¯|›°JG|, $L ùæÖÔÀ:|²èÜi†ktʘúª£Âæ›s‚D-µÌP²è¢ümšhúýòJ=øÕðܰOC6´ÓÞ
8¸ï<ïhÈç¤JŸê›tñ9tž|-HÑ<V¯ôZá„ÏU‚
`‡6'Û'CŽ+ñ„6¾2"M)uBVú"‚M×HÐ>°q ñK^˜à¸bàOGòœIÜ7c4@†æ–…n¯qy³„|õ‡5È@%C`—
«Ri`PåÈœ)´çAÚ™àŽK ßÁ1”ìB_þÒx€(D!ÄÌÉ®†Û³ÝΆ¶C¥Áe(¨¤q!‘ˆÈ@··¼ïU ‡Js’Êù©4¸âi ŠRl1~Þ£ØÄx…&m0¢K%¡Ãi D+>€>øA,LðFÚÍOŽ«@éV–†ý$=ajD9†HIQ°ñàÁ#€ ƒBÖ"OË]¾Å*1JP$ŠYáUZh‹¦ƒ P…| KU„@‹oaÔæ¥#FœÐ$C8w¾10 •–´$9h9ËZªâ¼(ä
ÍF_¥á.*I0Uù0”e@&÷PËfÒR–(Åì¶h;³=AG©XCL kѪÑþ(Ã7ËIÒ€œåd¦*j)HBn±JˆZ1Ð
X0‚Œ$ €Ä4‡2,@Ÿ]€-@NðÀ)H?RN¾1޳šÒà
zªá€Q‡¤1‡ŒbÔ¢¶ØÃF*R‘z´§<¸åi² )âXBI †J¨Á
«€.@€6ÔÀ¢7eÀnÑž†”¤$åG¡¹EPšì>³ã)?ÂT<àa• ê
¨ª¬Z4äxÆ3ªÁÕ°úÔ¯$Mçå°30š¡¿ÉÔ0…)À•| @d½ N¼‚ЀÆ34Ë×>ÈR ufAkhC@m #´À1JÆ:¶•þ,([ƒ7Pc³šÍ-4:ZföV&õàè¯gÁÂ
óŒhcÙȶŸÄØ,n¥›ÙÍòv ¾u&3…êA„>®Wu€¨H¸±\Ø6·ªåƒ^uKÝÜêµ³¡=§oÉêA@mÚ°@KI‚:¼5®TmÃqtÃXxÌ`ë5Á€è«X½*V¸1zÀ¡îº
¥–$ d…€ma£Äy(01Âàà+øÁ
ÆÂ¸úW r 4k³ž€†:„#%¡¸ÂNpŽŸÅ6@‡'Âã¿ØÅXúU‘÷ƒ[¨(a“ ¹ÈŠMœ‡${¢Nn°þ“¥ÜÀö”»É3Aí‹Õ¾$ æØ ˜Ålä2·Àêe¯f¥+å.|6´ôM^;¥¦^$f È@NpäÛàÏc¨î u[hš3ëT^B/ñˆ*Aþ@ÎQbKczÓÓ…F§MËÑÒ hV„°_ÊÐÂË{>r.Z°ÌÆZ¯îí•3Ô¦ÃûÁ³žÃ|âaÆ/.4XA
g³¶Â?.Ð."=éj›0NpF *û Ñ„…€[ tBÈ«ÎÃ Îæuë §¦ì;ŽHÔû DÈ—üïháÉ^`·XGk»YX OH®¡ç4üá Ž¸o0¹ÉN"ô §ÎøAš@î\8Âášù@…ªbôZ呾s‘¿›N.p™|ÙpЂ¿ÓV„›è¡Ç@OÜB±à —¡^\à„ÊPF&¸ž)¡ !»Ú×Îö¶»ýíp—E@ ; geometry/vignettes/qhull/html/qh-opto.html 0000644 0001762 0000144 00000037055 14664417655 020517 0 ustar ligges users
Qhull output options
Up: Home page for Qhull (local)
Up: Qhull manual: contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
Qhull output options
This section lists the output options for Qhull. These options
are indicated by lower case characters. See Formats, Print, and Geomview for other output
options.
Copyright © 1995-2020 C.B. Barber
» Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
Output options
Qhull prints its output to standard out. All output is printed
text. The default output is a summary (option 's').
Other outputs may be specified as follows.
- f
- print all fields of all facets
- i
- print vertices incident to each facet
- m
- print Mathematica output (2-d and 3-d)
- n
- print hyperplane normals with offsets
- o
- print OFF file format (dim, points and facets)
- p
- print vertex and point coordinates
- s
- print summary to stderr
-
-
- Related options
- F
- additional input/output formats
- Ft
- print triangulation with added points
- G
- Geomview output
- P
- Print options
-
Print all fields of facetT for all facets.
The facet is the primary data structure for
Qhull.
Option 'f' is for
debugging. Most of the fields are available via the 'F' options. If you need specialized
information from Qhull, you can use the Qhull library or C++ interface.
Use the 'FF' option to print the
facets but not the ridges.
The first line is the number of facets. The remaining lines
list the vertices for each facet, one facet per line. The indices
are 0-relative indices of the corresponding input points. The
facets are oriented. Option 'Fv'
displays an unoriented list of vertices with a vertex count per
line. Options 'o' and 'Ft' displays coordinates for each
vertex prior to the vertices for each facet.
Simplicial facets (e.g., triangles in 3-d) consist of d
vertices. Non-simplicial facets in 3-d consist of 4 or more
vertices. For example, a facet of a cube consists of 4 vertices.
Use option 'Qt' to triangulate non-simplicial facets.
For 4-d and higher convex hulls and 3-d and higher Delaunay
triangulations, d vertices are listed for all facets. A
non-simplicial facet is triangulated with its centrum and each
ridge. The index of the centrum is higher than any input point.
Use option 'Fv' to list the vertices
of non-simplicial facets as is. Use option 'Ft' to print the coordinates of the
centrums as well as those of the input points. The centrum indices
for option 'i' are one more than the centrum indices for option 'Ft'.
For halfspace intersection (qhalf), a "facet"
is an intersection point and a "point" is a halfspace. Option 'i' lists the
non-redundant halfspaces incident to each intersection point.
The first line is the number of non-redundant halfspaces. Each remaining
line lists the incident, non-redundant halfspaces for that intersection point.
Qhull writes a Mathematica file for 2-d and 3-d convex hulls,
2-d and 3-d halfspace intersections,
and 2-d Delaunay triangulations. Qhull produces a list of
objects that you can assign to a variable in Mathematica, for
example: "list= << <outputfilename> ".
If the object is 2-d, it can be visualized by "Show[Graphics[list]]
". For 3-d objects the command is "Show[Graphics3D[list]]
". Now the object can be manipulated by commands of the
form "Show[%, <parametername> ->
<newvalue>]".
For Delaunay triangulation orthogonal projection is better.
This can be specified, for example, by "BoxRatios:
Show[%, BoxRatios -> {1, 1, 1e-8}]". To see the
meaningful side of the 3-d object used to visualize 2-d Delaunay,
you need to change the viewpoint: "Show[%, ViewPoint
-> {0, 0, -1}]". By specifying different viewpoints
you can slowly rotate objects.
For halfspace intersections, Qhull produces the dual
convex hull.
See Is Qhull available for Mathematica?
for URLs.
The first line is the dimension plus one. The second line is
the number of facets. The remaining lines are the normals for
each facet, one normal per line. The facet's offset follows its
normal coefficients.
The normals point outward, i.e., the convex hull satisfies Ax
<= -b where A is the matrix of coefficients and b
is the vector of offsets.
A point is inside or below a hyperplane if its distance
to the hyperplane is negative. A point is outside or above a hyperplane
if its distance to the hyperplane is positive. Otherwise a point is on or
coplanar to the hyperplane.
If cdd output is specified ('FD'),
Qhull prints the command line, the keyword "begin", the
number of facets, the dimension (plus one), the keyword
"real", and the normals for each facet. The facet's
negative offset precedes its normal coefficients (i.e., if the
origin is an interior point, the offset is positive). Qhull ends
the output with the keyword "end".
The output is:
- The first line is the dimension
- The second line is the number of points, the number of
facets, and the number of ridges.
- All of the input points follow, one per line.
- Then Qhull prints the vertices for each facet. Each facet
is on a separate line. The first number is the number of
vertices. The remainder is the indices of the
corresponding points. The vertices are oriented in 2-d,
3-d, and in simplicial facets.
Option 'Ft' prints the same
information with added points for non-simplicial facets.
Option 'i' displays vertices
without the point coordinates. Option 'p'
displays the point coordinates without vertex and facet information.
In 3-d, Geomview can load the file directly if you delete the
first line (e.g., by piping through 'tail +2').
For Voronoi diagrams (qvoronoi), option
'o' prints Voronoi vertices and Voronoi regions instead of input
points and facets. The first vertex is the infinity vertex
[-10.101, -10.101, ...]. Then, option 'o' lists the vertices in
the Voronoi region for each input site. The regions appear in
site ID order. In 2-d, the vertices of a Voronoi region are
sorted by adjacency (non-oriented). In 3-d and higher, the
Voronoi vertices are sorted by index. See the 'FN' option for listing Voronoi regions
without listing Voronoi vertices.
If you are using the Qhull library, options 'v o' have the
side effect of reordering the neighbors for a vertex.
The first line is the dimension. The second line is the number
of vertices. The remaining lines are the vertices, one vertex per
line. A vertex consists of its point coordinates
With the 'Gc' and 'Gi' options, option 'p' also prints
coplanar and interior points respectively.
For qvoronoi, it prints the
coordinates of each Voronoi vertex.
For qdelaunay, it prints the
input sites as lifted to a paraboloid. For qhalf
it prints the dual points. For both, option 'p' is the same as the first
section of option 'o'.
Use 'Fx' to list the point ids of
the extreme points (i.e., vertices).
If a subset of the facets is selected ('Pdk', 'PDk',
'Pg' options), option 'p' only
prints vertices and points associated with those facets.
If cdd-output format is selected ('FD'),
the first line is "begin". The second line is the
number of vertices, the dimension plus one, and "real".
The vertices follow with a leading "1". Output ends
with "end".
The default output of Qhull is a summary to stderr. Options 'FS' and 'Fs'
produce the same information for programs. Note: Windows 95 and 98
treats stderr the same as stdout. Use option 'TO file' to separate
stderr and stdout.
The summary lists the number of input points, the dimension,
the number of vertices in the convex hull, and the number of
facets in the convex hull. It lists the number of selected
("good") facets for options 'Pg',
'Pdk', qdelaunay,
or qvoronoi (Delaunay triangulations only
use the lower half of a convex hull). It lists the number of
coplanar points. For Delaunay triangulations without 'Qc', it lists the total number of
coplanar points. It lists the number of simplicial facets in
the output.
The terminology depends on the output structure.
The summary lists these statistics:
- number of points processed by Qhull
- number of hyperplanes created
- number of distance tests (not counting statistics,
summary, and checking)
- number of merged facets (if any)
- number of distance tests for merging (if any)
- CPU seconds to compute the hull
- the maximum joggle for 'QJ'
or, the probability of precision errors for 'QJ TRn'
- total area and volume (if computed, see 'FS' 'FA'
'Fa' 'PAn')
- max. distance of a point above a facet (if non-zero)
- max. distance of a vertex below a facet (if non-zero)
The statistics include intermediate hulls. For example 'rbox d
D4 | qhull' reports merged facets even though the final hull is
simplicial.
Qhull starts counting CPU seconds after it has read and
projected the input points. It stops counting before producing
output. In the code, CPU seconds measures the execution time of
function qhull() in libqhull.c. If the number of CPU
seconds is clearly wrong, check qh_SECticks in user.h.
The last two figures measure the maximum distance from a point
or vertex to a facet. They are not printed if less than roundoff
or if not merging. They account for roundoff error in computing
the distance (c.f., option 'Rn').
Use 'Fs' to report the maximum outer
and inner plane.
A number may appear in parentheses after the maximum distance
(e.g., 2.1x). It is the ratio between the maximum distance and
the worst-case distance due to merging two simplicial facets. It
should be small for 2-d, 3-d, and 4-d, and for higher dimensions
with 'Qx'. It is not printed if less
than 0.05.
Up: Home page for Qhull (local)
Up: Qhull manual: contents
To: Programs
Options
Output
Formats
Geomview
Print
Qhull
Precision
Trace
Functions (local)
The Geometry Center
Home Page
Comments to: qhull@qhull.org
Created: Sept. 25, 1995 --- Last modified: see top
geometry/vignettes/qhull/html/qh--rand.gif 0000644 0001762 0000144 00000007443 13431000556 020311 0 ustar ligges users GIF87ad d ç =*2-E>,^0GI*c‹cNk_(*&Ø×Ö^?DN2A…>L0Be(E@Io¥Jn¥I6-LFƒ‡uBm+‘Ž:DU2)VT!‹~_ Iƒ!F>99=;`G #(5"nW]„hl¦§¡AN aˆ]üüüøøø/D"E4fŽesjaEPF[I*1'RVv *fFŽBƒFIML4L*:#_@DK2-fmoM+²±³U9+$DN=}uuUL&??=%)F$B‚U<;?|[ÌÊÉ5?4>-E;K8‚7'F …‘ƒ4j{ov=eF5z4tzet+UGTF8l7:TMX}<ëëç9[BO:#'*UlC63(ng*7f".b-d”-2hA3„GŽ„F`XeHETH:^N+Sie?`:3ZK2M[]L…©¬©ÞÝÝ4\";'†Mk_hI;VK<:iG[.“‡†[vR<4-BFtydV>J1#'6@9E :&jc,C89T'yeUe•-t@CcV2ht:-;?¼²±3RRRsBGJ>E-GT*zqEfŽfr…)>L!RfO>yE|wJZ|ZL(Z)04@*+…†‹7..Q2FIMT`)3 8‚87€7b‘3%:ÿÿÿ(/W,M3ilDg^xc`õõõž˜™V;8@B@`JOïïï2A=ˆ›tjZˆAu‰*…G·¹·`Ye5(N‘+\h Ô , d d þ ‰ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0c†|&3¥²Êéª2ˆÁ*ÒjÎÄ©³W<}œ(Æ)C†jW„^”6&ß•+ŒÊ•»’o£mkÊu†J&§NOU¡)U¢²mÊ^»¢‹¡5>è§Z´œäkK‘Èã̆A6FæôøKù”.•-Óeޱ>}ccbnËŒ[~)ÿŤ+.f…W¶„ý9ôhl·äŒP²D5e9[®½FxmÜšÚ´iƒ+R$
¤ÐåxñýWŽ.wÃ1'ã(íÆ Áþõ&