Reputation: 450
I have a map with a lot of markers on it. And I have a two not intersecting polygons (Box). I want to get all markers which covered by these polygons.
qb_1 = Polygon.from_bbox((-35.19153, -5.84512, -35.24054, -5.78552))
qb_2 = Polygon.from_bbox((64.16016, 50.26125, 61.80359, 52.04911))
q_box = MultiPolygon(qb_1, qb_2)
test1 = Marker.objects.filter(point__contained=qb_1)
test2 = Marker.objects.filter(point__contained=qb_2)
test = Marker.objects.filter(point__contained=q_box)
print "Count of Polygon 1 = %s" % test1.count()
print "Count of Polygon 2 = %s" % test2.count()
print "Count of MultiPolygon = %s" % test.count()
But the results are:
Count of Polygon 1 = 4
Count of Polygon 2 = 12
Count of MultiPolygon = 237
Why Polygon 1 + Polygon 2 is not equal MultiPolygon ?
Upvotes: 2
Views: 646
Reputation: 53734
The secret lies in the words I have highlighted (from the geoqueryset documentation)
contained
Availability: PostGIS, MySQL, SpatiaLite
Tests if the geometry field’s bounding box is completely contained by the lookup geometry’s bounding box
The two polygons you have created happen to be have small areas, and the multipoligon you have created also has a small area, but the same cannot be said about it's bounding box.
qb_1.envelope.area # 0.0029209960000001417
qb_2.envelope.area # 4.213217240200014
qbox.envelope.area # 5754.726987961
as you will see the last one is huge in comparison an it covers a lot more points than the two polygons taken on their own. Thus the whole is greater than the sum of it's parts.
You should be able to get the actual points covered by the two polygons as follows:
from django.db.models import Q Marker.objects.filter(Q(point__contained=qb_1) | Q(point__contained=qb_1))
But perhaps contains_properly is what you are really looking for? But that's available only in postgresql so contains is a good substitute.
contains
Availability: PostGIS, Oracle, MySQL, SpatiaLite
Tests if the geometry field spatially contains the lookup geometry.
Then your query becomes
Marker.objects.filter(Q(point__contains=qb_1) | Q(point__contains=qb_1))
Upvotes: 3