Release v1.0.0
This is the first releas of dpg-map, an AI coded dearpygui map widget built due to a lack of time to build it myself. It features multi-widget abilities, with layers, overlays etc
This commit is contained in:
411
docs/API_REFERENCE.md
Normal file
411
docs/API_REFERENCE.md
Normal file
@@ -0,0 +1,411 @@
|
||||
# API Reference
|
||||
|
||||
Public imports are available from:
|
||||
|
||||
```python
|
||||
import dpg_map as dpgm
|
||||
```
|
||||
|
||||
Unless stated otherwise, runtime public functions are safe to call from non-GUI threads. They
|
||||
update logical state and enqueue GUI-thread renderer work. `map_widget(...)` is the main exception:
|
||||
it creates Dear PyGui items and must run on the GUI thread.
|
||||
|
||||
## Common Types
|
||||
|
||||
- `Tag`: `str | int`
|
||||
- `LatLon`: `tuple[float, float]` as `(lat, lon)`
|
||||
- `Point`: `tuple[float, float]` as `(x, y)`
|
||||
- `Bounds`: `tuple[LatLon, LatLon]` as `((south, west), (north, east))`
|
||||
- `Color`: RGB or RGBA integer tuple, usually `(r, g, b, a)`
|
||||
|
||||
## Configuration
|
||||
|
||||
### `configure(...) -> None`
|
||||
|
||||
Configure package-wide defaults used by subsequently created maps.
|
||||
|
||||
```python
|
||||
dpgm.configure(
|
||||
user_agent=None,
|
||||
cache_dir=None,
|
||||
default_provider="osm",
|
||||
memory_cache_max_tiles=512,
|
||||
disk_cache_max_bytes=2_000_000_000,
|
||||
prefetch_margin_tiles=1,
|
||||
tile_worker_count=4,
|
||||
overlay_update_policy="coalesce",
|
||||
debug=False,
|
||||
)
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `user_agent`: HTTP user agent for tile requests.
|
||||
- `cache_dir`: persistent tile cache root. Defaults to a platform user cache directory.
|
||||
- `default_provider`: provider name or `TileProvider` used by new maps.
|
||||
- `memory_cache_max_tiles`: maximum decoded runtime tile count per map.
|
||||
- `disk_cache_max_bytes`: maximum disk cache size. Use `None` for no size limit.
|
||||
- `prefetch_margin_tiles`: number of tiles to request around the visible viewport.
|
||||
- `tile_worker_count`: background worker count for disk/network/decode work.
|
||||
- `overlay_update_policy`: currently only `"coalesce"` is supported.
|
||||
- `debug`: store debug mode flag in global config.
|
||||
|
||||
Raises `ValueError` for invalid cache, worker, prefetch, or update-policy settings.
|
||||
|
||||
## Widget
|
||||
|
||||
### `map_widget(...) -> Iterator[Tag | None]`
|
||||
|
||||
Create a Dear PyGui child-window map shell and logical map context.
|
||||
|
||||
```python
|
||||
with dpgm.map_widget(
|
||||
tag="map",
|
||||
center=(47.9029, 1.9093),
|
||||
zoom=15,
|
||||
provider="osm",
|
||||
width=-1,
|
||||
height=-1,
|
||||
):
|
||||
dpgm.add_marker("vehicle", lat=47.9029, lon=1.9093)
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `tag`: map tag. If omitted, a generated tag is used.
|
||||
- `center`: initial `(lat, lon)`.
|
||||
- `zoom`: initial zoom, clamped to provider range.
|
||||
- `provider`: provider name or `TileProvider`; defaults to configured default provider.
|
||||
- `width`, `height`: Dear PyGui child-window size arguments.
|
||||
- `autosize_x`, `autosize_y`: Dear PyGui child-window autosize flags.
|
||||
- `cache_dir`: optional per-map cache directory passed as keyword argument.
|
||||
- `user_agent`: optional per-map tile user agent passed as keyword argument.
|
||||
- Other keyword arguments are forwarded to `dpg.add_child_window(...)`.
|
||||
|
||||
GUI-thread only.
|
||||
|
||||
## View
|
||||
|
||||
### `set_center(lat, lon, *, map_tag=None) -> None`
|
||||
|
||||
Set the map center without changing zoom.
|
||||
|
||||
### `get_center(*, map_tag=None) -> LatLon`
|
||||
|
||||
Return the current logical map center.
|
||||
|
||||
### `set_zoom(zoom, *, map_tag=None) -> None`
|
||||
|
||||
Set the zoom, clamped to the current provider range.
|
||||
|
||||
### `get_zoom(*, map_tag=None) -> int`
|
||||
|
||||
Return the current logical zoom.
|
||||
|
||||
### `set_view(*, center=None, zoom=None, map_tag=None) -> None`
|
||||
|
||||
Set center and/or zoom as one logical view update.
|
||||
|
||||
```python
|
||||
dpgm.set_view(center=(47.9029, 1.9093), zoom=15, map_tag="map")
|
||||
```
|
||||
|
||||
### `fit_bounds(bounds, *, map_tag=None) -> None`
|
||||
|
||||
Set center and zoom so bounds fit the current draw area.
|
||||
|
||||
```python
|
||||
dpgm.fit_bounds(((47.89, 1.89), (47.92, 1.93)), map_tag="map")
|
||||
```
|
||||
|
||||
### `screen_to_latlon(x, y, *, map_tag=None) -> LatLon`
|
||||
|
||||
Convert map-local screen coordinates to latitude/longitude.
|
||||
|
||||
### `latlon_to_screen(lat, lon, *, map_tag=None) -> Point`
|
||||
|
||||
Convert latitude/longitude to map-local screen coordinates.
|
||||
|
||||
## Markers
|
||||
|
||||
### `add_marker(tag, *, lat, lon, label=None, layer="default", show=True, map_tag=None, **kwargs) -> Tag`
|
||||
|
||||
Add or replace a marker overlay.
|
||||
|
||||
Keyword options:
|
||||
|
||||
- `color`: marker fill color, default `(255, 80, 80, 255)`.
|
||||
- `radius`: marker radius in pixels, default `5.0`.
|
||||
- `show_label`: draw `label` next to the marker, default `False`.
|
||||
- `user_data`: stored with the overlay model.
|
||||
- `callback`: stored with the overlay model for application use.
|
||||
|
||||
### `update_marker(tag, *, lat=None, lon=None, label=None, map_tag=None, **kwargs) -> None`
|
||||
|
||||
Update marker properties without changing map view.
|
||||
|
||||
Supported keyword updates:
|
||||
|
||||
- `show`
|
||||
- `color`
|
||||
- `radius`
|
||||
|
||||
### `set_marker_position(tag, lat, lon, *, map_tag=None) -> None`
|
||||
|
||||
Shortcut for `update_marker(..., lat=lat, lon=lon)`.
|
||||
|
||||
### `set_marker_label(tag, label, *, map_tag=None) -> None`
|
||||
|
||||
Shortcut for `update_marker(..., label=label)`.
|
||||
|
||||
## Polylines
|
||||
|
||||
### `add_polyline(tag, *, points=None, lats=None, lons=None, layer="default", show=True, map_tag=None, **kwargs) -> Tag`
|
||||
|
||||
Add or replace a polyline overlay.
|
||||
|
||||
Provide either:
|
||||
|
||||
- `points=[(lat, lon), ...]`
|
||||
- or `lats=[...], lons=[...]`
|
||||
|
||||
Keyword options:
|
||||
|
||||
- `color`: line color, default `(80, 180, 255, 255)`.
|
||||
- `thickness`: line thickness, default `2.0`.
|
||||
- `closed`: close the polyline, default `False`.
|
||||
- `simplify`: stored with the overlay model, default `True`.
|
||||
- `user_data`: stored with the overlay model.
|
||||
|
||||
### `update_polyline(tag, *, points=None, lats=None, lons=None, map_tag=None, **kwargs) -> None`
|
||||
|
||||
Update polyline points or properties.
|
||||
|
||||
Supported keyword updates:
|
||||
|
||||
- `show`
|
||||
- `color`
|
||||
- `thickness`
|
||||
|
||||
### `set_polyline_points(tag, points, *, map_tag=None) -> None`
|
||||
|
||||
Shortcut for replacing a polyline point sequence.
|
||||
|
||||
## Trajectories
|
||||
|
||||
### `add_trajectory(tag, *, points=None, lats=None, lons=None, layer="default", show=True, map_tag=None, **kwargs) -> Tag`
|
||||
|
||||
Add or replace a trajectory overlay.
|
||||
|
||||
Provide either `points` or `lats`/`lons`. Empty trajectories are valid for live updates.
|
||||
|
||||
Keyword options:
|
||||
|
||||
- `timestamps`: optional sequence with the same length as points.
|
||||
- `color`: trajectory color, default `(255, 180, 60, 255)`.
|
||||
- `thickness`: line thickness, default `2.0`.
|
||||
- `show_points`: draw point markers along the trajectory, default `False`.
|
||||
- `point_stride`: draw every Nth point when `show_points=True`, default `1`.
|
||||
- `user_data`: stored with the overlay model.
|
||||
|
||||
### `update_trajectory(tag, *, points=None, lats=None, lons=None, map_tag=None, **kwargs) -> None`
|
||||
|
||||
Update trajectory points or properties.
|
||||
|
||||
Supported keyword updates:
|
||||
|
||||
- `timestamps`
|
||||
- `show`
|
||||
- `color`
|
||||
- `thickness`
|
||||
|
||||
## Generic Overlay Control
|
||||
|
||||
### `set_overlay_show(tag, show, *, map_tag=None) -> None`
|
||||
|
||||
Show or hide an overlay without deleting it.
|
||||
|
||||
### `delete_overlay(tag, *, map_tag=None) -> None`
|
||||
|
||||
Delete an overlay from its map and layer.
|
||||
|
||||
When `map_tag` is omitted, the API can resolve an overlay only if the tag is unambiguous across
|
||||
registered maps. In multi-map apps, pass `map_tag`.
|
||||
|
||||
## Layers
|
||||
|
||||
### `add_layer(name, *, z_index=None, show=True, map_tag=None) -> None`
|
||||
|
||||
Create or update a logical overlay layer.
|
||||
|
||||
### `show_layer(name, *, map_tag=None) -> None`
|
||||
|
||||
Show all overlays assigned to a layer.
|
||||
|
||||
### `hide_layer(name, *, map_tag=None) -> None`
|
||||
|
||||
Hide all overlays assigned to a layer.
|
||||
|
||||
### `clear_layer(name, *, map_tag=None) -> None`
|
||||
|
||||
Delete all overlays assigned to a layer.
|
||||
|
||||
### `clear_map(*, map_tag=None) -> None`
|
||||
|
||||
Delete all overlays and invalidate map tile resources.
|
||||
|
||||
## Tile Providers
|
||||
|
||||
### `TileProvider`
|
||||
|
||||
Immutable tile provider definition.
|
||||
|
||||
```python
|
||||
dpgm.TileProvider(
|
||||
name="custom",
|
||||
url_template="https://example.com/{z}/{x}/{y}.png",
|
||||
min_zoom=0,
|
||||
max_zoom=19,
|
||||
tile_size=256,
|
||||
attribution="Tiles (c) Example",
|
||||
headers={},
|
||||
subdomains=(),
|
||||
retina=False,
|
||||
file_extension=None,
|
||||
)
|
||||
```
|
||||
|
||||
Fields:
|
||||
|
||||
- `name`: provider registry name.
|
||||
- `url_template`: XYZ URL template with `{z}`, `{x}`, and `{y}`.
|
||||
- `min_zoom`, `max_zoom`: valid zoom range.
|
||||
- `tile_size`: tile size in pixels.
|
||||
- `attribution`: text drawn on the map.
|
||||
- `headers`: request headers.
|
||||
- `subdomains`: values for `{s}`.
|
||||
- `retina`: if true, `{r}` expands to `"@2x"`.
|
||||
- `file_extension`: value for `{ext}` and disk cache extension.
|
||||
|
||||
### `register_provider(provider, *, replace=False) -> None`
|
||||
|
||||
Register a provider by name.
|
||||
|
||||
### `unregister_provider(name) -> None`
|
||||
|
||||
Remove a registered provider.
|
||||
|
||||
### `get_provider(name) -> TileProvider`
|
||||
|
||||
Return a registered provider.
|
||||
|
||||
### `list_providers() -> list[str]`
|
||||
|
||||
Return registered provider names in sorted order.
|
||||
|
||||
### `set_provider(provider, *, map_tag=None) -> None`
|
||||
|
||||
Switch a map to another provider while preserving overlays and center.
|
||||
|
||||
`provider` may be a provider name or a `TileProvider`. Provider switching clamps zoom to the new
|
||||
provider range and invalidates stale tile loads.
|
||||
|
||||
## Cache
|
||||
|
||||
### `CacheStats`
|
||||
|
||||
Public cache statistics snapshot.
|
||||
|
||||
Fields:
|
||||
|
||||
- `memory_tiles`
|
||||
- `memory_max_tiles`
|
||||
- `memory_hits`
|
||||
- `memory_misses`
|
||||
- `disk_bytes`
|
||||
- `disk_max_bytes`
|
||||
- `disk_hits`
|
||||
- `disk_misses`
|
||||
- `disk_path`
|
||||
|
||||
### `get_cache_stats(*, map_tag=None) -> CacheStats`
|
||||
|
||||
Return memory and disk cache diagnostics. With `map_tag=None`, returns global disk-cache stats and
|
||||
configured memory limit.
|
||||
|
||||
### `clear_memory_cache(*, map_tag=None) -> None`
|
||||
|
||||
Clear decoded in-memory tile data. If `map_tag` is omitted outside a map context, all registered
|
||||
maps are targeted.
|
||||
|
||||
### `clear_disk_cache(provider=None, *, map_tag=None) -> None`
|
||||
|
||||
Clear persistent tile cache data.
|
||||
|
||||
- `provider=None`: clear all provider namespaces.
|
||||
- `provider="osm"`: clear only one provider namespace.
|
||||
- `map_tag="map"`: enqueue a map-scoped clear through the renderer.
|
||||
|
||||
## Diagnostics
|
||||
|
||||
### `get_map_debug_state(*, map_tag=None) -> dict[str, Any]`
|
||||
|
||||
Return a diagnostic snapshot for a map. Keys include:
|
||||
|
||||
- `tag`
|
||||
- `center`
|
||||
- `zoom`
|
||||
- `requested_size`
|
||||
- `measured_size`
|
||||
- `visible`
|
||||
- `provider`
|
||||
- `overlay_count`
|
||||
- `layers`
|
||||
- `dirty_flags`
|
||||
- `pending_command_count`
|
||||
- `generation`
|
||||
- `active_drag`
|
||||
- `last_mouse_position`
|
||||
- `tiles`
|
||||
|
||||
This output is for debugging and logging. It is not guaranteed to be a stable serialization
|
||||
format.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Public exception classes are defined in `dpg_map.exceptions`:
|
||||
|
||||
- `DpgMapError`
|
||||
- `ProviderError`
|
||||
- `ProviderExistsError`
|
||||
- `ProviderNotFoundError`
|
||||
- `InvalidProviderError`
|
||||
- `ProjectionError`
|
||||
- `MapNotFoundError`
|
||||
- `OverlayNotFoundError`
|
||||
- `CoordinateError`
|
||||
- `ThreadingError`
|
||||
- `CacheError`
|
||||
|
||||
Common error cases:
|
||||
|
||||
- Invalid latitude/longitude raises `CoordinateError`.
|
||||
- Unknown map tags raise `MapNotFoundError`.
|
||||
- Unknown overlay tags raise `OverlayNotFoundError`.
|
||||
- Unknown or invalid providers raise provider-specific errors.
|
||||
|
||||
## Threading Contract
|
||||
|
||||
GUI-thread only:
|
||||
|
||||
- `map_widget(...)`
|
||||
- Dear PyGui setup and application code that creates widgets
|
||||
|
||||
Runtime-safe public areas:
|
||||
|
||||
- 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 and cache updates: `set_provider`, `clear_memory_cache`, `clear_disk_cache`
|
||||
|
||||
The renderer owns Dear PyGui draw commands, textures, input handlers, and frame callbacks.
|
||||
146
docs/EXAMPLES.md
Normal file
146
docs/EXAMPLES.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Examples
|
||||
|
||||
The `examples/` directory contains runnable Dear PyGui programs:
|
||||
|
||||
```bash
|
||||
uv run python examples/basic_map.py
|
||||
uv run python examples/custom_provider.py
|
||||
uv run python examples/cache_stress.py
|
||||
uv run python examples/markers_live_thread.py
|
||||
uv run python examples/trajectory_live_thread.py
|
||||
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
|
||||
```
|
||||
|
||||
## Basic Map
|
||||
|
||||
Creates one map and one marker.
|
||||
|
||||
```python
|
||||
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)
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
uv run python examples/basic_map.py
|
||||
```
|
||||
|
||||
## Live Marker Updates
|
||||
|
||||
Use explicit `map_tag` from background threads or callbacks.
|
||||
|
||||
```python
|
||||
dpgm.add_marker("vehicle", lat=47.9029, lon=1.9093, map_tag="map")
|
||||
|
||||
def update_from_telemetry(lat: float, lon: float) -> None:
|
||||
dpgm.update_marker("vehicle", lat=lat, lon=lon, map_tag="map")
|
||||
```
|
||||
|
||||
Run a threaded stress example:
|
||||
|
||||
```bash
|
||||
uv run python examples/markers_live_thread.py
|
||||
```
|
||||
|
||||
## Live Trajectory
|
||||
|
||||
Keep an application-owned point buffer and pass immutable snapshots to `update_trajectory(...)`.
|
||||
|
||||
```python
|
||||
points: list[tuple[float, float]] = []
|
||||
dpgm.add_trajectory("track", points=[], show_points=True, point_stride=12, map_tag="map")
|
||||
|
||||
def push_point(lat: float, lon: float) -> None:
|
||||
points.append((lat, lon))
|
||||
dpgm.update_trajectory("track", points=tuple(points), map_tag="map")
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
uv run python examples/trajectory_live_thread.py
|
||||
```
|
||||
|
||||
## Multiple Maps
|
||||
|
||||
Each map is independent. Reusing overlay tags across different maps is valid, but runtime updates
|
||||
should pass `map_tag` to avoid ambiguity.
|
||||
|
||||
```python
|
||||
with dpgm.map_widget(tag="live-map", center=(47.9, 1.9), zoom=15, width=-1, height=300):
|
||||
dpgm.add_marker("vehicle", lat=47.9, lon=1.9)
|
||||
|
||||
with dpgm.map_widget(tag="recap-map", center=(47.9, 1.9), zoom=13, width=-1, height=300):
|
||||
dpgm.add_trajectory("vehicle", points=[])
|
||||
|
||||
dpgm.update_marker("vehicle", lat=47.901, lon=1.902, map_tag="live-map")
|
||||
dpgm.update_trajectory("vehicle", points=lap_points, map_tag="recap-map")
|
||||
```
|
||||
|
||||
## Custom Provider Switch
|
||||
|
||||
Register a provider, create the map with it, and switch at runtime.
|
||||
|
||||
```python
|
||||
carto = dpgm.TileProvider(
|
||||
name="carto-light",
|
||||
url_template="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
|
||||
subdomains=("a", "b", "c", "d"),
|
||||
attribution="(c) OpenStreetMap contributors (c) CARTO",
|
||||
)
|
||||
|
||||
dpgm.register_provider(carto)
|
||||
dpgm.set_provider("carto-light", map_tag="map")
|
||||
dpgm.set_provider("osm", map_tag="map")
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
uv run python examples/custom_provider.py
|
||||
```
|
||||
|
||||
## Cache Controls
|
||||
|
||||
Configure a local cache and expose buttons in your UI.
|
||||
|
||||
```python
|
||||
dpgm.configure(cache_dir=".tile-cache", memory_cache_max_tiles=128)
|
||||
|
||||
def clear_memory() -> None:
|
||||
dpgm.clear_memory_cache(map_tag="map")
|
||||
|
||||
def clear_disk() -> None:
|
||||
dpgm.clear_disk_cache(map_tag="map")
|
||||
|
||||
def refresh_stats() -> str:
|
||||
stats = dpgm.get_cache_stats(map_tag="map")
|
||||
return f"{stats.memory_tiles} memory tiles, {stats.disk_bytes} disk bytes"
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
uv run python examples/cache_stress.py
|
||||
```
|
||||
|
||||
## Layout And Sizing
|
||||
|
||||
The widget works inside windows, child windows, tables, and hidden tabs.
|
||||
|
||||
```python
|
||||
with dpg.child_window(width=-1, height=420):
|
||||
with dpgm.map_widget(tag="map-child", width=-1, height=-1):
|
||||
dpgm.add_marker("inside-child", lat=47.0, lon=2.0)
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
uv run python examples/sizing_child.py
|
||||
```
|
||||
286
docs/GETTING_STARTED.md
Normal file
286
docs/GETTING_STARTED.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Getting Started
|
||||
|
||||
This guide walks through installing `dpg-map`, creating a map widget, adding overlays, updating
|
||||
the map from runtime code, and configuring tile providers and caches.
|
||||
|
||||
## Requirements
|
||||
|
||||
`dpg-map` currently targets Python `>=3.14` and uses:
|
||||
|
||||
- Dear PyGui for the UI
|
||||
- Pillow for decoding tile images
|
||||
- Requests for tile HTTP requests
|
||||
- Platformdirs for the default disk cache location
|
||||
|
||||
The project is managed with `uv`.
|
||||
|
||||
## Install From This Repository
|
||||
|
||||
For development inside this repository:
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
uv run python -c "import dpg_map as dpgm; print(dpgm.list_providers())"
|
||||
```
|
||||
|
||||
For another local app using this checkout:
|
||||
|
||||
```bash
|
||||
cd /path/to/your-app
|
||||
uv add --editable /home/hector/projects/dpg-map
|
||||
```
|
||||
|
||||
Then import it as:
|
||||
|
||||
```python
|
||||
import dpg_map as dpgm
|
||||
```
|
||||
|
||||
## Configure The Package
|
||||
|
||||
Configure package-wide defaults before creating maps:
|
||||
|
||||
```python
|
||||
dpgm.configure(
|
||||
user_agent="my-product/1.0 contact@example.com",
|
||||
cache_dir=".tile-cache",
|
||||
memory_cache_max_tiles=512,
|
||||
disk_cache_max_bytes=2_000_000_000,
|
||||
)
|
||||
```
|
||||
|
||||
Set an application-specific `user_agent` when using OpenStreetMap tiles. If no user agent is
|
||||
configured, `dpg-map` emits a runtime warning and uses a fallback package user agent.
|
||||
|
||||
## Create A Map
|
||||
|
||||
`map_widget(...)` is a Dear PyGui context manager. It creates a child window containing the map
|
||||
drawlist and installs internal render and input handlers.
|
||||
|
||||
```python
|
||||
from typing import Any
|
||||
|
||||
import dearpygui.dearpygui as _dpg
|
||||
import dpg_map as dpgm
|
||||
|
||||
dpg: Any = _dpg
|
||||
|
||||
dpgm.configure(user_agent="getting-started/0.1 contact@example.com")
|
||||
|
||||
dpg.create_context()
|
||||
dpg.create_viewport(title="dpg-map", width=900, height=600)
|
||||
|
||||
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("start", lat=47.9029, lon=1.9093, label="Start")
|
||||
|
||||
dpg.setup_dearpygui()
|
||||
dpg.show_viewport()
|
||||
dpg.start_dearpygui()
|
||||
dpg.destroy_context()
|
||||
```
|
||||
|
||||
`map_widget(...)` must be called on the GUI thread inside an active Dear PyGui context.
|
||||
|
||||
## Tags And Map Scope
|
||||
|
||||
Each map has a `tag`. Runtime calls should pass `map_tag` when there may be more than one map:
|
||||
|
||||
```python
|
||||
dpgm.set_center(47.9029, 1.9093, map_tag="live-map")
|
||||
dpgm.update_marker("vehicle", lat=47.9030, lon=1.9098, map_tag="live-map")
|
||||
```
|
||||
|
||||
Inside a `with dpgm.map_widget(...)` block, overlay creation can omit `map_tag` because the map is
|
||||
the current map context:
|
||||
|
||||
```python
|
||||
with dpgm.map_widget(tag="live-map"):
|
||||
dpgm.add_marker("vehicle", lat=47.9029, lon=1.9093)
|
||||
```
|
||||
|
||||
Use explicit `map_tag` in callbacks, worker threads, and apps with multiple maps.
|
||||
|
||||
## Add Overlays
|
||||
|
||||
Markers:
|
||||
|
||||
```python
|
||||
dpgm.add_marker(
|
||||
"vehicle",
|
||||
lat=47.9029,
|
||||
lon=1.9093,
|
||||
label="Vehicle",
|
||||
show_label=True,
|
||||
color=(255, 80, 80, 255),
|
||||
radius=6,
|
||||
map_tag="map",
|
||||
)
|
||||
```
|
||||
|
||||
Polylines:
|
||||
|
||||
```python
|
||||
dpgm.add_polyline(
|
||||
"route",
|
||||
points=[(47.9029, 1.9093), (47.9050, 1.9150), (47.9080, 1.9180)],
|
||||
color=(80, 180, 255, 255),
|
||||
thickness=3,
|
||||
map_tag="map",
|
||||
)
|
||||
```
|
||||
|
||||
Trajectories:
|
||||
|
||||
```python
|
||||
dpgm.add_trajectory(
|
||||
"track",
|
||||
points=[],
|
||||
color=(255, 180, 60, 255),
|
||||
thickness=3,
|
||||
show_points=True,
|
||||
point_stride=10,
|
||||
map_tag="map",
|
||||
)
|
||||
```
|
||||
|
||||
Coordinates are `(lat, lon)` pairs in degrees. Latitude must be between `-90` and `90`;
|
||||
longitude must be between `-180` and `180`.
|
||||
|
||||
## Runtime Updates
|
||||
|
||||
Runtime public calls are intended to be safe from background threads. They update logical state
|
||||
and enqueue GUI-thread work instead of calling Dear PyGui directly.
|
||||
|
||||
```python
|
||||
dpgm.update_marker("vehicle", lat=current_lat, lon=current_lon, map_tag="map")
|
||||
dpgm.update_trajectory("track", points=tuple(track_points), map_tag="map")
|
||||
```
|
||||
|
||||
Overlay updates do not reset map center or zoom.
|
||||
|
||||
## View Control
|
||||
|
||||
```python
|
||||
dpgm.set_center(47.9029, 1.9093, map_tag="map")
|
||||
dpgm.set_zoom(15, map_tag="map")
|
||||
dpgm.set_view(center=(47.9029, 1.9093), zoom=15, map_tag="map")
|
||||
dpgm.fit_bounds(((47.89, 1.89), (47.92, 1.93)), map_tag="map")
|
||||
```
|
||||
|
||||
`set_zoom(...)` and `set_view(...)` clamp zoom to the active provider range.
|
||||
|
||||
Coordinate conversion helpers use map-local screen coordinates:
|
||||
|
||||
```python
|
||||
lat, lon = dpgm.screen_to_latlon(120, 80, map_tag="map")
|
||||
x, y = dpgm.latlon_to_screen(47.9029, 1.9093, map_tag="map")
|
||||
```
|
||||
|
||||
## Layers
|
||||
|
||||
Overlays belong to named layers. Layers can be shown, hidden, cleared, and ordered with
|
||||
`z_index`.
|
||||
|
||||
```python
|
||||
dpgm.add_layer("vehicles", z_index=80, map_tag="map")
|
||||
dpgm.add_marker("car-1", lat=47.9, lon=1.9, layer="vehicles", map_tag="map")
|
||||
|
||||
dpgm.hide_layer("vehicles", map_tag="map")
|
||||
dpgm.show_layer("vehicles", map_tag="map")
|
||||
dpgm.clear_layer("vehicles", map_tag="map")
|
||||
```
|
||||
|
||||
Default layers include `default`, `markers`, `lines`, and `trajectories`.
|
||||
|
||||
## Tile Providers
|
||||
|
||||
OpenStreetMap is registered by default as `osm`.
|
||||
|
||||
Custom providers use XYZ URL templates. Required template fields are `{z}`, `{x}`, and `{y}`.
|
||||
Optional fields are `{s}` for subdomain, `{r}` for retina suffix, and `{ext}` for file extension.
|
||||
|
||||
```python
|
||||
provider = dpgm.TileProvider(
|
||||
name="carto-light",
|
||||
url_template="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
|
||||
subdomains=("a", "b", "c", "d"),
|
||||
attribution="(c) OpenStreetMap contributors (c) CARTO",
|
||||
file_extension="png",
|
||||
)
|
||||
|
||||
dpgm.register_provider(provider)
|
||||
dpgm.set_provider("carto-light", map_tag="map")
|
||||
```
|
||||
|
||||
Provider switching preserves overlays and center, clamps zoom to the new provider range, and
|
||||
invalidates stale tile loads from the previous provider.
|
||||
|
||||
## Cache
|
||||
|
||||
`dpg-map` uses:
|
||||
|
||||
- A memory cache for decoded runtime tiles
|
||||
- A persistent provider-namespaced disk cache
|
||||
|
||||
```python
|
||||
stats = dpgm.get_cache_stats(map_tag="map")
|
||||
print(stats.memory_tiles, stats.disk_bytes, stats.disk_path)
|
||||
|
||||
dpgm.clear_memory_cache(map_tag="map")
|
||||
dpgm.clear_disk_cache(provider="osm")
|
||||
```
|
||||
|
||||
`clear_memory_cache(...)` is routed through the renderer command queue so Dear PyGui textures are
|
||||
deleted on the GUI thread. `clear_disk_cache(...)` can clear all providers, one provider, or a
|
||||
map-scoped cache directory.
|
||||
|
||||
## Sizing
|
||||
|
||||
The map widget is a Dear PyGui child window containing a measured drawlist.
|
||||
|
||||
Common sizing modes:
|
||||
|
||||
- `width=-1`, `height=-1`: fill available space where Dear PyGui supports it
|
||||
- Positive `width` and `height`: fixed requested size
|
||||
- `autosize_x=True` or `autosize_y=True`: pass Dear PyGui autosize flags to the child
|
||||
- Hidden layouts preserve the last non-zero measured size until visible again
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
## Multiple Maps
|
||||
|
||||
Multiple maps can be used in the same Dear PyGui app. Give each map a distinct tag and pass
|
||||
`map_tag` for runtime updates.
|
||||
|
||||
```python
|
||||
with dpgm.map_widget(tag="live-map", center=(47.9, 1.9), zoom=15, width=-1, height=300):
|
||||
dpgm.add_marker("vehicle", lat=47.9, lon=1.9)
|
||||
|
||||
with dpgm.map_widget(tag="recap-map", center=(47.9, 1.9), zoom=13, width=-1, height=300):
|
||||
dpgm.add_trajectory("lap", points=[])
|
||||
|
||||
dpgm.update_marker("vehicle", lat=47.901, lon=1.902, map_tag="live-map")
|
||||
dpgm.update_trajectory("lap", points=lap_points, map_tag="recap-map")
|
||||
```
|
||||
|
||||
Pan, zoom, tile rendering, overlays, providers, and caches are isolated per map unless you choose
|
||||
to share global configuration.
|
||||
|
||||
## Diagnostics
|
||||
|
||||
Use `get_map_debug_state(...)` and `get_cache_stats(...)` while developing or troubleshooting:
|
||||
|
||||
```python
|
||||
debug = dpgm.get_map_debug_state(map_tag="map")
|
||||
stats = dpgm.get_cache_stats(map_tag="map")
|
||||
```
|
||||
|
||||
These snapshots are intended for diagnostics and logging, not as a stable serialization format.
|
||||
Reference in New Issue
Block a user