## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)
library(hexify)

## ----cover-image, echo=FALSE, message=FALSE, warning=FALSE, fig.width=8, fig.height=4, fig.align='center'----
# Generate cover image: multi-resolution grids over different regions
library(sf)
library(ggplot2)

# Get world basemap
countries <- hexify_world

# Generate grids at different resolutions for specific regions (coarser for speed)
# Coarse grid: South America
grid_sa <- hex_grid(area_km2 = 300000)
sa_hexes <- grid_rect(c(-80, -40, -35, 10), grid_sa)

# Medium grid: Europe/Africa
grid_eu <- hex_grid(area_km2 = 80000)
eu_hexes <- grid_rect(c(-10, -10, 40, 50), grid_eu)

# Fine grid: East Asia
grid_asia <- hex_grid(area_km2 = 50000)
asia_hexes <- grid_rect(c(90, 10, 140, 50), grid_asia)

ggplot() +
  geom_sf(data = countries, fill = "gray95", color = "gray80", linewidth = 0.15) +
  geom_sf(data = sa_hexes, fill = NA, color = "#1B9E77", linewidth = 0.5) +
  geom_sf(data = eu_hexes, fill = NA, color = "#D95F02", linewidth = 0.4) +
  geom_sf(data = asia_hexes, fill = NA, color = "#7570B3", linewidth = 0.3) +
  coord_sf(xlim = c(-100, 150), ylim = c(-50, 60)) +
  theme_void() +
  theme(panel.background = element_rect(fill = "white", color = NA))

## ----basic-usage--------------------------------------------------------------
# Sample data: European cities
cities <- data.frame(
  name = c("Vienna", "Paris", "Madrid", "Berlin", "Rome"),
  lon = c(16.37, 2.35, -3.70, 13.40, 12.50),
  lat = c(48.21, 48.86, 40.42, 52.52, 41.90)
)

# Create a grid specification
grid <- hex_grid(area_km2 = 10000)
grid

# Assign cities to hexagonal cells
result <- hexify(cities, lon = "lon", lat = "lat", grid = grid)
result

## ----hexdata-access-----------------------------------------------------------
# Get the grid specification
grid_info(result)

# Get unique cell IDs
cells(result)

# Count unique cells
n_cells(result)

# Access all cell IDs (one per row)
result@cell_id

# Access cell centers
head(result@cell_center)

# Extract original data as data.frame
head(as.data.frame(result))

## ----sf-usage, eval = requireNamespace("sf", quietly = TRUE)------------------
library(sf)

# Create sf object (any CRS works - hexify transforms automatically)
pts <- st_as_sf(cities, coords = c("lon", "lat"), crs = 4326)

# hexify handles CRS transformation automatically
result_sf <- hexify(pts, area_km2 = 10000)
class(result_sf)

## ----bird-setup, message=FALSE, warning=FALSE---------------------------------
library(sf)
library(ggplot2)

# Simulate bird observation data (reduced for faster vignette build)
set.seed(123)
n_obs <- 500

# Generate observations with realistic spatial clustering
birds <- data.frame(
  lon = c(
    rnorm(150, mean = 10, sd = 15),    # Western Europe
    rnorm(100, mean = 25, sd = 10),    # Eastern Europe
    rnorm(100, mean = 20, sd = 20),    # Mediterranean
    rnorm(80, mean = 0, sd = 15),      # West Africa
    rnorm(70, mean = 35, sd = 10)      # East Africa
  ),
  lat = c(
    rnorm(150, mean = 50, sd = 8),     # Western Europe
    rnorm(100, mean = 55, sd = 6),     # Eastern Europe
    rnorm(100, mean = 42, sd = 5),     # Mediterranean
    rnorm(80, mean = 10, sd = 10),     # West Africa
    rnorm(70, mean = -5, sd = 12)      # East Africa
  ),
  species = sample(c("Passer domesticus", "Turdus merula", "Parus major",
                     "Columba palumbus", "Sturnus vulgaris"), n_obs, replace = TRUE)
)

# Clip to valid ranges
birds$lon <- pmax(-30, pmin(60, birds$lon))
birds$lat <- pmax(-35, pmin(70, birds$lat))

## ----bird-assign--------------------------------------------------------------
# Create grid and assign observations (coarser grid for faster build)
grid <- hex_grid(area_km2 = 50000)
birds_hex <- hexify(birds, lon = "lon", lat = "lat", grid = grid)

# Extract data with cell IDs
birds_gridded <- as.data.frame(birds_hex)
birds_gridded$cell_id <- birds_hex@cell_id

# Count observations per cell
obs_counts <- aggregate(
  species ~ cell_id,
  data = birds_gridded,
  FUN = length
)
names(obs_counts)[2] <- "n_observations"

# Species richness per cell
richness <- aggregate(
  species ~ cell_id,
  data = birds_gridded,
  FUN = function(x) length(unique(x))
)
names(richness)[2] <- "n_species"

obs_counts <- merge(obs_counts, richness, by = "cell_id")
head(obs_counts)

## ----bird-plot, fig.width=8, fig.height=6, message=FALSE, warning=FALSE-------
# Generate polygons for cells with data
cell_polys <- cell_to_sf(obs_counts$cell_id, grid)
cell_polys <- merge(cell_polys, obs_counts, by = "cell_id")

# Get relevant countries
region <- hexify_world[hexify_world$continent %in% c("Europe", "Africa"), ]

ggplot() +
  geom_sf(data = region, fill = "gray95", color = "gray70", linewidth = 0.2) +
  geom_sf(data = cell_polys, aes(fill = n_observations), color = "white", linewidth = 0.3) +
  scale_fill_viridis_c(option = "plasma", name = "Observations", trans = "sqrt") +
  coord_sf(xlim = c(-30, 60), ylim = c(-35, 70)) +
  labs(
    title = "Bird Observations in Equal-Area Hexagonal Cells",
    subtitle = sprintf("ISEA3H grid at resolution %d (~%.0f km² cells)",
                       grid@resolution, grid@area_km2)
  ) +
  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_line(color = "gray90")
  )

## ----richness-plot, fig.width=8, fig.height=6, message=FALSE------------------
ggplot() +
  geom_sf(data = region, fill = "gray95", color = "gray70", linewidth = 0.2) +
  geom_sf(data = cell_polys, aes(fill = n_species), color = "white", linewidth = 0.3) +
  scale_fill_viridis_c(option = "mako", name = "Species\nRichness", direction = -1) +
  coord_sf(xlim = c(-30, 60), ylim = c(-35, 70)) +
  labs(
    title = "Species Richness per Grid Cell",
    subtitle = "Number of unique species observed in each equal-area cell"
  ) +
  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.ticks = element_blank(),
    panel.grid = element_line(color = "gray90")
  )

