OSM 3D Model

One-click OpenStreetMap to interactive Three.js 3D city viewer • v1.2.0

1. Overview

OSM 3D Model is a single-click QGIS-to-browser pipeline that downloads live OpenStreetMap data for a user-defined study area and opens an interactive Three.js 3D city viewer. The plugin handles the entire data pipeline—Overpass API download with multi-mirror fallback and 7-day disk cache, OSM tag parsing into 11 memory layers, GeoJSON export with a manifest, and a local HTTP server that launches the browser-based PlanX 3D City engine. The viewer renders procedural buildings with roof styles, roads with lane markings and animated traffic, sidewalks with pedestrians, trees, street furniture, water features, and optional DEM terrain and basemap underlay.

2. Theoretical Foundations

2.1 OSM Data Quality for 3D Urban Modelling

Goetz (2013) demonstrated the feasibility of generating CityGML-compliant 3D city models from OpenStreetMap data, establishing the methodological foundation this plugin follows. The approach uses OSM's two-dimensional geometry (building footprints, road centrelines, green-space polygons) enriched with semantic tags and optional height attributes, then procedurally extrudes the third dimension. Fan et al. (2014) validated building footprint completeness and positional accuracy in OSM, finding >80% completeness in well-mapped urban areas. Biljecki et al. (2017) demonstrated that LOD1 building models generated from OSM without external elevation data can achieve useful accuracy when building height or floor-count attributes are present, directly supporting the plugin's three-tier height derivation strategy.

2.2 Procedural Content Generation in Urban Contexts

The web viewer follows Parish and Muller's (2001) procedural city generation paradigm, extended from their CityEngine system. Buildings are generated from footprint polygons using parametric roof styles (flat, pyramid, gable, hip, shed). Roads are extruded from linestrings with lane marking shaders. Trees are instanced with multiple stylistic variants. Street furniture (benches, lamps, bins) is aligned to road edges. The deterministic PRNG for tree placement ensures reproducibility using a seeded LCG based on polygon coordinates. This approach produces visually rich results without requiring detailed 3D model libraries.

2.3 Web-Based 3D GIS Visualisation

The viewer uses WebGL via Three.js for browser-based rendering, following the trend identified by Resch et al. (2014) toward web-based 3D GIS platforms. The architecture separates data preparation (Python/QGIS) from visualisation (JavaScript/WebGL), communicating through a local HTTP server with GeoJSON as the interchange format. This separation enables offline operation while maintaining browser-based interactivity and cross-platform compatibility.

3. Data Pipeline

Ten-Step Export Pipeline

  1. Area resolution: User selects canvas extent or polygon features. Returns (QgsGeometry, QgsCoordinateReferenceSystem).
  2. Study area preparation: Reproject to WGS84 for Overpass, UTM for geometry. compute_study_area() applies shape (circle/rounded/extent/polygon) and area clamp (1–300 ha, default 150 ha). Circle uses pole-of-inaccessibility algorithm. Creates model base by buffering 5 m outward.
  3. OSM download: QgsTask background thread fetches from Overpass API with multi-mirror fallback.
  4. Parse and build: Iterates every OSM element, clips to study boundary, builds 11 in-memory vector layers with computed attributes.
  5. GeoJSON export: Writes each layer to GeoJSON via QgsVectorFileWriter.writeAsVectorFormatV3().
  6. Atomic publish: Staging directory → web/data/yerlesim/ with backup on failure. Every GeoJSON validated as valid FeatureCollection.
  7. Optional DEM export: gdal:warpreproject, bounded to ~512 px max dimension, output as web/data/dem/mydem.tif.
  8. Optional basemap export: QgsMapRendererCustomPainterJob at max 2048 px, transparent PNG, output as web/data/basemap/basemap.png.
  9. Manifest: Writes planx_manifest.json with schema, field mappings, theme colours, and viewer defaults.
  10. Viewer launch: HTTP server starts on a free port (8120–8139), browser opens http://127.0.0.1:{port}/src/.

4. Study Area Definition

Area Sources and Boundary Shapes

Two area sources: Current map extent (canvas) or Selected polygon features (active layer, dissolved via unaryUnion()). Four boundary shapes: Circle (pole of inaccessibility algorithm, largest inscribed circle, clamped to max area, default), Rounded rectangle (corners at ~16% of short side via double-buffer technique), Extent (plain bounding box), and Polygon (exact selected geometry). Area is auto-reprojected to local UTM zone: \(\mathrm{zone} = \lfloor(\lambda + 180)/6\rfloor + 1\), EPSG = 32600 + zone (north) or 32700 + zone (south). Clamped to a configurable maximum (1–300 ha, default 150 ha). Study area inherits a 5 m presentation platform extending beyond the clip boundary with rounded corners.

5. OSM Data Download

Overpass API Pipeline with Multi-Mirror and Cache

Queries Overpass API for buildings, highways (including cycleway deduplication), waterways, water areas, green spaces (parks, forests, pitches, cemeteries, parking lots, pedestrian squares), trees, bus stops, benches, street lamps, and waste baskets within the WGS84 bounding box. Uses out body geom; suffix for full geometry with 60-second timeout.

Multi-mirror: Three endpoints tried in order: overpass-api.de, overpass.kumi.systems, overpass.private.coffee. HTTP 429 triggers next mirror. First valid non-empty JSON wins.

Cache: SHA-256 of query string, first 40 chars, stored in %TEMP%/osm_3d_model_cache/. TTL: 7 days (604800 s). Cache validation checks payload structure for corrupt files.

6. Data Layers (11)

Exported GeoJSON Layers

LayerGeometryKey Attributes
OSM BuildingsMultiPolygonosm_id, building, building_levels, height, roof_shape, roof_height, name
OSM RoadsMultiLineStringosm_id, highway, width, name
OSM Bike lanesMultiLineStringosm_id, highway, width, name, road_width, side
OSM GreensMultiPolygonosm_id, leisure, landuse, natural, amenity, highway, place, name
OSM WaterlinesMultiLineStringosm_id, waterway, width, name
OSM Water areasMultiPolygonosm_id, natural, waterway, landuse, name
OSM TreesPointosm_id, natural, height
OSM Bus stopsPointosm_id, highway, name
OSM BenchesPointosm_id, amenity
OSM Street lightsPointosm_id, highway
OSM Trash binsPointosm_id, amenity

Export uses QgsVectorFileWriter.writeAsVectorFormatV3() with GeoJSON driver and UTF-8. Atomic publish: staging directory → target via Path.replace() with backup on failure. Each GeoJSON validated as a non-empty FeatureCollection.

7. Building Height Logic

Three-Tier Fallback with 57 Type-Specific Defaults

  1. Parse building:levels or levels tag, rounded to integer, clamped to ≥1.
  2. If absent: parse height tag (supports m, cm, km, ft, feet, inch units), divide by 3.0, round, clamp to ≥1.
  3. Function-based default from 57-entry dictionary: apartments=4, residential=4, house/detached/terrace=2, bungalow=1, office=5, retail/supermarket/kiosk=1, commercial=3, industrial=1, school=3, university/college=4, hospital=5, church/mosque/temple/synagogue/chapel=1 (cathedral=2), warehouse/hangar/manufacture=1, garage/shed/hut/roof/carport=1, unknown=3.
  4. Add roof:levels if present. Final: max(1, base + roof_levels).

Additional columns: height (OSM height tag, float metres), roof_height (OSM roof:height tag), footprint_m2 (computed), gfa_m2 (computed = footprint × building_levels).

8. Three.js Viewer

Scene Composition and Rendering

The viewer (web/src/app.js, ~9500+ lines) is a single-page Three.js application. Core rendering: WebGLRenderer with antialiasing, PCFSoftShadowMap shadows, ACES filmic tone mapping (exposure 1.32). Post-processing: EffectComposer chain: RenderPassSSAOPass (optional) → UnrealBloomPass (optional, strength 0.3, radius 0.4, threshold 0.85) → OutputPass. CSS2DRenderer for 2D labels overlaid on 3D.

Lighting: DirectionalLight (intensity 1.38, shadow map 2048x2048, position 200,450,150) + AmbientLight (intensity 1.18). Procedural sky dome with ShaderMaterial (horizon #f6fbff to zenith #9ed8ff), star field (pseudo-random hash) at night.

Camera: PerspectiveCamera (45° FOV, near 1, far 10000). OrbitControls (damping 0.05, max polar angle ~90°). Also supports PointerLockControls for first-person walk mode (WASD, Shift sprint, C crouch). Fit algorithm: distance = max(220, min(maxDim × 2.4, 320, 1800)).

Boot sequence: loadManifest → applyManifestDefaults → loadGeoJson (all layers) → loadProjectDem → loadBaseMapTexture → buildTerrain → buildIslandLayer → building/road/sidewalk/waterline/fences/trees/furniture/traffic layers all rebuilt based on settings → loading screen fades out.

9. Viewer Panel System

Eight Dockable Panels with Toolbar Tray

PanelControls
DashboardScene metrics (building count, green area, avg floors, population, dwellings, vehicles), project metadata, area statistics
LayersPer-category visibility: buildings, roads, bike lanes, waterways, greens, trees, sidewalks, furniture, cars, cyclists, pedestrians, outside-ROI terrain
StyleBlock texture/transparency, road colour/texture, ground texture, terrain tile size, asset theme, tree render mode/variant/height, building mode/facade scale/floor height/roof shape/height/texture, procedural rules (ledges, storefronts, setback, ledge projection), per-category block styles
Scene & SunTime-of-day slider (6:00–22:00), solar animation, weather presets, fog density, SSAO/Bloom toggles, traffic/pedestrian density, model base controls, camera bookmarks
Basemap & TextureShow basemap toggle, opacity, blend mode (Normal/Multiply/Screen/Add/Difference), shadow catching, drape height, brightness/contrast/saturation/tint
Model StudioUpload custom GLB models per furniture category, library management, tree model pool (random selection), per-category transforms (position/scale/rotation)
Export StudioPNG/JPEG/WebP/PDF/SVG/HTML stills, WebM/MP4 screen recording (30/60 fps, standard/high/ultra bitrate), clipboard copy
Walk ModeFirst-person WASD navigation at pedestrian eye height, Shift sprint, C crouch

All settings are persisted to localStorage under the key planx_3d_city_settings (schema v13) with migration logic. Scene rebuild tokens abort stale rebuilds when settings change rapidly.

10. Color Themes (11)

Coordinated Palettes for Island, Terrain, Roads, Parks, Water, Roofs

ThemeCharacterIsland Base
Editorial PaperWarm ivory; default#e6dfd3
Plugin TonesSalmon and grey#d4c5c0
Tinted Gray TealMuted cool grey-green#c8d6d2
Teal & SalmonWarm-cool contrast#c8c0b8
Light Purple & BlackElegant purple accents#d8d5e0
Warm Sand & SlateNatural earth tones#ddd5c8
Anime (Anime Cel)Bright cel-shaded pastels#9fb6c4
CartoonBold primary colours#c4c8c0
PixarWarm creams and oranges#e8dcc8
Futuristic CityDark neon, cyan/violet glass#121420
Classic EraVintage sepia, terracotta roofs#d4c8b0

QGIS parallel styling: qgis_styling.py applies a categorised symbol renderer to buildings (6 function categories), roads (8 hierarchy levels with metric width expressions), and greens (8 categories including water, parking, pedestrian squares). Point layers receive single-symbol renderers. Theme palette is mirrored in both the QGIS project layers and the viewer manifest, ensuring visual consistency across environments.

11. Procedural Buildings and Facades

Canvas-Drawn Textures and Parametric Roofs

Facade textures: Canvas-drawn at runtime using FACADE_RECIPES with a storey-based window grid. Ground floor: shopfronts for Commercial/Mixed-Use (light blue glazing), entrance doors for Residential/Civic. Upper floors: coloured window rectangles, ~48% randomly lit (warm gold, amber/orange, cool blue, soft teal). A separate emissive map texture enables night glow when the day/night cycle enters night mode. 17 procedural roof texture variants (tile patterns, standing seam, shingle, solar, ceramic).

Roof geometry: Flat (with penthouse, HVAC, helipad/solar panels), Pyramid (concave-footprint-aware), Hip (ridge line at mid-height), Gable (ridge along OBB long axis), Shed (single slope).

Building setback: offsetRing() performs iterative vertex offset with hole detection, producing the footprint available for building generation. perBuildingColorVariation adds HSL lightness variation seeded by OSM ID for visual distinction.

Procedural ground textures: Asphalt, water, island block, and fence materials all generated via canvas drawing routines with configurable colours from the active theme.

12. Roads and Traffic

Road Surfaces, Sidewalks, Bike Lanes, and Animated Traffic

Roads: buildRoadLayer() constructs ribbon meshes along OSM way linestrings, extruded with configurable width per road class (motorway, trunk, primary, secondary, tertiary, residential, service, footway, cycleway). Lane markings: procedural dashed centre/side lines.

Sidewalks: Kerbed sidewalk ribbons on both sides, width scaled by road class. Placed via offset from road centrelines. Streetlights and trees alternate along sidewalks.

Bike lanes: Green ribbon strips offset to road-relative sides, using the OSM cycleway side tag when available.

Traffic: Instanced meshes for cars, vans, buses, and trucks with wheels and lights. Spawned on car-capable roads (excludes footways, cycleways). Frame-rate independent motion controlled by settings.trafficSpeed. Pedestrians keep to sidewalks with sidewalk-relative positioning. Cyclists ride on bike lanes when present. Night mode activates vehicle headlights/taillights and streetlight bulbs.

13. Terrain and Basemap

Optional DEM and Raster Underlay

DEM: Warped via gdal:warpreproject to the model base extent, bounded to ~512 px maximum dimension to keep file size manageable. The viewer loads GeoTIFF via the geotiff.js library and constructs a height-mapped terrain mesh. Terrain resolution is configurable.

Basemap: Rendered via QgsMapRendererCustomPainterJob at max 2048 px to transparent PNG. In the viewer, it appears as a flat underlay beneath the city with configurable opacity, blend mode (Normal/Multiply/Screen/Add/Difference), brightness, contrast, saturation, and tint. Shadow catching can be enabled to project building shadows onto the basemap surface. Drape height controls the vertical offset between basemap and city features.

14. Export Studio

Stills, Video Recording, and Clipboard

Still formats: PNG, JPEG (quality slider), WebP, PDF (raw PDF 1.4 from JPEG with proper cross-reference table), SVG (embeds JPEG as href), HTML (self-contained page). Size options: viewport, Full HD (1920x1080), QHD (2560x1440), 4K (3840x2160), custom. Video recording: WebM or MP4, 30 or 60 fps, standard/high/ultra bitrate. Filename sanitisation and timestamped generation. Clipboard copy via navigator.clipboard.write().

15. Caching and HTTP Server

Atomic Data Publish with Security Headers

Cache: SHA-256 of Overpass query (first 40 chars), stored as JSON in %TEMP%/osm_3d_model_cache/. TTL: 7 days. On-hit validation: corrupt files are discarded and re-fetched. Cache management UI exposes clear-cache button with count and byte-freed report.

HTTP server: ThreadingTCPServer on 127.0.0.1, ports 8120–8139, daemon threads. QuietHandler adds security headers: Cache-Control: no-store, Cross-Origin-Resource-Policy: same-origin, Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff, X-Frame-Options: DENY. Custom MIME types: application/json (.geojson), image/tiff (.tif), image/webp (.webp), application/javascript (.js).

16. Parameters and Controls

ParameterTypeRangeDefault
Study area sourceRadioMap view / SelectionMap view
Boundary shapeComboCircle / Rounded / Extent / PolygonCircle
Max study areaQDoubleSpinBox1–300 ha150 ha
Map & web themeCombo11 optionsEditorial Paper
DEM (optional)QgsMapLayerComboBoxRaster layersNone
Basemap (optional)QgsMapLayerComboBoxAny layerNone
Open viewer automaticallyQCheckBoxOn / OffOn
Clear OSM cacheQPushButtonReports files + bytes freed

17. Workflow Guide

  1. Pan and zoom the QGIS canvas to the desired study area, or select polygon features.
  2. Click the OSM 3D Model toolbar icon to open the dialog.
  3. Optionally click Add OSM basemap to the map for a reference tile layer.
  4. Choose area source, boundary shape, and max area. The live area readout shows estimated hectares.
  5. Select a theme from the dropdown (affects both QGIS layer styling and 3D viewer colours).
  6. Optionally expand Advanced to add a DEM raster or basemap layer, or clear the OSM cache.
  7. Click Create OSM layers & export 3D viewer. The plugin downloads, processes, exports, and opens the viewer.
  8. In the viewer, use the toolbar to open panels. Switch themes live via the Style dock without re-exporting.
  9. The export result is also added as a styled QGIS layer group ("3D OSM Model") for inspection and analysis.
  10. Use Export Studio for stills, video, or clipboard output. Use Walk Mode for first-person exploration.

18. Technical Notes

19. Literature

  1. Haklay, M. & Weber, P. (2008). OpenStreetMap: User-generated street maps. IEEE Pervasive Computing, 7(4), 12–18. DOI: 10.1109/MPRV.2008.80
  2. Biljecki, F., Ledoux, H., & Stoter, J. (2017). Generating 3D city models without elevation data. Computers, Environment and Urban Systems, 64, 1–18. DOI: 10.1016/j.compenvurbsys.2017.01.001
  3. Goetz, M. (2013). Towards generating highly detailed 3D CityGML models from OpenStreetMap. International Journal of Geographical Information Science, 27(5), 845–865. DOI: 10.1080/13658816.2012.721552
  4. Kolbe, T. H. (2009). Representing and exchanging 3D city models with CityGML. In J. Lee & S. Zlatanova (Eds.), 3D Geo-Information Sciences (pp. 15–31). Springer. DOI: 10.1007/978-3-540-87395-2_2
  5. Parish, Y. I. H. & Muller, P. (2001). Procedural modeling of cities. Proceedings of SIGGRAPH 2001, 301–308. DOI: 10.1145/383259.383292
  6. Fan, H., Zipf, A., Fu, Q., & Neis, P. (2014). Quality assessment for building footprints data on OpenStreetMap. International Journal of Geographical Information Science, 28(4), 700–719. DOI: 10.1080/13658816.2013.867495
  7. Resch, B., Wohlfahrt, R., & Wosniok, C. (2014). Web-based 4D visualization of marine geo-data using WebGL. Cartography and Geographic Information Science, 41(3), 235–247. DOI: 10.1080/15230406.2014.901001
  8. Goodchild, M. F. (2007). Citizens as sensors: The world of volunteered geography. GeoJournal, 69(4), 211–221. DOI: 10.1007/s10708-007-9111-y
  9. Dirksen, C. (2014). Three.js Essentials. Packt Publishing.
  10. Muller, P., Wonka, P., Haegler, S., Ulmer, A., & Van Gool, L. (2006). Procedural modeling of buildings. ACM Transactions on Graphics, 25(3), 614–623. DOI: 10.1145/1141911.1141931