---
title: "Getting Started with mapycusmaximus"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting Started with mapycusmaximus}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5,
  fig.align = "center",
  message = FALSE,
  warning = FALSE
)
```

## Introduction

**mapycusmaximus** brings fisheye transformations to R's spatial ecosystem. Just as `ggplot2` transforms how we visualize data and `dplyr` transforms how we manipulate it, mapycusmaximus transforms how we view geographic space—allowing you to magnify local detail while preserving regional context.

The package implements the **Focus-Glue-Context (FGC)** model, a three-zone radial transformation that:

- **Magnifies** features in the focus region (like zooming in)
- **Smoothly transitions** through the glue zone (preventing jarring distortions)
- **Preserves** the outer context (maintaining geographic orientation)

This vignette will show you how to use mapycusmaximus with real spatial data, following tidyverse principles of working with data.

```{r setup}
library(mapycusmaximus)
library(sf)
library(ggplot2)

# Use a minimal theme for clean visualizations
theme_set(theme_minimal())
```

## Your First Fisheye

Let's start with the built-in Victoria LGA dataset. The goal is to magnify Melbourne while keeping the rest of Victoria visible.

```{r first-fisheye}
# Examine the data
data(vic)
vic
```

The simplest fisheye uses defaults and automatically determines the center:

```{r simple-fisheye, fig.cap = "A basic fisheye transformation of Victoria's LGAs"}
# Apply fisheye transformation
vic_warped <- sf_fisheye(
  vic,
  r_in = 0.3,        # Focus radius
  r_out = 0.6,       # Glue boundary
  zoom_factor = 2,   # Magnification strength
  squeeze_factor = 0.35
)

# Visualize with ggplot2
ggplot(vic_warped) +
  geom_sf(fill = "grey90", color = "white", linewidth = 0.3) +
  labs(title = "Victoria LGAs with Default Fisheye")
```

That's it! But to really control the transformation, you'll want to specify a focus point.

## Specifying the Focus Point

The fisheye center determines what gets magnified. There are several ways to specify it:

### Using a Geometry

The most natural approach—pass an `sf` object and mapycusmaximus uses its centroid:

```{r center-geometry, fig.cap = "Fisheye centered on Melbourne CBD"}
# Extract Melbourne CBD as the focus
melbourne <- vic[vic$LGA_NAME == "MELBOURNE", ]

vic_melbourne <- sf_fisheye(
  vic,
  center = melbourne,      # Centroid becomes the warp center
  r_in = 0.34,
  r_out = 0.60,
  zoom_factor = 15,
  squeeze_factor = 0.35
)

ggplot() +
  geom_sf(data = vic_melbourne, fill = "grey92", color = "white", linewidth = 0.2) +
  geom_sf(data = melbourne, fill = NA, color = "tomato", linewidth = 0.8) +
  labs(title = "Melbourne CBD Magnified",
       subtitle = "Focus defined by Melbourne LGA geometry")
```

### Using Longitude/Latitude

Specify coordinates directly in WGS84:

```{r center-lonlat, fig.cap = "Fisheye using lon/lat coordinates"}
# Melbourne CBD coordinates (WGS84)
melb_coords <- c(144.9631, -37.8136)

vic_coords <- sf_fisheye(
  vic,
  center = melb_coords,
  center_crs = "EPSG:4326",   # Explicitly state CRS
  r_in = 0.30,
  r_out = 0.55,
  zoom_factor = 12,
  squeeze_factor = 0.30
)

ggplot(vic_coords) +
  geom_sf(fill = "grey92", color = "white", linewidth = 0.2) +
  labs(title = "Center Specified as Lon/Lat",
       subtitle = "Coordinates: 144.96°E, 37.81°S")
```

### Using Projected Coordinates

If you're already working in a projected CRS, pass coordinates directly:

```{r center-projected, eval = FALSE}
# Example: coordinates in the working CRS (meters)
vic_projected <- sf_fisheye(
  vic,
  cx = 321000,      # Easting (meters)
  cy = 5813000,     # Northing (meters)
  r_in = 0.3,
  r_out = 0.6,
  zoom_factor = 10,
  squeeze_factor = 0.35
)
```

## Understanding Parameters

The transformation is controlled by four key parameters:

### Focus and Glue Radii

`r_in` and `r_out` define the transformation zones in **normalized space** (roughly -1 to 1):

```{r parameter-demo-radii, fig.cap = "Effect of different radius settings", fig.height = 6}
# Small focus, narrow glue
vic_tight <- sf_fisheye(vic, center = melbourne, r_in = 0.2, r_out = 0.3, 
                        zoom_factor = 8, squeeze_factor = 0.35)

# Large focus, wide glue
vic_wide <- sf_fisheye(vic, center = melbourne, r_in = 0.4, r_out = 0.7, 
                       zoom_factor = 8, squeeze_factor = 0.35)

p1 <- ggplot(vic_tight) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Tight Focus (r_in=0.2, r_out=0.3)")

p2 <- ggplot(vic_wide) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Wide Focus (r_in=0.4, r_out=0.7)")

# Display side by side (requires patchwork or cowplot)
# p1 + p2
p1
p2
```

### Zoom Factor

Controls magnification strength inside the focus:

```{r parameter-demo-zoom, fig.cap = "Effect of zoom factor", fig.height = 6}
# Gentle zoom
vic_gentle <- sf_fisheye(vic, center = melbourne, r_in = 0.3, r_out = 0.5, 
                         zoom_factor = 3, squeeze_factor = 0.35)

# Aggressive zoom
vic_aggressive <- sf_fisheye(vic, center = melbourne, r_in = 0.3, r_out = 0.5, 
                             zoom_factor = 20, squeeze_factor = 0.35)

ggplot(vic_gentle) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Gentle Magnification (zoom = 3)")

ggplot(vic_aggressive) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Strong Magnification (zoom = 20)")
```

### Squeeze Factor

Controls compression in the glue zone (0 to 1):

```{r parameter-demo-squeeze, fig.height = 6}
# Minimal squeeze (wider glue transition)
vic_loose <- sf_fisheye(vic, center = melbourne, r_in = 0.3, r_out = 0.5, 
                        zoom_factor = 8, squeeze_factor = 0.1)

# Strong squeeze (narrow glue transition)
vic_tight_squeeze <- sf_fisheye(vic, center = melbourne, r_in = 0.3, r_out = 0.5, 
                                zoom_factor = 8, squeeze_factor = 0.8)

ggplot(vic_loose) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Loose Squeeze (0.1)")

ggplot(vic_tight_squeeze) + 
  geom_sf(fill = "grey90", color = "white", linewidth = 0.2) +
  labs(title = "Tight Squeeze (0.8)")
```

## Working with Multiple Layers

When you have multiple layers (points, lines, polygons), transform them together to ensure alignment:

```{r multi-layer, fig.cap = "Multiple aligned layers with fisheye transformation"}
# Create centroids as a point layer
centroids <- st_centroid(vic)

# Add a layer identifier to each
vic_layer <- vic |> 
  dplyr::mutate(layer = "polygon")

centroids_layer <- centroids |> 
  dplyr::mutate(layer = "centroid")

# Combine layers before transformation
both_layers <- rbind(
  vic_layer[, c("LGA_NAME", "geometry", "layer")],
  centroids_layer[, c("LGA_NAME", "geometry", "layer")]
)

# Apply fisheye once to combined data
both_warped <- sf_fisheye(
  both_layers,
  center = melbourne,
  r_in = 0.34,
  r_out = 0.60,
  zoom_factor = 12,
  squeeze_factor = 0.35
)

# Separate for plotting
polygons_warped <- both_warped[both_warped$layer == "polygon", ]
points_warped <- both_warped[both_warped$layer == "centroid", ]

# Plot together
ggplot() +
  geom_sf(data = polygons_warped, fill = "grey92", color = "white", 
          linewidth = 0.2) +
  geom_sf(data = points_warped, color = "#2b6cb0", size = 1.2, alpha = 0.7) +
  labs(title = "Aligned Layers: Polygons and Centroids",
       subtitle = "Transformed together to ensure perfect alignment")
```

**Why combine first?** When layers are transformed separately, they may have different bounding boxes, leading to slightly different normalized coordinates and misalignment.

## Projection Handling

mapycusmaximus is projection-aware and handles CRS transformations automatically:

### Geographic to Projected

If your data is in longitude/latitude, the package automatically selects an appropriate projected CRS:

```{r crs-handling}
# Create data in WGS84
vic_lonlat <- st_transform(vic, "EPSG:4326")
st_crs(vic_lonlat)$proj4string

# Apply fisheye - auto-projects to GDA2020/MGA55 for Victoria
vic_auto <- sf_fisheye(
  vic_lonlat,
  center = melbourne,
  r_in = 0.3,
  r_out = 0.5,
  zoom_factor = 10,
  squeeze_factor = 0.35
)

# Original CRS is restored
st_crs(vic_auto)$proj4string
```

The package uses sensible defaults:
- Victoria region → **EPSG:7855** (GDA2020 / MGA Zone 55)
- Other areas → **UTM** zones based on centroid

### Custom Projection

Override the automatic selection with `target_crs`:

```{r custom-crs, eval = FALSE}
vic_custom <- sf_fisheye(
  vic_lonlat,
  center = melbourne,
  target_crs = "EPSG:3111",  # VicGrid
  r_in = 0.3,
  r_out = 0.5,
  zoom_factor = 10,
  squeeze_factor = 0.35
)
```

## Advanced: Grid Diagnostics

For understanding the transformation itself, use the low-level `fisheye_fgc()` function with test grids:

```{r diagnostics, fig.cap = "Understanding the FGC transformation with a test grid", fig.width = 8, fig.height = 4}
# Create a regular grid
grid <- create_test_grid(range = c(-1, 1), spacing = 0.1)

# Apply transformation
warped <- fisheye_fgc(
  grid,
  r_in = 0.34,
  r_out = 0.5,
  zoom_factor = 1.3,
  squeeze_factor = 0.5
)

# Visualize the transformation
plot_fisheye_fgc(grid, warped, r_in = 0.34, r_out = 0.5)
```

The visualization shows:
- **Red zone**: Focus (magnified)
- **Blue zone**: Glue (transitional compression)
- **Yellow zone**: Context (unchanged)

## Real-World Example: Metropolitan Focus

Here's a complete workflow showing how to emphasize a metro area while maintaining state context:

```{r real-world-example, fig.cap = "Complete workflow: Metropolitan Melbourne in Victorian context", fig.width = 8}
# 1. Define the metropolitan region
metro_lgas <- c("MELBOURNE", "PORT PHILLIP", "STONNINGTON", "YARRA", 
                "MARIBYRNONG", "MOONEE VALLEY", "BOROONDARA", 
                "GLEN EIRA", "BAYSIDE")

metro_region <- vic[vic$LGA_NAME %in% metro_lgas, ]
metro_center <- st_union(metro_region) |> st_centroid()

# 2. Add a population indicator (example)
vic_pop <- vic |> 
  dplyr::mutate(is_metro = LGA_NAME %in% metro_lgas)

# 3. Apply fisheye
vic_focused <- sf_fisheye(
  vic_pop,
  center = metro_center,
  r_in = 0.25,
  r_out = 0.40,
  zoom_factor = 12,
  squeeze_factor = 0.35
)

# 4. Create publication-ready plot
ggplot(vic_focused) +
  geom_sf(aes(fill = is_metro), color = "white", linewidth = 0.2) +
  scale_fill_manual(
    values = c("TRUE" = "#d95f02", "FALSE" = "grey85"),
    labels = c("Metropolitan", "Regional"),
    name = NULL
  ) +
  theme_minimal() +
  theme(
    legend.position = c(0.85, 0.15),
    legend.background = element_rect(fill = "white", color = "grey70"),
    panel.grid = element_blank()
  ) +
  labs(
    title = "Metropolitan Melbourne with Regional Context",
    subtitle = "Fisheye magnification preserves spatial relationships",
    caption = "Transformation: r_in = 0.25, r_out = 0.40, zoom = 12"
  )
```

## Best Practices

### Parameter Selection

Start conservative and iterate:

```{r best-practices-params, eval = FALSE}
# Start here
sf_fisheye(data, r_in = 0.3, r_out = 0.5, zoom_factor = 5, squeeze_factor = 0.35)

# Too distorted? Reduce zoom or widen glue
sf_fisheye(data, r_in = 0.3, r_out = 0.6, zoom_factor = 3, squeeze_factor = 0.35)

# Need more magnification? Increase zoom gradually
sf_fisheye(data, r_in = 0.3, r_out = 0.5, zoom_factor = 10, squeeze_factor = 0.35)
```

### Layer Alignment

Always combine layers before transformation:

```{r best-practices-layers, eval = FALSE}
# Good: Single transformation
combined <- rbind(layer1, layer2, layer3)
warped <- sf_fisheye(combined, ...)

# Avoid: Separate transformations
layer1_warped <- sf_fisheye(layer1, ...)  # Different normalization
layer2_warped <- sf_fisheye(layer2, ...)  # May not align perfectly
```

### Reproducibility

Be explicit about parameters for reproducible analyses:

```{r best-practices-reproducibility, eval = FALSE}
# Explicit and reproducible
result <- sf_fisheye(
  data,
  center = st_point(c(144.9631, -37.8136)),
  center_crs = "EPSG:4326",
  target_crs = "EPSG:7855",
  r_in = 0.34,
  r_out = 0.60,
  zoom_factor = 12,
  squeeze_factor = 0.35,
  preserve_aspect = TRUE,
  revolution = 0
)
```

## Performance Tips

For large datasets:

1. **Simplify geometries** before transformation if appropriate
2. **Remove empty geometries** (done automatically, but pre-filtering helps)
3. **Transform once**, not repeatedly in a loop

```{r performance, eval = FALSE}
# Pre-process large data
data_clean <- data |>
  filter(!st_is_empty(geometry)) |>
  st_simplify(dTolerance = 100)  # Adjust tolerance as needed

# Transform once
data_warped <- sf_fisheye(data_clean, ...)
```

## Common Issues

### Layers Don't Align

**Problem**: Points and polygons don't line up after transformation.

**Solution**: Transform together (see "Working with Multiple Layers").

### Excessive Distortion

**Problem**: Features look overly warped.

**Solution**: Reduce `zoom_factor` or increase `r_out` to widen the glue zone.

### Features Overlap in Focus

**Problem**: Too much magnification causes overlap.

**Solution**: This is expected behavior. Reduce `zoom_factor` if problematic.

## Next Steps

- **Advanced transformations**: Explore the `revolution` parameter for rotational effects
- **Interactive visualization**: Use `shiny_fisheye()` for interactive parameter tuning
- **Custom workflows**: Combine with other sf operations in analysis pipelines

## Getting Help

- Package documentation: `?sf_fisheye`, `?fisheye_fgc`
- GitHub issues: [Report bugs or request features]
- Examples: See `?vic` for built-in datasets

## References

The Focus-Glue-Context model is based on:

- Yamamoto, D., et al. (2009). "A Focus+Glue+Context Information Visualization Technique for Web Map Services"
- Furnas, G. W. (1986). "Generalized fisheye views"

---

**Remember**: Fisheye transformations distort distances and areas. Use them for visualization and exploration, but perform quantitative analyses on the original geometries.
