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