Skip to content

Latest commit

 

History

History
181 lines (143 loc) · 11.6 KB

File metadata and controls

181 lines (143 loc) · 11.6 KB

SVG Cave Mapper Architecture

Overview

The SVG Cave Mapper is a layered application for converting SVG cave survey maps into georeferenced GIS formats. It supports both CLI and GUI interfaces with proper separation of concerns.

Architecture Layers

┌─────────────────────────────────────────────────────────┐
│                    Presentation Layer                    │
│  ┌──────────────┐                    ┌──────────────┐  │
│  │     CLI      │                    │     GUI      │  │
│  │  (argparse)  │                    │   (PyQt5)    │  │
│  └──────────────┘                    └──────────────┘  │
│         │                                     │         │
└─────────┼─────────────────────────────────────┼─────────┘
          │                                     │
┌─────────┴─────────────────────────────────────┴─────────┐
│                      Services Layer                      │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐          │
│  │ Processing │ │    File    │ │  Geometry  │          │
│  │  Service   │ │  Service   │ │  Service   │          │
│  └────────────┘ └────────────┘ └────────────┘          │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐          │
│  │   Export   │ │    Tile    │ │ Tile Cache │          │
│  │  Service   │ │  Service   │ │  (SQLite)  │          │
│  └────────────┘ └────────────┘ └────────────┘          │
└──────────────────────────────────────────────────────────┘
          │                                     │
┌─────────┴─────────────────────────────────────┴─────────┐
│              State Management Layer                      │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │ Application  │  │   Session    │  │    Config    │  │
│  │    State     │  │   Manager    │  │   Manager    │  │
│  └──────────────┘  └──────────────┘  └──────────────┘  │
│  ┌──────────────────────────────────────────────────┐  │
│  │               Event Bus (Pub/Sub)                │  │
│  └──────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────┘
          │
┌─────────┴─────────────────────────────────────┐
│            Core Domain Layer                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐    │
│  │ Parsers  │  │ Geometry │  │  Models  │    │
│  └──────────┘  └──────────┘  └──────────┘    │
└────────────────────────────────────────────────┘

Core Domain Layer

SVG Processing Pipeline

SVGCaveMapProcessor (core/processor.py) orchestrates:

  1. Parse SVG file → Extract element coordinates via SVGParserFactory
  2. Normalize coordinates → Ensure (0,0) origin via CoordinateNormalizer
  3. Build geometries → Convert to Shapely objects via GeometryBuilder
  4. Return GeometryData objects with metadata and SVG styling

The processor uses parse_element_multi() to handle elements that produce multiple geometries (e.g., paths with multiple subpaths).

Parser Architecture (Factory Pattern)

SVGParserFactory (parsers/factory.py) dynamically selects parsers for each SVG element type. All parsers implement the SVGElementParser protocol.

Parsers:

  • PathParser (path_parser.py): Handles <path> elements using svgpathtools. Splits paths at discontinuities (multiple M commands) into separate subpaths. Uses adaptive sampling — straight line segments get 2 points, curves scale by length (~1 sample per 5 SVG units, capped at 100).
  • RectParser (shape_parsers.py): Handles <rect> with optional rx/ry rounded corners (8 arc points per corner).
  • CircleParser / EllipseParser (shape_parsers.py): 64-point discretization.
  • LineParser (shape_parsers.py): Simple two-point lines.
  • PolygonParser / PolylineParser (polygon_parser.py): Coordinate list parsing.
  • TextParser / TspanParser (text_parser.py): Text position extraction as Point geometry.
  • UseParser / SymbolParser (use_parser.py): SVG <use> element resolution.

Multi-geometry support: parse_element_multi() returns a list of coordinate lists per element, enabling proper handling of compound paths.

Geometry Builder

GeometryBuilder (geometry/builder.py) converts coordinates to Shapely geometries:

  • Closed polygons: SVG <polygon>, <rect>, <circle>, <ellipse> are always treated as closed polygons. Other elements are classified as polygons if first == last coordinate.
  • Lines: Open coordinate sequences become LineString.
  • Markers: Zero-size rects (width=0, height=0) become Point geometries with type marker (used for survey stations).
  • Text: Text/tspan elements become Point with text content in attributes.
  • SVG style extraction: Stroke, fill, stroke-width, stroke-linecap, stroke-linejoin, and opacity are extracted from both direct attributes and the style attribute (style takes precedence).

Data Models

models.py defines:

  • Point2D: Pixel coordinates with unpacking and offset support
  • BoundingBox: Bounds calculation from point lists
  • GeometryData: Wraps Shapely geometry + attributes dict (type, id, class, svg_tag, stroke, fill, stroke-width, etc.)

Services Layer

Export Service

ExportService (services/export_service.py) handles GIS export:

  • Converts SVG coordinates to geographic coordinates using geodesic calculations (pyproj Geod on WGS84 ellipsoid)
  • Exports to GeoPackage (.gpkg) and Shapefile (.shp) via geopandas
  • Separates geometry types (polygons, lines, points) into appropriate layers
  • Supports multiple CRS: WGS84, ETRS89/PT TM06, UTM zones, OSGB, JGD2011, and custom EPSG codes
  • Uses pyproj.Transformer for datum transformations

Tile Service & Cache

  • TileService (services/tile_service.py): Fetches map tiles from ESRI World Imagery or OpenStreetMap. Parallel fetching with ThreadPoolExecutor (8 workers).
  • TileCache (services/tile_cache.py): Two-tier caching system:
    • Memory: True LRU cache using OrderedDict (default 500 tiles)
    • Disk: SQLite metadata database + image files on disk (default 500MB limit, 30-day TTL)
    • Automatic cleanup of expired tiles and size-based eviction

Declination Service

DeclinationService (services/declination_service.py): Magnetic declination calculation:

  • WMM (via pygeomag): World Magnetic Model, most accurate for current dates (2025-2030)
  • IGRF (via ppigrf): International Geomagnetic Reference Field, supports historical dates (1900-2030)
  • Automatic model selection based on date range
  • Returns declination value and secular variation (annual change rate)

Other Services

  • ProcessingService: Bridge to SVGCaveMapProcessor for geometry extraction
  • FileService: SVG file loading, validation, recent files tracking
  • GeometryService: Spatial queries (find at point, in bounding box), statistics

State Management Layer

  • ApplicationState: Central state container (file, control point, geometries, settings, scale, background map config)
  • SessionManager: JSON-based session save/restore with all georeferencing parameters (control point pixel + lat/lon, scale, declination, CRS, view settings)
  • ConfigManager: User preferences with JSON persistence and default values
  • EventBus: Pub/sub event system for loose coupling between components

GUI Layer

Main Window

MainWindow (gui/main_window.py):

  • Menu bar: File, View (control point, axes, background map, map type), Export, Tools (ruler, inspect, tile cache)
  • Side panel: Info panel, georeferencing panel, export panel
  • Footer/status bar: NAMMI branding, SVG coordinates, geographic coordinates

Map Canvas

MapCanvas (gui/map_canvas.py):

  • SVG-faithful rendering: Uses original SVG stroke colors, fill colors, stroke widths, line caps, and line joins per geometry
  • Filled polygons: Polygons with SVG fill attributes are rendered with the original fill color
  • Survey station markers: Rendered as small dots
  • Background map tiles: Satellite or OSM imagery under the SVG overlay
  • Geodesic coordinate conversion: _world_to_latlon() and _latlon_to_world() use pyproj Geod (Vincenty's formula on WGS84 ellipsoid)
  • Performance: Cached background pixmap, instant pan via pixmap translation, deferred cache rebuild, LOD simplification during interaction, viewport culling

Widgets

  • CoordinateInputDialog: Modal dialog for lat/lon entry
  • GeorefPanel: Declination, scale, control point coordinate editing
  • ExportPanel: CRS selection dropdown with custom EPSG input, GeoPackage and Shapefile export buttons
  • DeclinationPanel: Magnetic declination calculator with date picker, WMM/IGRF model selection, and auto-apply

Configuration

~/.svg_cave_mapper/
├── config.json              # User preferences
├── recent_files.txt         # Recent files list
├── tile_cache/              # Persistent tile cache
│   ├── tile_cache.db        # SQLite metadata
│   └── tiles/               # Cached tile images
└── sessions/
    └── last_session.json    # Auto-saved session

Performance Optimizations

  • Cached background rendering: Geometries + tiles rendered to an offscreen pixmap
  • Instant pan: During panning, the cached pixmap is translated (zero re-rendering)
  • Deferred cache rebuild: Cache is rebuilt during idle time after interaction ends
  • LOD simplification: Complex geometries simplified during zoom/pan interaction
  • Viewport culling: Only visible geometries are rendered
  • Adaptive curve sampling: Lines get 2 points; curves scale by length
  • Parallel tile fetching: 8 concurrent workers for tile downloads
  • Two-tier tile cache: LRU memory cache + persistent SQLite-tracked disk cache