Exemplo n.º 1
0
    def get_prep_value(self, value):
        obj = super().get_prep_value(value)
        if obj is None:
            return None
        # When the input is not a geometry or raster, attempt to construct one
        # from the given string input.
        if isinstance(obj, GEOSGeometry):
            pass
        else:
            # Check if input is a candidate for conversion to raster or geometry.
            is_candidate = isinstance(obj, (bytes, str)) or hasattr(
                obj, '__geo_interface__')
            # Try to convert the input to raster.
            raster = self.get_raster_prep_value(obj, is_candidate)

            if raster:
                obj = raster
            elif is_candidate:
                try:
                    obj = GEOSGeometry(obj)
                except (GEOSException, GDALException):
                    raise ValueError(
                        "Couldn't create spatial object from lookup value '%s'."
                        % obj)
            else:
                raise ValueError(
                    'Cannot use object with type %s for a spatial lookup parameter.'
                    % type(obj).__name__)

        # Assigning the SRID value.
        obj.srid = self.get_srid(obj)
        return obj
Exemplo n.º 2
0
 def setUp(self):
     # A point we are testing distances with -- using a WGS84
     # coordinate that'll be implicitly transformed to that to
     # the coordinate system of the field, EPSG:32140 (Texas South Central
     # w/units in meters)
     self.stx_pnt = GEOSGeometry(
         'POINT (-95.370401017314293 29.704867409475465)', 4326)
     # Another one for Australia
     self.au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326)
Exemplo n.º 3
0
    def test04_wkbwriter(self):
        wkb_w = WKBWriter()

        # Representations of 'POINT (5 23)' in hex -- one normal and
        # the other with the byte order changed.
        g = GEOSGeometry('POINT (5 23)')
        hex1 = b'010100000000000000000014400000000000003740'
        wkb1 = memoryview(binascii.a2b_hex(hex1))
        hex2 = b'000000000140140000000000004037000000000000'
        wkb2 = memoryview(binascii.a2b_hex(hex2))

        self.assertEqual(hex1, wkb_w.write_hex(g))
        self.assertEqual(wkb1, wkb_w.write(g))

        # Ensuring bad byteorders are not accepted.
        for bad_byteorder in (-1, 2, 523, 'foo', None):
            # Equivalent of `wkb_w.byteorder = bad_byteorder`
            with self.assertRaises(ValueError):
                wkb_w._set_byteorder(bad_byteorder)

        # Setting the byteorder to 0 (for Big Endian)
        wkb_w.byteorder = 0
        self.assertEqual(hex2, wkb_w.write_hex(g))
        self.assertEqual(wkb2, wkb_w.write(g))

        # Back to Little Endian
        wkb_w.byteorder = 1

        # Now, trying out the 3D and SRID flags.
        g = GEOSGeometry('POINT (5 23 17)')
        g.srid = 4326

        hex3d = b'0101000080000000000000144000000000000037400000000000003140'
        wkb3d = memoryview(binascii.a2b_hex(hex3d))
        hex3d_srid = b'01010000A0E6100000000000000000144000000000000037400000000000003140'
        wkb3d_srid = memoryview(binascii.a2b_hex(hex3d_srid))

        # Ensuring bad output dimensions are not accepted
        for bad_outdim in (-1, 0, 1, 4, 423, 'foo', None):
            with self.assertRaisesMessage(
                    ValueError, 'WKB output dimension must be 2 or 3'):
                wkb_w.outdim = bad_outdim

        # Now setting the output dimensions to be 3
        wkb_w.outdim = 3

        self.assertEqual(hex3d, wkb_w.write_hex(g))
        self.assertEqual(wkb3d, wkb_w.write(g))

        # Telling the WKBWriter to include the srid in the representation.
        wkb_w.srid = True
        self.assertEqual(hex3d_srid, wkb_w.write_hex(g))
        self.assertEqual(wkb3d_srid, wkb_w.write(g))
Exemplo n.º 4
0
    def test_field_with_text_widget(self):
        class PointForm(forms.Form):
            pt = forms.PointField(srid=4326, widget=forms.TextInput)

        form = PointForm()
        cleaned_pt = form.fields['pt'].clean('POINT(5 23)')
        self.assertEqual(cleaned_pt, GEOSGeometry('POINT(5 23)', srid=4326))
        self.assertEqual(4326, cleaned_pt.srid)
        with self.assertRaisesMessage(ValidationError,
                                      'Invalid geometry value.'):
            form.fields['pt'].clean('POINT(5)')

        point = GEOSGeometry('SRID=4326;POINT(5 23)')
        form = PointForm(data={'pt': 'POINT(5 23)'}, initial={'pt': point})
        self.assertFalse(form.has_changed())
Exemplo n.º 5
0
 def deserialize(self, value):
     try:
         return GEOSGeometry(value)
     except (GEOSException, ValueError, TypeError) as err:
         logger.error("Error creating geometry from value '%s' (%s)", value,
                      err)
     return None
Exemplo n.º 6
0
    def test_custom_serialization_widget(self):
        class CustomGeometryWidget(forms.BaseGeometryWidget):
            template_name = 'gis/openlayers.html'
            deserialize_called = 0

            def serialize(self, value):
                return value.json if value else ''

            def deserialize(self, value):
                self.deserialize_called += 1
                return GEOSGeometry(value)

        class PointForm(forms.Form):
            p = forms.PointField(widget=CustomGeometryWidget)

        point = GEOSGeometry("SRID=4326;POINT(9.052734375 42.451171875)")
        form = PointForm(data={'p': point})
        self.assertIn(escape(point.json), form.as_p())

        CustomGeometryWidget.called = 0
        widget = form.fields['p'].widget
        # Force deserialize use due to a string value
        self.assertIn(escape(point.json), widget.render('p', point.json))
        self.assertEqual(widget.deserialize_called, 1)

        form = PointForm(data={'p': point.json})
        self.assertTrue(form.is_valid())
        self.assertEqual(form.cleaned_data['p'].srid, 4326)
Exemplo n.º 7
0
    def test_union(self):
        """Union with all combinations of geometries/geometry fields."""
        geom = Point(-95.363151, 29.763374, srid=4326)

        union = City.objects.annotate(union=functions.Union('point', geom)).get(name='Dallas').union
        expected = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)', srid=4326)
        self.assertTrue(expected.equals(union))

        union = City.objects.annotate(union=functions.Union(geom, 'point')).get(name='Dallas').union
        self.assertTrue(expected.equals(union))

        union = City.objects.annotate(union=functions.Union('point', 'point')).get(name='Dallas').union
        expected = GEOSGeometry('POINT(-96.801611 32.782057)', srid=4326)
        self.assertTrue(expected.equals(union))

        union = City.objects.annotate(union=functions.Union(geom, geom)).get(name='Dallas').union
        self.assertTrue(geom.equals(union))
Exemplo n.º 8
0
 def _load_polygon_data(self):
     bbox_wkt, bbox_z = bbox_data
     bbox_2d = GEOSGeometry(bbox_wkt, srid=32140)
     bbox_3d = Polygon(tuple(
         (x, y, z) for (x, y), z in zip(bbox_2d[0].coords, bbox_z)),
                       srid=32140)
     Polygon2D.objects.create(name='2D BBox', poly=bbox_2d)
     Polygon3D.objects.create(name='3D BBox', poly=bbox_3d)
Exemplo n.º 9
0
 def test_result_of_gis_lookup_with_rasters(self):
     # Point is in the interior
     qs = RasterModel.objects.filter(
         rast__contains=GEOSGeometry('POINT (-0.5 0.5)', 4326))
     self.assertEqual(qs.count(), 1)
     # Point is in the exterior
     qs = RasterModel.objects.filter(
         rast__contains=GEOSGeometry('POINT (0.5 0.5)', 4326))
     self.assertEqual(qs.count(), 0)
     # A point on the boundary is not contained properly
     qs = RasterModel.objects.filter(
         rast__contains_properly=GEOSGeometry('POINT (0 0)', 4326))
     self.assertEqual(qs.count(), 0)
     # Raster is located left of the point
     qs = RasterModel.objects.filter(
         rast__left=GEOSGeometry('POINT (1 0)', 4326))
     self.assertEqual(qs.count(), 1)
Exemplo n.º 10
0
    def test02_wktwriter(self):
        # Creating a WKTWriter instance, testing its ptr property.
        wkt_w = WKTWriter()
        with self.assertRaises(TypeError):
            wkt_w.ptr = WKTReader.ptr_type()

        ref = GEOSGeometry('POINT (5 23)')
        ref_wkt = 'POINT (5.0000000000000000 23.0000000000000000)'
        self.assertEqual(ref_wkt, wkt_w.write(ref).decode())
Exemplo n.º 11
0
 def test_srid(self):
     "Testing GeometryField with a SRID set."
     # Input that doesn't specify the SRID is assumed to be in the SRID
     # of the input field.
     fld = forms.GeometryField(srid=4326)
     geom = fld.clean('POINT(5 23)')
     self.assertEqual(4326, geom.srid)
     # Making the field in a different SRID from that of the geometry, and
     # asserting it transforms.
     fld = forms.GeometryField(srid=32140)
     tol = 0.0000001
     xform_geom = GEOSGeometry('POINT (951640.547328465 4219369.26171664)',
                               srid=32140)
     # The cleaned geometry is transformed to 32140 (the widget map_srid is 3857).
     cleaned_geom = fld.clean(
         'SRID=3857;POINT (-10615777.40976205 3473169.895707852)')
     self.assertEqual(cleaned_geom.srid, 32140)
     self.assertTrue(xform_geom.equals_exact(cleaned_geom, tol))
Exemplo n.º 12
0
 def setUp(self):
     self.geometries = {
         'point':
         GEOSGeometry("SRID=4326;POINT(9.052734375 42.451171875)"),
         'multipoint':
         GEOSGeometry("SRID=4326;MULTIPOINT("
                      "(13.18634033203125 14.504356384277344),"
                      "(13.207969665527 14.490966796875),"
                      "(13.177070617675 14.454917907714))"),
         'linestring':
         GEOSGeometry("SRID=4326;LINESTRING("
                      "-8.26171875 -0.52734375,"
                      "-7.734375 4.21875,"
                      "6.85546875 3.779296875,"
                      "5.44921875 -3.515625)"),
         'multilinestring':
         GEOSGeometry("SRID=4326;MULTILINESTRING("
                      "(-16.435546875 -2.98828125,"
                      "-17.2265625 2.98828125,"
                      "-0.703125 3.515625,"
                      "-1.494140625 -3.33984375),"
                      "(-8.0859375 -5.9765625,"
                      "8.525390625 -8.7890625,"
                      "12.392578125 -0.87890625,"
                      "10.01953125 7.646484375))"),
         'polygon':
         GEOSGeometry("SRID=4326;POLYGON("
                      "(-1.669921875 6.240234375,"
                      "-3.8671875 -0.615234375,"
                      "5.9765625 -3.955078125,"
                      "18.193359375 3.955078125,"
                      "9.84375 9.4921875,"
                      "-1.669921875 6.240234375))"),
         'multipolygon':
         GEOSGeometry("SRID=4326;MULTIPOLYGON("
                      "((-17.578125 13.095703125,"
                      "-17.2265625 10.8984375,"
                      "-13.974609375 10.1953125,"
                      "-13.359375 12.744140625,"
                      "-15.732421875 13.7109375,"
                      "-17.578125 13.095703125)),"
                      "((-8.525390625 5.537109375,"
                      "-8.876953125 2.548828125,"
                      "-5.888671875 1.93359375,"
                      "-5.09765625 4.21875,"
                      "-6.064453125 6.240234375,"
                      "-8.525390625 5.537109375)))"),
         'geometrycollection':
         GEOSGeometry("SRID=4326;GEOMETRYCOLLECTION("
                      "POINT(5.625 -0.263671875),"
                      "POINT(6.767578125 -3.603515625),"
                      "POINT(8.525390625 0.087890625),"
                      "POINT(8.0859375 -2.13134765625),"
                      "LINESTRING("
                      "6.273193359375 -1.175537109375,"
                      "5.77880859375 -1.812744140625,"
                      "7.27294921875 -2.230224609375,"
                      "7.657470703125 -1.25244140625))"),
     }
Exemplo n.º 13
0
 def test_empty_polygon_wkb(self):
     p = Polygon(srid=4326)
     p_no_srid = Polygon()
     wkb_w = WKBWriter()
     wkb_w.srid = True
     for byteorder, hexes in enumerate([
         (b'000000000300000000', b'0020000003000010E600000000'),
         (b'010300000000000000', b'0103000020E610000000000000'),
     ]):
         wkb_w.byteorder = byteorder
         for srid, hex in enumerate(hexes):
             wkb_w.srid = srid
             self.assertEqual(wkb_w.write_hex(p), hex)
             self.assertEqual(GEOSGeometry(wkb_w.write_hex(p)),
                              p if srid else p_no_srid)
             self.assertEqual(wkb_w.write(p),
                              memoryview(binascii.a2b_hex(hex)))
             self.assertEqual(GEOSGeometry(wkb_w.write(p)),
                              p if srid else p_no_srid)
Exemplo n.º 14
0
 def get_geoms(self, geos=False):
     """
     Return a list containing the OGRGeometry for every Feature in
     the Layer.
     """
     if geos:
         from djmodels.contrib.gis.geos import GEOSGeometry
         return [GEOSGeometry(feat.geom.wkb) for feat in self]
     else:
         return [feat.geom for feat in self]
Exemplo n.º 15
0
 def test_unionagg(self):
     """
     Testing the `Union` aggregate.
     """
     tx = Country.objects.get(name='Texas').mpoly
     # Houston, Dallas -- Ordering may differ depending on backend or GEOS version.
     union = GEOSGeometry(
         'MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
     qs = City.objects.filter(point__within=tx)
     with self.assertRaises(ValueError):
         qs.aggregate(Union('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.aggregate(Union('point'))['point__union']
     u2 = qs.order_by('name').aggregate(Union('point'))['point__union']
     self.assertTrue(union.equals(u1))
     self.assertTrue(union.equals(u2))
     qs = City.objects.filter(name='NotACity')
     self.assertIsNone(qs.aggregate(Union('point'))['point__union'])
Exemplo n.º 16
0
 def test_distance_simple(self):
     """
     Test a simple distance query, with projected coordinates and without
     transformation.
     """
     lagrange = GEOSGeometry('POINT(805066.295722839 4231496.29461335)',
                             32140)
     houston = SouthTexasCity.objects.annotate(
         dist=Distance('point', lagrange)).order_by('id').first()
     tol = 2 if oracle else 5
     self.assertAlmostEqual(houston.dist.m, 147075.069813, tol)
Exemplo n.º 17
0
    def _load_interstate_data(self):
        # Interstate (2D / 3D and Geographic/Projected variants)
        for name, line, exp_z in interstate_data:
            line_3d = GEOSGeometry(line, srid=4269)
            line_2d = LineString([l[:2] for l in line_3d.coords], srid=4269)

            # Creating a geographic and projected version of the
            # interstate in both 2D and 3D.
            Interstate3D.objects.create(name=name, line=line_3d)
            InterstateProj3D.objects.create(name=name, line=line_3d)
            Interstate2D.objects.create(name=name, line=line_2d)
            InterstateProj2D.objects.create(name=name, line=line_2d)
Exemplo n.º 18
0
    def test_empty_point_wkb(self):
        p = Point(srid=4326)
        wkb_w = WKBWriter()

        wkb_w.srid = False
        with self.assertRaisesMessage(
                ValueError, 'Empty point is not representable in WKB.'):
            wkb_w.write(p)
        with self.assertRaisesMessage(
                ValueError, 'Empty point is not representable in WKB.'):
            wkb_w.write_hex(p)

        wkb_w.srid = True
        for byteorder, hex in enumerate([
                b'0020000001000010E67FF80000000000007FF8000000000000',
                b'0101000020E6100000000000000000F87F000000000000F87F',
        ]):
            wkb_w.byteorder = byteorder
            self.assertEqual(wkb_w.write_hex(p), hex)
            self.assertEqual(GEOSGeometry(wkb_w.write_hex(p)), p)
            self.assertEqual(wkb_w.write(p), memoryview(binascii.a2b_hex(hex)))
            self.assertEqual(GEOSGeometry(wkb_w.write(p)), p)
Exemplo n.º 19
0
    def test_geom_type(self):
        "Testing GeometryField's handling of different geometry types."
        # By default, all geometry types are allowed.
        fld = forms.GeometryField()
        for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))',
                    'LINESTRING(0 0, 1 1)'):
            with self.subTest(wkt=wkt):
                # to_python() uses the SRID of OpenLayersWidget if the
                # converted value doesn't have an SRID.
                self.assertEqual(GEOSGeometry(wkt, srid=fld.widget.map_srid),
                                 fld.clean(wkt))

        pnt_fld = forms.GeometryField(geom_type='POINT')
        self.assertEqual(
            GEOSGeometry('POINT(5 23)', srid=pnt_fld.widget.map_srid),
            pnt_fld.clean('POINT(5 23)'))
        # a WKT for any other geom_type will be properly transformed by `to_python`
        self.assertEqual(
            GEOSGeometry('LINESTRING(0 0, 1 1)', srid=pnt_fld.widget.map_srid),
            pnt_fld.to_python('LINESTRING(0 0, 1 1)'))
        # but rejected by `clean`
        with self.assertRaises(forms.ValidationError):
            pnt_fld.clean('LINESTRING(0 0, 1 1)')
Exemplo n.º 20
0
    def test_make_line(self):
        """
        Testing the `MakeLine` aggregate.
        """
        if not connection.features.supports_make_line_aggr:
            with self.assertRaises(NotSupportedError):
                City.objects.all().aggregate(MakeLine('point'))
            return

        # MakeLine on an inappropriate field returns simply None
        self.assertIsNone(
            State.objects.aggregate(MakeLine('poly'))['poly__makeline'])
        # Reference query:
        # SELECT AsText(ST_MakeLine(geoapp_city.point)) FROM geoapp_city;
        ref_line = GEOSGeometry(
            'LINESTRING(-95.363151 29.763374,-96.801611 32.782057,'
            '-97.521157 34.464642,174.783117 -41.315268,-104.609252 38.255001,'
            '-95.23506 38.971823,-87.650175 41.850385,-123.305196 48.462611)',
            srid=4326)
        # We check for equality with a tolerance of 10e-5 which is a lower bound
        # of the precisions of ref_line coordinates
        line = City.objects.aggregate(MakeLine('point'))['point__makeline']
        self.assertTrue(ref_line.equals_exact(line, tolerance=10e-5),
                        "%s != %s" % (ref_line, line))
Exemplo n.º 21
0
 def test_union(self):
     """
     Testing the Union aggregate of 3D models.
     """
     # PostGIS query that returned the reference EWKT for this test:
     #  `SELECT ST_AsText(ST_Union(point)) FROM geo3d_city3d;`
     self._load_city_data()
     ref_ewkt = (
         'SRID=4326;MULTIPOINT(-123.305196 48.462611 15,-104.609252 38.255001 1433,'
         '-97.521157 34.464642 380,-96.801611 32.782057 147,-95.363151 29.763374 18,'
         '-95.23506 38.971823 251,-87.650175 41.850385 181,174.783117 -41.315268 14)'
     )
     ref_union = GEOSGeometry(ref_ewkt)
     union = City3D.objects.aggregate(Union('point'))['point__union']
     self.assertTrue(union.hasz)
     # Ordering of points in the resulting geometry may vary between implementations
     self.assertEqual({p.ewkt for p in ref_union}, {p.ewkt for p in union})
Exemplo n.º 22
0
 def test_to_python(self):
     """
     Testing to_python returns a correct GEOSGeometry object or
     a ValidationError
     """
     fld = forms.GeometryField()
     # to_python returns the same GEOSGeometry for a WKT
     for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))',
                 'LINESTRING(0 0, 1 1)'):
         with self.subTest(wkt=wkt):
             self.assertEqual(GEOSGeometry(wkt, srid=fld.widget.map_srid),
                              fld.to_python(wkt))
     # but raises a ValidationError for any other string
     for wkt in ('POINT(5)', 'MULTI   POLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))',
                 'BLAH(0 0, 1 1)'):
         with self.subTest(wkt=wkt):
             with self.assertRaises(forms.ValidationError):
                 fld.to_python(wkt)
Exemplo n.º 23
0
 def test_db_function_errors(self):
     """
     Errors are raised when using DB functions with raster content.
     """
     point = GEOSGeometry(
         "SRID=3086;POINT (-697024.9213808845 683729.1705516104)")
     rast = GDALRaster(json.loads(JSON_RASTER))
     msg = "Distance function requires a geometric argument in position 2."
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("geom", rast))
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("rastprojected", rast))
     msg = "Distance function requires a GeometryField in position 1, got RasterField."
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("rastprojected", point)).count()
Exemplo n.º 24
0
    def test01_wktreader(self):
        # Creating a WKTReader instance
        wkt_r = WKTReader()
        wkt = 'POINT (5 23)'

        # read() should return a GEOSGeometry
        ref = GEOSGeometry(wkt)
        g1 = wkt_r.read(wkt.encode())
        g2 = wkt_r.read(wkt)

        for geom in (g1, g2):
            self.assertEqual(ref, geom)

        # Should only accept string objects.
        with self.assertRaises(TypeError):
            wkt_r.read(1)
        with self.assertRaises(TypeError):
            wkt_r.read(memoryview(b'foo'))
Exemplo n.º 25
0
    def test03_wkbreader(self):
        # Creating a WKBReader instance
        wkb_r = WKBReader()

        hex = b'000000000140140000000000004037000000000000'
        wkb = memoryview(binascii.a2b_hex(hex))
        ref = GEOSGeometry(hex)

        # read() should return a GEOSGeometry on either a hex string or
        # a WKB buffer.
        g1 = wkb_r.read(wkb)
        g2 = wkb_r.read(hex)
        for geom in (g1, g2):
            self.assertEqual(ref, geom)

        bad_input = (1, 5.23, None, False)
        for bad_wkb in bad_input:
            with self.assertRaises(TypeError):
                wkb_r.read(bad_wkb)
Exemplo n.º 26
0
    def test_distance_projected(self):
        """
        Test the `Distance` function on projected coordinate systems.
        """
        # The point for La Grange, TX
        lagrange = GEOSGeometry('POINT(-96.876369 29.905320)', 4326)
        # Reference distances in feet and in meters. Got these values from
        # using the provided raw SQL statements.
        #  SELECT ST_Distance(point, ST_Transform(ST_GeomFromText('POINT(-96.876369 29.905320)', 4326), 32140))
        #  FROM distapp_southtexascity;
        m_distances = [
            147075.069813, 139630.198056, 140888.552826, 138809.684197,
            158309.246259, 212183.594374, 70870.188967, 165337.758878,
            139196.085105
        ]
        #  SELECT ST_Distance(point, ST_Transform(ST_GeomFromText('POINT(-96.876369 29.905320)', 4326), 2278))
        #  FROM distapp_southtexascityft;
        ft_distances = [
            482528.79154625, 458103.408123001, 462231.860397575,
            455411.438904354, 519386.252102563, 696139.009211594,
            232513.278304279, 542445.630586414, 456679.155883207
        ]

        # Testing using different variations of parameters and using models
        # with different projected coordinate systems.
        dist1 = SouthTexasCity.objects.annotate(
            distance=Distance('point', lagrange)).order_by('id')
        dist2 = SouthTexasCityFt.objects.annotate(
            distance=Distance('point', lagrange)).order_by('id')
        dist_qs = [dist1, dist2]

        # Original query done on PostGIS, have to adjust AlmostEqual tolerance
        # for Oracle.
        tol = 2 if oracle else 5

        # Ensuring expected distances are returned for each distance queryset.
        for qs in dist_qs:
            for i, c in enumerate(qs):
                with self.subTest(c=c):
                    self.assertAlmostEqual(m_distances[i], c.distance.m, tol)
                    self.assertAlmostEqual(ft_distances[i],
                                           c.distance.survey_ft, tol)
Exemplo n.º 27
0
    def test_field_string_value(self):
        """
        Initialization of a geometry field with a valid/empty/invalid string.
        Only the invalid string should trigger an error log entry.
        """
        class PointForm(forms.Form):
            pt1 = forms.PointField(srid=4326)
            pt2 = forms.PointField(srid=4326)
            pt3 = forms.PointField(srid=4326)

        form = PointForm({
            'pt1': 'SRID=4326;POINT(7.3 44)',  # valid
            'pt2': '',  # empty
            'pt3': 'PNT(0)',  # invalid
        })

        with self.assertLogs('djmodels.contrib.gis', 'ERROR') as logger_calls:
            output = str(form)

        # The first point can't use assertInHTML() due to non-deterministic
        # ordering of the rendered dictionary.
        pt1_serialized = re.search(r'<textarea [^>]*>({[^<]+})<',
                                   output).groups()[0]
        pt1_json = pt1_serialized.replace('&quot;', '"')
        pt1_expected = GEOSGeometry(form.data['pt1']).transform(3857,
                                                                clone=True)
        self.assertJSONEqual(pt1_json, pt1_expected.json)

        self.assertInHTML(
            '<textarea id="id_pt2" class="vSerializedField required" cols="150"'
            ' rows="10" name="pt2"></textarea>', output)
        self.assertInHTML(
            '<textarea id="id_pt3" class="vSerializedField required" cols="150"'
            ' rows="10" name="pt3"></textarea>', output)
        # Only the invalid PNT(0) triggers an error log entry.
        # Deserialization is called in form clean and in widget rendering.
        self.assertEqual(len(logger_calls.records), 2)
        self.assertEqual(
            logger_calls.records[0].getMessage(),
            "Error creating geometry from value 'PNT(0)' (String input "
            "unrecognized as WKT EWKT, and HEXEWKB.)")
Exemplo n.º 28
0
    def test_dwithin_gis_lookup_ouptut_with_rasters(self):
        """
        Check the logical functionality of the dwithin lookup for different
        input parameters.
        """
        # Create test raster and geom.
        rast = GDALRaster(json.loads(JSON_RASTER))
        stx_pnt = GEOSGeometry(
            'POINT (-95.370401017314293 29.704867409475465)', 4326)
        stx_pnt.transform(3086)

        # Filter raster with different lookup raster formats.
        qs = RasterModel.objects.filter(rastprojected__dwithin=(rast, D(km=1)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(
            rastprojected__dwithin=(json.loads(JSON_RASTER), D(km=1)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(JSON_RASTER,
                                                                D(km=1)))
        self.assertEqual(qs.count(), 1)

        # Filter in an unprojected coordinate system.
        qs = RasterModel.objects.filter(rast__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter with band index transform.
        qs = RasterModel.objects.filter(rast__1__dwithin=(rast, 1, 40))
        self.assertEqual(qs.count(), 1)
        qs = RasterModel.objects.filter(rast__1__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)
        qs = RasterModel.objects.filter(rast__dwithin=(rast, 1, 40))
        self.assertEqual(qs.count(), 1)

        # Filter raster by geom.
        qs = RasterModel.objects.filter(rast__dwithin=(stx_pnt, 500))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(stx_pnt,
                                                                D(km=10000)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rast__dwithin=(stx_pnt, 5))
        self.assertEqual(qs.count(), 0)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(stx_pnt,
                                                                D(km=100)))
        self.assertEqual(qs.count(), 0)

        # Filter geom by raster.
        qs = RasterModel.objects.filter(geom__dwithin=(rast, 500))
        self.assertEqual(qs.count(), 1)

        # Filter through related model.
        qs = RasterRelatedModel.objects.filter(
            rastermodel__rast__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter through related model with band index transform
        qs = RasterRelatedModel.objects.filter(
            rastermodel__rast__1__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter through conditional statements.
        qs = RasterModel.objects.filter(
            Q(rast__dwithin=(rast, 40))
            & Q(rastprojected__dwithin=(stx_pnt, D(km=10000))))
        self.assertEqual(qs.count(), 1)

        # Filter through different lookup.
        qs = RasterModel.objects.filter(rastprojected__bbcontains=rast)
        self.assertEqual(qs.count(), 1)
Exemplo n.º 29
0
 def geos(self):
     "Return a GEOSGeometry object from this OGRGeometry."
     from djmodels.contrib.gis.geos import GEOSGeometry
     return GEOSGeometry(self._geos_ptr(), self.srid)
Exemplo n.º 30
0
    def test_all_gis_lookups_with_rasters(self):
        """
        Evaluate all possible lookups for all input combinations (i.e.
        raster-raster, raster-geom, geom-raster) and for projected and
        unprojected coordinate systems. This test just checks that the lookup
        can be called, but doesn't check if the result makes logical sense.
        """
        from djmodels.contrib.gis.db.backends.postgis.operations import PostGISOperations

        # Create test raster and geom.
        rast = GDALRaster(json.loads(JSON_RASTER))
        stx_pnt = GEOSGeometry(
            'POINT (-95.370401017314293 29.704867409475465)', 4326)
        stx_pnt.transform(3086)

        lookups = [(name, lookup)
                   for name, lookup in BaseSpatialField.get_lookups().items()
                   if issubclass(lookup, GISLookup)]
        self.assertNotEqual(lookups, [], 'No lookups found')
        # Loop through all the GIS lookups.
        for name, lookup in lookups:
            # Construct lookup filter strings.
            combo_keys = [
                field + name for field in [
                    'rast__',
                    'rast__',
                    'rastprojected__0__',
                    'rast__',
                    'rastprojected__',
                    'geom__',
                    'rast__',
                ]
            ]
            if issubclass(lookup, DistanceLookupBase):
                # Set lookup values for distance lookups.
                combo_values = [
                    (rast, 50, 'spheroid'),
                    (rast, 0, 50, 'spheroid'),
                    (rast, 0, D(km=1)),
                    (stx_pnt, 0, 500),
                    (stx_pnt, D(km=1000)),
                    (rast, 500),
                    (json.loads(JSON_RASTER), 500),
                ]
            elif name == 'relate':
                # Set lookup values for the relate lookup.
                combo_values = [
                    (rast, 'T*T***FF*'),
                    (rast, 0, 'T*T***FF*'),
                    (rast, 0, 'T*T***FF*'),
                    (stx_pnt, 0, 'T*T***FF*'),
                    (stx_pnt, 'T*T***FF*'),
                    (rast, 'T*T***FF*'),
                    (json.loads(JSON_RASTER), 'T*T***FF*'),
                ]
            elif name == 'isvalid':
                # The isvalid lookup doesn't make sense for rasters.
                continue
            elif PostGISOperations.gis_operators[name].func:
                # Set lookup values for all function based operators.
                combo_values = [
                    rast, (rast, 0), (rast, 0), (stx_pnt, 0), stx_pnt, rast,
                    json.loads(JSON_RASTER)
                ]
            else:
                # Override band lookup for these, as it's not supported.
                combo_keys[2] = 'rastprojected__' + name
                # Set lookup values for all other operators.
                combo_values = [
                    rast, None, rast, stx_pnt, stx_pnt, rast,
                    json.loads(JSON_RASTER)
                ]

            # Create query filter combinations.
            self.assertEqual(
                len(combo_keys),
                len(combo_values),
                'Number of lookup names and values should be the same',
            )
            combos = [x for x in zip(combo_keys, combo_values) if x[1]]
            self.assertEqual(
                [(n, x) for n, x in enumerate(combos) if x in combos[:n]],
                [],
                'There are repeated test lookups',
            )
            combos = [{k: v} for k, v in combos]

            for combo in combos:
                # Apply this query filter.
                qs = RasterModel.objects.filter(**combo)

                # Evaluate normal filter qs.
                self.assertIn(qs.count(), [0, 1])

            # Evaluate on conditional Q expressions.
            qs = RasterModel.objects.filter(Q(**combos[0]) & Q(**combos[1]))
            self.assertIn(qs.count(), [0, 1])