Files
dpg-map/README.md

5.1 KiB

dpg-map

dpg-map is a Dear PyGui map widget for XYZ raster tiles and geographic overlays.

The rebuilt beta exposes a stable public import:

import dpg_map as dpgm

Install

Use uv for development and dependency management:

uv sync
uv run pytest

From another local project, add this package as an editable dependency:

uv add --editable ../dpg-map
uv run python -c "import dpg_map as dpgm; print(dpgm.list_providers())"

Basic Map

from typing import Any

import dearpygui.dearpygui as _dpg
import dpg_map as dpgm

dpg: Any = _dpg

dpgm.configure(user_agent="my-app/0.1 contact@example.com")

dpg.create_context()
dpg.create_viewport(title="Map", width=1000, height=700)

with dpg.window(label="Map", width=-1, height=-1):
    with dpgm.map_widget(tag="map", center=(47.9029, 1.9093), zoom=15, width=-1, height=-1):
        dpgm.add_marker("vehicle", lat=47.9029, lon=1.9093, label="Vehicle")

dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Sizing

The widget is a Dear PyGui child_window containing a measured drawlist. The child keeps the requested Dear PyGui sizing intent while the drawlist uses concrete measured pixels.

Supported sizing modes:

  • width=0 and height=0 keep Dear PyGui default sizing.
  • width=-1 and height=-1 fill available space where Dear PyGui supports it.
  • Positive dimensions request fixed sizes.
  • autosize_x and autosize_y are passed to the child window.
  • Hidden layouts preserve the last non-zero measured size until visible again.

Examples:

uv run python examples/sizing_window.py
uv run python examples/sizing_child.py
uv run python examples/sizing_table.py
uv run python examples/hidden_tab.py

Live Updates

Runtime overlay updates are safe to call from background threads. They update logical state and enqueue renderer commands; Dear PyGui drawing, texture, handler, and viewport calls stay on the GUI thread.

Live marker update:

dpgm.add_marker("vehicle", lat=47.9029, lon=1.9093, map_tag="map")
dpgm.update_marker("vehicle", lat=current_lat, lon=current_lon, map_tag="map")

Live trajectory update:

dpgm.add_trajectory("track", points=[], map_tag="map")
dpgm.update_trajectory("track", points=tuple(points), map_tag="map")

Stress examples:

uv run python examples/markers_live_thread.py
uv run python examples/trajectory_live_thread.py

Providers

OpenStreetMap is registered as osm by default. Custom XYZ providers can be registered and selected at runtime:

provider = dpgm.TileProvider(
    name="custom",
    url_template="https://example.com/{z}/{x}/{y}.png",
    attribution="Tiles (c) Example",
)
dpgm.register_provider(provider)
dpgm.set_provider("custom", map_tag="map")

Provider switching preserves overlays and center, clamps zoom to the new provider range, increments the tile generation, and ignores stale tile results from the previous provider.

Example:

uv run python examples/custom_provider.py

Cache

Tiles use an in-memory cache and a persistent provider-namespaced disk cache.

dpgm.configure(
    user_agent="my-app/0.1 contact@example.com",
    cache_dir=".tile-cache",
    memory_cache_max_tiles=512,
    disk_cache_max_bytes=2_000_000_000,
)

stats = dpgm.get_cache_stats(map_tag="map")
dpgm.clear_memory_cache(map_tag="map")
dpgm.clear_disk_cache(provider="osm")

disk_cache_max_bytes=None disables the disk size limit. Memory cache clears are routed through the renderer command queue so texture deletion happens on the GUI thread. Disk cache clears can target all providers or a single provider namespace.

Cache example:

uv run python examples/cache_stress.py

OpenStreetMap Usage

The default OpenStreetMap provider requires attribution and should use an application-specific User-Agent.

dpgm.configure(user_agent="my-product/1.0 contact@example.com")

If no user agent is configured, dpg-map emits a runtime warning and falls back to a package user agent. Applications are responsible for displaying provider attribution in accordance with provider terms; the renderer draws the provider attribution text on the map.

Thread-Safety Contract

Public runtime functions are intended to be callable from non-GUI threads unless explicitly documented otherwise. They acquire map locks briefly, update logical state, and/or enqueue commands.

Thread-safe runtime areas include:

  • view updates: set_center, set_zoom, set_view, fit_bounds
  • overlay updates: add_marker, update_marker, update_trajectory, delete_overlay
  • layer updates: add_layer, show_layer, hide_layer, clear_layer
  • provider/cache updates: set_provider, clear_memory_cache, clear_disk_cache

map_widget(...) creates Dear PyGui items and must be used on the GUI thread inside an active Dear PyGui context.

Examples

uv run python examples/basic_map.py
uv run python examples/cache_stress.py
uv run python examples/custom_provider.py
uv run python examples/markers_live_thread.py
uv run python examples/trajectory_live_thread.py