diff --git a/django/contrib/gis/tests/geo3d/tests.py b/django/contrib/gis/tests/geo3d/tests.py index dfd0e496ff1..0aba38f5cab 100644 --- a/django/contrib/gis/tests/geo3d/tests.py +++ b/django/contrib/gis/tests/geo3d/tests.py @@ -1,16 +1,17 @@ -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals import os import re -from django.utils.unittest import TestCase from django.contrib.gis.db.models import Union, Extent3D from django.contrib.gis.geos import GEOSGeometry, Point, Polygon from django.contrib.gis.utils import LayerMapping, LayerMapError +from django.test import TestCase from .models import (City3D, Interstate2D, Interstate3D, InterstateProj2D, InterstateProj3D, Point2D, Point3D, MultiPoint3D, Polygon2D, Polygon3D) + data_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data')) city_file = os.path.join(data_path, 'cities', 'cities.shp') vrt_file = os.path.join(data_path, 'test_vrt', 'test_vrt.vrt') @@ -46,12 +47,11 @@ interstate_data = ( # Bounding box polygon for inner-loop of Houston (in projected coordinate # system 32140), with elevation values from the National Elevation Dataset # (see above). -bbox_wkt = 'POLYGON((941527.97 4225693.20,962596.48 4226349.75,963152.57 4209023.95,942051.75 4208366.38,941527.97 4225693.20))' -bbox_z = (21.71, 13.21, 9.12, 16.40, 21.71) -def gen_bbox(): - 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) - return bbox_2d, bbox_3d +bbox_data = ( + 'POLYGON((941527.97 4225693.20,962596.48 4226349.75,963152.57 4209023.95,942051.75 4208366.38,941527.97 4225693.20))', + (21.71, 13.21, 9.12, 16.40, 21.71) +) + class Geo3DTest(TestCase): """ @@ -63,20 +63,7 @@ class Geo3DTest(TestCase): http://postgis.refractions.net/documentation/manual-1.4/ch08.html#PostGIS_3D_Functions """ - def test01_3d(self): - "Test the creation of 3D models." - # 3D models for the rest of the tests will be populated in here. - # For each 3D data set create model (and 2D version if necessary), - # retrieve, and assert geometry is in 3D and contains the expected - # 3D values. - for name, pnt_data in city_data: - x, y, z = pnt_data - pnt = Point(x, y, z, srid=4326) - City3D.objects.create(name=name, point=pnt) - city = City3D.objects.get(name=name) - self.assertTrue(city.point.hasz) - self.assertEqual(z, city.point.z) - + 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) @@ -90,26 +77,51 @@ class Geo3DTest(TestCase): Interstate2D.objects.create(name=name, line=line_2d) InterstateProj2D.objects.create(name=name, line=line_2d) - # Retrieving and making sure it's 3D and has expected - # Z values -- shouldn't change because of coordinate system. + def _load_city_data(self): + for name, pnt_data in city_data: + City3D.objects.create(name=name, point=Point(*pnt_data, srid=4326)) + + 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) + + def test_3d_hasz(self): + """ + Make sure data is 3D and has expected Z values -- shouldn't change + because of coordinate system. + """ + self._load_interstate_data() + for name, line, exp_z in interstate_data: interstate = Interstate3D.objects.get(name=name) interstate_proj = InterstateProj3D.objects.get(name=name) for i in [interstate, interstate_proj]: self.assertTrue(i.line.hasz) self.assertEqual(exp_z, tuple(i.line.z)) - # Creating 3D Polygon. - bbox2d, bbox3d = gen_bbox() - Polygon2D.objects.create(name='2D BBox', poly=bbox2d) - Polygon3D.objects.create(name='3D BBox', poly=bbox3d) + self._load_city_data() + for name, pnt_data in city_data: + city = City3D.objects.get(name=name) + z = pnt_data[2] + self.assertTrue(city.point.hasz) + self.assertEqual(z, city.point.z) + + def test_3d_polygons(self): + """ + Test the creation of polygon 3D models. + """ + self._load_polygon_data() p3d = Polygon3D.objects.get(name='3D BBox') self.assertTrue(p3d.poly.hasz) - self.assertEqual(bbox3d, p3d.poly) - - def test01a_3d_layermapping(self): - "Testing LayerMapping on 3D models." - from .models import Point2D, Point3D + self.assertIsInstance(p3d.poly, Polygon) + self.assertEqual(p3d.poly.srid, 32140) + def test_3d_layermapping(self): + """ + Testing LayerMapping on 3D models. + """ point_mapping = {'point' : 'POINT'} mpoint_mapping = {'mpoint' : 'MULTIPOINT'} @@ -134,34 +146,46 @@ class Geo3DTest(TestCase): lm.save() self.assertEqual(3, MultiPoint3D.objects.count()) - def test02a_kml(self): - "Test GeoQuerySet.kml() with Z values." + def test_kml(self): + """ + Test GeoQuerySet.kml() with Z values. + """ + self._load_city_data() h = City3D.objects.kml(precision=6).get(name='Houston') # KML should be 3D. # `SELECT ST_AsKML(point, 6) FROM geo3d_city3d WHERE name = 'Houston';` ref_kml_regex = re.compile(r'^-95.363\d+,29.763\d+,18$') self.assertTrue(ref_kml_regex.match(h.kml)) - def test02b_geojson(self): - "Test GeoQuerySet.geojson() with Z values." + def test_geojson(self): + """ + Test GeoQuerySet.geojson() with Z values. + """ + self._load_city_data() h = City3D.objects.geojson(precision=6).get(name='Houston') # GeoJSON should be 3D # `SELECT ST_AsGeoJSON(point, 6) FROM geo3d_city3d WHERE name='Houston';` ref_json_regex = re.compile(r'^{"type":"Point","coordinates":\[-95.363151,29.763374,18(\.0+)?\]}$') self.assertTrue(ref_json_regex.match(h.geojson)) - def test03a_union(self): - "Testing the Union aggregate of 3D models." + 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) self.assertEqual(ref_union, union) - def test03b_extent(self): - "Testing the Extent3D aggregate for 3D models." + def test_extent(self): + """ + Testing the Extent3D aggregate for 3D models. + """ + self._load_city_data() # `SELECT ST_Extent3D(point) FROM geo3d_city3d;` ref_extent3d = (-123.305196, -41.315268, 14,174.783117, 48.462611, 1433) extent1 = City3D.objects.aggregate(Extent3D('point'))['point__extent3d'] @@ -174,8 +198,11 @@ class Geo3DTest(TestCase): for e3d in [extent1, extent2]: check_extent3d(e3d) - def test04_perimeter(self): - "Testing GeoQuerySet.perimeter() on 3D fields." + def test_perimeter(self): + """ + Testing GeoQuerySet.perimeter() on 3D fields. + """ + self._load_polygon_data() # Reference query for values below: # `SELECT ST_Perimeter3D(poly), ST_Perimeter2D(poly) FROM geo3d_polygon3d;` ref_perim_3d = 76859.2620451 @@ -188,12 +215,15 @@ class Geo3DTest(TestCase): Polygon3D.objects.perimeter().get(name='3D BBox').perimeter.m, tol) - def test05_length(self): - "Testing GeoQuerySet.length() on 3D fields." + def test_length(self): + """ + Testing GeoQuerySet.length() on 3D fields. + """ # ST_Length_Spheroid Z-aware, and thus does not need to use # a separate function internally. # `SELECT ST_Length_Spheroid(line, 'SPHEROID["GRS 1980",6378137,298.257222101]') # FROM geo3d_interstate[2d|3d];` + self._load_interstate_data() tol = 3 ref_length_2d = 4368.1721949481 ref_length_3d = 4368.62547052088 @@ -217,16 +247,22 @@ class Geo3DTest(TestCase): InterstateProj3D.objects.length().get(name='I-45').length.m, tol) - def test06_scale(self): - "Testing GeoQuerySet.scale() on Z values." + def test_scale(self): + """ + Testing GeoQuerySet.scale() on Z values. + """ + self._load_city_data() # Mapping of City name to reference Z values. zscales = (-3, 4, 23) for zscale in zscales: for city in City3D.objects.scale(1.0, 1.0, zscale): self.assertEqual(city_dict[city.name][2] * zscale, city.scale.z) - def test07_translate(self): - "Testing GeoQuerySet.translate() on Z values." + def test_translate(self): + """ + Testing GeoQuerySet.translate() on Z values. + """ + self._load_city_data() ztranslations = (5.23, 23, -17) for ztrans in ztranslations: for city in City3D.objects.translate(0, 0, ztrans):