Skip to content

Commit

Permalink
Adapt ConnectionNodeCheck to match projected crs in meters (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
margrietpalm authored Jan 13, 2025
1 parent 9f24514 commit c193706
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Changelog of threedi-modelchecker
- Remove checks for model_settings.epsg_code (317 and 318)
- Remove usage of epsg 4326 in the tests because this CRS is no longer valid
- Remove no longer needed transformations
- Change ConnectionNodeCheck (201) to require minimum distance of 10cm


2.15.0 (2025-01-08)
Expand Down
32 changes: 14 additions & 18 deletions threedi_modelchecker/checks/other.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,30 +320,26 @@ def get_invalid(self, session: Session) -> List[NamedTuple]:
distance between all connection nodes.
"""
query = text(
f"""SELECT *
FROM connection_node AS cn1, connection_node AS cn2
WHERE
distance(cn1.geom, cn2.geom) < :min_distance
AND cn1.ROWID != cn2.ROWID
AND cn2.ROWID IN (
SELECT ROWID
FROM SpatialIndex
WHERE (
f_table_name = "connection_node"
AND search_frame = Buffer(cn1.geom, {self.minimum_distance / 2})));
f"""
SELECT *
FROM connection_node AS cn1, connection_node AS cn2
WHERE ST_Distance(cn1.geom, cn2.geom) < {self.minimum_distance}
AND cn1.ROWID != cn2.ROWID
AND cn2.ROWID IN (
SELECT ROWID
FROM SpatialIndex
WHERE (
f_table_name = "connection_node"
AND search_frame = Buffer(cn1.geom, {self.minimum_distance / 2})))
"""
)
results = (
session.connection()
.execute(query, {"min_distance": self.minimum_distance})
.fetchall()
)

results = session.connection().execute(query).fetchall()
return results

def description(self) -> str:

return (
f"The connection_node is within {self.minimum_distance} degrees of "
f"The connection_node is within {self.minimum_distance * 100 } cm of "
f"another connection_node."
)

Expand Down
2 changes: 1 addition & 1 deletion threedi_modelchecker/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ def is_none_or_empty(col):

## 020x: Spatial checks

CHECKS += [ConnectionNodesDistance(error_code=201, minimum_distance=0.001)]
CHECKS += [ConnectionNodesDistance(error_code=201, minimum_distance=0.1)]
CHECKS += [
QueryCheck(
error_code=202,
Expand Down
38 changes: 12 additions & 26 deletions threedi_modelchecker/tests/test_checks_other.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from unittest import mock

import pytest
from sqlalchemy import func, select, text
from sqlalchemy.orm import aliased, Query
from sqlalchemy import select, text
from threedi_schema import constants, models, ThreediDatabase
from threedi_schema.beta_features import BETA_COLUMNS, BETA_VALUES

Expand Down Expand Up @@ -224,31 +223,18 @@ def test_channel_manhole_level_check(
assert len(errors) == errors_number


def test_node_distance(session):
con1_too_close = factories.ConnectionNodeFactory(
geom=f"SRID={SRID};POINT(142740 473443)",
)
con2_too_close = factories.ConnectionNodeFactory(
geom=f"SRID={SRID};POINT(142743 473443)",
)
# Good distance
factories.ConnectionNodeFactory(
geom=f"SRID={SRID};POINT(142755 473443)",
)
# sanity check to see the distances between the nodes
node_a = aliased(models.ConnectionNode)
node_b = aliased(models.ConnectionNode)
distances_query = Query(func.ST_Distance(node_a.geom, node_b.geom)).filter(
node_a.id != node_b.id
)
# Shows the distances between all 3 nodes: node 1 and 2 are too close
distances_query.with_session(session).all()
check = ConnectionNodesDistance(minimum_distance=10)
@pytest.mark.parametrize("other_x, valid", [(142740.05, False), (142740.15, True)])
def test_node_distance_alt(session, other_x, valid):
factories.ConnectionNodeFactory(id=0, geom=f"SRID={SRID};POINT(142740 473443)")
factories.ConnectionNodeFactory(id=1, geom=f"SRID={SRID};POINT({other_x} 473443)")
# Note that the test uses plain sqlite, so this needs to be committed
session.commit()
check = ConnectionNodesDistance(minimum_distance=0.1)
invalid = check.get_invalid(session)
assert len(invalid) == 2
invalid_ids = [i.id for i in invalid]
assert con1_too_close.id in invalid_ids
assert con2_too_close.id in invalid_ids
assert (len(invalid) == 0) == valid
# Remove connection nodes
session.query(models.ConnectionNode).delete()
session.commit()


class TestCrossSectionSameConfiguration:
Expand Down

0 comments on commit c193706

Please sign in to comment.