Projet

Général

Profil

0001-opengis-add-preferred-projection-system-20826.patch

Voir les différences:

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
passerelle/apps/opengis/migrations/0004_auto_20180219_1613.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('opengis', '0003_auto_20171220_1058'),
11
    ]
12

  
13
    operations = [
14
        migrations.AddField(
15
            model_name='opengis',
16
            name='projection',
17
            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)')]),
18
        ),
19
    ]
passerelle/apps/opengis/models.py
43 43
            d[attribute_name] = build_dict_from_xml(child)
44 44
    return d
45 45

  
46
PROJECTIONS = (
47
    ('EPSG:2154', _('EPSG:2154 (Lambert-93)')),
48
    ('EPSG:3857', _('EPSG:3857 (WGS 84 / Pseudo-Mercator)')),
49
    ('EPSG:3945', _('EPSG:3945 (CC45)')),
50
    ('EPSG:4326', _('EPSG:4326 (WGS 84)')),
51
)
52

  
46 53

  
47 54
class OpenGIS(BaseResource):
48 55
    category = _('Geographic information system')
49 56
    wms_service_url = models.URLField(_('Web Map Service (WMS) URL'), max_length=256, blank=True)
50 57
    wfs_service_url = models.URLField(_('Web Feature Service (WFS) URL'), max_length=256, blank=True)
51 58
    query_layer = models.CharField(_('Query Layer'), max_length=256)
59
    projection = models.CharField(_('GIS projection'), choices=PROJECTIONS,
60
                                  default='EPSG:3857', max_length=16)
52 61

  
53 62
    class Meta:
54 63
        verbose_name = _('OpenGIS')
......
150 159
                  'lon': {'description': _('Longitude'), 'example_value': '4.78414'},
151 160
              })
152 161
    def feature_info(self, request, lat, lon):
153
        bbox = '%s,%s,%s,%s' % (lat, lon, float(lat) + 0.002, float(lon) + 0.002)
162
        lon_b, lat_b = float(lon) + 0.002, float(lat) + 0.002
163
        if self.projection != 'EPSG:4326':
164
            wgs84 = pyproj.Proj(init='EPSG:4326')
165
            target_projection = pyproj.Proj(init=self.projection)
166
            lon_b, lat_b = pyproj.transform(wgs84, target_projection, lon_b, lat_b)
167
            lon, lat = pyproj.transform(wgs84, target_projection, lon, lat)
168
        bbox = '%s,%s,%s,%s' % (lat, lon, lat_b, lon_b)
154 169
        params = {
155 170
            'VERSION': '1.3.0',
156 171
            'SERVICE': 'WMS',
......
161 176
            'J': '0',
162 177
            'HEIGHT': '500',
163 178
            'WIDTH': '500',
164
            'CRS': 'EPSG:4171',
179
            'CRS': self.projection,
165 180
            'LAYERS': self.query_layer,
166 181
            'QUERY_LAYERS': self.query_layer,
167 182
            'BBOX': bbox,
......
192 207
            lat_deg = math.degrees(lat_rad)
193 208
            return (lon_deg, lat_deg)
194 209

  
195
        wgs84 = pyproj.Proj(init='epsg:4326')
196
        epsg3857 = pyproj.Proj(init='epsg:3857')
197 210
        # lower left
198
        ll_lon, ll_lat = pyproj.transform(wgs84, epsg3857, *num2deg(tile_x, tile_y+1, zoom))
211
        ll_lon, ll_lat = num2deg(tile_x, tile_y+1, zoom)
199 212
        # upper right
200
        ur_lon, ur_lat = pyproj.transform(wgs84, epsg3857, *num2deg(tile_x+1, tile_y, zoom))
213
        ur_lon, ur_lat = num2deg(tile_x+1, tile_y, zoom)
214

  
215
        # convert only when projection system is other than WGS84
216
        if self.projection != 'EPSG:4326':
217
            wgs84 = pyproj.Proj(init='EPSG:4326')
218
            target_projection = pyproj.Proj(init=self.projection)
219
            ll_lon, ll_lat = pyproj.transform(wgs84, target_projection, ll_lon, ll_lat)
220
            ur_lon, ur_lat = pyproj.transform(wgs84, target_projection, ur_lon, ur_lat)
221

  
201 222
        bbox = '%s,%s,%s,%s' % (ll_lon, ll_lat, ur_lon, ur_lat)
202 223

  
203 224
        params = {
......
210 231
            'TRANSPARENT': 'false',
211 232
            'HEIGHT': '256',
212 233
            'WIDTH': '256',
213
            'SRS': 'EPSG:3857',
234
            'SRS': self.projection,
214 235
            'BBOX': bbox,
215 236
        }
216 237
        return HttpResponse(
tests/test_opengis.py
130 130
    assert endpoint == '/opengis/test/feature_info'
131 131
    mocked_get.return_value = utils.FakedResponse(content=FAKE_FEATURE_INFO, status_code=200)
132 132
    resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'})
133
    assert mocked_get.call_args[1]['params']['BBOX'] == '5747860.22776,532568.028684,5748179.56467,532790.667665'
134
    assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:3857'
133 135
    assert resp.json['data']['cad_cadastrecadparcelle_layer']['cad_cadastrecadparcelle_feature']['natureproprietaire'] == 'Particulier'
136
    connector.projection = 'EPSG:4326'
137
    connector.save()
138
    resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'})
139
    assert mocked_get.call_args[1]['params']['BBOX'] == '45.796890,4.784140,45.79889,4.78614'
140
    assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:4326'
134 141

  
135 142
@mock.patch('passerelle.utils.Request.get')
136 143
def test_tile(mocked_get, app, connector):
......
138 145
    assert endpoint == '/opengis/test/tile'
139 146
    mocked_get.return_value = utils.FakedResponse(content='\x89PNG\r\n\x1a\n\x00\x00...', status_code=200)
140 147
    resp = app.get(endpoint + '/16/33650/23378.png')
148
    assert mocked_get.call_args[1]['params']['SRS'] == 'EPSG:3857'
149
    assert mocked_get.call_args[1]['params']['BBOX'] == '539339.67158,5741338.06856,539951.167806,5741949.56478'
150
    connector.projection = 'EPSG:4326'
151
    connector.save()
152
    resp = app.get(endpoint + '/16/33650/23378.png')
153
    assert mocked_get.call_args[1]['params']['SRS'] == 'EPSG:4326'
154
    assert mocked_get.call_args[1]['params']['BBOX'] == '4.84497070312,45.7560261559,4.85046386719,45.7598586879'
141 155
    assert resp.content == '\x89PNG\r\n\x1a\n\x00\x00...'
142 156

  
143 157

  
144
-