perf: accelerate regional building partitioning
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
- Added an explicit regional GRB building operator that fetches the approved Kempen scope in 28 resumable municipality partitions and follows every OGC API pagination link.
|
- Added an explicit regional GRB building operator that fetches the approved Kempen scope in 28 resumable municipality partitions and follows every OGC API pagination link.
|
||||||
- Assigned boundary-crossing GRB features to exactly one partition using maximum municipality intersection, with deterministic NIS-code tie breaking and one retained source identity.
|
- Assigned boundary-crossing GRB features to exactly one partition using maximum municipality intersection, with deterministic NIS-code tie breaking and one retained source identity.
|
||||||
|
- Added a covered-by-member fast path so ordinary interior buildings avoid the regional boundary-owner scan while true border cases retain the exact overlap rule.
|
||||||
- Added streaming artifact copy and batch-wise partition indexing through `DatasetService` and `VectorFeatureService`, avoiding one giant multipart parse while preserving one normal regional dataset for existing map and PostGIS selection flows.
|
- Added streaming artifact copy and batch-wise partition indexing through `DatasetService` and `VectorFeatureService`, avoiding one giant multipart parse while preserving one normal regional dataset for existing map and PostGIS selection flows.
|
||||||
- Added truncation guards, source/checksum manifests, immutable observation dates, duplicate-source rejection and focused service/operator tests.
|
- Added truncation guards, source/checksum manifests, immutable observation dates, duplicate-source rejection and focused service/operator tests.
|
||||||
- Kept the provider endpoint contract unchanged and retained explicit operator-only fetching; no source request runs during application startup or interactive map use.
|
- Kept the provider endpoint contract unchanged and retained explicit operator-only fetching; no source request runs during application startup or interactive map use.
|
||||||
|
|||||||
@@ -84,6 +84,41 @@ def test_partition_assignment_is_deterministic_and_has_no_cross_member_duplicate
|
|||||||
assert alpha_features[1]["properties"]["partition_assignment"] == "maximum_boundary_intersection"
|
assert alpha_features[1]["properties"]["partition_assignment"] == "maximum_boundary_intersection"
|
||||||
|
|
||||||
|
|
||||||
|
def test_interior_buildings_skip_regional_owner_scan(monkeypatch) -> None:
|
||||||
|
operator = load_operator()
|
||||||
|
scopes = importlib.import_module("geographic_scopes")
|
||||||
|
member = scopes.ScopeMember("Alpha", "10001")
|
||||||
|
boundary = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
|
||||||
|
scope = scopes.GeographicScope(
|
||||||
|
key="single",
|
||||||
|
display_name="Single",
|
||||||
|
project_name="Single",
|
||||||
|
project_region="Single",
|
||||||
|
area_name="Single boundary",
|
||||||
|
authority_name="Test",
|
||||||
|
authority_url="https://example.test",
|
||||||
|
scope_type="municipality",
|
||||||
|
limitation_message="Test.",
|
||||||
|
members=(member,),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
operator,
|
||||||
|
"assign_owner_nis",
|
||||||
|
lambda *_args, **_kwargs: (_ for _ in ()).throw(AssertionError("interior feature used slow owner scan")),
|
||||||
|
)
|
||||||
|
|
||||||
|
features, _ = operator.build_partition_features(
|
||||||
|
[({"type": "FeatureCollection", "features": [feature("GBG.inside", Polygon([(0.1, 0.1), (0.2, 0.1), (0.2, 0.2), (0.1, 0.2)]))]}, "https://example.test/grb")],
|
||||||
|
member=member,
|
||||||
|
members=[(member, boundary)],
|
||||||
|
regional_boundary=boundary,
|
||||||
|
scope=scope,
|
||||||
|
max_features=10,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert [item["id"] for item in features] == ["GBG.inside"]
|
||||||
|
|
||||||
|
|
||||||
def test_combined_artifact_streams_partitions_and_rejects_duplicate_source_ids(tmp_path: Path) -> None:
|
def test_combined_artifact_streams_partitions_and_rejects_duplicate_source_ids(tmp_path: Path) -> None:
|
||||||
operator = load_operator()
|
operator = load_operator()
|
||||||
scope = importlib.import_module("geographic_scopes").KEMPEN_TRANSPORT_REGION_SCOPE
|
scope = importlib.import_module("geographic_scopes").KEMPEN_TRANSPORT_REGION_SCOPE
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ def build_partition_features(
|
|||||||
assigned_elsewhere_count = 0
|
assigned_elsewhere_count = 0
|
||||||
outside_scope_count = 0
|
outside_scope_count = 0
|
||||||
clipped_to_scope_count = 0
|
clipped_to_scope_count = 0
|
||||||
|
member_boundary = next(boundary for candidate, boundary in members if candidate.nis_code == member.nis_code)
|
||||||
|
|
||||||
for payload, source_url in pages:
|
for payload, source_url in pages:
|
||||||
source_urls.append(source_url)
|
source_urls.append(source_url)
|
||||||
@@ -247,7 +248,11 @@ def build_partition_features(
|
|||||||
if source_geometry is None or not source_geometry.intersects(regional_boundary):
|
if source_geometry is None or not source_geometry.intersects(regional_boundary):
|
||||||
outside_scope_count += 1
|
outside_scope_count += 1
|
||||||
continue
|
continue
|
||||||
owner_nis = assign_owner_nis(source_geometry, members)
|
owner_nis = (
|
||||||
|
member.nis_code
|
||||||
|
if member_boundary.covers(source_geometry)
|
||||||
|
else assign_owner_nis(source_geometry, members)
|
||||||
|
)
|
||||||
if owner_nis != member.nis_code:
|
if owner_nis != member.nis_code:
|
||||||
assigned_elsewhere_count += 1
|
assigned_elsewhere_count += 1
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user