Как сделать пространственный поиск "содержащимся" на MultiPolygon или нескольких полигонах?

У меня есть карта с множеством маркеров. И у меня есть два непересекающихся полигона (Box). Я хочу получить все маркеры, которые покрыты этими полигонами.

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()

Но результаты таковы:

Count of Polygon 1 = 4
Count of Polygon 2 = 12
Count of MultiPolygon = 237

Почему Polygon 1 + Polygon 2 не равен MultiPolygon?

1 ответ

Решение

Секрет кроется в словах, которые я выделил (из документации по geoqueryset)

содержащиеся

Доступность: PostGIS, MySQL, SpatiaLite

Проверяет, полностью ли содержит ограничивающий прямоугольник геометрического поля ограничивающий прямоугольник поисковой геометрии

Два созданных вами полигона имеют небольшие области, а созданный вами мультиполигон также имеет небольшую область, но этого нельзя сказать о его ограничительной рамке.

qb_1.envelope.area   # 0.0029209960000001417
qb_2.envelope.area   # 4.213217240200014
qbox.envelope.area   # 5754.726987961

как вы увидите, последний из них огромен по сравнению с ним, и он охватывает гораздо больше точек, чем два полигона, взятых самостоятельно. Таким образом, целое больше, чем сумма его частей.

Вы должны быть в состоянии получить действительные точки, покрытые двумя полигонами, следующим образом:

из django.db.models import Q Marker.objects.filter(Q(point__contained=qb_1) | Q(point__contained=qb_1))

Но, возможно, вы действительно ищете, если вы действительно ищете Но это доступно только в postgresql, так что содержит хорошую замену.

содержит

Доступность: PostGIS, Oracle, MySQL, SpatiaLite

Проверяет, содержит ли поле геометрии пространственную геометрию поиска.

Тогда ваш запрос становится

Marker.objects.filter(Q(point__contains=qb_1) | Q(point__contains=qb_1))
Другие вопросы по тегам