def conditional_transform( expression: str | functions.GeoFunc, expression_srid: int, output_srid: int ) -> str | functions.Transform: """Apply a CRS Transform to the queried field if that is needed.""" if expression_srid != output_srid: expression = functions.Transform(expression, srid=output_srid) return expression
def test_simplify_geojson(self): fn = functions.AsGeoJSON(query.Simplify( functions.Transform('geom', self.srid), self.tol), precision=2) sqs = self.qs.all().annotate(geojson=fn) geom = geos.GEOSGeometry(sqs[0].geojson, self.srid) source = self.qs[0].geom self.assertNotEqual(geom, source) self.assertNotEqual(geom.srid, source.srid) self.assertLess(geom.num_coords, source.num_coords)
def test_transform(self): # Pre-transformed points for Houston and Pueblo. 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. h = City.objects.annotate(pt=functions.Transform('point', ptown.srid)).get(name='Pueblo') self.assertEqual(2774, h.pt.srid) self.assertAlmostEqual(ptown.x, h.pt.x, prec) self.assertAlmostEqual(ptown.y, h.pt.y, prec)
def test_inherited_geofields(self): "Database functions on inherited Geometry fields." # Creating a Pennsylvanian city. PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)') # All transformation SQL will need to be performed on the # _parent_ table. qs = PennsylvaniaCity.objects.annotate(new_point=functions.Transform('point', srid=32128)) self.assertEqual(1, qs.count()) for pc in qs: self.assertEqual(32128, pc.new_point.srid)
def test_transform(self): # Pre-transformed points for Houston and Pueblo. ptown = fromstr("POINT(992363.390841912 481455.395105533)", srid=2774) # Asserting the result of the transform operation with the values in # the pre-transformed points. h = City.objects.annotate( pt=functions.Transform("point", ptown.srid)).get(name="Pueblo") self.assertEqual(2774, h.pt.srid) # Precision is low due to version variations in PROJ and GDAL. self.assertLess(ptown.x - h.pt.x, 1) self.assertLess(ptown.y - h.pt.y, 1)
def extent(self, srid=None): """Returns the GeoQuerySet extent as a 4-tuple. Keyword args: srid -- EPSG id for for transforming the output geometry. """ expr = self.geo_field.name if srid: expr = geofn.Transform(expr, srid) expr = models.Extent(expr) clone = self.all() name, val = clone.aggregate(expr).popitem() return val
def test_serialize_queryset_simplify(self): fn = query.Simplify(functions.Transform('geom', 4269), 1.01) qs = Location.objects.all() for obj in qs: obj.geom = obj.geom.buffer(1.5) obj.save() qs = qs.annotate(simplify=fn) obj = qs[0] serializer = SimplifyLocationSerializer(obj) g = geos.GEOSGeometry(json.dumps(serializer.data['geometry']), srid=obj.simplify.srid) self.assertEqual(g, obj.simplify) self.assertEqual(obj.simplify.srid, 4269) self.assertEqual(serializer.data['crs']['properties']['name'][-4:], '4269')
def select(self): kwargs = {} data = self.cleaned_data tolerance, srs, format = map(data.get, ('simplify', 'srs', 'format')) expr = field = query.geo_field(self.queryset).name srid = getattr(srs, 'srid', None) if srid: expr = functions.Transform(expr, srid) if data['op']: expr = data['op'](expr) if data['precision'] is not None: kwargs.update(precision=data['precision']) if tolerance: expr = query.Simplify(expr, tolerance) if format: expr = format(expr, **kwargs) if expr != field: attrname = self.data.get('format') self.queryset = self.queryset.annotate(**{attrname: expr})
def tile(self, bbox, z=0, format=None, clip=True): """Returns a GeoQuerySet intersecting a tile boundary. Arguments: bbox -- tile extent as geometry Keyword args: z -- tile zoom level used as basis for geometry simplification format -- vector tile format as str (pbf, geojson) clip -- clip geometries to tile boundary as boolean """ # Tile grid uses 3857, but GeoJSON coordinates should be in 4326. tile_srid = 3857 bbox = getattr(bbox, 'geos', bbox) clone = filter_geometry(self, intersects=bbox) field = clone.geo_field srid = field.srid sql = field.name try: tilew = self.tilewidths[z] except IndexError: tilew = self.tilewidths[-1] if bbox.srid != srid: bbox = bbox.transform(srid, clone=True) # Estimate tile width in degrees instead of meters. if bbox.srs.geographic: p = geos.Point(tilew, tilew, srid=tile_srid) p.transform(srid) tilew = p.x if clip: bufbox = bbox.buffer(tilew) sql = geofn.Intersection(sql, bufbox.envelope) sql = SimplifyPreserveTopology(sql, tilew) if format == 'pbf': return clone.pbf(bbox, geo_col=sql) sql = geofn.Transform(sql, 4326) return clone.annotate(**{format: sql})