tests/testthat/test-icosahedron.R

# tests/testthat/test-icosahedron.R
# Tests for icosahedron construction and face detection
#
# Functions tested:
# - hexify_build_icosa()
# - hexify_face_centers()
# - hexify_which_face()

# =============================================================================
# ICOSAHEDRON CONSTRUCTION
# =============================================================================

test_that("icosahedron builds successfully with default orientation", {
  expect_no_error(hexify_build_icosa())
})

test_that("icosahedron builds with custom orientation", {
  # ISEA3H default orientation
  expect_no_error(hexify_build_icosa(11.25, 58.28252559, 0))

  # Alternative orientations
  expect_no_error(hexify_build_icosa(0, 58.28252559, 0))
  expect_no_error(hexify_build_icosa(11.25, 58.28252559, 45))
})

# =============================================================================
# FACE CENTERS
# =============================================================================

test_that("face_centers returns 20 faces with valid coordinates", {
  hexify_build_icosa()

  centers <- hexify_face_centers()

  expect_equal(nrow(centers), 20)
  expect_true("lon" %in% names(centers))
  expect_true("lat" %in% names(centers))

  # All coordinates should be finite
  expect_true(all(is.finite(centers$lon)))
  expect_true(all(is.finite(centers$lat)))

  # Valid coordinate ranges
  expect_true(all(centers$lon >= -180 & centers$lon <= 180))
  expect_true(all(centers$lat >= -90 & centers$lat <= 90))
})

test_that("face centers span the globe", {
  hexify_build_icosa()
  centers <- hexify_face_centers()

  # Should have faces in both hemispheres
  expect_true(any(centers$lat > 0))
  expect_true(any(centers$lat < 0))

  # Should have faces across longitude range
  # Note: coordinates may be in radians (range ~[-pi, pi]) or degrees
  lon_range <- max(centers$lon) - min(centers$lon)
  expect_true(lon_range > 2.0)  # Works for both radians (~5.5 rad) and degrees (>100°)
})

# =============================================================================
# FACE DETECTION (which_face)
# =============================================================================

test_that("which_face returns valid face numbers", {
  hexify_build_icosa()

  test_points <- data.frame(
    lon = c(0, 90, -90, 180, 0, 0),
    lat = c(0, 0, 0, 0, 45, -45)
  )

  for (i in seq_len(nrow(test_points))) {
    face <- hexify_which_face(test_points$lon[i], test_points$lat[i])
    expect_true(face >= 0 && face <= 19,
                info = sprintf("lon=%.2f, lat=%.2f",
                              test_points$lon[i], test_points$lat[i]))
  }
})

test_that("which_face is deterministic", {
  hexify_build_icosa()

  lon <- 16.37
  lat <- 48.21

  face1 <- hexify_which_face(lon, lat)
  face2 <- hexify_which_face(lon, lat)

  expect_equal(face1, face2)
})

test_that("which_face handles extreme coordinates", {
  hexify_build_icosa()

  # Near poles
  expect_true(hexify_which_face(0, 89.9999) %in% 0:19)
  expect_true(hexify_which_face(0, -89.9999) %in% 0:19)

  # Near antimeridian
  expect_true(hexify_which_face(179.9999, 0) %in% 0:19)
  expect_true(hexify_which_face(-179.9999, 0) %in% 0:19)
})

test_that("which_face matches reference data", {
  hexify_build_icosa()

  truth <- read.csv(testthat::test_path("data/truth_faces.csv"))
  expect_true(all(c("lon", "lat", "tnum") %in% names(truth)))

  mismatches <- 0L
  msgs <- character()

  for (i in seq_len(nrow(truth))) {
    got <- hexify_which_face(truth$lon[i], truth$lat[i])
    if (got != truth$tnum[i]) {
      mismatches <- mismatches + 1L
      if (mismatches <= 5L) {
        msgs <- c(msgs, sprintf(
          "row %d: got %d vs expected %d (lon=%.9f lat=%.9f)",
          i, got, truth$tnum[i], truth$lon[i], truth$lat[i]
        ))
      }
    }
  }

  if (mismatches > 0L) {
    message(paste(msgs, collapse = "\n"))
  }
  expect_equal(mismatches, 0L)
})

# =============================================================================
# FACE CENTER CONSISTENCY
# =============================================================================

test_that("face center detection returns valid faces", {
  hexify_build_icosa()
  centers <- hexify_face_centers()

  # Face center detection may return a different face due to numerical
  # precision at face boundaries (this is expected behavior).
  # We just verify that valid faces are returned.
  for (face in 0:19) {
    detected <- hexify_which_face(centers$lon[face + 1], centers$lat[face + 1])
    expect_true(detected >= 0 && detected <= 19,
                info = sprintf("Face center %d returned valid face %d", face, detected))
  }
})

Try the hexify package in your browser

Any scripts or data that you put into this service are public.

hexify documentation built on March 1, 2026, 1:07 a.m.