MCP HubMCP Hub
Вернуться к навыкам

create-spatial-visualization

pjt222
Обновлено Yesterday
5 просмотров
17
2
17
Посмотреть на GitHub
Метаdesigndata

О программе

Этот навык создает интерактивные пространственные визуализации, такие как карты и профили высот, из данных GPX или маршрутов. Он поддерживает реализацию на R (sf, leaflet) или Observable (D3, deck.gl) для таких задач, как визуализация маршрутов путешествий или создание дашбордов поездок. Он охватывает весь рабочий процесс — от импорта данных и работы с системами координат до вывода стилизованных карт в форматах HTML или изображений.

Быстрая установка

Claude Code

Рекомендуется
Основной
npx skills add pjt222/agent-almanac -a claude-code
Команда плагинаАльтернативный
/plugin add https://github.com/pjt222/agent-almanac
Git клонированиеАльтернативный
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/create-spatial-visualization

Скопируйте и вставьте эту команду в Claude Code для установки этого навыка

Документация

Create Spatial Visualization

Interactive maps + elev profiles + spatial viz from GPX/waypoints/routes.

Use When

  • Viz tour route on map
  • Elev profile hike/bike
  • Overlay waypoints + POIs
  • Static map → print
  • Web trip dashboard

In

  • Required: Spatial src (GPX, CSV lat/lon, GeoJSON, waypoints)
  • Required: Viz type (interactive, static, elev profile, heatmap)
  • Optional: Basemap (OSM, satellite, terrain, topo)
  • Optional: Styling (colors, width, icons)
  • Optional: Out fmt (HTML widget, PNG, SVG, Quarto)
  • Optional: Extra layers (POI, areas, dist markers)

Do

Step 1: Import

R (sf):

# GPX file
track <- sf::st_read("route.gpx", layer = "tracks")
waypoints <- sf::st_read("route.gpx", layer = "waypoints")

# CSV with coordinates
points <- readr::read_csv("stops.csv") |>
  sf::st_as_sf(coords = c("lon", "lat"), crs = 4326)

# GeoJSON
route <- sf::st_read("route.geojson")

JS (Observable/D3):

// GPX parsing
const gpxText = await FileAttachment("route.gpx").text();
const parser = new DOMParser();
const gpxDoc = parser.parseFromString(gpxText, "text/xml");

// Extract track points
const trkpts = gpxDoc.querySelectorAll("trkpt");
const coordinates = Array.from(trkpts).map(pt => ({
  lat: +pt.getAttribute("lat"),
  lon: +pt.getAttribute("lon"),
  ele: +pt.querySelector("ele")?.textContent || 0
}));

CRS = WGS 84 (EPSG:4326) for web maps.

Got: Data as sf / coord array, valid geometries. Pt counts match (GPX track = 100s-1000s pts).

If err: GPX parse fail → check XML valid. Common: truncated (GPS battery), mixed ns, GPX 1.0 vs 1.1. No CRS → sf::st_set_crs(data, 4326). Inverted coords → check col order.

Step 2: Process + Clean

Processing Pipeline:
┌─────────────────────┬──────────────────────────────────────────┐
│ Operation           │ Purpose                                  │
├─────────────────────┼──────────────────────────────────────────┤
│ Remove duplicates   │ GPS often logs identical points at stops │
│ Smooth track        │ Reduce GPS jitter in dense urban areas   │
│ Calculate distances │ Cumulative distance along track          │
│ Extract elevation   │ Build elevation profile data             │
│ Segment by day      │ Split multi-day tracks into daily legs   │
│ Buffer route        │ Create corridor for POI discovery        │
│ Simplify geometry   │ Reduce point count for web performance   │
└─────────────────────┴──────────────────────────────────────────┘

R:

# Calculate cumulative distance
track_points <- sf::st_cast(track, "POINT")
distances <- sf::st_distance(track_points[-nrow(track_points), ],
                             track_points[-1, ],
                             by_element = TRUE)
cumulative_km <- cumsum(as.numeric(distances)) / 1000

# Extract elevation profile data
elevation_df <- data.frame(
  distance_km = c(0, cumulative_km),
  elevation_m = sf::st_coordinates(track_points)[, 3]
)

# Simplify for web display (keep 1% of points)
track_simple <- sf::st_simplify(track, dTolerance = 0.001)

Got: Clean data + distances + elev + simplified geom. No NA coords, no zero-length.

If err: No elev (some GPS) → DEM lookup / note unavail. Simplify removes detail → reduce tol. Dist NA → check empties: sf::st_is_empty().

Step 3: Viz Type

Visualization Decision Matrix:
┌─────────────────────┬──────────────────────┬───────────────────┐
│ Type                │ Best for             │ Tool              │
├─────────────────────┼──────────────────────┼───────────────────┤
│ Interactive map     │ Web, exploration     │ leaflet (R),      │
│                     │                      │ deck.gl (JS)      │
├─────────────────────┼──────────────────────┼───────────────────┤
│ Static map          │ Print, reports       │ tmap (R),         │
│                     │                      │ ggplot2 + ggspatial│
├─────────────────────┼──────────────────────┼───────────────────┤
│ Elevation profile   │ Hiking/cycling       │ ggplot2, D3       │
│                     │ analysis             │                   │
├─────────────────────┼──────────────────────┼───────────────────┤
│ Heatmap             │ Visit density,       │ leaflet.extras,   │
│                     │ coverage             │ deck.gl HeatmapLayer│
├─────────────────────┼──────────────────────┼───────────────────┤
│ 3D terrain          │ Mountain routes      │ rayshader (R),    │
│                     │                      │ deck.gl TerrainLayer│
└─────────────────────┴──────────────────────┴───────────────────┘

Basemap tiles:

  • OSM: General, good labels
  • Stamen Terrain: Hike/outdoor
  • ESRI World Imagery: Satellite
  • OpenTopoMap: Topo contours (elev context)

Got: Viz type + toolchain + basemap decided.

If err: Tool can't handle vol (100k+ pts leaflet) → simplify / switch canvas (deck.gl). Tiles unavail → fallback OSM.

Step 4: Render

Interactive (R/leaflet):

leaflet::leaflet() |>
  leaflet::addProviderTiles("OpenTopoMap") |>
  leaflet::addPolylines(
    data = track,
    color = "#2563eb",
    weight = 4,
    opacity = 0.8
  ) |>
  leaflet::addCircleMarkers(
    data = waypoints,
    radius = 8,
    color = "#dc2626",
    fillOpacity = 0.9,
    popup = ~name
  ) |>
  leaflet::addScaleBar(position = "bottomleft") |>
  leaflet::addMiniMap(position = "bottomright")

Elev profile (R/ggplot2):

ggplot2::ggplot(elevation_df, ggplot2::aes(x = distance_km, y = elevation_m)) +
  ggplot2::geom_area(fill = "#93c5fd", alpha = 0.4) +
  ggplot2::geom_line(color = "#2563eb", linewidth = 0.8) +
  ggplot2::labs(
    x = "Distance (km)",
    y = "Elevation (m)",
    title = "Elevation Profile"
  ) +
  ggplot2::theme_minimal()

Add layers: dist markers / N km, day-break, difficulty-color, POI icons.

Got: Viz shows route + waypoints + info. Interactive = responsive popups + zoom. Profile = correct scales.

If err: No data → CRS correct (EPSG:4326 leaflet). Empty popups → col name in formula. Elev spikes → filter GPS elev errs (>100m deviation from neighbors).

Step 5: Export + Embed

Export Options:
┌───────────────────┬────────────────────────────────────────────┐
│ Format            │ Method                                     │
├───────────────────┼────────────────────────────────────────────┤
│ HTML widget       │ htmlwidgets::saveWidget(map, "map.html")   │
│ PNG (static)      │ mapview::mapshot() or ggplot2::ggsave()    │
│ SVG (vector)      │ ggplot2::ggsave("plot.svg")                │
│ Quarto embed      │ Place leaflet/ggplot code in .qmd chunk    │
│ GeoJSON export    │ sf::st_write(data, "output.geojson")       │
│ KML (Google Earth)│ sf::st_write(data, "output.kml")           │
└───────────────────┴────────────────────────────────────────────┘

Quarto embed:

  1. Code chunk w/ labels
  2. #| fig-cap: static / #| label: fig-map xref
  3. self-contained: true YAML → bundle tiles (bigger file)

Got: File viewable in target. Size OK (<5MB HTML widget, <1MB images).

If err: HTML too big → reduce tile cache / simplify geom. Quarto fail w/ leaflet → htmlwidgets installed + HTML out (leaflet no PDF). PDF → static map alt (tmap tmap_mode("plot")).

Check

  • Data imports no err, correct CRS
  • All pts render in expected area
  • Elev profile plausible, no spikes
  • Interactive map: zoom + pan + popups work
  • Scales labeled
  • Export viewable
  • Size OK

Traps

  • CRS mismatch: EPSG:4326 (deg) vs projected (m) → wrong loc/scale. Transform to EPSG:4326 web.
  • GPS elev noise: GPS elev less accurate than horizontal. Smooth / use DEM.
  • Tile rate limits: Many tiles → rate limit on free servers. Cache local, respect policies.
  • Over-detailed tracks: 1s GPS → huge files. Simplify before web.
  • Leaflet in PDF: No render in PDF. Use tmap / ggplot2 + ggspatial for print.
  • Missing popups: Forgot popup = ~column_name → no info on click.

  • plan-tour-route — gen route data
  • generate-tour-report — embed viz in report
  • plan-hiking-tour — GPX + elev src
  • create-quarto-report — Quarto render

GitHub репозиторий

pjt222/agent-almanac
Путь: i18n/caveman-ultra/skills/create-spatial-visualization
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

Похожие навыки

content-collections

Мета

Этот навык предоставляет проверенную в продакшене настройку для Content Collections — TypeScript-ориентированного инструмента, который преобразует файлы Markdown/MDX в типобезопасные коллекции данных с валидацией Zod. Используйте его при создании блогов, сайтов документации или контентных приложений на Vite + React для обеспечения типобезопасности и автоматической проверки содержимого. Он охватывает всё: от настройки плагина Vite и компиляции MDX до оптимизации развертывания и валидации схем.

Просмотреть навык

polymarket

Мета

Этот навык позволяет разработчикам создавать приложения на платформе прогнозных рынков Polymarket, включая интеграцию с API для торговли и получения рыночных данных. Он также обеспечивает потоковую передачу данных в реальном времени через WebSocket для отслеживания текущих сделок и рыночной активности. Используйте его для реализации торговых стратегий или создания инструментов, обрабатывающих обновления рынка в реальном времени.

Просмотреть навык

creating-opencode-plugins

Мета

Этот навык помогает разработчикам создавать плагины OpenCode, которые подключаются к более чем 25 типам событий, таким как команды, файлы и операции LSP. Он предоставляет структуру плагина, спецификации API событий и шаблоны реализации для модулей на JavaScript/TypeScript. Используйте его, когда вам нужно перехватывать, отслеживать или расширять жизненный цикл ассистента OpenCode AI с помощью пользовательской событийно-ориентированной логики.

Просмотреть навык

sglang

Мета

SGLang — это высокопроизводительный фреймворк для обслуживания больших языковых моделей (LLM), специализирующийся на быстрой структурированной генерации JSON, regex и рабочих процессов агентов с использованием кэширования префиксов RadixAttention. Он обеспечивает значительно более высокую скорость вывода, особенно для задач с повторяющимися префиксами, что делает его идеальным для сложных структурированных результатов и многократных диалогов. Выбирайте SGLang вместо альтернатив, таких как vLLM, когда вам требуется ограниченное декодирование или вы создаете приложения с интенсивным совместным использованием префиксов.

Просмотреть навык