document selection-bounded change detection and export provenance

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jens
2026-08-22 14:56:38 +02:00
co-authored by Claude Opus 5
parent 9614307669
commit 52c2bfd120
2 changed files with 53 additions and 2 deletions
+44 -2
View File
@@ -1080,6 +1080,21 @@ Return vector stats (feature counts and geometry summary).
Return vector bounds and feature count.
### Export provenance
Every exported GeoJSON carries a `geointel_provenance` foreign member on the
FeatureCollection. RFC 7946 requires parsers to ignore members they do not
know, so QGIS and ogr2ogr read the file normally.
It names the source, the dataset and its `source_version`/`observed_at`, the
selection the export was taken from, and — most importantly — whether the file
is complete. A capped selection export previously recorded `truncated` on the
export *record* only: the downloaded file looked whole, and an operator opening
250 of 1.400 buildings in QGIS had nothing to tell them so. Completeness is
derived from the counts as well as the flag, so a caller that forgets to pass
it cannot produce a file that claims to hold everything.
### POST `/api/v1/projects/{project_id}/datasets/{dataset_id}/vector/select`
Selection metrics describe two different populations and now say so.
@@ -2015,7 +2030,7 @@ If the segmentation run has no persisted geometries, the endpoint returns `SEGME
### POST `/api/v1/analysis/change-detection`
Compares two persisted vector datasets in the same project and returns a synchronous
job envelope. This is a lightweight V1 foundation for added/removed object review,
job envelope. This is a lightweight V1 foundation for object-level change review,
not a temporal run-history engine.
Request:
@@ -2025,10 +2040,37 @@ Request:
"source_dataset_id": "uuid",
"target_dataset_id": "uuid",
"iou_threshold": 0.8,
"include_unchanged": true
"modified_threshold": 0.3,
"include_unchanged": true,
"bbox": {"min_x": 5.0, "min_y": 51.1, "max_x": 5.2, "max_y": 51.3, "crs": "EPSG:4326"},
"area_id": "uuid",
"preview_limit": 2000
}
```
`bbox` and `area_id` bound the comparison to the operator's selection, resolved
the same way every other analysis resolves it: the drawn rectangle intersected
with the named work area. Both populations are loaded through an indexed
`ST_Intersects` predicate rather than being read into Python in full. Without a
selection the comparison still covers both datasets entire, which is rarely the
question and — with `include_unchanged` true — previously returned a
FeatureCollection holding both datasets.
Features are **not** clipped to the selection. A change class describes a whole
object, so comparing a clipped earlier footprint against an unclipped later one
would manufacture "modified" along the selection edge. Features the edge crosses
are compared in full and counted in a warning instead.
`modified_threshold` separates a redrawn footprint from two distinct objects.
Between it and `iou_threshold` the change class is `modified`; below it the
source is `removed` and the target `added`. Without that class an extended
building appeared as one removal plus one addition, hiding the category the
analysis exists to show and inflating both counts.
`preview_limit` caps the returned geometry — modified, added, removed and only
then unchanged — while every count still describes the whole selection.
`preview_truncated` says whether the cap applied.
Response is a canonical API envelope containing a `JobRead` payload. On success,
`result_json` contains:
+9
View File
@@ -53,6 +53,15 @@ runtime source of truth.
- Flood-hazard percentages are shares of the modelled area. Where the VMM model
does not cover the selection, that is reported as missing coverage and never
as an absence of risk.
- Change detection compares whole objects and does not clip them to the
selection, so a footprint crossing the selection edge is compared in full.
That is deliberate: clipping one snapshot and not the other would report the
selection edge itself as a change. The count of such objects is reported.
- The change-detection GeoJSON is capped by `preview_limit` (changes first).
The counts always describe the whole selection; the map does not.
- An export states its own completeness in `geointel_provenance`. A capped
export is still a valid, usable file — it simply no longer implies it holds
everything the selection contains.
## Historical analysis