Example #1
0
	def _check_extent(self, layer, geom_query, projection=None, **kwargs):
		model_projection = geom_query.model._meta.get_field(find_geom_field(geom_query)).srid
		if projection is not None and projection != model_projection:
			poly = Polygon.from_bbox(geom_query.extent())
			poly.srid = model_projection
			poly.transform(projection)
			query_extent = poly.extent
		else:
			query_extent = geom_query.extent()
		# layer.extent is useless, cause it computes extents from geometry, so it bypass geojson's value
		numpy.testing.assert_almost_equal(json.loads(self.geojson)["bbox"], query_extent, decimal=3)
Example #2
0
	def _test_render_to_json(self, geom_query, properties=(), **kwargs):
		"Generic testing function of rendering json from queryset geom_query"""
		geom_field = find_geom_field(geom_query)

		self.assertGreater(len(geom_query), 0)

		ds = self._generate_data_source_from_json(geom_query, properties=properties, **kwargs)
		self.assertEqual(ds.layer_count, 1)
		layer = ds[0]
		self.assertEqual(layer.num_feat, geom_query.count())

		self._check_extent(layer, geom_query, **kwargs)
		self._check_geometry(layer, geom_query, **kwargs)
		self._check_attributes(layer, geom_query, properties=properties)
Example #3
0
	def _check_geometry(self, layer, geom_query, projection=None, simplify=None, **kwargs):
		model_projection = geom_query.model._meta.get_field(find_geom_field(geom_query)).srid
		if projection is not None and projection != model_projection:
			# prepare geometry for comparing in requested projection
			geom_query = geom_query.transform(projection)

		features_data = {}
		for feature in geom_query:
			if simplify:
				features_data[feature.pk] = feature.the_geom.simplify(simplify)
			else:
				features_data[feature.pk] = feature.the_geom

		for feature in layer:
			gid = feature["gid"].as_int()
			self.assertTrue(feature.geom.geos.equals_exact(features_data[gid], tolerance=0.001))
Example #4
0
def render_to_geojson(queryset, projection=None, simplify=None, extent=None, maxfeatures=None, priorityfield=None, properties=None, prettyprint=False):
	'''
	Shortcut to render a GeoJson FeatureCollection from a Django QuerySet.
	Currently computes a bbox and adds a crs member as a sr.org link.
	Parameters:
	* queryset (django.db.models.query.QuerySet) - queryset of models containing geometry data
	* projection (int) - projection code used when geometry data should be transformed to other projection
	* simplify (float) - value specifies tolerance in Douglas-Peucker algorithm for simplifying geometry
	* extent (django.contrib.gis.geos.Polygon instance) - limits features to features inside extent's bounds
	* maxfeatures (int) - gives maximum number of rendered features based on priority field
	* priorityfield (string) - name of the priority field used for reducing features
	* properties ([(string, string or callable), ...]) - list of feature's non geometry attributes defined as couples \
	  (title, value), where value can be field name or callable (that accepts a feature instance as argument and returns attribute's value)
	* prettyprint (boolean) - flag influencing indentation used in geojson (for better readability)
	'''

	geom_field = find_geom_field(queryset)

	if extent is not None:
		#queryset.filter(<geom_field>__intersects=extent)
		queryset = queryset.filter(**{'%s__intersects' % geom_field: extent})

	if maxfeatures is not None:
		if priorityfield is None:
			raise RuntimeError("priorityfield must be defined")
		queryset.order_by(priority_field)
		queryset = queryset[:maxfeatures]

	src_projection = None
	if queryset.exists():
		src_projection = queryset.model._meta.get_field(geom_field).srid

	if projection is None:
		projection = src_projection

	if projection is not None and src_projection != projection:
		queryset = queryset.transform(projection)

	if properties is None:
		properties = [(field.name, field.name) for field in queryset.model._meta.fields]

	features = list()
	collection = dict()
	if src_projection is not None:
		crs = dict()
		crs[GEOJSON_FIELD_TYPE] = GEOJSON_VALUE_LINK
		crs_properties = dict()
		crs_properties[GEOJSON_FIELD_HREF] = '%s%s/' % (SPATIAL_REF_SITE, projection)
		crs_properties[GEOJSON_FIELD_TYPE] = 'proj4'
		crs[GEOJSON_FIELD_PROPERTIES] = crs_properties
		collection[GEOJSON_FIELD_CRS] = crs
		collection[GEOJSON_FIELD_SRID] = projection

	for item in queryset:
		feat = dict()
		feat[GEOJSON_FIELD_ID] = item.pk

		#filling feature properties with dict: {<field_name>:<field_value>}
		feat[GEOJSON_FIELD_PROPERTIES] = dict()
		for title, attrib in properties:
			if attrib == geom_field:
				continue
			if isroutine(attrib):
				value = attrib(item)
			else:
				value = getattr(item, attrib)
			feat[GEOJSON_FIELD_PROPERTIES][title] = __simple_render_to_json(value)
		feat[GEOJSON_FIELD_TYPE] = GEOJSON_VALUE_FEATURE
		geom = getattr(item, geom_field)
		if simplify:
			geom = geom.simplify(simplify)

		# We have to use gdal.OGRGeometry geometry class directly and without srid parameter
		# to prevent creating a SpatialReference instance, which causes memory leaks
		feat[GEOJSON_FIELD_GEOMETRY] = simplejson.loads(gdal.OGRGeometry(geom.wkb).json)
		features.append(feat)

	collection[GEOJSON_FIELD_TYPE] = GEOJSON_VALUE_FEATURE_COLLECTION
	collection[GEOJSON_FIELD_FEATURES] = features

	if queryset.exists():
		if projection is not None and src_projection != projection:
			poly = Polygon.from_bbox(queryset.extent())
			# We have to use gdal.OGRGeometry geometry class directly and without srid parameter
			# to prevent creating a SpatialReference instance, which causes memory leaks
			ogr_geom = gdal.OGRGeometry(poly.wkb)
			ogr_geom.srs = __get_spatial_reference(src_projection)
			ogr_geom.transform(__get_spatial_reference(projection))
			collection[GEOJSON_FIELD_BBOX] = ogr_geom.extent
		else:
			collection[GEOJSON_FIELD_BBOX] = queryset.extent()

	if prettyprint == True:
		return simplejson.dumps(collection, indent=4)
	else:
		return simplejson.dumps(collection)