Skip to content

Commit

Permalink
Merge pull request #2786 from Geoportail-Luxembourg/export_shape
Browse files Browse the repository at this point in the history
It allows to download shapefile of a mymaps
  • Loading branch information
rmichaelis authored Sep 23, 2021
2 parents 8502391 + 0ba547f commit 3934fe6
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 5 deletions.
9 changes: 7 additions & 2 deletions geoportal/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@ RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes --no-install-recommends \
ghostscript \
libgs-dev \
imagemagick && \
imagemagick \
gdal-bin \
libgdal-dev \
build-essential \
python3.7-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

RUN sed -i 's/rights="none" pattern="PDF"/rights="read" pattern="PDF"/g' /etc/ImageMagick-6/policy.xml

ENV CPLUS_INCLUDE_PATH=/usr/include/gdal
ENV C_INCLUDE_PATH=/usr/include/gdal
COPY luxembourg_requirements.txt /tmp/requirements.txt
RUN \
python3 -m pip install --upgrade pip && \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {listen, unlistenByKey} from 'ol/events.js';
import {getCenter} from 'ol/extent.js';
import {transform, getPointResolution, METERS_PER_UNIT} from 'ol/proj.js';
import olFormatKML from 'ol/format/KML.js';
import olFormatGeoJSON from 'ol/format/GeoJSON.js';
import olGeomCircle from 'ol/geom/Circle.js';
import olGeomPoint from 'ol/geom/Point.js';
import {fromCircle} from 'ol/geom/Polygon.js';
Expand Down Expand Up @@ -83,6 +84,12 @@ const exports = function($scope, $sce, appFeaturePopup,
*/
this.kmlFormat_ = new olFormatKML();

/**
* @private
* @type {ol.format.GeoJSON}
*/
this.geoJsonFormat_ = new olFormatGeoJSON();

/**
* @private
* @type {string}
Expand Down Expand Up @@ -392,6 +399,21 @@ exports.prototype.createNewCircle = function(radius) {
};


/**
* Export a zipped shapefile.
* @export
*/
exports.prototype.exportShape = function() {
var json = this.geoJsonFormat_.writeFeatures([this.feature], {
dataProjection: 'EPSG:4326',
featureProjection: this['map'].getView().getProjection()
});
this.exportFeatures_(json, 'shape',
appMiscFile.sanitizeFilename(/** @type {string} */(this.feature.get('name'))));
this.appFeaturePopup_.toggleDropdown();
};


/**
* Export a KML file.
* @export
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<ul class="dropdown-menu {{ctrl.isDocked()?'dropdown-menu-right':''}}" role="menu">
<li ng-click="ctrl.exportGpx(true)"><a href translate>Exporter un GPX</a></li>
<li ng-click="ctrl.exportKml()"><a href translate>Exporter un KML</a></li>
<li ng-click="ctrl.exportShape()"><a href translate>Exporter un Shapefile</a></li>
<li ng-show="ctrl.isEditable() && ctrl.isLineString()" ng-click="ctrl.continueLine()"><a href translate>Continuer la ligne</a></li>
<li ng-show="ctrl.isEditable() && ctrl.isLineString()" ng-click="ctrl.reverseLine()"><a href translate>Changer sens de la ligne</a></li>
<li ng-show="ctrl.isCircle()" ng-click="ctrl.tempCircleRadius = ctrl.getCircleRadius() ; ctrl.askRadius = true"><a href translate>Créer cercle concentrique</a></li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import appNotifyNotificationType from '../NotifyNotificationType.js';
import {extend} from 'ol/extent.js';
import olFormatGPX from 'ol/format/GPX.js';
import olFormatKML from 'ol/format/KML.js';
import olFormatGeoJSON from 'ol/format/GeoJSON.js';
import olGeomGeometryType from 'ol/geom/GeometryType.js';
import olGeomLineString from 'ol/geom/LineString.js';
import * as olExtent from 'ol/extent.js';
Expand Down Expand Up @@ -165,6 +166,12 @@ const exports = function($scope, $compile, $sce,
*/
this.kmlFormat_ = new olFormatKML();

/**
* @private
* @type {ol.format.GeoJSON}
*/
this.geoJsonFormat_ = new olFormatGeoJSON();

/**
* @private
* @type {ol.format.GPX}
Expand Down Expand Up @@ -684,6 +691,24 @@ exports.prototype.exportKml = function() {
};


/**
* Export a zipped shapefile.
* @export
*/
exports.prototype.exportShape = function() {
var features = this.drawnFeatures_.getCollection();
var mymapsFeatures = features.getArray().filter(function(feature) {
return !!feature.get('__map_id__');
});
var json = this.geoJsonFormat_.writeFeatures(mymapsFeatures, {
dataProjection: 'EPSG:4326',
featureProjection: this['map'].getView().getProjection()
});
this.exportFeatures_(json, 'shape',
appMiscFile.sanitizeFilename(this.appMymaps_.mapTitle));
};


/**
* Import a KML file.
* @param {string=} kml The kml as text.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<li class="divider"></li>
<li ng-click="ctrl.exportGpx(true)"><a href translate>Exporter un GPX</a></li>
<li ng-click="ctrl.exportKml()"><a href translate>Exporter un KML</a></li>
<li ng-click="ctrl.exportShape()"><a href translate>Exporter un Shapefile</a></li>
<li ng-show="ctrl.isEditable()"><div class="mymapsFileUpload"><a href translate>Importer un GPX/KML/KMZ</a>
<input type="file" class="mymapsUpload"
accept=".gpx, .kml, .kmz"
Expand Down
93 changes: 90 additions & 3 deletions geoportal/geoportailv3_geoportal/views/mymaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@
from shapely.geometry import asShape, shape
from shapely.ops import transform
from functools import partial


from osgeo import ogr, osr
from shapely.geometry import Polygon
import tempfile
import shutil
import logging
import urllib.request
import json
Expand Down Expand Up @@ -308,6 +310,88 @@ def getroute_old(self):
headers = {"Content-Type": f.info()['Content-Type']}
return Response(data, headers=headers)

def create_layer(self, ds, type, srs):
if type == ogr.wkbLineString:
name = "lines"
elif type == ogr.wkbPolygon:
name = "polygons"
elif type == ogr.wkbPoint:
name = "points"
layer = ds.CreateLayer(name, srs, type)
layer.CreateField(ogr.FieldDefn("id", ogr.OFTInteger))
layer.CreateField(ogr.FieldDefn("name", ogr.OFTString))
layer.CreateField(ogr.FieldDefn("descr", ogr.OFTString))
return layer

def exportshape(self):
doc = self.request.params.get("doc")
if doc is None:
return HTTPBadRequest("doc parameter is required")
feature_collection = geojson.\
loads(doc, object_hook=geojson.GeoJSON.to_instance)
name = self.request.params.get("name")
if name is None:
name = "shape"
filename = name + ".zip"
#dirpath = tempfile.mkdtemp()
from tempfile import TemporaryDirectory
with TemporaryDirectory() as dirpath:
driver = ogr.GetDriverByName('Esri Shapefile')
ds = driver.CreateDataSource(dirpath)
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
layer_line = None
layer_polygon = None
layer_point = None
i = 0
for feature in feature_collection.features:
i = i + 1
geom = ogr.CreateGeometryFromJson(geojson.dumps(feature.geometry))
if (feature.geometry.type == 'LineString'):
if layer_line is None:
layer_line = self.create_layer(ds, ogr.wkbLineString, srs)
featureDefn = layer_line.GetLayerDefn()
featureogr = ogr.Feature(featureDefn)
featureogr.SetGeometry(geom)
featureogr.SetField("id", i)
featureogr.SetField("name", str(feature.properties.get('name')))
featureogr.SetField("descr", str(feature.properties.get('description')))
layer_line.CreateFeature(featureogr)
if (feature.geometry.type == 'Polygon'):
if layer_polygon is None:
layer_polygon = self.create_layer(ds, ogr.wkbPolygon, srs)
featureDefn = layer_polygon.GetLayerDefn()
featureogr = ogr.Feature(featureDefn)
featureogr.SetGeometry(geom)
featureogr.SetField("id", i)
featureogr.SetField("name", str(feature.properties.get('name')))
featureogr.SetField("descr", str(feature.properties.get('description')))
layer_polygon.CreateFeature(featureogr)
if (feature.geometry.type == 'Point'):
if layer_point is None:
layer_point = self.create_layer(ds, ogr.wkbPoint, srs)
featureDefn = layer_point.GetLayerDefn()
featureogr = ogr.Feature(featureDefn)
featureogr.SetGeometry(geom)
featureogr.SetField("id", i)
featureogr.SetField("name", str(feature.properties.get('name')))
featureogr.SetField("descr", str(feature.properties.get('description')))
layer_point.CreateFeature(featureogr)
featureogr = None
ds = None
zippath = dirpath + ".zip"
shutil.make_archive(dirpath, 'zip', dirpath)


charset = "utf-8"
headers = {"Content-Type": "application/octet-stream",
"Content-Disposition": "attachment; filename=\""
+ str(filename) + "\""}
f = open(zippath, "rb")
response = Response(f.read(), headers=headers)
os.remove(zippath)
return response

@view_config(route_name="exportgpxkml")
def exportgpxkml(self):
"""
Expand All @@ -317,8 +401,11 @@ def exportgpxkml(self):
fmt = self.request.params.get("format")
if fmt is None:
return HTTPBadRequest("format parameter is required")
if fmt == 'shape':
return self.exportshape()

if fmt not in _CONTENT_TYPES:
return HTTPBadRequest("format is not supported")
return HTTPBadRequest("format is not supported : '" + fmt + "'")

name = self.request.params.get("name")
if name is None:
Expand Down
1 change: 1 addition & 0 deletions geoportal/luxembourg_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ gpxpy==1.4.2
pyramid_assetviews==1.0a3
transifex-client
pyyaml
gdal==2.2

0 comments on commit 3934fe6

Please sign in to comment.