tests/testthat/test-geocentric.R

test_that("geocentric_fwd works with single point", {
  result <- geocentric_fwd(c(0, 0))
  
  expect_s3_class(result, "data.frame")
  expect_named(result, c("X", "Y", "Z", "lon", "lat", "h"))
  expect_equal(nrow(result), 1)
  
  # At equator/prime meridian, X should be ~6378km, Y and Z should be 0
  expect_equal(result$X, 6378137, tolerance = 1)
  expect_equal(result$Y, 0, tolerance = 1)
  expect_equal(result$Z, 0, tolerance = 1)
})

test_that("geocentric_fwd works at poles", {
  # North pole
  north <- geocentric_fwd(c(0, 90))
  expect_equal(north$X, 0, tolerance = 1)
  expect_equal(north$Y, 0, tolerance = 1)
  expect_true(north$Z > 6350000)  # Semi-minor axis
  
 # South pole
  south <- geocentric_fwd(c(0, -90))
  expect_equal(south$X, 0, tolerance = 1)
  expect_equal(south$Y, 0, tolerance = 1)
  expect_true(south$Z < -6350000)
})

test_that("geocentric_fwd works with multiple points", {
  pts <- cbind(lon = c(0, 90, 180, -90), lat = c(0, 0, 0, 0))
  result <- geocentric_fwd(pts)
  
  expect_equal(nrow(result), 4)
  
  # At equator, radius should be constant
  r <- sqrt(result$X^2 + result$Y^2 + result$Z^2)
  expect_equal(r, rep(6378137, 4), tolerance = 1)
})

test_that("geocentric_fwd handles height", {
  result_0 <- geocentric_fwd(c(0, 0), h = 0)
  result_1000 <- geocentric_fwd(c(0, 0), h = 1000)
  
  # X should increase by 1000m
  expect_equal(result_1000$X - result_0$X, 1000, tolerance = 0.01)
})

test_that("geocentric_fwd accepts different input formats", {
  result1 <- geocentric_fwd(c(10, 45))
  result2 <- geocentric_fwd(cbind(10, 45))
  result3 <- geocentric_fwd(list(lon = 10, lat = 45))
  
  expect_equal(result1$X, result2$X)
  expect_equal(result1$X, result3$X)
})

test_that("geocentric_rev returns correct structure", {
  result <- geocentric_rev(6378137, 0, 0)
  
  expect_s3_class(result, "data.frame")
  expect_named(result, c("lon", "lat", "h", "X", "Y", "Z"))
  expect_equal(nrow(result), 1)
})

test_that("geocentric_rev is vectorized", {
  X <- c(6378137, 0, -6378137)
  Y <- c(0, 6378137, 0)
  Z <- c(0, 0, 0)
  result <- geocentric_rev(X, Y, Z)
  
  expect_equal(nrow(result), 3)
  expect_equal(result$lat, c(0, 0, 0), tolerance = 1e-6)
  expect_equal(result$lon, c(0, 90, 180), tolerance = 1e-6)
})

test_that("geocentric round-trip preserves location", {
  pts <- cbind(lon = c(-0.1, 147, -74), lat = c(51.5, -42, 40.7))
  h <- c(100, 500, 0)
  
  fwd <- geocentric_fwd(pts, h = h)
  rev <- geocentric_rev(fwd$X, fwd$Y, fwd$Z)
  
  expect_equal(rev$lon, pts[, 1], tolerance = 1e-9)
  expect_equal(rev$lat, pts[, 2], tolerance = 1e-9)
  expect_equal(rev$h, h, tolerance = 1e-6)
})

test_that("geocentric handles extreme heights", {
  # GPS satellite altitude ~20,000 km
  result <- geocentric_fwd(c(0, 0), h = 20000000)
  
  expect_true(result$X > 26000000)
  
  # Round-trip
  rev <- geocentric_rev(result$X, result$Y, result$Z)
  expect_equal(rev$h, 20000000, tolerance = 1)
})

Try the geographiclib package in your browser

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

geographiclib documentation built on March 4, 2026, 9:07 a.m.