Hotspot Clusterer – Technical Details

Back to Demo

High-Level System Overview

  • Purpose: Group spatial points into density-based clusters (hotspots) and separate genuine clusters from scattered noise using DBSCAN.
  • Business problem: Hotspot detection is a core GIS analytic — incident clustering, crime/complaint hotspots, retail catchment cores, and sensor-anomaly grouping all reduce to "which points form dense neighborhoods."
  • Architecture: Razor Page controls → /api/v1/clustering endpoint → ISpatialClusterService → optional spatial_cluster_kernel native library → managed fallback.
  • Technologies: .NET 10, Razor Pages, Bootstrap, vanilla JavaScript, inline SVG, C++20/CMake, P/Invoke.
  • Scope: Euclidean DBSCAN over 2-D coordinates. Great-circle (haversine) distance and spatial indexing are natural next steps for real geographic datasets.

Algorithm

  • DBSCAN: Two parameters — epsilon (neighborhood radius) and minPoints (density threshold). Core points have at least minPoints neighbors within epsilon; density-reachable points join the same cluster; everything else is noise.
  • No pre-set cluster count: Unlike k-means, DBSCAN discovers the number of clusters from the data and is robust to arbitrary cluster shapes.
  • Border reclamation: Points first labelled as noise are reclaimed as border points when they fall inside a later cluster's neighborhood — a subtle correctness detail preserved identically in both the native and managed paths.
  • Complexity: The MVP uses a brute-force O(n²) region query, which is honest and simple; a grid or k-d tree index would bring it toward O(n log n) for large inputs.

API Layer

  • Controller: SpatialClusterController is versioned at /api/v1/clustering and allows anonymous demo access.
  • Endpoint: POST /api/v1/clustering/dbscan accepts DbscanRequestDto (points, epsilon, minPoints).
  • Response: DbscanResultDto returns per-point cluster labels (-1 = noise), a cluster count, per-cluster sizes, and a noise tally.
  • Validation: The service enforces a point cap, a finite positive epsilon, a minimum-points floor, and finite coordinates.

Services and Native Boundary

  • Service: SpatialClusterService validates input, dispatches to SpatialClusterNativeBridge, and assembles the labelled result shared by both paths.
  • Native bridge: SpatialClusterNativeBridge marshals a contiguous point array and a preallocated label buffer into C++ and reads the returned cluster count.
  • C++ library: native/spatial_cluster_kernel exposes Cluster_RunDbscan, returning the cluster count and writing one label per point.
  • Why C++ here: DBSCAN's inner region-query loop is a tight numeric distance kernel over contiguous memory — a strong SIMD/cache-locality candidate as point counts grow.
  • Managed fallback: SpatialClusterService reproduces the identical algorithm in C#, so the workflow is correct with no native library present.

Engineering Decisions and Tradeoffs

  • DBSCAN over k-means: Chosen because hotspot analysis needs shape-agnostic clusters and an explicit noise class, which k-means cannot express.
  • Brute-force neighbors: Keeps the kernel transparent for a portfolio demo; the interface is stable enough to swap in a spatial index without changing the API.
  • Parity by construction: Native and managed code share the same label conventions and border-reclamation rule, making numeric-parity testing straightforward.
  • Future improvements: Haversine distance, k-d tree/grid acceleration, HDBSCAN, and Leaflet/ArcGIS overlays for real geographic incident data.

Interview Discussion Points

  • How do epsilon and minPoints trade off cluster granularity against noise sensitivity?
  • Why is DBSCAN a better fit than k-means for hotspot detection?
  • Where would a spatial index change the asymptotic complexity, and what does it cost to build?
  • How would you validate native/managed parity when floating-point order can differ?