3D-ULPIN is a spatial computing backend. It provides a robust API to process, store, validate, and retrieve 3D cadastral parcels and their volumetric boundaries.
The entire API backend system is containerized for seamless reproducibility and isolation across different host environments.
It handles varied inputs like raw LiDAR point clouds, aerial drone surveys using a mix of exact geometric computation (EGC) and statistical fusion.
The system relies on five main engines to process and validate data:
- Spatial Indexing: PostGIS GiST indexes provide high-performance spatial queries on 3D polyhedral surfaces.
- Bayesian Sensor Fusion: Sensors lie. When we get conflicting height data (e.g., a drone scan vs. a ground survey), we use inverse-variance Bayesian inference to calculate the actual ground truth and drop the outliers.
- Anomaly Detection: An unsupervised Scikit-Learn
IsolationForestmonitors footprint and height variances to flag illegal or anomalous vertical developments. - 3D ULPIN Generation: We create deterministic, immutable spatial IDs by combining 3D Morton code bit-shifting with salted SHA-256 checksums.
- Collision Detection: Checks if two infrastructure volumes (like a basement and a proposed metro tunnel) intersect. We use Shapely for fast in-memory checks and PostGIS SFCGAL (
ST_3DIntersects) for persistent database validation.
- API & Core: Python 3.12, FastAPI, SQLAlchemy 2.0, Pydantic
- Async Task Queue: Celery + Redis (with AOF persistence)
- Math & ML: Shapely, Open3D, Scikit-Learn, Ultralytics YOLOv8-Seg
- Database: PostgreSQL + PostGIS (with SFCGAL 3D extension)
- Environment:
uv(package management), Docker Compose - Frontend: React.js + Tailswind CSS
These endpoints handle mathematical computations and database writes on the fly.
| Method | Endpoint | What it does |
|---|---|---|
POST |
/api/v1/cadastre/validate-building |
Takes sensor data and 2D footprints. Computes the real height, runs anomaly checks, generates a 3D ULPIN, and saves a POLYHEDRALSURFACE Z to PostGIS. |
POST |
/api/v1/cadastre/check-conflict |
In-memory check to prove two spatial volumes do not intersect. |
GET |
/api/v1/cadastre/db-conflict/{id1}/{id2} |
Asks PostGIS to verify if two saved parcels collide in 3D space. |
GET |
/api/v1/cadastre/parcels |
Returns paginated 3D parcels as Well-Known Text (WKT) with computed bounding boxes. Supports limit and offset query params. |
Heavy processing jobs offloaded to Celery. Submit a file and poll the status using the returned job_id.
| Method | Endpoint | What it does |
|---|---|---|
POST |
/api/v1/cadastre/ingest-lidar |
Upload a .ply/.pcd/.las/.laz point cloud (max 500 MB). Open3D downsamples it, removes the ground plane via RANSAC, and isolates structures with DBSCAN. |
POST |
/api/v1/cadastre/ingest-drone |
Upload a .jpg/.png/.tif drone image (max 500 MB). YOLOv8-Seg and the Ramer-Douglas-Peucker algorithm extract the vector footprints. |
GET |
/api/v1/cadastre/job-status/{id} |
Check if your Celery task is PENDING, COMPLETED, or FAILED. |
Clone the repo and set up your environment variables.
cp .env.example .envEdit your .env with secure values:
DATABASE_URL="postgresql://ulpin_worker:<your_password>@db:5432/ulpin_db"
HEXCODE_SALT="<generate_a_random_64_char_hex_string>"
POSTGRES_SUPER_PASS="<your_admin_password>"
DB_WORKER_PASSWORD="<your_password>"
ALLOWED_ORIGINS="http://localhost:3000,http://localhost:5173"
⚠️ Security Note: Never commit.envfiles to version control. The.gitignorealready excludes.env— always use.env.exampleas a template reference.
The entire architecture is containerized:
docker compose up --buildThis spins up PostgreSQL (with PostGIS + SFCGAL), Redis (with AOF persistence), the Celery worker, and the FastAPI server. A shared Docker volume (shared-uploads) ensures uploaded files are accessible to both the API and the Celery worker.
- Interactive API Docs:
http://127.0.0.1:8000/docs
We use pytest with mocked database connections and Celery workers to keep tests fast and isolated.
If running locally outside of Docker:
uv sync
uv run --env-file .env pytest -v