Skip to content

Commit

Permalink
Use ST_Covers not ST_Contains for subdivision point lookup
Browse files Browse the repository at this point in the history
ST_Contains doesn’t match if the point is on the boundary of
the subdivision.
  • Loading branch information
davea committed Dec 10, 2024
1 parent 0e8d3cd commit b372a8c
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 4 deletions.
4 changes: 2 additions & 2 deletions mapit/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ def get_queryset(self):
def by_location(self, location, query):
if not location:
return []
query &= Q(polygons__subdivided__division__contains=location)
return Area.objects.filter(query)
query &= Q(polygons__subdivided__division__covers=location)
return Area.objects.filter(query).distinct()

def by_postcode(self, postcode, query):
return list(itertools.chain(
Expand Down
14 changes: 14 additions & 0 deletions mapit/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ def test_areas_by_point(self):
set((x.id for x in (self.big_area, self.small_area_1)))
)

def test_subdivided_areas_by_point(self):
# Choose a point that is directly on the boundary of a subdivision, and ensure that
# looking up the areas for that point returns the correct area.
(x, y) = self.big_shape.subdivided.first().division.coords[0][1]
url = f'/point/{settings.MAPIT_AREA_SRID}/{x},{y}.json'
response = self.client.get(url, HTTP_ACCEPT_ENCODING='gzip')

content = get_content(response)

self.assertEqual(
int(list(content.keys())[0]),
self.big_area.id
)

@override_settings(MAPIT_WITHIN_MAXIMUM=1000)
def test_areas_by_point_within(self):
url = '/point/4326/-4.001,51.json?within=Bad'
Expand Down
4 changes: 2 additions & 2 deletions mapit/views/areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,11 @@ def areas_by_point(request, srid, x, y, bb=False, format=''):
raise ViewException(format, _('Bad "within" parameter specified'), 400)

if method == 'box':
q &= Q(polygons__subdivided__division__bbcontains=location)
q &= Q(polygons__subdivided__division__bbcovers=location)
elif within:
q &= Q(polygons__subdivided__division__dwithin=(location, within))
else:
q &= Q(polygons__subdivided__division__contains=location)
q &= Q(polygons__subdivided__division__covers=location)
areas = Area.objects.filter(q).distinct()

return output_areas(
Expand Down

0 comments on commit b372a8c

Please sign in to comment.