pipeworks_mud_mapper.components.map_view
Plotly-based map visualization component for the MUD Mapper.
This module provides the core visualization functions for rendering MUD zone maps using Plotly. It creates interactive 2D map views that display rooms as nodes and exits as connecting lines, with support for:
Flattened multi-level display: All Z-levels shown on a single 2D plane
Visual Z-level differentiation: Size and color distinguish floor levels
Room selection highlighting: Selected room shown in red
Exit visualization: Lines for cardinal directions, labels for up/down, and triangle markers for cross-zone exits
Interactive pan, zoom, and hover tooltips
Design Principles
Flattened View: All rooms rendered on one plane regardless of Z
Z-Ordered Rendering: Rooms drawn back-to-front so ground level is clickable
Separation of Concerns: Base figure creation separate from room rendering
Graceful Degradation: Handles missing data, empty rooms, invalid exits
Deterministic Output: Same inputs produce identical figures
Coordinate System
The map follows standard cartographic conventions:
X-axis: East (+) / West (-), displayed left-to-right
Y-axis: North (+) / South (-), displayed bottom-to-top
Z-axis: Represented by visual styling (size/color), not position
The coordinate range is -20 to +20 on both axes, with gridlines every 5 units.
Visual Design
Rooms are styled by Z-level for easy identification:
z=-1 (Down): Black filled, 14px (smallest) - cellars, basements
z=+1 (Up): White with black border, 18px (medium) - towers, attics
z=0 (Ground): Blue filled, 20px (largest) - main floor
Selected: Red, regardless of Z-level
Exit connections:
Cardinal exits (N/E/S/W): Gray lines between rooms on same Z-level
Vertical exits (U/D): Dashed lines between stacked rooms plus U/D labels
Zone exits: Triangle markers pointing in the exit direction
Crosshair: Dashed gray lines at origin for orientation
Constants
- Z_LEVEL_STYLESdict[int, dict]
Visual styling for each Z-level (size, color, border)
- Z_RENDER_ORDERlist[int]
Order in which Z-levels are rendered (back to front)
- SELECTED_ROOM_COLORstr
Color for highlighted/selected rooms
Functions
- create_map_figure(title) -> go.Figure
Create empty map canvas with grid and crosshair
- create_map_figure_with_rooms(rooms, visible_z_levels, selected_room) -> go.Figure
Create map with rooms and exits rendered across multiple Z-levels
Internal Functions
- _group_rooms_by_z_level(rooms, visible_z_levels) -> dict
Group rooms into buckets by their Z coordinate
- _find_stacked_positions(rooms, visible_z_levels) -> dict
Find X,Y positions with rooms at multiple Z-levels
- _draw_all_exit_lines(fig, rooms, visible_z_levels) -> None
Draw connecting lines for cardinal exits
- _draw_vertical_exit_lines(fig, rooms, visible_z_levels) -> None
Draw dashed lines for up/down exits
- _draw_zone_exit_markers(fig, rooms, visible_z_levels) -> None
Draw directional markers for cross-zone exits
- _draw_rooms_at_z_level(fig, rooms_at_level, z_level, selected_room) -> None
Render rooms for a single Z-level as a Scatter trace
- _add_vertical_exit_labels(fig, stacked_positions, rooms) -> None
Add “U/D” labels near stacked rooms with vertical exits
Usage
Create an empty map canvas:
>>> from pipeworks_mud_mapper.components.map_view import create_map_figure
>>> fig = create_map_figure()
>>> fig.show() # Opens in browser
Render rooms from all Z-levels:
>>> from pipeworks_mud_mapper.components.map_view import (
... create_map_figure_with_rooms
... )
>>> rooms = {
... "ground": {"name": "Ground", "coords": [0, 0, 0], "exits": {"down": "cellar"}},
... "cellar": {"name": "Cellar", "coords": [0, 0, -1], "exits": {"up": "ground"}},
... }
>>> fig = create_map_figure_with_rooms(rooms, selected_room="ground")
>>> fig.show()
Filter to specific Z-levels:
>>> fig = create_map_figure_with_rooms(rooms, visible_z_levels=[0]) # Ground only
Integration with Dash:
>>> import dash
>>> from dash import dcc
>>> fig = create_map_figure_with_rooms(rooms)
>>> graph = dcc.Graph(figure=fig, id="map-graph")
Architecture
The module uses a layered rendering approach:
Base Figure (create_map_figure) - Creates the canvas with grid, crosshair, and axis labels - Fixed dimensions (700x650) to prevent layout thrashing
Exit Lines (_draw_all_exit_lines) - Drawn first so rooms appear on top - Only cardinal directions on same Z-level
Vertical Exit Lines (_draw_vertical_exit_lines) - Dashed connectors between stacked rooms with U/D exits
Zone Exit Markers (_draw_zone_exit_markers) - Directional triangles for cross-zone exits
Room Nodes (_draw_rooms_at_z_level) - Rendered in Z-order: z=-1 first, z=+1 second, z=0 last - Ground level on top ensures it receives clicks
Vertical Labels (_add_vertical_exit_labels) - Added last as annotations - Show U/D for stacked rooms with vertical exits
Performance Considerations
Rooms batched into single Scatter trace per Z-level
Exit lines deduplicated (bidirectional exits draw once)
Zone exit markers render as a single Scatter trace
For zones with 100+ rooms, consider filter controls
Figure creation is synchronous and typically < 50ms
Attributes
Visual styling configuration for each Z-level. |
|
Order in which Z-levels are rendered (back to front). |
|
Color used for the currently selected room. |
|
Visual X,Y offset applied to rooms based on Z-level. |
|
Color used for cross-zone exit markers. |
|
Offsets for positioning zone exit markers relative to the room node. |
|
Plotly marker symbols for zone exits by direction. |
Functions
|
Create the base map figure with crosshair and grid. |
|
Create map figure with all rooms flattened onto a single 2D plane. |
Module Contents
- pipeworks_mud_mapper.components.map_view.Z_LEVEL_STYLES: dict[int, dict]
Visual styling configuration for each Z-level.
Each Z-level maps to a dictionary containing:
size: Marker diameter in pixels
color: Fill color (rgba string)
border_color: Marker outline color
border_width: Marker outline width in pixels
label: Human-readable label for legends/tooltips
The size hierarchy (14 < 18 < 20) ensures that when rooms overlap at the same X,Y position, the ground-level room (largest) is most visible and receives clicks first due to render order.
- pipeworks_mud_mapper.components.map_view.Z_RENDER_ORDER: list[int]
Order in which Z-levels are rendered (back to front).
Rooms are drawn in this order, meaning:
z=-1 (Down) is drawn first, appearing at the back
z=+1 (Up) is drawn second
z=0 (Ground) is drawn last, appearing on top
This ensures that when rooms overlap at the same X,Y position (stacked vertically), the ground-level room is on top and receives mouse clicks. Users can use the Z-level filter to hide ground level when they need to select a room below or above.
- pipeworks_mud_mapper.components.map_view.SELECTED_ROOM_COLOR: str = 'rgba(255, 100, 100, 1)'
Color used for the currently selected room.
This red color overrides the Z-level-based color when a room is selected, providing clear visual feedback regardless of which floor the selected room is on. The color is intentionally bright and distinct from all Z-level colors.
- pipeworks_mud_mapper.components.map_view.Z_LEVEL_VISUAL_OFFSET: dict[int, tuple[float, float]]
Visual X,Y offset applied to rooms based on Z-level.
When rooms are stacked at the same logical X,Y position but different Z-levels, this offset separates them visually so they don’t overlap. The diagonal offset creates an intuitive “stacking” effect:
z=-1 (Down): Shifted left and down, appearing “behind”
z=0 (Ground): No offset, the reference position
z=+1 (Up): Shifted right and up, appearing “in front”
The offset value (0.4) is small enough that stacked rooms are clearly at the “same position” but large enough to be visually distinct and separately clickable.
Note: This is purely visual. The logical coordinates used for U/D connections remain unchanged.
- pipeworks_mud_mapper.components.map_view.ZONE_EXIT_MARKER_COLOR: str = 'rgba(255, 165, 0, 0.85)'
Color used for cross-zone exit markers.
Zone exits are visually distinct from local exits so authors can quickly spot which directions lead out of the current zone. The orange hue reads as a “handoff” indicator without overpowering room nodes.
- pipeworks_mud_mapper.components.map_view.ZONE_EXIT_MARKER_OFFSETS: dict[str, tuple[float, float]]
Offsets for positioning zone exit markers relative to the room node.
Each offset is expressed in map units and is applied after the Z-level visual offset. This keeps markers near their originating room but prevents overlap with the room node itself.
- pipeworks_mud_mapper.components.map_view.ZONE_EXIT_MARKER_SYMBOLS: dict[str, str]
Plotly marker symbols for zone exits by direction.
- pipeworks_mud_mapper.components.map_view.create_map_figure(title=None)[source]
Create the base map figure with crosshair and grid.
Creates an empty Plotly figure configured as a 2D map canvas with:
Cartesian grid with 5-unit spacing
Crosshair at origin for orientation
Compass-labeled axes (N/S/E/W at extremes)
Fixed dimensions to prevent resize loops in Dash
This function creates only the canvas - use create_map_figure_with_rooms to add room visualizations.
- Parameters:
title (
str | None, optional) – Title text to display above the map (default: None). If None, no title is shown. This is the default for flattened views where a Z-level title would be misleading.- Returns:
Plotly Figure configured as an interactive map canvas. The figure has:
Range: -20 to +20 on both axes
Grid: 5-unit spacing with light gray lines
Crosshair: Dashed gray lines at x=0 and y=0
Dimensions: 700x650 pixels (fixed)
- Return type:
go.Figure
Examples
Create a map canvas with no title (default):
>>> fig = create_map_figure() >>> fig.layout.title is None or fig.layout.title.text is None True
Create a map canvas with a custom title:
>>> fig = create_map_figure(title="Crooked Pipe District") >>> fig.layout.title.text 'Crooked Pipe District'
Notes
The figure uses fixed dimensions (autosize=False) to prevent infinite resize loops when embedded in Dash layouts
Axis labels show compass directions at the extremes: “W 20” at x=-20, “E 20” at x=+20, “S 20” at y=-20, “N 20” at y=+20
The scaleanchor constraint ensures 1:1 aspect ratio (square grid)
Pan and zoom are enabled (fixedrange=False)
See also
create_map_figure_with_roomsAdd rooms to the map canvas
- pipeworks_mud_mapper.components.map_view.create_map_figure_with_rooms(rooms=None, visible_z_levels=None, selected_room=None, visual_offset_x=1.0, visual_offset_y=1.0)[source]
Create map figure with all rooms flattened onto a single 2D plane.
Renders a complete zone map showing rooms from multiple Z-levels simultaneously. Rooms are visually differentiated by Z-level using size and color, with the selected room highlighted in red.
The rendering order ensures that ground-level rooms (z=0) appear on top and receive clicks first when rooms overlap at the same X,Y position.
- Parameters:
rooms (
dict[str,dict] | None, optional) –Dictionary mapping room IDs to room data. Each room should have:
”coords”: [x, y, z] list of coordinates
”name”: Display name (falls back to room_id if missing)
”exits”: Dict mapping direction to target room_id
If None or empty, returns base map only.
visible_z_levels (
list[int] | None, optional) – List of Z-levels to display (default: None, which shows all). Pass[-1, 0, 1]explicitly for all levels, or a subset like[0]to show only ground level,[-1, 0]to hide upper level.selected_room (
str | None, optional) – Room ID to highlight as selected (default: None). Selected room appears in red regardless of its Z-level.visual_offset_x (
float, optional) – X-axis scale factor for Z-level visual offset (default: 1.0).visual_offset_y (
float, optional) – Y-axis scale factor for Z-level visual offset (default: 1.0).
- Returns:
go.Figure– Plotly Figure with rooms rendered in Z-order.Visual Styling--------------Rooms are styled based on their Z coordinate- **z=-1 (Down)** (
Black filled,14px - smallest,drawn first (back))- **z=+1 (Up)** (
White with black border,18px - medium,drawn second)- **z=0 (Ground)** (
Blue filled,20px - largest,drawn last (front))- **Selected** (
Always red,regardlessofZ-level)Exit connections- **Cardinal (N/E/S/W)** (
Gray lines between rooms on same Z-level)- **Vertical (U/D)** (
"U","D", or"U/D"labels near stacked rooms)
- Return type:
plotly.graph_objects.Figure
Examples
Render all rooms from a zone:
>>> rooms = { ... "ground": { ... "name": "Ground Floor", ... "coords": [0, 0, 0], ... "exits": {"down": "cellar", "north": "hall"} ... }, ... "cellar": { ... "name": "The Cellar", ... "coords": [0, 0, -1], ... "exits": {"up": "ground"} ... }, ... "hall": { ... "name": "Great Hall", ... "coords": [0, 5, 0], ... "exits": {"south": "ground"} ... }, ... } >>> fig = create_map_figure_with_rooms(rooms)
Filter to ground level only:
>>> fig = create_map_figure_with_rooms(rooms, visible_z_levels=[0])
Highlight a selected room:
>>> fig = create_map_figure_with_rooms( ... rooms, selected_room="cellar" ... )
Handle empty rooms gracefully:
>>> fig = create_map_figure_with_rooms(None) # Returns base map >>> fig = create_map_figure_with_rooms({}) # Returns base map
Notes
Rooms without “coords” key are treated as being at [0, 0, 0]
Cross-zone exits (containing ‘:’) are skipped during line drawing
Exit lines are drawn before room nodes (proper layering)
Vertical exits show text labels instead of lines
Hover text shows room name, ID, Z-level, and exit directions
When rooms overlap (stacked vertically), ground level is on top
When rooms share the same X,Y but different Z, they overlap visually. Due to render order, ground level (z=0) receives clicks first. To select a lower-level room:
Uncheck “Ground (z=0)” in the layer filter
Click the now-visible lower-level room
Re-check ground level when done
See also
create_map_figureCreate empty map canvas
Z_LEVEL_STYLESVisual configuration for each Z-level
Z_RENDER_ORDERRendering order for Z-levels