Search code examples
djangogisgeodjango

django get polygons inside coordinates


I have a coordinate that the frontend gives me like

"[[{"lat":45.36324254131911,"lng":2.471923828125},{"lat":46.667815881216754,"lng":2.471923828125},{"lat":46.667815881216754,"lng":6.50390625},{"lat":45.36324254131911,"lng":6.50390625}]]"

This is a rectangle.

I have a model where I am storing Polygon data

from djgeojson.fields import PolygonField

class MyCords(models.Model):

    geom = PolygonField()

a single instance of Mycords.geom gives me data like:

{'type': 'Polygon',
 'coordinates': [[[5.328369, 45.251688],
   [5.910645, 44.980342],
   [6.328125, 45.375302],
   [6.075439, 45.859412],
   [5.471191, 45.698507],
   [5.328369, 45.251688]]]}

Here I want to filter all the MyCords that lie in the given coordinates.

How can I get this through queryset?


Solution

  • The solution requires 2 steps:

    1. Create a Polygon from the input coordinates. We need to read through the list and create a list of coordinate tuples (as per the linked documentation):

      input_coords = json.loads("[[{"lat":45.36324254131911,"lng":2.471923828125},{"lat":46.667815881216754,"lng":2.471923828125},{"lat":46.667815881216754,"lng":6.50390625},{"lat":45.36324254131911,"lng":6.50390625}]]")
      coord_lst = [(pair['lat'], pair['lng']) for pair in input_coords]
      
      # Note: In order to have a valid Polygon, the first coord pair 
      # needs to be equal to the last pair:
      coord_lst.append(coord_lst[0])
      input_polygon = Polygon(coord_lst)
      

      Note: if the input is a bounding box and you know the (Xmin, Ymin) and (Xmax, Ymax) pairs, you can create a valid Polygon as follows:
      input_polygon = Polygon.from_bbox((Xmin, Ymin, Xmax, Ymax))

    2. We should consider 2 possibilities for our data (MyCords) in conjunction with the input_polygon (follows the same pattern presented in this answer filter by polygon draw in geodjango):

      1. The input_polygon intersects our data.

        Then the query should look like this:

        MyCords.objects.filter(geom__intersects=input_polygon)
        
      2. The data are completely within the input_polygon.

        Then the query should look like this:

        MyCords.objects.filter(geom__within=input_polygon)
        

      We can even combine the 2 and search for data that are either within or intersect the given input_polygon. To achieve that we can use Django's Q() object and the | (OR) operator as follows:

      MyCords.objects.filter(
          Q(geom__intersects=input_polygon) |
          Q(geom__within=input_polygon)
      )