def test20_pointonsurface(self):
        "Testing the `point_on_surface` GeoQuerySet method."
        # Reference values.
        if oracle:
            # SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_GEOM.SDO_POINTONSURFACE(GEOAPP_COUNTRY.MPOLY, 0.05)) FROM GEOAPP_COUNTRY;
            ref = {
                'New Zealand': fromstr('POINT (174.616364 -36.100861)',
                                       srid=4326),
                'Texas': fromstr('POINT (-103.002434 36.500397)', srid=4326),
            }

        elif postgis or spatialite:
            # Using GEOSGeometry to compute the reference point on surface values
            # -- since PostGIS also uses GEOS these should be the same.
            ref = {
                'New Zealand':
                Country.objects.get(name='New Zealand').mpoly.point_on_surface,
                'Texas':
                Country.objects.get(name='Texas').mpoly.point_on_surface
            }

        for c in Country.objects.point_on_surface():
            if spatialite:
                # XXX This seems to be a WKT-translation-related precision issue?
                tol = 0.00001
            else:
                tol = 0.000000001
            self.assertEqual(True,
                             ref[c.name].equals_exact(c.point_on_surface, tol))
    def test15_relate(self):
        "Testing the 'relate' lookup type."
        # To make things more interesting, we will have our Texas reference point in
        # different SRIDs.
        pnt1 = fromstr('POINT (649287.0363174 4177429.4494686)', srid=2847)
        pnt2 = fromstr('POINT(-98.4919715741052 29.4333344025053)', srid=4326)

        # Not passing in a geometry as first param shoud
        # raise a type error when initializing the GeoQuerySet
        self.assertRaises(ValueError,
                          Country.objects.filter,
                          mpoly__relate=(23, 'foo'))

        # Making sure the right exception is raised for the given
        # bad arguments.
        for bad_args, e in [((pnt1, 0), ValueError),
                            ((pnt2, 'T*T***FF*', 0), ValueError)]:
            qs = Country.objects.filter(mpoly__relate=bad_args)
            self.assertRaises(e, qs.count)

        # Relate works differently for the different backends.
        if postgis or spatialite:
            contains_mask = 'T*T***FF*'
            within_mask = 'T*F**F***'
            intersects_mask = 'T********'
        elif oracle:
            contains_mask = 'contains'
            within_mask = 'inside'
            # TODO: This is not quite the same as the PostGIS mask above
            intersects_mask = 'overlapbdyintersect'

        # Testing contains relation mask.
        self.assertEqual(
            'Texas',
            Country.objects.get(mpoly__relate=(pnt1, contains_mask)).name)
        self.assertEqual(
            'Texas',
            Country.objects.get(mpoly__relate=(pnt2, contains_mask)).name)

        # Testing within relation mask.
        ks = State.objects.get(name='Kansas')
        self.assertEqual(
            'Lawrence',
            City.objects.get(point__relate=(ks.poly, within_mask)).name)

        # Testing intersection relation mask.
        if not oracle:
            self.assertEqual(
                'Texas',
                Country.objects.get(mpoly__relate=(pnt1,
                                                   intersects_mask)).name)
            self.assertEqual(
                'Texas',
                Country.objects.get(mpoly__relate=(pnt2,
                                                   intersects_mask)).name)
            self.assertEqual(
                'Lawrence',
                City.objects.get(point__relate=(ks.poly,
                                                intersects_mask)).name)
    def test27_snap_to_grid(self):
        "Testing GeoQuerySet.snap_to_grid()."
        # Let's try and break snap_to_grid() with bad combinations of arguments.
        for bad_args in ((), range(3), range(5)):
            self.assertRaises(ValueError, Country.objects.snap_to_grid,
                              *bad_args)
        for bad_args in (('1.0', ), (1.0, None), tuple(map(unicode,
                                                           range(4)))):
            self.assertRaises(TypeError, Country.objects.snap_to_grid,
                              *bad_args)

        # Boundary for San Marino, courtesy of Bjorn Sandvik of thematicmapping.org
        # from the world borders dataset he provides.
        wkt = (
            'MULTIPOLYGON(((12.41580 43.95795,12.45055 43.97972,12.45389 43.98167,'
            '12.46250 43.98472,12.47167 43.98694,12.49278 43.98917,'
            '12.50555 43.98861,12.51000 43.98694,12.51028 43.98277,'
            '12.51167 43.94333,12.51056 43.93916,12.49639 43.92333,'
            '12.49500 43.91472,12.48778 43.90583,12.47444 43.89722,'
            '12.46472 43.89555,12.45917 43.89611,12.41639 43.90472,'
            '12.41222 43.90610,12.40782 43.91366,12.40389 43.92667,'
            '12.40500 43.94833,12.40889 43.95499,12.41580 43.95795)))')
        sm = Country.objects.create(name='San Marino', mpoly=fromstr(wkt))

        # Because floating-point arithmetic isn't exact, we set a tolerance
        # to pass into GEOS `equals_exact`.
        tol = 0.000000001

        # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.1)) FROM "geoapp_country" WHERE "geoapp_country"."name" = 'San Marino';
        ref = fromstr(
            'MULTIPOLYGON(((12.4 44,12.5 44,12.5 43.9,12.4 43.9,12.4 44)))')
        self.assertTrue(
            ref.equals_exact(
                Country.objects.snap_to_grid(0.1).get(
                    name='San Marino').snap_to_grid, tol))

        # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.05, 0.23)) FROM "geoapp_country" WHERE "geoapp_country"."name" = 'San Marino';
        ref = fromstr(
            'MULTIPOLYGON(((12.4 43.93,12.45 43.93,12.5 43.93,12.45 43.93,12.4 43.93)))'
        )
        self.assertTrue(
            ref.equals_exact(
                Country.objects.snap_to_grid(
                    0.05, 0.23).get(name='San Marino').snap_to_grid, tol))

        # SELECT AsText(ST_SnapToGrid("geoapp_country"."mpoly", 0.5, 0.17, 0.05, 0.23)) FROM "geoapp_country" WHERE "geoapp_country"."name" = 'San Marino';
        ref = fromstr(
            'MULTIPOLYGON(((12.4 43.87,12.45 43.87,12.45 44.1,12.5 44.1,12.5 43.87,12.45 43.87,12.4 43.87)))'
        )
        self.assertTrue(
            ref.equals_exact(
                Country.objects.snap_to_grid(
                    0.05, 0.23, 0.5, 0.17).get(name='San Marino').snap_to_grid,
                tol))
    def __init__(self, geom, title=None, draggable=False, icon=None):
        """
        The GMarker object may initialize on GEOS Points or a parameter
        that may be instantiated into a GEOS point.  Keyword options map to
        GMarkerOptions -- so far only the title option is supported.

        Keyword Options:
         title:
           Title option for GMarker, will be displayed as a tooltip.

         draggable:
           Draggable option for GMarker, disabled by default.
        """
        # If a GEOS geometry isn't passed in, try to construct one.
        if isinstance(geom, basestring): geom = fromstr(geom)
        if isinstance(geom, (tuple, list)): geom = Point(geom)
        if isinstance(geom, Point):
            self.latlng = self.latlng_from_coords(geom.coords)
        else:
            raise TypeError(
                'GMarker may only initialize on GEOS Point geometry.')
        # Getting the envelope for automatic zoom determination.
        self.envelope = geom.envelope
        # TODO: Add support for more GMarkerOptions
        self.title = title
        self.draggable = draggable
        self.icon = icon
        super(GMarker, self).__init__()
    def __init__(self, geom, color='#0000ff', weight=2, opacity=1):
        """
        The GPolyline object may be initialized on GEOS LineStirng, LinearRing,
        and Polygon objects (internal rings not supported) or a parameter that
        may instantiated into one of the above geometries.

        Keyword Options:

          color:
            The color to use for the polyline.  Defaults to '#0000ff' (blue).

          weight:
            The width of the polyline, in pixels.  Defaults to 2.

          opacity:
            The opacity of the polyline, between 0 and 1.  Defaults to 1.
        """
        # If a GEOS geometry isn't passed in, try to contsruct one.
        if isinstance(geom, basestring): geom = fromstr(geom)
        if isinstance(geom, (tuple, list)): geom = Polygon(geom)
        # Generating the lat/lng coordinate pairs.
        if isinstance(geom, (LineString, LinearRing)):
            self.latlngs = self.latlng_from_coords(geom.coords)
        elif isinstance(geom, Polygon):
            self.latlngs = self.latlng_from_coords(geom.shell.coords)
        else:
            raise TypeError(
                'GPolyline may only initialize on GEOS LineString, LinearRing, and/or Polygon geometries.'
            )

        # Getting the envelope for automatic zoom determination.
        self.envelope = geom.envelope
        self.color, self.weight, self.opacity = color, weight, opacity
        super(GPolyline, self).__init__()
 def test14_equals(self):
     "Testing the 'same_as' and 'equals' lookup types."
     pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326)
     c1 = City.objects.get(point=pnt)
     c2 = City.objects.get(point__same_as=pnt)
     c3 = City.objects.get(point__equals=pnt)
     for c in [c1, c2, c3]:
         self.assertEqual('Houston', c.name)
    def test11_lookup_insert_transform(self):
        "Testing automatic transform for lookups and inserts."
        # San Antonio in 'WGS84' (SRID 4326)
        sa_4326 = 'POINT (-98.493183 29.424170)'
        wgs_pnt = fromstr(sa_4326, srid=4326)  # Our reference point in WGS84

        # Oracle doesn't have SRID 3084, using 41157.
        if oracle:
            # San Antonio in 'Texas 4205, Southern Zone (1983, meters)' (SRID 41157)
            # Used the following Oracle SQL to get this value:
            #  SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_GEOMETRY('POINT (-98.493183 29.424170)', 4326), 41157)) FROM DUAL;
            nad_wkt = 'POINT (300662.034646583 5416427.45974934)'
            nad_srid = 41157
        else:
            # San Antonio in 'NAD83(HARN) / Texas Centric Lambert Conformal' (SRID 3084)
            nad_wkt = 'POINT (1645978.362408288754523 6276356.025927528738976)'  # Used ogr.py in gdal 1.4.1 for this transform
            nad_srid = 3084

        # Constructing & querying with a point from a different SRID. Oracle
        # `SDO_OVERLAPBDYINTERSECT` operates differently from
        # `ST_Intersects`, so contains is used instead.
        nad_pnt = fromstr(nad_wkt, srid=nad_srid)
        if oracle:
            tx = Country.objects.get(mpoly__contains=nad_pnt)
        else:
            tx = Country.objects.get(mpoly__intersects=nad_pnt)
        self.assertEqual('Texas', tx.name)

        # Creating San Antonio.  Remember the Alamo.
        sa = City.objects.create(name='San Antonio', point=nad_pnt)

        # Now verifying that San Antonio was transformed correctly
        sa = City.objects.get(name='San Antonio')
        self.assertAlmostEqual(wgs_pnt.x, sa.point.x, 6)
        self.assertAlmostEqual(wgs_pnt.y, sa.point.y, 6)

        # If the GeometryField SRID is -1, then we shouldn't perform any
        # transformation if the SRID of the input geometry is different.
        # SpatiaLite does not support missing SRID values.
        if not spatialite:
            m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
            m1.save()
            self.assertEqual(-1, m1.geom.srid)
    def test04_transform(self):
        "Testing the transform() GeoManager method."
        # Pre-transformed points for Houston and Pueblo.
        htown = fromstr('POINT(1947516.83115183 6322297.06040572)', srid=3084)
        ptown = fromstr('POINT(992363.390841912 481455.395105533)', srid=2774)
        prec = 3  # Precision is low due to version variations in PROJ and GDAL.

        # Asserting the result of the transform operation with the values in
        #  the pre-transformed points.  Oracle does not have the 3084 SRID.
        if not oracle:
            h = City.objects.transform(htown.srid).get(name='Houston')
            self.assertEqual(3084, h.point.srid)
            self.assertAlmostEqual(htown.x, h.point.x, prec)
            self.assertAlmostEqual(htown.y, h.point.y, prec)

        p1 = City.objects.transform(ptown.srid,
                                    field_name='point').get(name='Pueblo')
        p2 = City.objects.transform(srid=ptown.srid).get(name='Pueblo')
        for p in [p1, p2]:
            self.assertEqual(2774, p.point.srid)
            self.assertAlmostEqual(ptown.x, p.point.x, prec)
            self.assertAlmostEqual(ptown.y, p.point.y, prec)
    def __init__(self,
                 poly,
                 stroke_color='#0000ff',
                 stroke_weight=2,
                 stroke_opacity=1,
                 fill_color='#0000ff',
                 fill_opacity=0.4):
        """
        The GPolygon object initializes on a GEOS Polygon or a parameter that
        may be instantiated into GEOS Polygon.  Please note that this will not
        depict a Polygon's internal rings.

        Keyword Options:

          stroke_color:
            The color of the polygon outline. Defaults to '#0000ff' (blue).

          stroke_weight:
            The width of the polygon outline, in pixels.  Defaults to 2.

          stroke_opacity:
            The opacity of the polygon outline, between 0 and 1.  Defaults to 1.

          fill_color:
            The color of the polygon fill.  Defaults to '#0000ff' (blue).

          fill_opacity:
            The opacity of the polygon fill.  Defaults to 0.4.
        """
        if isinstance(poly, basestring): poly = fromstr(poly)
        if isinstance(poly, (tuple, list)): poly = Polygon(poly)
        if not isinstance(poly, Polygon):
            raise TypeError('GPolygon may only initialize on GEOS Polygons.')

        # Getting the envelope of the input polygon (used for automatically
        # determining the zoom level).
        self.envelope = poly.envelope

        # Translating the coordinates into a JavaScript array of
        # Google `GLatLng` objects.
        self.points = self.latlng_from_coords(poly.shell.coords)

        # Stroke settings.
        self.stroke_color, self.stroke_opacity, self.stroke_weight = stroke_color, stroke_opacity, stroke_weight

        # Fill settings.
        self.fill_color, self.fill_opacity = fill_color, fill_opacity

        super(GPolygon, self).__init__()
 def test17_unionagg(self):
     "Testing the `unionagg` (aggregate union) GeoManager method."
     tx = Country.objects.get(name='Texas').mpoly
     # Houston, Dallas -- Oracle has different order.
     union1 = fromstr(
         'MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
     union2 = fromstr(
         'MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
     qs = City.objects.filter(point__within=tx)
     self.assertRaises(TypeError, qs.unionagg, 'name')
     # Using `field_name` keyword argument in one query and specifying an
     # order in the other (which should not be used because this is
     # an aggregate method on a spatial column)
     u1 = qs.unionagg(field_name='point')
     u2 = qs.order_by('name').unionagg()
     tol = 0.00001
     if oracle:
         union = union2
     else:
         union = union1
     self.assertEqual(True, union.equals_exact(u1, tol))
     self.assertEqual(True, union.equals_exact(u2, tol))
     qs = City.objects.filter(name='NotACity')
     self.assertEqual(None, qs.unionagg(field_name='point'))