1# encoding: utf-8
2
3from __future__ import absolute_import, division, print_function, unicode_literals
4
5from django.contrib.gis.geos import Point
6from django.contrib.gis.measure import D, Distance
7
8from haystack.constants import WGS_84_SRID
9from haystack.exceptions import SpatialError
10
11
12def ensure_geometry(geom):
13    """
14    Makes sure the parameter passed in looks like a GEOS ``GEOSGeometry``.
15    """
16    if not hasattr(geom, 'geom_type'):
17        raise SpatialError("Point '%s' doesn't appear to be a GEOS geometry." % geom)
18
19    return geom
20
21
22def ensure_point(geom):
23    """
24    Makes sure the parameter passed in looks like a GEOS ``Point``.
25    """
26    ensure_geometry(geom)
27
28    if geom.geom_type != 'Point':
29        raise SpatialError("Provided geometry '%s' is not a 'Point'." % geom)
30
31    return geom
32
33
34def ensure_wgs84(point):
35    """
36    Ensures the point passed in is a GEOS ``Point`` & returns that point's
37    data is in the WGS-84 spatial reference.
38    """
39    ensure_point(point)
40    # Clone it so we don't alter the original, in case they're using it for
41    # something else.
42    new_point = point.clone()
43
44    if not new_point.srid:
45        # It has no spatial reference id. Assume WGS-84.
46        new_point.srid = WGS_84_SRID
47    elif new_point.srid != WGS_84_SRID:
48        # Transform it to get to the right system.
49        new_point.transform(WGS_84_SRID)
50
51    return new_point
52
53
54def ensure_distance(dist):
55    """
56    Makes sure the parameter passed in is a 'Distance' object.
57    """
58    try:
59        # Since we mostly only care about the ``.km`` attribute, make sure
60        # it's there.
61        km = dist.km
62    except AttributeError:
63        raise SpatialError("'%s' does not appear to be a 'Distance' object." % dist)
64
65    return dist
66
67
68def generate_bounding_box(bottom_left, top_right):
69    """
70    Takes two opposite corners of a bounding box (order matters!) & generates
71    a two-tuple of the correct coordinates for the bounding box.
72
73    The two-tuple is in the form ``((min_lat, min_lng), (max_lat, max_lng))``.
74    """
75    west, lat_1 = bottom_left.coords
76    east, lat_2 = top_right.coords
77    min_lat, max_lat = min(lat_1, lat_2), max(lat_1, lat_2)
78    return ((min_lat, west), (max_lat, east))
79