From 174170c7d5ddc3fb56a9e52866f00416c6be33d7 Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Mon, 19 Feb 2018 11:03:06 +0100 Subject: [PATCH] opengis: add preferred projection system (#20826) --- .../opengis/migrations/0004_auto_20180219_1613.py | 19 ++++++++++++ passerelle/apps/opengis/models.py | 35 +++++++++++++++++----- tests/test_opengis.py | 14 +++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 passerelle/apps/opengis/migrations/0004_auto_20180219_1613.py diff --git a/passerelle/apps/opengis/migrations/0004_auto_20180219_1613.py b/passerelle/apps/opengis/migrations/0004_auto_20180219_1613.py new file mode 100644 index 00000000..08ea9a1d --- /dev/null +++ b/passerelle/apps/opengis/migrations/0004_auto_20180219_1613.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('opengis', '0003_auto_20171220_1058'), + ] + + operations = [ + migrations.AddField( + model_name='opengis', + name='projection', + field=models.CharField(default=b'EPSG:3857', max_length=16, verbose_name='GIS projection', choices=[(b'EPSG:4326', 'EPSG:4326 (WGS 84)'), (b'EPSG:2154', 'EPSG:2154 (Lambert-93)'), (b'EPSG:3857', 'EPSG:3857 (WGS84 / Pseudo-Mercator)'), (b'EPSG:3945', 'EPSG:3945 (CC45)')]), + ), + ] diff --git a/passerelle/apps/opengis/models.py b/passerelle/apps/opengis/models.py index 98abfbb3..dead4ca6 100644 --- a/passerelle/apps/opengis/models.py +++ b/passerelle/apps/opengis/models.py @@ -43,12 +43,21 @@ def build_dict_from_xml(elem): d[attribute_name] = build_dict_from_xml(child) return d +PROJECTIONS = ( + ('EPSG:2154', _('EPSG:2154 (Lambert-93)')), + ('EPSG:3857', _('EPSG:3857 (WGS 84 / Pseudo-Mercator)')), + ('EPSG:3945', _('EPSG:3945 (CC45)')), + ('EPSG:4326', _('EPSG:4326 (WGS 84)')), +) + class OpenGIS(BaseResource): category = _('Geographic information system') wms_service_url = models.URLField(_('Web Map Service (WMS) URL'), max_length=256, blank=True) wfs_service_url = models.URLField(_('Web Feature Service (WFS) URL'), max_length=256, blank=True) query_layer = models.CharField(_('Query Layer'), max_length=256) + projection = models.CharField(_('GIS projection'), choices=PROJECTIONS, + default='EPSG:3857', max_length=16) class Meta: verbose_name = _('OpenGIS') @@ -150,7 +159,13 @@ class OpenGIS(BaseResource): 'lon': {'description': _('Longitude'), 'example_value': '4.78414'}, }) def feature_info(self, request, lat, lon): - bbox = '%s,%s,%s,%s' % (lat, lon, float(lat) + 0.002, float(lon) + 0.002) + lon_b, lat_b = float(lon) + 0.002, float(lat) + 0.002 + if self.projection != 'EPSG:4326': + wgs84 = pyproj.Proj(init='EPSG:4326') + target_projection = pyproj.Proj(init=self.projection) + lon_b, lat_b = pyproj.transform(wgs84, target_projection, lon_b, lat_b) + lon, lat = pyproj.transform(wgs84, target_projection, lon, lat) + bbox = '%s,%s,%s,%s' % (lat, lon, lat_b, lon_b) params = { 'VERSION': '1.3.0', 'SERVICE': 'WMS', @@ -161,7 +176,7 @@ class OpenGIS(BaseResource): 'J': '0', 'HEIGHT': '500', 'WIDTH': '500', - 'CRS': 'EPSG:4171', + 'CRS': self.projection, 'LAYERS': self.query_layer, 'QUERY_LAYERS': self.query_layer, 'BBOX': bbox, @@ -192,12 +207,18 @@ class OpenGIS(BaseResource): lat_deg = math.degrees(lat_rad) return (lon_deg, lat_deg) - wgs84 = pyproj.Proj(init='epsg:4326') - epsg3857 = pyproj.Proj(init='epsg:3857') # lower left - ll_lon, ll_lat = pyproj.transform(wgs84, epsg3857, *num2deg(tile_x, tile_y+1, zoom)) + ll_lon, ll_lat = num2deg(tile_x, tile_y+1, zoom) # upper right - ur_lon, ur_lat = pyproj.transform(wgs84, epsg3857, *num2deg(tile_x+1, tile_y, zoom)) + ur_lon, ur_lat = num2deg(tile_x+1, tile_y, zoom) + + # convert only when projection system is other than WGS84 + if self.projection != 'EPSG:4326': + wgs84 = pyproj.Proj(init='EPSG:4326') + target_projection = pyproj.Proj(init=self.projection) + ll_lon, ll_lat = pyproj.transform(wgs84, target_projection, ll_lon, ll_lat) + ur_lon, ur_lat = pyproj.transform(wgs84, target_projection, ur_lon, ur_lat) + bbox = '%s,%s,%s,%s' % (ll_lon, ll_lat, ur_lon, ur_lat) params = { @@ -210,7 +231,7 @@ class OpenGIS(BaseResource): 'TRANSPARENT': 'false', 'HEIGHT': '256', 'WIDTH': '256', - 'SRS': 'EPSG:3857', + 'SRS': self.projection, 'BBOX': bbox, } return HttpResponse( diff --git a/tests/test_opengis.py b/tests/test_opengis.py index 66a8a54d..263550d0 100644 --- a/tests/test_opengis.py +++ b/tests/test_opengis.py @@ -130,7 +130,14 @@ def test_feature_info(mocked_get, app, connector): assert endpoint == '/opengis/test/feature_info' mocked_get.return_value = utils.FakedResponse(content=FAKE_FEATURE_INFO, status_code=200) resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'}) + assert mocked_get.call_args[1]['params']['BBOX'] == '5747860.22776,532568.028684,5748179.56467,532790.667665' + assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:3857' assert resp.json['data']['cad_cadastrecadparcelle_layer']['cad_cadastrecadparcelle_feature']['natureproprietaire'] == 'Particulier' + connector.projection = 'EPSG:4326' + connector.save() + resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'}) + assert mocked_get.call_args[1]['params']['BBOX'] == '45.796890,4.784140,45.79889,4.78614' + assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:4326' @mock.patch('passerelle.utils.Request.get') def test_tile(mocked_get, app, connector): @@ -138,6 +145,13 @@ def test_tile(mocked_get, app, connector): assert endpoint == '/opengis/test/tile' mocked_get.return_value = utils.FakedResponse(content='\x89PNG\r\n\x1a\n\x00\x00...', status_code=200) resp = app.get(endpoint + '/16/33650/23378.png') + assert mocked_get.call_args[1]['params']['SRS'] == 'EPSG:3857' + assert mocked_get.call_args[1]['params']['BBOX'] == '539339.67158,5741338.06856,539951.167806,5741949.56478' + connector.projection = 'EPSG:4326' + connector.save() + resp = app.get(endpoint + '/16/33650/23378.png') + assert mocked_get.call_args[1]['params']['SRS'] == 'EPSG:4326' + assert mocked_get.call_args[1]['params']['BBOX'] == '4.84497070312,45.7560261559,4.85046386719,45.7598586879' assert resp.content == '\x89PNG\r\n\x1a\n\x00\x00...' -- 2.16.2