Nothing
# Create dummy occluders
occluders_geom <- sf::st_sfc(
create_occluder(1, 1, 1, 0.5),
create_occluder(4, 1, 1.5, 0.7),
create_occluder(7, 1, 0.8, 0.8),
create_occluder(2, 5, 2, 1),
create_occluder(5, 5, 1, 1.5),
create_occluder(1, 7, 1.2, 0.6),
create_occluder(7, 7, 1.8, 0.9)
)
occluders <- sf::st_sf(id = 1:7, geometry = occluders_geom)
# Create dummy line
line_geom <- sf::st_sfc(
sf::st_linestring(matrix(c(0, 3, 9, 3), ncol = 2, byrow = TRUE))
)
line <- sf::st_sf(id = 1, geometry = line_geom)
test_that("the correct number of viewpoints is created", {
density <- 1
vpoints <- get_viewpoints(sf::st_geometry(line), density = density)
expect_equal(length(vpoints), ceiling(sf::st_length(line) * density))
})
test_that("density of viewpoints is a non-zero positive number", {
expect_error(get_viewpoints(line, density = 0))
expect_error(get_viewpoints(line, density = -1.3))
})
test_that("input cannot be a POINT or MULTIPOINT", {
expect_error(get_viewpoints(sf::st_point(c(1, 1))))
expect_error(get_viewpoints(
sf::st_multipoint(matrix(c(1, 1, 2, 2), ncol = 2, byrow = TRUE))
))
})
test_that("POLYGON input is converted to LINESTRING", {
density <- 1
line <- sf::st_sf(geometry = sf::st_sfc(sf::st_polygon(
list(rbind(c(0, 0), c(0, 1), c(1, 1), c(1, 0), c(0, 0)))
)))
# Get viewpoints with POLYGON as input
vpoints <- get_viewpoints(line, density = density)
# Cast to LINESTRING to allow for length calculation
line <- sf::st_cast(line, "MULTILINESTRING") |>
sf::st_cast("LINESTRING")
expect_equal(length(vpoints), ceiling(sf::st_length(line) * density))
})
test_that("An isovist is properly constructed for a single viewpoint", {
viewpoint <- sf::st_sfc(sf::st_point(c(6, 3)))
ray_length <- 5
isovist <- get_isovist(viewpoint, occluders, ray_length = ray_length)
expect_true(inherits(isovist, "sfc"))
expect_equal(length(isovist), 1)
expect_true(sf::st_is(isovist, "POLYGON"))
# isovist should be smaller than unoccluded buffer
buffer <- sf::st_buffer(viewpoint, ray_length)
expect_true(sf::st_contains(buffer, isovist, sparse = FALSE))
})
test_that("An isovist is properly constructed for multiple viewpoints", {
viewpoints <- sf::st_cast(sf::st_sample(line_geom, 3), "POINT")
ray_length <- 5
isovist <- get_isovist(viewpoints, occluders, ray_length = ray_length)
expect_true(inherits(isovist, "sfc"))
expect_equal(length(isovist), 1)
expect_true(sf::st_is(isovist, "POLYGON"))
# isovist should be smaller than unoccluded buffer
buffer <- sf::st_union(sf::st_buffer(viewpoints, ray_length))
expect_true(sf::st_contains(buffer, isovist, sparse = FALSE))
})
test_that("Rays are properly constructed from a list of viewpoints", {
ray_length <- 1
ray_num <- 160
viewpoints <- sf::st_sfc(
sf::st_point(c(0, 1)), sf::st_point(c(1, 1)), sf::st_point(c(1, 0))
)
rays <- get_rays(viewpoints, ray_num = ray_num, ray_length = ray_length)
expect_equal(nrow(rays), length(viewpoints) * ray_num)
expect_true(all(sf::st_is(rays, "LINESTRING")))
expect_contains(sf::st_length(rays), ray_length)
})
test_that("Rays construction fails for incorrect input arguments", {
ray_length <- 1
ray_num <- 160
viewpoints <- sf::st_sfc(
sf::st_point(c(0, 1)), sf::st_point(c(1, 1)), sf::st_point(c(1, 0))
)
expect_no_error(get_rays(viewpoints, ray_num = ray_num,
ray_length = ray_length))
# ray_num must be a whole number
expect_error(get_rays(viewpoints, ray_num = 0.1, ray_length = ray_length))
# ray_length must be positive
expect_error(get_rays(viewpoints, ray_num = ray_num, ray_length = 0))
# viewpoints must consist of point geometries
expect_error(get_rays(line, ray_num = ray_num, ray_length = 0))
})
test_that("The number of rays are rounded to the closest multiple of four", {
viewpoint <- sf::st_sfc(sf::st_point(c(0, 1)))
# Multiple of four, no warning
ray_num <- 40
expect_no_warning(get_rays(viewpoint, ray_num = ray_num))
# Expect warning otherwise
ray_num <- 41 # round down to 40
expect_warning(get_rays(viewpoint, ray_num = ray_num), "40")
ray_num <- 43 # round up to 44
expect_warning(get_rays(viewpoint, ray_num = ray_num), "44")
})
test_that("Occluding rays without occluders return untouched rays", {
ray_geoms <- sf::st_sfc(
sf::st_linestring(cbind(c(0, 1), c(0, 0))),
sf::st_linestring(cbind(c(0, 0), c(0, 1))),
sf::st_linestring(cbind(c(0, -1), c(0, 0))),
sf::st_linestring(cbind(c(0, 0), c(0, -1)))
)
rays <- sf::st_as_sf(ray_geoms)
occluded_rays <- occlude_rays(rays)
expect_setequal(ray_geoms, sf::st_geometry(occluded_rays))
})
test_that("Occluding rays with a polygon returns modified rays", {
ray_geoms <- sf::st_sfc(
sf::st_linestring(cbind(c(0, 0), c(0, 1))),
sf::st_linestring(cbind(c(0, 1), c(0, 0))),
sf::st_linestring(cbind(c(0, -1), c(0, 0))),
sf::st_linestring(cbind(c(0, 0), c(0, -1)))
)
rays <- sf::st_as_sf(ray_geoms)
occluder <- create_occluder(-0.5, 0, 0.2, 0.2)
actual <- occlude_rays(rays, occluders = occluder)
expected <- sf::st_sfc(
sf::st_linestring(cbind(c(0, 1), c(0, 0))),
sf::st_linestring(cbind(c(0, 0), c(0, 1))),
sf::st_linestring(cbind(c(0, -0.4), c(0, 0))),
sf::st_linestring(cbind(c(0, 0), c(0, -1)))
)
expect_setequal(sf::st_geometry(actual), expected)
})
test_that("get_isovists transforms rays to polygons", {
center_isovist_1 <- sf::st_point(c(0, 0))
points_isovist_1 <- sf::st_sfc(
sf::st_point(c(0, 1)), sf::st_point(c(1, 0)),
sf::st_point(c(0, -1)), sf::st_point(c(-1, 0))
)
center_isovist_2 <- sf::st_point(c(2, 0))
points_isovist_2 <- sf::st_sfc(
sf::st_point(c(2, 1)), sf::st_point(c(3, 0)), sf::st_point(c(2, -1))
)
ray_geoms <- sf::st_sfc(
sf::st_linestring(c(center_isovist_1, points_isovist_1[[1]])),
sf::st_linestring(c(center_isovist_1, points_isovist_1[[2]])),
sf::st_linestring(c(center_isovist_1, points_isovist_1[[3]])),
sf::st_linestring(c(center_isovist_1, points_isovist_1[[4]])),
sf::st_linestring(c(center_isovist_2, points_isovist_2[[1]])),
sf::st_linestring(c(center_isovist_2, points_isovist_2[[2]])),
sf::st_linestring(c(center_isovist_2, points_isovist_2[[3]]))
)
rays <- sf::st_as_sf(ray_geoms)
rays["isovist_id"] <- c(1, 1, 1, 1, 2, 2, 2)
isovists <- get_isovists(rays)
# Check that the isovist boundaries contain all original points
expect_setequal(sf::st_cast(isovists[1], "POINT"), points_isovist_1)
expect_setequal(sf::st_cast(isovists[2], "POINT"), points_isovist_2)
})
test_that("merge_isovists returns the merged polygon, with or without holes", {
isovist_1 <- sf::st_buffer(sf::st_point(c(0, 0)), 2)
isovist_2 <- sf::st_buffer(sf::st_point(c(2, 0)), 2)
hole <- sf::st_buffer(sf::st_point(c(-1, 0)), 0.5)
isovist_1_hole <- sf::st_difference(isovist_1, hole)
isovists <- sf::st_sfc(isovist_1, isovist_2)
isovists_hole <- sf::st_sfc(isovist_1_hole, isovist_2)
# if remove_holes is FALSE, hole remains
actual <- merge_isovists(isovists_hole, remove_holes = FALSE)
expected <- sf::st_union(isovists_hole)
expect_equal(actual, expected)
# if remove_holes is TRUE, hole is removed
actual <- merge_isovists(isovists_hole, remove_holes = TRUE)
expected <- sf::st_union(isovists)
expect_equal(actual, expected)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.