Exemplo n.º 1
0
Arquivo: views.py Projeto: mci/mpatlas
def lookup_point(request):
    """Find nearby polygons with a point and search radius.
    Three lookup methods are supported:
        sphericalmercator: radius (in km) is applied to search buffer in
            900913 (aka Google Spherical Mercator) projection.  This method
            is appropriate when used in conjuction with web maps.
        greatcircle: uses PostGIS ST_DWithin spatial query on a geography
            column, using great circle distances.
        point: simple test if point is inside polygons (e.g., radius=0)
    These methods assume the geometries are in a Geography column.  Edge
    cases across the dateline are handled correctly.
    Different methods are needed if a regular Geometry column is used
    in order to handle cases across the dateline."""
    mpa_list = ()
    default_method = 'webmercator'
    try:
        lon = float(request.GET['lon'])
        lat = float(request.GET['lat'])
        try:
            radius = float(request.GET['radius'])
        except:
            radius = 225.0 # km
        try:
            method = request.GET['method'] or default_method # set default if empty string passed
        except (KeyError):
            method = default_method
        if method not in ('point', 'greatcircle', 'webmercator', 'webmercator_buffer', 'webmercator_box', 'webmercator_simple'):
            raise LookupMethodError('Unknown or malformed lookup method passed in GET query string.')
        if (radius == 0):
            method = 'point'
    except:
        # Bad input, return empty list
        return render(request, 'wdpa/mpalookup.json', {
            'mpa_list': mpa_list,
        }, content_type='application/json; charset=utf-8')
    else:
        # We need to normalize the longitude into the range -180 to 180 so we don't
        # make the cast to PostGIS Geography type complain
        point = geos.Point(normalize_lon(lon), lat, srid=gdal.SpatialReference('WGS84').srid) # srid=4326 , WGS84 geographic
        if (method == 'webmercator'):
            if (normalize_lon(lon) < 0):
                lon360 = normalize_lon(lon) + 360
            else:
                lon360 = normalize_lon(lon) - 360
            point360 = geos.Point(lon360, lat, srid=gdal.SpatialReference('WGS84').srid)
            point.transform(900913) # Google Spherical Mercator srid
            point360.transform(900913)
            #mpa_list = WdpaPolygon.objects.filter(geom_smerc__dwithin=(point, Distance(km=radius))).defer(*WdpaPolygon.get_geom_fields())
            mpa_list = WdpaPolygon.objects.filter(Q(geom_smerc__dwithin=(point, Distance(km=radius))) | Q(geom_smerc__dwithin=(point360, Distance(km=radius)))).defer(*WdpaPolygon.get_geom_fields())
            search = point
        elif (method == 'webmercator_buffer'):
            point.transform(900913) # Google Spherical Mercator srid
            searchbuffer = point.buffer(radius * 1000) # convert km to m, create buffer
            mpa_list = WdpaPolygon.objects.filter(geog__intersects=searchbuffer).defer(*WdpaPolygon.get_geom_fields())
            search = searchbuffer
        elif (method == 'webmercator_box'):
            point.transform(900913) # Google Spherical Mercator srid
            searchbuffer = point.buffer(radius * 1000)
            mpa_list = WdpaPolygon.objects.filter(geog__intersects=searchbuffer.envelope).defer(*WdpaPolygon.get_geom_fields()) # use simple bounding box instead
            search = searchbuffer.envelope
        elif (method == 'webmercator_simple'):
            point.transform(900913) # Google Spherical Mercator srid
            searchbuffer = point.buffer(radius * 1000, quadsegs=2) # simple buffer with 2 segs per quarter circle
            mpa_list = WdpaPolygon.objects.filter(geog__intersects=searchbuffer).defer(*WdpaPolygon.get_geom_fields())
            search = searchbuffer
        elif (method == 'greatcircle'):
            mpa_list = WdpaPolygon.objects.filter(geog__dwithin=(point, Distance(km=radius))).defer(*WdpaPolygon.get_geom_fields())
            search = point
        elif (method == 'point'):
            mpa_list = WdpaPolygon.objects.filter(geog__intersects=point).defer(*WdpaPolygon.get_geom_fields())
            search = point
        candidate_radius = radius * 2.2 # We're using big icons on a point, this let's us catch it better
        mpa_candidate_list = MpaCandidate.objects.filter(geog__dwithin=(point, Distance(km=candidate_radius))).defer(*MpaCandidate.get_geom_fields())
        search.transform(4326)
        return render(request, 'wdpa/mpalookup.json', {
            'search': search.coords,
            'mpa_list': mpa_list,
            'mpa_candidate_list': mpa_candidate_list,
        }, content_type='application/json; charset=utf-8')