A microservice platform for the quantitative analysis of sketch maps
Developed by the Spatial Intelligence Lab (SIL) Β· Institute for Geoinformatics (IFGI) Β· University of MΓΌnster
Quick Start Β· Architecture Β· Services Β· Analysis Features Β· API Β· Deployment Β· Docs
SketchMapia compares hand-drawn sketch maps against reference base maps and quantifies how accurately people represent space. A central web application (the Sketchmap Analyser) orchestrates a family of independent Django microservices, each implementing one analysis method β from completeness and qualitative spatial relations to the Gardony Map Drawing Analyzer (GMDA) and Bi-Dimensional Regression (BDR).
Every service is containerized, published automatically to the GitHub Container Registry, and deployed behind a single HTTPS reverse proxy.
Each analysis method lives in its own Django microservice with its own port and URL prefix, orchestrated through Docker Compose. The main application calls the services from the browser β directly via ports in local development, via Apache reverse-proxy paths in production.
flowchart TB
subgraph Browser["Browser - localhost:8000"]
HTML["generalizingmaps.html"]
Analyzer["sketchmap analyzer (Web Page)"]
JS["project.js"]
Result["Result Summary Table with selected metrics"]
end
subgraph Container["SketchMapia Microservices Container"]
GenMaps["Generalized Maps (Basemap & Sketchmaps)"]
Gen["generalizations : 8001"]
Comp["completeness : 8002"]
Acc["accuracy / qualitativerelations : 8003"]
Val["validation : 8004"]
Gmda["gmda : 8005"]
Bdr["bdr : 8006"]
Boundary["Container Boundary"]
GenMaps -- creates --> Gen
GenMaps --> Comp
GenMaps --> Acc
GenMaps --> Bdr
GenMaps --> Gmda
Boundary -. compulsory .-> Comp
Boundary -. compulsory .-> Gen
Comp -. output .-> Boundary
Acc -. output .-> Boundary
Gen -. output .-> Boundary
Gmda -. output .-> Boundary
Bdr -. output .-> Boundary
end
HTML --> Analyzer
Analyzer -- "Selected microservices" --> Boundary
Analyzer -- "sends the data" --> JS
Boundary -- "JSON metrics for selected microservices" --> JS
JS --> Result
sequenceDiagram
autonumber
box rgba(122,182,41,0.10) π€ User + Orchestrator
actor R as Researcher
participant UI as Sketchmap Analyser (browser 8000)
end
box rgba(230,160,30,0.14) π§Ή Prep (researcher-initiated)
participant V as validation 8004
end
box rgba(122,182,41,0.22) βοΈ Pipeline core
participant G as generalizations 8001
end
box rgba(70,130,180,0.14) π Metric services
participant C as completeness 8002
participant A as accuracy 8003
participant M as gmda 8005
participant B as bdr 8006
end
Note over R,B: getServiceUrl() picks localhost:PORT in dev, same-origin via Apache in prod.
rect rgba(122,182,41,0.10)
Note over R,UI: 1. Load
R->>UI: Load project (base map + sketch maps)
end
rect rgba(230,160,30,0.14)
Note over R,V: 2. Optional geometry cleanup (separate from Analyse)
opt Validation
R->>UI: Run validation on base / sketch
UI->>V: POST /validation/validate/ (action=preview)
V-->>UI: audit { snap, merge }
R->>UI: Approve snaps / merges
UI->>V: POST /validation/validate/ (action=apply)
V-->>UI: modifiedStreets (corrected geometry)
Note over UI: Written back into allOriginalSketchMaps[...]
end
end
rect rgba(122,182,41,0.10)
Note over R,UI: 3. Align + trigger
R->>UI: Align sketch features to base features
R->>UI: Click Analyse, Run Analysis
end
loop For each sketch map
rect rgba(122,182,41,0.22)
Note over UI,G: 4. Generalization (runs first, once per sketch map)
UI->>G: POST /generalizations/requestFME/ (basedata, sketchdata, aligndata)
G-->>UI: generalized base map (features tagged with gen_id)
Note over UI: Cached in allGenBaseMap[sketchmap]. prepareDataForQualifier() filters into metricdata / sketchdata
end
rect rgba(70,130,180,0.14)
Note over UI,B: 5. Metrics
par Base analysis (Promise.all)
UI->>C: POST /completeness/analyzeCompleteness/
C-->>UI: landmark / street / overall completeness
and
opt Accuracy checked
UI->>A: POST /accuracy/analyzeQualitative/
A-->>UI: per-calculus counts + precision/recall + QCNs
end
end
opt Buildings GMDA checked
UI->>M: POST /gmda/calculateGMDA/ (from allGenBaseMap)
M-->>UI: 6 metrics + nTL/nDL
end
opt Junctions GMDA checked
UI->>M: POST /gmda/calculateJunctionGMDA/
M-->>UI: 6 metrics + junction layers
end
opt BDR variants
UI->>B: POST /bdr/calculateLandmarksBDR/ and /calculateJunctionsBDR/
B-->>UI: r, DI, phi, theta, alpha1, alpha2
end
end
Note over UI: Write into genResultArray, populateGMDAResults() renders row in #OrderingofMaps
end
rect rgba(122,182,41,0.10)
Note over R,UI: 6. Export
R->>UI: Download Results
Note over UI: JSZip builds ResultSummary.csv + DetailedOutput CSVs + QualitativeRelations/ (if Accuracy ran)
UI-->>R: results.zip
end
| Service | Port | URL Prefix | Purpose |
|---|---|---|---|
| sketchmap_analyser | 8000 |
/ |
Main web application β sketch map editor, project management, results UI |
| generalizations | 8001 |
/generalizations/ |
Map generalization processing |
| completeness | 8002 |
/completeness/ |
Completeness analysis (recalled vs. omitted features) |
| qualitativerelations | 8003 |
/accuracy/ |
Qualitative spatial relations accuracy (from accuracy/) |
| validation | 8004 |
/validation/ |
Sketch map validation |
| gmda | 8005 |
/gmda/ |
Gardony Map Drawing Analyzer β six spatial accuracy metrics |
| bdr | 8006 |
/bdr/ |
Bi-Dimensional Regression β similarity-transform fit and distortion |
git clone https://github.com/ifgi-sil/SketchMapia-Microservices.git
cd SketchMapia-Microservices
docker-compose up --build- Open http://localhost:8000/generalizingmaps/ in your browser.
- Load a project and click Analyse.
- In the modal, Completeness is always included β additionally check Accuracy, Buildings GMDA, and/or Junctions GMDA, then click Run Analysis.
- Results appear as grouped column sets in the results table; only the columns for selected metrics are shown.
- Click Download Results for a zip of all CSV outputs (
ResultSummary.csv,CompletenessDetailedOutput.csv,GeneralizationDetailedOutput.csv,QADetailedOutput.csv,GMDADetailedOutput.csv).
Implementation of the sketch map analysis method from Gardony, Taylor & BrunyΓ© (2016), computing six spatial accuracy metrics between a sketch map and its reference map β in two variants:
- π Landmark-based β uses polygon features (e.g. buildings). Implements the paper's Advanced Mode: each landmark is represented by 8 peripheral points along its minimum bounding rectangle (instead of a single centroid), capturing position and spatial extent/orientation. Feature pairs are aligned via a
SketchAlignattribute and filtered to strict 1:1 matches using a Union-Find structure. - π£ Junction-based β uses street junctions detected from road-segment endpoints that coincide across two or more segments. Sketch junctions are matched to base junctions via a topological subset check on shared road IDs.
| Metric | Measures | Penalizes omissions? |
|---|---|---|
| CanOrg | Canonical organization β overall N/S/E/W topological accuracy | β |
| CanAcc | Canonical accuracy β layout accuracy of drawn landmarks only | β |
| DistAcc | Distance accuracy β normalized pairwise distance error | β |
| ScaBias | Scaling bias β systematic expansion (+) or compression (β) | β |
| AngAcc | Angular accuracy β normalized pairwise angular error | β |
| RotBias | Rotational bias β systematic clockwise (+) / counterclockwise (β) rotation | β |
π Metric formulas & combinatorics
Combinatorics (Advanced Mode)
With 8 peripheral points per landmark, comparisons between points of the same landmark must be excluded. For
Formulas
Canonical Organization β uses all target pairs as denominator, so omitted landmarks lower the score:
$$CanOrg = \frac{\sum_{i=1}^{N_{TL}} \text{CanonicalScore}i}{2N{TL}}$$
Canonical Accuracy β denominator switches to drawn pairs, isolating layout accuracy from recall:
$$CanAcc = \frac{\sum_{i=1}^{N_{DL}} \text{CanonicalScore}i}{2N{DL}}$$
Distance Accuracy β with
Scaling Bias β signed version of the same comparison:
Angular Accuracy β absolute angular deviations scaled against the maximum error of
Rotational Bias β circular mean via trigonometric summation (np.arctan2), gracefully handling the
A second, independent accuracy method: BDR fits a similarity transform (uniform scale, rotation, translation) that best maps the base-map configuration onto the sketch-map configuration by least squares, then measures the residual distortion. It reuses GMDA's 8-point MBR extraction and SketchAlign 1:1 alignment pipeline, and comes in the same Landmarks / Junctions split.
| Metric | Meaning |
|---|---|
| r | Bidimensional correlation β goodness-of-fit of the similarity transform |
| DI | Distortion Index β |
| phi | Fitted uniform scale factor |
| theta | Fitted rotation (degrees) |
| alpha1, alpha2 | Fitted x/y translation |
β‘οΈ Full derivations and implementation notes: bdr/README.md
Both analysis services accept two GeoJSON feature collections and return metrics as JSON.
| Endpoint | Method | Description |
|---|---|---|
/gmda/calculateGMDA/ |
POST |
Landmark-based GMDA |
/gmda/calculateJunctionGMDA/ |
POST |
Junction-based GMDA |
/bdr/calculateLandmarksBDR/ |
POST |
Landmark-based BDR |
/bdr/calculateJunctionsBDR/ |
POST |
Junction-based BDR |
Request / response format
Request (both services):
POST /gmda/calculateGMDA/
Content-Type: application/x-www-form-urlencoded
basemapdata=[GeoJSON string]&sketchmapdata=[GeoJSON string]
Response (GMDA example):
{
"CanOrg": 0.0962,
"CanAcc": 0.8917,
"ScaBias": -0.0001,
"DistAcc": 0.9358,
"RotBias": -30.2334,
"AngAcc": 0.7942,
"nTL": 14,
"nDL": 5
}Production runs on prebuilt images, not source builds:
- CI β every push to
maintriggersregistry-build-publish.yml, building and pushing all service images toghcr.io/ifgi-sil/<service>:latest. - Server β
docker-compose.server.ymlpulls those images; Watchtower polls the registry and auto-updates running containers. - Reverse proxy β an Apache vhost (reference copy) terminates TLS on 443 and proxies each
/service/path to its localhost port. Service ports are never exposed externally.
Adding a new microservice touches six places (service code, both compose files, CI workflow, frontend port map, Apache vhost) β follow the step-by-step checklist in docs/adding-a-new-service.md.
| Document | Contents |
|---|---|
docs/adding-a-new-service.md |
Checklist for adding a microservice, with deploy procedure and failure symptoms |
docs/apache-sketchmapia-ssl.conf |
Reference copy of the production Apache vhost |
docker-compose.server.yml |
Reference copy of the production compose file |
docs/gmda-integration-notes.md |
GMDA implementation details and integration change log |
bdr/README.md |
BDR method background, formulas, and implementation details |
- Gardony, A. L., Taylor, H. A., & BrunyΓ©, T. T. (2016). Gardony Map Drawing Analyzer: Software for quantitative analysis of sketch maps. Behavior Research Methods, 48, 151β177. doi:10.3758/s13428-014-0556-x
- Bi-Dimensional Regression as introduced for cognitive-map comparison by Tobler and formalized by Friedman & Kohler (2003).
The GMDA and BDR features were built with the help of:
- Clement Amirault β @CL-77
- Ajay β @ajay-sheokand
Released under the MIT License Β© 2023 Spatial Intelligence Lab, Institute for Geoinformatics, University of MΓΌnster.
