mpeltriaux
b0d068e8a6
* adds bugfixes and improvements - point / line auto buffer key input change buffer - pass default buffer values from config - update area label while vertex editing - auto buffer remove source geoms when done - toggle cut tool off when done - toggle delete tool off when done - allow panning while vertex editing (middle mouse button)
2319 lines
59 KiB
JavaScript
2319 lines
59 KiB
JavaScript
/* global ol, jsts, shp, proj4 */
|
|
|
|
"use strict";
|
|
|
|
var netgis = netgis || {};
|
|
|
|
/**
|
|
* Map module implementation for OpenLayers 6+.
|
|
*/
|
|
netgis.MapOpenLayers = function()
|
|
{
|
|
netgis.Map.call( this );
|
|
|
|
this.mode = null;
|
|
this.toolbars = {};
|
|
this.view = null;
|
|
this.map = null;
|
|
this.layers = [];
|
|
this.interactions = {};
|
|
this.snap = null;
|
|
this.snapFeatures = null;
|
|
this.editLayer = null;
|
|
this.parcelLayer = null;
|
|
|
|
this.hover = null;
|
|
this.selected = null;
|
|
this.sketch = null;
|
|
|
|
this.editEventsSilent = false;
|
|
|
|
this.importLayerID = 20000;
|
|
this.editLayerID = 30000;
|
|
this.labelFont = "4mm Verdana, sans-serif";
|
|
this.drawBufferRadius = 100.0;
|
|
this.drawBufferSegments = 3;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype = Object.create( netgis.Map.prototype );
|
|
netgis.MapOpenLayers.prototype.constructor = netgis.MapOpenLayers;
|
|
|
|
//TODO: not much benefits from Map class inheritance, may be dropped soon
|
|
|
|
netgis.MapOpenLayers.prototype.load = function()
|
|
{
|
|
// Elements
|
|
netgis.Map.prototype.load.call( this ); //TODO: ?
|
|
|
|
this.dropTarget = document.createElement( "div" );
|
|
this.dropTarget.className = "netgis-drop-target netgis-hide";
|
|
this.dropTarget.innerHTML = "Datei hier ablegen!";
|
|
this.root.appendChild( this.dropTarget );
|
|
|
|
this.root.addEventListener( "dragenter", this.onDragEnter.bind( this ) );
|
|
this.root.addEventListener( "dragover", this.onDragEnter.bind( this ) );
|
|
this.root.addEventListener( "dragend", this.onDragLeave.bind( this ) );
|
|
this.root.addEventListener( "dragleave", this.onDragLeave.bind( this ) );
|
|
this.root.addEventListener( "drop", this.onDragDrop.bind( this ) );
|
|
|
|
// Map Renderer
|
|
this.initMap();
|
|
this.initDefaultLayers();
|
|
this.initInteractions();
|
|
|
|
// Events
|
|
this.client.on( netgis.Events.CONTEXT_UPDATE, this.onContextUpdate.bind( this ) );
|
|
this.client.on( netgis.Events.MAP_UPDATE_STYLE, this.onUpdateStyle.bind( this ) );
|
|
this.client.on( netgis.Events.EDIT_FEATURES_LOADED, this.onEditFeaturesLoaded.bind( this ) );
|
|
this.client.on( netgis.Events.SET_MODE, this.onSetMode.bind( this ) );
|
|
this.client.on( netgis.Events.SNAP_ON, this.onSnapOn.bind( this ) );
|
|
this.client.on( netgis.Events.SNAP_OFF, this.onSnapOff.bind( this ) );
|
|
this.client.on( netgis.Events.TRACING_ON, this.onTracingOn.bind( this ) );
|
|
this.client.on( netgis.Events.TRACING_OFF, this.onTracingOff.bind( this ) );
|
|
this.client.on( netgis.Events.LAYER_SHOW, this.onLayerShow.bind( this ) );
|
|
this.client.on( netgis.Events.LAYER_HIDE, this.onLayerHide.bind( this ) );
|
|
this.client.on( netgis.Events.MAP_ZOOM_WKT, this.onZoomWKT.bind( this ) );
|
|
this.client.on( netgis.Events.MAP_SET_EXTENT, this.onSetExtent.bind( this ) );
|
|
this.client.on( netgis.Events.MAP_CHANGE_ZOOM, this.onChangeZoom.bind( this ) );
|
|
this.client.on( netgis.Events.BUFFER_CHANGE, this.onBufferChange.bind( this ) );
|
|
this.client.on( netgis.Events.BUFFER_ACCEPT, this.onBufferAccept.bind( this ) );
|
|
this.client.on( netgis.Events.BUFFER_CANCEL, this.onBufferCancel.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_GEOJSON, this.onImportGeoJSON.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_GML, this.onImportGML.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_SHAPEFILE, this.onImportShapefile.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_WKT, this.onImportWKT.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_SPATIALITE, this.onImportSpatialite.bind( this ) );
|
|
this.client.on( netgis.Events.IMPORT_GEOPACKAGE, this.onImportGeopackage.bind( this ) );
|
|
this.client.on( netgis.Events.EXPORT_PDF, this.onExportPDF.bind( this ) );
|
|
this.client.on( netgis.Events.EXPORT_JPEG, this.onExportJPEG.bind( this ) );
|
|
this.client.on( netgis.Events.EXPORT_PNG, this.onExportPNG.bind( this ) );
|
|
this.client.on( netgis.Events.EXPORT_GIF, this.onExportGIF.bind( this ) );
|
|
this.client.on( netgis.Events.PARCEL_SHOW_PREVIEW, this.onParcelShowPreview.bind( this ) );
|
|
this.client.on( netgis.Events.PARCEL_HIDE_PREVIEW, this.onParcelHidePreview.bind( this ) );
|
|
this.client.on( netgis.Events.ADD_SERVICE_WMS, this.onAddServiceWMS.bind( this ) );
|
|
this.client.on( netgis.Events.ADD_SERVICE_WFS, this.onAddServiceWFS.bind( this ) );
|
|
this.client.on( netgis.Events.DRAW_BUFFER_ON, this.onDrawBufferOn.bind( this ) );
|
|
this.client.on( netgis.Events.DRAW_BUFFER_OFF, this.onDrawBufferOff.bind( this ) );
|
|
this.client.on( netgis.Events.DRAW_BUFFER_RADIUS_CHANGE, this.onDrawBufferRadiusChange.bind( this ) );
|
|
this.client.on( netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE, this.onDrawBufferSegmentsChange.bind( this ) );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.initMap = function()
|
|
{
|
|
var config = this.client.config;
|
|
|
|
// Projections ( WGS / Lon-Lat supported out of the box )
|
|
if ( typeof proj4 !== "undefined" )
|
|
{
|
|
proj4.defs( config.projections );
|
|
proj4.defs( "urn:ogc:def:crs:OGC:1.3:CRS84", proj4.defs( "EPSG:4326" ) );
|
|
ol.proj.proj4.register( proj4 );
|
|
}
|
|
|
|
// View
|
|
var viewParams =
|
|
{
|
|
projection: config.map.projection,
|
|
center: config.map.center,
|
|
minZoom: config.map.minZoom,
|
|
maxZoom: config.map.maxZoom,
|
|
zoom: config.map.zoom
|
|
};
|
|
|
|
this.view = new ol.View
|
|
(
|
|
viewParams
|
|
);
|
|
|
|
// Map
|
|
this.map = new ol.Map
|
|
(
|
|
{
|
|
target: this.root,
|
|
view: this.view,
|
|
pixelRatio: 1.0,
|
|
moveTolerance: 5,
|
|
controls: []
|
|
}
|
|
);
|
|
|
|
this.map.on( "pointermove", this.onPointerMove.bind( this ) );
|
|
this.map.on( "click", this.onSingleClick.bind( this ) );
|
|
|
|
this.map.on( "movestart", this.onMoveStart.bind( this ) );
|
|
this.map.on( "moveend", this.onMoveEnd.bind( this ) );
|
|
|
|
this.view.on( "change:resolution", this.onChangeResolution.bind( this ) );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.initDefaultLayers = function()
|
|
{
|
|
//TODO: why id as z index ?
|
|
|
|
this.editLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleEdit.bind( this ), zIndex: this.editLayerID } );
|
|
this.map.addLayer( this.editLayer );
|
|
|
|
this.previewLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleSketch.bind( this ), zIndex: this.editLayerID + 10 } );
|
|
this.map.addLayer( this.previewLayer );
|
|
|
|
this.parcelLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleParcel.bind( this ), zIndex: this.editLayerID + 20 } );
|
|
this.map.addLayer( this.parcelLayer );
|
|
|
|
this.editEventsOn();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.editEventsOn = function()
|
|
{
|
|
this.editLayer.getSource().on( "addfeature", this.onEditLayerAdd.bind( this ) );
|
|
//this.editLayer.getSource().on( "changefeature", this.onEditLayerChange.bind( this ) ); //TODO: fired on feature style change? use only one style function with selected/hover states?
|
|
this.editLayer.getSource().on( "removefeature", this.onEditLayerRemove.bind( this ) );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.editEventsOff = function()
|
|
{
|
|
//NOTE: this doesn't work because OL does not allow removing all listeners and listener function ref is changed by binding
|
|
//NOTE: see this.editEventsCommit
|
|
|
|
//this.editLayer.getSource().un( "addfeature"/*, this.onEditLayerAdd*/ );
|
|
//this.editLayer.getSource().un( "changefeature", this.onEditLayerChange.bind( this ) ); //TODO: fired on feature style change? use only one style function with selected/hover states?
|
|
//this.editLayer.getSource().un( "removefeature"/*, this.onEditLayerRemove*/ );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.initInteractions = function()
|
|
{
|
|
// View
|
|
this.interactions[ netgis.Modes.VIEW ] =
|
|
[
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.PANNING ] = this.interactions[ netgis.Modes.VIEW ];
|
|
this.interactions[ netgis.Modes.ZOOMING_IN ] = this.interactions[ netgis.Modes.VIEW ];
|
|
this.interactions[ netgis.Modes.ZOOMING_OUT ] = this.interactions[ netgis.Modes.VIEW ];
|
|
|
|
// Draw
|
|
this.interactions[ netgis.Modes.DRAW_POINTS ] =
|
|
[
|
|
new ol.interaction.Draw( { type: "Point", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.DRAW_POINTS ][ 0 ].on( "drawend", this.onDrawPointsEnd.bind( this ) );
|
|
|
|
this.interactions[ netgis.Modes.DRAW_LINES ] =
|
|
[
|
|
new ol.interaction.Draw( { type: "LineString", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.DRAW_LINES ][ 0 ].on( "drawend", this.onDrawLinesEnd.bind( this ) );
|
|
|
|
this.interactions[ netgis.Modes.DRAW_POLYGONS ] =
|
|
[
|
|
new ol.interaction.Draw( { type: "Polygon", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
// Edit
|
|
this.interactions[ netgis.Modes.CUT_FEATURE_BEGIN ] =
|
|
[
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.CUT_FEATURE_DRAW ] =
|
|
[
|
|
new ol.interaction.Draw( { type: "Polygon" /*, source: this.editLayer.getSource()*/, style: this.styleSketch.bind( this ) } ),
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.CUT_FEATURE_DRAW ][ 0 ].on( "drawend", this.onCutFeatureDrawEnd.bind( this ) );
|
|
|
|
this.interactions[ netgis.Modes.MODIFY_FEATURES ] =
|
|
[
|
|
new ol.interaction.Modify( { source: this.editLayer.getSource(), deleteCondition: ol.events.condition.doubleClick, style: this.styleModify.bind( this ) } ),
|
|
new ol.interaction.DragPan( { condition: function( e ) { return ( e.originalEvent.which === 2 ); } } ),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.MODIFY_FEATURES ][ 0 ].on( "modifyend", this.onModifyFeaturesEnd.bind( this ) );
|
|
|
|
this.interactions[ netgis.Modes.DELETE_FEATURES ] =
|
|
[
|
|
//new ol.interaction.Select( { layers: [ this.editLayer ], addCondition: ol.events.condition.pointerMove } ),
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.BUFFER_FEATURE_BEGIN ] =
|
|
[
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.BUFFER_FEATURE_EDIT ] =
|
|
[
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
// Snapping
|
|
this.snapFeatures = new ol.Collection();
|
|
|
|
// Search
|
|
this.interactions[ netgis.Modes.SEARCH_PLACE ] =
|
|
[
|
|
new ol.interaction.DragPan(),
|
|
new ol.interaction.MouseWheelZoom()
|
|
];
|
|
|
|
this.interactions[ netgis.Modes.SEARCH_PARCEL ] = this.interactions[ netgis.Modes.VIEW ];
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayer = function( data )
|
|
{
|
|
var layer = null;
|
|
|
|
// Create Specific Layer By Type
|
|
switch ( data.type )
|
|
{
|
|
case netgis.LayerTypes.XYZ:
|
|
{
|
|
layer = this.createLayerXYZ( data.url );
|
|
break;
|
|
}
|
|
|
|
case netgis.LayerTypes.OSM:
|
|
{
|
|
layer = this.createLayerOSM();
|
|
break;
|
|
}
|
|
|
|
case netgis.LayerTypes.WMS:
|
|
{
|
|
layer = this.createLayerWMS( data.url, data.name, data.format, data.username, data.password );
|
|
break;
|
|
}
|
|
|
|
case netgis.LayerTypes.WFS:
|
|
{
|
|
layer = this.createLayerWFS( data.url, data.name, this.client.config.map.projection, data.outputFormat, data.username, data.password );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Common Settings
|
|
if ( layer )
|
|
{
|
|
if ( data.minZoom ) layer.setMinZoom( Number.parseFloat( data.minZoom ) - 1.0 );
|
|
if ( data.maxZoom ) layer.setMaxZoom( Number.parseFloat( data.maxZoom ) );
|
|
}
|
|
|
|
return layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerXYZ = function( url )
|
|
{
|
|
var layer = new ol.layer.Tile
|
|
(
|
|
{
|
|
source: new ol.source.XYZ
|
|
(
|
|
{
|
|
url: url,
|
|
crossOrigin: "anonymous"
|
|
}
|
|
)
|
|
}
|
|
);
|
|
|
|
return layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerOSM = function()
|
|
{
|
|
var layer = new ol.layer.Tile
|
|
(
|
|
{
|
|
source: new ol.source.XYZ
|
|
(
|
|
{
|
|
url: "https://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",
|
|
crossOrigin: "anonymous"
|
|
}
|
|
)
|
|
}
|
|
);
|
|
|
|
return layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerWMS = function( url, layerName, format, user, password )
|
|
{
|
|
var params =
|
|
{
|
|
url: url,
|
|
params:
|
|
{
|
|
"LAYERS": layerName,
|
|
"FORMAT": format ? format : "image/png",
|
|
"TRANSPARENT": "true",
|
|
"VERSION": "1.1.1"
|
|
},
|
|
serverType: "mapserver",
|
|
crossOrigin: "anonymous",
|
|
hidpi: false
|
|
//ratio: 3.0
|
|
};
|
|
|
|
// User Auth
|
|
if ( user && password )
|
|
{
|
|
params.imageLoadFunction = function( image, src )
|
|
{
|
|
var request = new XMLHttpRequest();
|
|
request.open( "GET", src );
|
|
request.setRequestHeader( "Authorization", "Basic " + window.btoa( user + ":" + password ) );
|
|
|
|
request.onload = function()
|
|
{
|
|
image.getImage().src = src;
|
|
};
|
|
|
|
request.send();
|
|
};
|
|
}
|
|
|
|
var source = new ol.source.ImageWMS( params );
|
|
|
|
var layer = new ol.layer.Image
|
|
(
|
|
{
|
|
source: source,
|
|
//zIndex: index,
|
|
opacity: 1.0
|
|
}
|
|
);
|
|
|
|
return layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerWFS = function( url, typeName, projection, outputFormat, user, password )
|
|
{
|
|
url = url
|
|
+ "service=WFS"
|
|
+ "&version=1.1.0"
|
|
+ "&request=GetFeature";
|
|
|
|
if ( ! outputFormat )
|
|
outputFormat = "application/json";
|
|
else
|
|
outputFormat = netgis.util.replace( outputFormat, " ", "+" ); //TODO: encode uri component ?
|
|
|
|
var source = new ol.source.Vector
|
|
(
|
|
{
|
|
format: new ol.format.GeoJSON(),
|
|
strategy: ol.loadingstrategy.bbox,
|
|
|
|
loader: function( extent, resolution, proj, success, failure )
|
|
{
|
|
//proj = proj.getCode();
|
|
|
|
var requestURL = url
|
|
+ "&typename=" + typeName
|
|
+ "&srsname=" + projection
|
|
+ "&bbox=" + extent.join( "," ) + "," + projection
|
|
+ "&outputFormat=" + outputFormat;
|
|
|
|
var request = new XMLHttpRequest();
|
|
request.open( "GET", requestURL );
|
|
|
|
if ( user && password )
|
|
{
|
|
request.setRequestHeader( "Authorization", "Basic " + window.btoa( user + ":" + password ) );
|
|
}
|
|
|
|
request.onerror = function()
|
|
{
|
|
console.error( "WFS Request Error" );
|
|
failure();
|
|
};
|
|
|
|
request.onload = function()
|
|
{
|
|
if ( request.status === 200 )
|
|
{
|
|
var features = source.getFormat().readFeatures( request.responseText );
|
|
source.addFeatures( features );
|
|
success( features );
|
|
}
|
|
else
|
|
{
|
|
console.error( "WFS Request Status", request.status );
|
|
failure();
|
|
}
|
|
};
|
|
|
|
request.send();
|
|
}
|
|
}
|
|
);
|
|
|
|
var layer = new ol.layer.Vector
|
|
(
|
|
{
|
|
source: source
|
|
}
|
|
);
|
|
|
|
var self = this;
|
|
source.on( "featuresloadstart", function( e ) { self.removeSnapLayer( layer ); } );
|
|
source.on( "featuresloadend", function( e ) { window.setTimeout( function() { self.addSnapLayer( layer ); }, 10 ); } );
|
|
//source.on( "featuresloaderror", function( e ) { console.info( "Layer Error:", e ); } );
|
|
|
|
return layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.clearAll = function()
|
|
{
|
|
for ( var i = 0; i < this.layers.length; i++ )
|
|
{
|
|
this.map.removeLayer( this.layers[ i ] );
|
|
}
|
|
|
|
this.layers = [];
|
|
|
|
this.snapFeatures.clear();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onUpdateStyle = function( e )
|
|
{
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
//image: new ol.style.Circle( { radius: 7, fill: new ol.style.Fill( { color: "#ff0000" } ) } ),
|
|
fill: new ol.style.Fill( { color: e.polygon.fill } ),
|
|
stroke: new ol.style.Stroke( { color: e.polygon.stroke, width: e.polygon.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
this.editLayer.setStyle( style );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.styleEdit = function( feature )
|
|
{
|
|
var radius = this.client.config.styles.editLayer.pointRadius;
|
|
var geom = feature.getGeometry();
|
|
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: radius, fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ) } ),
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.fill } ),
|
|
stroke: new ol.style.Stroke( { color: this.client.config.styles.editLayer.stroke, width: this.client.config.styles.editLayer.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
if ( geom instanceof ol.geom.Polygon )
|
|
{
|
|
var area = geom.getArea();
|
|
|
|
style.setText
|
|
(
|
|
new ol.style.Text
|
|
(
|
|
{
|
|
text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
|
|
font: this.labelFont,
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ),
|
|
backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
|
|
padding: [ 2, 4, 2, 4 ]
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
return style;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.styleSelect = function( feature )
|
|
{
|
|
var geom = feature.getGeometry();
|
|
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: this.client.config.styles.select.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.select.stroke } ) } ),
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.select.fill } ),
|
|
stroke: new ol.style.Stroke( { color: this.client.config.styles.select.stroke, width: this.client.config.styles.select.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
if ( geom instanceof ol.geom.Polygon )
|
|
{
|
|
var area = geom.getArea();
|
|
|
|
style.setText
|
|
(
|
|
new ol.style.Text
|
|
(
|
|
{
|
|
text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
|
|
font: this.labelFont,
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.select.stroke } ),
|
|
backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
|
|
padding: [ 2, 4, 2, 4 ]
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
return style;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.styleModify = function( feature )
|
|
{
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: this.client.config.styles.modify.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ) } ),
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.modify.fill } ),
|
|
stroke: new ol.style.Stroke( { color: this.client.config.styles.modify.stroke, width: this.client.config.styles.modify.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
var vertex = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: this.client.config.styles.modify.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ) } ),
|
|
geometry: this.getGeometryPoints( feature )
|
|
}
|
|
);
|
|
|
|
var geom = feature.getGeometry();
|
|
|
|
if ( geom instanceof ol.geom.Polygon )
|
|
{
|
|
var area = geom.getArea();
|
|
|
|
style.setText
|
|
(
|
|
new ol.style.Text
|
|
(
|
|
{
|
|
text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
|
|
font: this.labelFont,
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ),
|
|
backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
|
|
padding: [ 2, 4, 2, 4 ]
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
return [ style, vertex ];
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.styleSketch = function( feature )
|
|
{
|
|
var geom = feature.getGeometry();
|
|
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: this.client.config.styles.sketch.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ) } ),
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.sketch.fill } ),
|
|
stroke: new ol.style.Stroke( { color: this.client.config.styles.sketch.stroke, width: this.client.config.styles.sketch.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
if ( geom instanceof ol.geom.Polygon )
|
|
{
|
|
var area = geom.getArea();
|
|
|
|
style.setText
|
|
(
|
|
new ol.style.Text
|
|
(
|
|
{
|
|
text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
|
|
font: this.labelFont,
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ),
|
|
backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
|
|
padding: [ 2, 4, 2, 4 ]
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
var vertex = new ol.style.Style
|
|
(
|
|
{
|
|
image: new ol.style.Circle( { radius: this.client.config.styles.sketch.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ) } ),
|
|
geometry: this.getGeometryPoints( feature )
|
|
}
|
|
);
|
|
|
|
return [ style, vertex ];
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.styleParcel = function()
|
|
{
|
|
//var radius = this.client.config.styles.editLayer.pointRadius;
|
|
|
|
var style = new ol.style.Style
|
|
(
|
|
{
|
|
//image: new ol.style.Circle( { radius: radius, fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ) } ),
|
|
fill: new ol.style.Fill( { color: this.client.config.styles.parcel.fill } ),
|
|
stroke: new ol.style.Stroke( { color: this.client.config.styles.parcel.stroke, width: this.client.config.styles.parcel.strokeWidth } )
|
|
}
|
|
);
|
|
|
|
return style;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.getGeometryPoints = function( feature )
|
|
{
|
|
var geometry = feature.getGeometry();
|
|
|
|
if ( geometry instanceof ol.geom.LineString )
|
|
{
|
|
return new ol.geom.MultiPoint( geometry.getCoordinates() );
|
|
}
|
|
else if ( geometry instanceof ol.geom.Polygon )
|
|
{
|
|
//return new ol.geom.MultiPoint( geometry.getCoordinates()[ 0 ] );
|
|
|
|
var points = [];
|
|
var geomCoords = geometry.getCoordinates();
|
|
|
|
for ( var g = 0; g < geomCoords.length; g++ )
|
|
{
|
|
var coords = geomCoords[ g ];
|
|
|
|
for ( var c = 0; c < coords.length; c++ )
|
|
points.push( coords[ c ] );
|
|
}
|
|
|
|
return new ol.geom.MultiPoint( points );
|
|
}
|
|
else if ( geometry instanceof ol.geom.MultiPolygon )
|
|
{
|
|
var points = [];
|
|
var polys = geometry.getPolygons();
|
|
|
|
for ( var l = 0; l < polys.length; l++ )
|
|
{
|
|
var geomCoords = polys[ l ].getCoordinates();
|
|
|
|
for ( var g = 0; g < geomCoords.length; g++ )
|
|
{
|
|
var coords = geomCoords[ g ];
|
|
|
|
for ( var c = 0; c < coords.length; c++ )
|
|
points.push( coords[ c ] );
|
|
}
|
|
}
|
|
|
|
return new ol.geom.MultiPoint( points );
|
|
}
|
|
else if ( geometry instanceof ol.geom.MultiLineString )
|
|
{
|
|
var points = [];
|
|
var lines = geometry.getPolygons();
|
|
|
|
for ( var l = 0; l < lines.length; l++ )
|
|
{
|
|
var geomCoords = lines[ l ].getCoordinates();
|
|
|
|
for ( var g = 0; g < geomCoords.length; g++ )
|
|
{
|
|
var coords = geomCoords[ g ];
|
|
|
|
for ( var c = 0; c < coords.length; c++ )
|
|
points.push( coords[ c ] );
|
|
}
|
|
}
|
|
|
|
return new ol.geom.MultiPoint( points );
|
|
}
|
|
|
|
return geometry;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.getActiveVectorLayers = function()
|
|
{
|
|
var vectorLayers = [];
|
|
var mapLayers = this.map.getLayers().getArray();
|
|
|
|
var layers = this.layers; // this.map.getLayers().getArray();
|
|
|
|
for ( var i = 0; i < layers.length; i++ )
|
|
{
|
|
//console.info( "Layer:", layers[ i ] );
|
|
|
|
var layer = layers[ i ];
|
|
|
|
if ( layer instanceof ol.layer.Vector && mapLayers.indexOf( layer ) > -1 )
|
|
{
|
|
vectorLayers.push( layer );
|
|
}
|
|
}
|
|
|
|
return vectorLayers;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.setMode = function( mode )
|
|
{
|
|
// Leave
|
|
switch ( this.mode )
|
|
{
|
|
case netgis.Modes.BUFFER_FEATURE_EDIT:
|
|
{
|
|
this.onBufferCancel( null );
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.DRAW_POINTS:
|
|
case netgis.Modes.DRAW_LINES:
|
|
{
|
|
this.onDrawBufferOff( null );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Enter
|
|
switch ( mode )
|
|
{
|
|
}
|
|
|
|
// Interactions
|
|
this.map.getInteractions().clear();
|
|
|
|
var interactions = this.interactions[ mode ];
|
|
|
|
if ( interactions )
|
|
{
|
|
for ( var i = 0; i < interactions.length; i++ )
|
|
{
|
|
this.map.addInteraction( interactions[ i ] );
|
|
}
|
|
}
|
|
|
|
//TODO: set to default pan interactions when none found for mode ?
|
|
|
|
if ( this.snap )
|
|
{
|
|
if ( mode === netgis.Modes.DRAW_POINTS || mode === netgis.Modes.DRAW_LINES || mode === netgis.Modes.DRAW_POLYGONS )
|
|
{
|
|
this.map.addInteraction( this.snap );
|
|
}
|
|
}
|
|
|
|
// Style
|
|
switch ( mode )
|
|
{
|
|
default:
|
|
{
|
|
this.editLayer.setStyle( this.styleEdit.bind( this ) );
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.MODIFY_FEATURES:
|
|
{
|
|
this.editLayer.setStyle( this.styleModify.bind( this ) );
|
|
break;
|
|
}
|
|
};
|
|
|
|
// Cursors
|
|
if ( this.mode ) this.root.classList.remove( this.getModeClassName( this.mode ) );
|
|
if ( mode ) this.root.classList.add( this.getModeClassName( mode ) );
|
|
|
|
this.mode = mode;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.getModeClassName = function( mode )
|
|
{
|
|
var modeClass = mode.toLowerCase();
|
|
//modeClass = modeClass.replace( "_", "-" );
|
|
modeClass = netgis.util.replace( modeClass, "_", "-" );
|
|
modeClass = "netgis-mode-" + modeClass;
|
|
|
|
return modeClass;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.setSnapOn = function()
|
|
{
|
|
//this.snapFeatures = new ol.Collection();
|
|
this.snap = new ol.interaction.Snap( { features: this.snapFeatures } );
|
|
this.map.addInteraction( this.snap );
|
|
|
|
this.snapFeatures.changed();
|
|
|
|
//this.updateSnapLayers();
|
|
|
|
//TODO: https://openlayers.org/en/latest/examples/tracing.html
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.setSnapOff = function()
|
|
{
|
|
if ( this.snap )
|
|
{
|
|
this.map.removeInteraction( this.snap );
|
|
this.snap = null;
|
|
//this.snapFeatures = null;
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.setTracingOn = function()
|
|
{
|
|
var source = new ol.source.Vector( { features: this.snapFeatures } );
|
|
|
|
this.tracing = new ol.interaction.Draw( { type: "Polygon", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ), trace: true, traceSource: source } );
|
|
|
|
var actions = this.interactions[ netgis.Modes.DRAW_POLYGONS ];
|
|
actions[ 0 ].setActive( false );
|
|
actions.push( this.tracing );
|
|
|
|
this.setMode( this.mode );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.setTracingOff = function()
|
|
{
|
|
var actions = this.interactions[ netgis.Modes.DRAW_POLYGONS ];
|
|
actions[ 0 ].setActive( true );
|
|
actions.splice( actions.indexOf( this.tracing ), 1 );
|
|
|
|
this.setMode( this.mode );
|
|
};
|
|
|
|
/*
|
|
netgis.MapOpenLayers.prototype.updateSnapLayers = function()
|
|
{
|
|
var snapLayers = this.getActiveVectorLayers();
|
|
|
|
this.snapFeatures.clear();
|
|
|
|
if ( snapLayers.length > 0 )
|
|
{
|
|
for ( var i = 0; i < snapLayers.length; i++ )
|
|
{
|
|
var layerFeatures = snapLayers[ i ].getSource().getFeatures();
|
|
|
|
for ( var j = 0; j < layerFeatures.length; j++ )
|
|
{
|
|
this.snapFeatures.push( layerFeatures[ j ] );
|
|
}
|
|
}
|
|
|
|
console.info( "Snap Features:", this.snapFeatures.getLength() );
|
|
}
|
|
};
|
|
*/
|
|
|
|
netgis.MapOpenLayers.prototype.addSnapLayer = function( vectorLayer )
|
|
{
|
|
var layerFeatures = vectorLayer.getSource().getFeatures();
|
|
|
|
for ( var j = 0; j < layerFeatures.length; j++ )
|
|
{
|
|
this.snapFeatures.push( layerFeatures[ j ] );
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.removeSnapLayer = function( vectorLayer )
|
|
{
|
|
var layerFeatures = vectorLayer.getSource().getFeatures();
|
|
|
|
for ( var j = 0; j < layerFeatures.length; j++ )
|
|
{
|
|
this.snapFeatures.remove( layerFeatures[ j ] );
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onSnapOn = function( e )
|
|
{
|
|
this.setSnapOn();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onSnapOff = function( e )
|
|
{
|
|
this.setSnapOff();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onTracingOn = function( e )
|
|
{
|
|
this.setTracingOn();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onTracingOff = function( e )
|
|
{
|
|
this.setTracingOff();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onLayerShow = function( e )
|
|
{
|
|
var layer = this.layers[ e.id ];
|
|
|
|
if ( ! layer ) return;
|
|
|
|
this.map.addLayer( layer );
|
|
|
|
//if ( /*this.snap &&*/ layer instanceof ol.layer.Vector ) this.addSnapLayer( layer ); //this.updateSnapLayers();
|
|
|
|
if ( layer instanceof ol.layer.Vector ) this.addSnapLayer( layer );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onLayerHide = function( e )
|
|
{
|
|
var layer = this.layers[ e.id ];
|
|
|
|
if ( ! layer ) return;
|
|
|
|
this.map.removeLayer( layer );
|
|
|
|
if ( layer instanceof ol.layer.Vector ) this.removeSnapLayer( layer ); //this.updateSnapLayers();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onContextUpdate = function( e )
|
|
{
|
|
this.clearAll();
|
|
|
|
var context = e;
|
|
|
|
// Bounding Box
|
|
var bbox = context.bbox;
|
|
|
|
if ( bbox )
|
|
{
|
|
var bbox1;
|
|
var bbox2;
|
|
|
|
if ( netgis.util.isDefined( this.client.config.map ) && netgis.util.isDefined( this.client.config.map.projection ) )
|
|
{
|
|
bbox1 = ol.proj.fromLonLat( [ bbox[ 0 ], bbox[ 1 ] ], this.client.config.map.projection );
|
|
bbox2 = ol.proj.fromLonLat( [ bbox[ 2 ], bbox[ 3 ] ], this.client.config.map.projection );
|
|
}
|
|
else
|
|
{
|
|
bbox1 = ol.proj.fromLonLat( [ bbox[ 0 ], bbox[ 1 ] ] );
|
|
bbox2 = ol.proj.fromLonLat( [ bbox[ 2 ], bbox[ 3 ] ] );
|
|
}
|
|
|
|
bbox[ 0 ] = bbox1[ 0 ];
|
|
bbox[ 1 ] = bbox1[ 1 ];
|
|
bbox[ 2 ] = bbox2[ 0 ];
|
|
bbox[ 3 ] = bbox2[ 1 ];
|
|
|
|
this.view.fit( bbox );
|
|
}
|
|
|
|
// Layers
|
|
//this.layers = [];
|
|
|
|
for ( var l = 0; l < context.layers.length; l++ )
|
|
//for ( var l = context.layers.length - 1; l >= 0; l-- )
|
|
{
|
|
var data = context.layers[ l ];
|
|
var layer = this.createLayer( data );
|
|
|
|
if ( layer )
|
|
{
|
|
layer.setZIndex( context.layers.length - l );
|
|
//this.layers.push( layer );
|
|
this.layers[ l ] = layer;
|
|
}
|
|
}
|
|
|
|
//this.map.getLayers().clear();
|
|
|
|
//TODO: active layers from context?
|
|
|
|
// Active State
|
|
/*for ( var l = 0; l < context.layers.length; l++ )
|
|
{
|
|
var data = context.layers[ l ];
|
|
if ( data.active ) this.onLayerShow( { id: l } );
|
|
}*/
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onAddServiceWMS = function( e )
|
|
{
|
|
var layer = this.createLayerWMS( e.url, e.name, e.format );
|
|
layer.setZIndex( e.id );
|
|
this.layers[ e.id ] = layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onAddServiceWFS = function( e )
|
|
{
|
|
var layer = this.createLayerWFS( e.url, e.name, this.client.config.map.projection, e.format );
|
|
layer.setZIndex( e.id );
|
|
this.layers[ e.id ] = layer;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onSetMode = function( e )
|
|
{
|
|
this.setMode( e );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onSetExtent = function( e )
|
|
{
|
|
var minxy = ol.proj.fromLonLat( [ e.minx, e.miny ], this.client.config.map.projection );
|
|
var maxxy = ol.proj.fromLonLat( [ e.maxx, e.maxy ], this.client.config.map.projection );
|
|
|
|
this.view.fit( [ minxy[ 0 ], minxy[ 1 ], maxxy[ 0 ], maxxy[ 1 ] ] );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onChangeZoom = function( e )
|
|
{
|
|
var delta = e;
|
|
this.view.animate( { zoom: this.view.getZoom() + delta, duration: 200 } );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onZoomWKT = function( e )
|
|
{
|
|
var parser = new ol.format.WKT();
|
|
var geom = parser.readGeometry( e );
|
|
var padding = 40;
|
|
|
|
this.view.fit( geom, { duration: 300, padding: [ padding, padding, padding, padding ] } );
|
|
|
|
//TODO: take visible panels into account when zooming
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onPointerMove = function( e )
|
|
{
|
|
var pixel = e.pixel;
|
|
var coords = e.coordinate;
|
|
|
|
var hover = this.hover;
|
|
var styleSelect = this.styleSelect.bind( this );
|
|
|
|
if ( hover )
|
|
{
|
|
hover.setStyle( this.styleEdit.bind( this ) );
|
|
hover = null;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
switch ( this.mode )
|
|
{
|
|
case netgis.Modes.DELETE_FEATURES:
|
|
{
|
|
this.map.forEachFeatureAtPixel
|
|
(
|
|
pixel,
|
|
function( feature, layer ) //TODO: bind to this?
|
|
{
|
|
if ( layer === self.editLayer )
|
|
{
|
|
hover = feature;
|
|
feature.setStyle( styleSelect );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.CUT_FEATURE_BEGIN:
|
|
{
|
|
this.map.forEachFeatureAtPixel
|
|
(
|
|
pixel,
|
|
function( feature, layer ) //TODO: bind to this?
|
|
{
|
|
if ( layer === self.editLayer )
|
|
{
|
|
hover = feature;
|
|
feature.setStyle( styleSelect );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.BUFFER_FEATURE_BEGIN:
|
|
{
|
|
this.map.forEachFeatureAtPixel
|
|
(
|
|
pixel,
|
|
function( feature, layer ) //TODO: bind to this?
|
|
{
|
|
if ( layer === self.editLayer )
|
|
{
|
|
hover = feature;
|
|
feature.setStyle( styleSelect );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.DRAW_POINTS:
|
|
case netgis.Modes.DRAW_LINES:
|
|
{
|
|
this.updateDrawBufferPreview();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//TODO: refactor to default hover handler?
|
|
|
|
this.hover = hover;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onSingleClick = function( e )
|
|
{
|
|
switch ( this.mode )
|
|
{
|
|
case netgis.Modes.DELETE_FEATURES:
|
|
{
|
|
if ( this.hover )
|
|
{
|
|
this.editLayer.getSource().removeFeature( this.hover );
|
|
this.hover = null;
|
|
|
|
this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.CUT_FEATURE_BEGIN:
|
|
{
|
|
if ( this.hover )
|
|
{
|
|
this.selected = this.hover;
|
|
this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.CUT_FEATURE_DRAW );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case netgis.Modes.BUFFER_FEATURE_BEGIN:
|
|
{
|
|
if ( this.hover )
|
|
{
|
|
this.selected = this.hover;
|
|
this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.BUFFER_FEATURE_EDIT );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onMoveStart = function( e )
|
|
{
|
|
//TODO: problem with toolbars after head menu click
|
|
//this.client.invoke( netgis.Events.MAP_SET_MODE, netgis.MapModes.PANNING );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onMoveEnd = function( e )
|
|
{
|
|
//TODO: problem with toolbars after head menu click
|
|
//this.client.invoke( netgis.Events.MAP_SET_MODE, netgis.MapModes.VIEW );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onChangeResolution = function( e )
|
|
{
|
|
//var d = e.oldValue - this.view.getResolution();
|
|
//this.client.invoke( netgis.Events.MAP_SET_MODE, ( d > 0.0 ) ? netgis.MapModes.ZOOMING_IN : netgis.MapModes.ZOOMING_OUT );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onCutFeatureDrawEnd = function( e )
|
|
{
|
|
var cutter = e.feature;
|
|
var target = this.selected;
|
|
|
|
if ( target )
|
|
{
|
|
// Cut Process
|
|
var parser = new jsts.io.OL3Parser();
|
|
|
|
var a = parser.read( target.getGeometry() );
|
|
var b = parser.read( cutter.getGeometry() );
|
|
|
|
var c = a.difference( b );
|
|
|
|
// Output
|
|
var geom = parser.write( c );
|
|
var feature = new ol.Feature( { geometry: geom } );
|
|
|
|
var source = this.editLayer.getSource();
|
|
source.removeFeature( target );
|
|
source.addFeature( feature );
|
|
|
|
this.selected = feature;
|
|
}
|
|
|
|
this.editEventsSilent = true;
|
|
this.splitMultiPolygons( this.editLayer );
|
|
this.editEventsSilent = false;
|
|
this.updateEditOutput();
|
|
|
|
this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onModifyFeaturesEnd = function( e )
|
|
{
|
|
this.updateEditOutput();
|
|
this.updateEditArea();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createBufferFeature = function( srcgeom, radius, segments )
|
|
{
|
|
var geom = this.createBufferGeometry( srcgeom, radius, segments );
|
|
var feature = new ol.Feature( { geometry: geom } );
|
|
|
|
return feature;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createBufferGeometry = function( srcgeom, radius, segments )
|
|
{
|
|
var parser = new jsts.io.OL3Parser();
|
|
|
|
var a = parser.read( srcgeom );
|
|
var b = a.buffer( radius, segments );
|
|
|
|
var geom = parser.write( b );
|
|
|
|
return geom;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onBufferChange = function( e )
|
|
{
|
|
var source = this.editLayer.getSource();
|
|
var target = this.selected;
|
|
|
|
if ( this.sketch )
|
|
{
|
|
source.removeFeature( this.sketch );
|
|
}
|
|
|
|
if ( target )
|
|
{
|
|
var feature = this.createBufferFeature( target.getGeometry(), e.radius, e.segments );
|
|
|
|
//source.removeFeature( target );
|
|
source.addFeature( feature );
|
|
|
|
this.sketch = feature;
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onBufferAccept = function( e )
|
|
{
|
|
if ( this.selected && this.sketch )
|
|
{
|
|
var source = this.editLayer.getSource();
|
|
|
|
// Delete Input Feature
|
|
//if ( ! ( this.selected.getGeometry() instanceof ol.geom.Point ) )
|
|
source.removeFeature( this.selected );
|
|
}
|
|
|
|
this.sketch = null;
|
|
this.selected = null;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onBufferCancel = function( e )
|
|
{
|
|
if ( this.sketch )
|
|
{
|
|
this.editLayer.getSource().removeFeature( this.sketch );
|
|
this.sketch = null;
|
|
}
|
|
|
|
this.selected = null;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawPointsEnd = function( e )
|
|
{
|
|
var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
|
|
|
|
if ( preview )
|
|
{
|
|
var src = this.editLayer.getSource();
|
|
|
|
// Add Buffer Feature
|
|
src.addFeature( preview.clone() );
|
|
|
|
// Remove Sketch Feature
|
|
window.setTimeout
|
|
(
|
|
function()
|
|
{
|
|
src.removeFeature( e.feature );
|
|
},
|
|
10
|
|
);
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawLinesEnd = function( e )
|
|
{
|
|
var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
|
|
|
|
if ( preview )
|
|
{
|
|
var src = this.editLayer.getSource();
|
|
|
|
// Add Buffer Feature
|
|
src.addFeature( preview.clone() );
|
|
|
|
// Remove Sketch Feature
|
|
window.setTimeout
|
|
(
|
|
function()
|
|
{
|
|
src.removeFeature( e.feature );
|
|
},
|
|
10
|
|
);
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawBufferOn = function( e )
|
|
{
|
|
var feature = this.createBufferFeature( new ol.geom.Point( this.client.config.map.center ), this.drawBufferRadius, this.drawBufferSegments );
|
|
this.previewLayer.getSource().addFeature( feature );
|
|
|
|
//TODO: send all draw buffer params with events ?
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawBufferOff = function( e )
|
|
{
|
|
this.previewLayer.getSource().clear();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawBufferRadiusChange = function( e )
|
|
{
|
|
var radius = e;
|
|
this.drawBufferRadius = radius;
|
|
|
|
this.updateDrawBufferPreview();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDrawBufferSegmentsChange = function( e )
|
|
{
|
|
var segs = e;
|
|
this.drawBufferSegments = segs;
|
|
|
|
this.updateDrawBufferPreview();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.updateDrawBufferPreview = function()
|
|
{
|
|
var draw = this.interactions[ this.mode ][ 0 ];
|
|
var overlays = draw.getOverlay().getSource().getFeatures();
|
|
if ( overlays.length < 1 ) return;
|
|
|
|
var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
|
|
if ( ! preview ) return;
|
|
|
|
var geom = overlays[ 0 ].getGeometry();
|
|
var buffer = this.createBufferGeometry( geom, this.drawBufferRadius, this.drawBufferSegments );
|
|
preview.setGeometry( buffer );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onEditLayerAdd = function( e )
|
|
{
|
|
////this.updateEditOutput();
|
|
this.updateEditLayerItem();
|
|
this.updateEditOutput();
|
|
this.snapFeatures.push( e.feature );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onEditLayerRemove = function( e )
|
|
{
|
|
this.updateEditOutput();
|
|
this.snapFeatures.remove( e.feature );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onEditLayerChange = function( e )
|
|
{
|
|
this.updateEditOutput();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.updateEditOutput = function()
|
|
{
|
|
var features = this.editLayer.getSource().getFeatures();
|
|
|
|
var proj = this.client.config.map.projection;
|
|
var format = new ol.format.GeoJSON();
|
|
var output = format.writeFeaturesObject( features, { dataProjection: proj, featureProjection: proj } );
|
|
|
|
// Projection
|
|
output[ "crs" ] =
|
|
{
|
|
"type": "name",
|
|
"properties": { "name": "urn:ogc:def:crs:" + proj.replace( ":", "::" ) }
|
|
};
|
|
|
|
// Total Area
|
|
var area = 0.0;
|
|
|
|
for ( var i = 0; i < features.length; i++ )
|
|
{
|
|
var geom = features[ i ].getGeometry();
|
|
if ( geom instanceof ol.geom.Polygon ) area += geom.getArea();
|
|
}
|
|
|
|
output[ "area" ] = area;
|
|
|
|
if ( ! this.editEventsSilent )
|
|
{
|
|
this.client.invoke( netgis.Events.EDIT_FEATURES_CHANGE, output );
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.updateEditLayerItem = function()
|
|
{
|
|
// Create layer item if not existing
|
|
var id = this.editLayerID;
|
|
|
|
if ( ! this.layers[ id ] )
|
|
{
|
|
this.layers[ id ] = this.editLayer;
|
|
this.client.invoke( netgis.Events.LAYER_CREATED, { id: id, title: "Zeichnung", checked: true, folder: "draw" } );
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.updateEditArea = function()
|
|
{
|
|
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onEditFeaturesLoaded = function( e )
|
|
{
|
|
var json = e;
|
|
var self = this;
|
|
window.setTimeout( function() { self.createLayerGeoJSON( "Import", json ); }, 10 );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDragEnter = function( e )
|
|
{
|
|
e.preventDefault();
|
|
|
|
this.dropTarget.classList.remove( "netgis-hide" );
|
|
|
|
//TODO: refactor into dragdrop module + events ?
|
|
|
|
return false;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDragLeave = function( e )
|
|
{
|
|
this.dropTarget.classList.add( "netgis-hide" );
|
|
|
|
return false;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDragDrop = function( e )
|
|
{
|
|
console.info( "Drag Drop" );
|
|
|
|
this.dropTarget.classList.add( "netgis-hide" );
|
|
|
|
e.preventDefault();
|
|
|
|
var file = e.dataTransfer.files[ 0 ];
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = this.onDragLoad.bind( this );
|
|
|
|
console.log( "File:", file );
|
|
|
|
//reader.readAsDataURL( file );
|
|
reader.readAsArrayBuffer( file );
|
|
|
|
return false;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onDragLoad = function( e )
|
|
{
|
|
console.log( "On Load:", e.target );
|
|
|
|
this.loadShape( e.target.result );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.loadShape = function( data )
|
|
{
|
|
var self = this;
|
|
|
|
shp( data ).then
|
|
(
|
|
function( geojson )
|
|
{
|
|
self.onShapeLoad( geojson );
|
|
}
|
|
);
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onShapeLoad = function( geojson )
|
|
{
|
|
console.info( "Shapefile To Geojson:", geojson );
|
|
|
|
var features = new ol.format.GeoJSON( { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } ).readFeatures( geojson );
|
|
this.importLayer.getSource().addFeatures( features );
|
|
|
|
this.view.fit( this.importLayer.getSource().getExtent(), {} );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportGeoJSON = function( e )
|
|
{
|
|
var file = e;
|
|
var title = file.name;
|
|
var self = this;
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function( e ) { self.createLayerGeoJSON( title, e.target.result ); };
|
|
reader.readAsText( file );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportGML = function( e )
|
|
{
|
|
var file = e;
|
|
var title = file.name;
|
|
var self = this;
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function( e ) { self.createLayerGML( title, e.target.result ); };
|
|
reader.readAsText( file );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportShapefile = function( e )
|
|
{
|
|
var file = e;
|
|
var title = file.name;
|
|
var self = this;
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function( e ) { self.createLayerShapefile( title, e.target.result ); };
|
|
reader.readAsArrayBuffer( file );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportSpatialite = function( e )
|
|
{
|
|
var file = e;
|
|
var title = file.name;
|
|
var self = this;
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function( e ) { self.createLayerSpatialite( title, e.target.result ); };
|
|
reader.readAsArrayBuffer( file );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportGeopackage = function( e )
|
|
{
|
|
var file = e;
|
|
var title = file.name;
|
|
var self = this;
|
|
|
|
var reader = new FileReader();
|
|
reader.onload = function( e ) { self.createLayerGeopackage( title, e.target.result ); };
|
|
reader.readAsArrayBuffer( file );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerGeoJSON = function( title, data )
|
|
{
|
|
var format = new ol.format.GeoJSON();
|
|
var projection = format.readProjection( data );
|
|
var features = format.readFeatures( data, { featureProjection: this.client.config.map.projection } );
|
|
|
|
//NOTE: proj4.defs[ "EPSG:4326" ]
|
|
//NOTE: netgis.util.foreach( proj4.defs, function( k,v ) { console.info( "DEF:", k, v ); } )
|
|
|
|
var projcode = projection.getCode();
|
|
|
|
switch ( projcode )
|
|
{
|
|
case "EPSG:3857":
|
|
case "EPSG:4326":
|
|
case this.client.config.map.projection:
|
|
{
|
|
// Projection OK
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
// Projection Not Supported
|
|
console.warn( "Unsupported Import Projection:", projcode );
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.addImportedFeatures( features );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerGML = function( title, data )
|
|
{
|
|
//NOTE: https://stackoverflow.com/questions/35935184/opening-qgis-exported-gml-in-openlayers-3
|
|
//NOTE: https://github.com/openlayers/openlayers/issues/5023
|
|
|
|
console.warn( "GML support is experimental!" );
|
|
|
|
//var format = new ol.format.GML3( { srsName: "EPSG::25832", featureType: "Test", featureNS: "http://www.opengis.net/gml" } );
|
|
//var format = new ol.format.GML( { featureNS: "ogr" } );
|
|
//var format = new ol.format.WFS( /*{ srsName: "EPSG:4326", featureType: "ogr:RLP_OG_utf8_epsg4326" }*/ );
|
|
//var format = new ol.format.GML( { featureNS: "ogr", featureType: "ogr:RLP_OG_utf8_epsg4326" } );
|
|
//var format = new ol.format.WFS();
|
|
//var format = new ol.format.WFS( { featureNS: "ogr", featureType: "RLP_OG_utf8_epsg4326" } );
|
|
//var projection = format.readProjection( data );
|
|
//var features = format.readFeatures( data, { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } );
|
|
|
|
//var features = format.readFeatures( data, { dataProjection: this.client.config.map.projection, featureProjection: this.client.config.map.projection } );
|
|
|
|
//console.info( "GML:", projection, features, features[ 0 ].getGeometry() );
|
|
|
|
var features = [];
|
|
|
|
var parser = new DOMParser();
|
|
var xml = parser.parseFromString( data, "text/xml" );
|
|
|
|
// Features
|
|
var featureMembers = xml.getElementsByTagName( "gml:featureMember" );
|
|
|
|
for ( var f = 0; f < featureMembers.length; f++ )
|
|
{
|
|
var props = {};
|
|
|
|
var node = featureMembers[ f ];
|
|
var child = node.children[ 0 ];
|
|
|
|
// Attributes
|
|
for ( var a = 0; a < child.attributes.length; a++ )
|
|
{
|
|
var attribute = child.attributes[ a ];
|
|
props[ attribute.nodeName ] = attribute.nodeValue;
|
|
}
|
|
|
|
for ( var c = 0; c < child.children.length; c++ )
|
|
{
|
|
var childNode = child.children[ c ];
|
|
|
|
if ( childNode.nodeName === "ogr:geometryProperty" ) continue;
|
|
|
|
var parts = childNode.nodeName.split( ":" );
|
|
var k = parts[ parts.length - 1 ];
|
|
var v = childNode.innerHTML;
|
|
|
|
props[ k ] = v;
|
|
}
|
|
|
|
// Geometry
|
|
var geomprop = child.getElementsByTagName( "ogr:geometryProperty" )[ 0 ];
|
|
|
|
//for ( var g = 0; g < geomprop.children.length; g++ )
|
|
{
|
|
var geom = geomprop.children[ 0 ];
|
|
var proj = geom.getAttribute( "srsName" );
|
|
|
|
if ( proj && proj !== "EPSG:4326" && proj !== this.client.config.map.projection )
|
|
console.warn( "Unsupported Import Projection:", proj );
|
|
|
|
switch ( geom.nodeName )
|
|
{
|
|
case "gml:Polygon":
|
|
{
|
|
props[ "geometry" ] = this.gmlParsePolygon( geom, proj );
|
|
break;
|
|
}
|
|
|
|
case "gml:MultiPolygon":
|
|
{
|
|
props[ "geometry" ] = this.gmlParseMultiPolygon( geom, proj );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
var feature = new ol.Feature( props );
|
|
features.push( feature );
|
|
}
|
|
|
|
this.addImportedFeatures( features );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.gmlParsePolygon = function( node, proj )
|
|
{
|
|
var rings = [];
|
|
|
|
var linearRings = node.getElementsByTagName( "gml:LinearRing" );
|
|
|
|
for ( var r = 0; r < linearRings.length; r++ )
|
|
{
|
|
var ring = linearRings[ r ];
|
|
var coords = ring.getElementsByTagName( "gml:coordinates" )[ 0 ].innerHTML;
|
|
rings.push( this.gmlParseCoordinates( coords, proj ) );
|
|
}
|
|
|
|
return new ol.geom.Polygon( rings );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.gmlParseMultiPolygon = function( node, proj )
|
|
{
|
|
var polygons = [];
|
|
|
|
var polygonMembers = node.getElementsByTagName( "gml:polygonMember" );
|
|
|
|
for ( var p = 0; p < polygonMembers.length; p++ )
|
|
{
|
|
var polygonMember = polygonMembers[ p ];
|
|
var polygonNode = polygonMember.getElementsByTagName( "gml:Polygon" )[ 0 ];
|
|
polygons.push( this.gmlParsePolygon( polygonNode, proj ) );
|
|
}
|
|
|
|
return new ol.geom.MultiPolygon( polygons );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.gmlParseCoordinates = function( s, proj )
|
|
{
|
|
var coords = s.split( " " );
|
|
|
|
for ( var c = 0; c < coords.length; c++ )
|
|
{
|
|
// Split
|
|
coords[ c ] = coords[ c ].split( "," );
|
|
|
|
// Parse
|
|
for ( var xy = 0; xy < coords[ c ].length; xy++ )
|
|
{
|
|
coords[ c ][ xy ] = Number.parseFloat( coords[ c ][ xy ] );
|
|
}
|
|
|
|
// Transform
|
|
if ( proj ) coords[ c ] = ol.proj.transform( coords[ c ], proj, this.client.config.map.projection );
|
|
}
|
|
|
|
return coords;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerShapefile = function( title, shapeData )
|
|
{
|
|
var self = this;
|
|
|
|
shp( shapeData ).then
|
|
(
|
|
function( geojson )
|
|
{
|
|
//var format = new ol.format.GeoJSON( { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } );
|
|
var format = new ol.format.GeoJSON();
|
|
var projection = format.readProjection( geojson );
|
|
var features = format.readFeatures( geojson, { featureProjection: self.client.config.map.projection } );
|
|
|
|
self.addImportedFeatures( features );
|
|
}
|
|
);
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerSpatialite = function( title, data )
|
|
{
|
|
var self = this;
|
|
|
|
window.initSqlJs().then
|
|
(
|
|
function( SQL )
|
|
{
|
|
var features = [];
|
|
|
|
var arr = new Uint8Array( data );
|
|
var db = new SQL.Database( arr );
|
|
|
|
// Tables
|
|
var results = db.exec
|
|
(
|
|
"SELECT name FROM sqlite_schema WHERE type = 'table' \n\
|
|
AND name NOT LIKE 'sqlite_%' \n\
|
|
AND name NOT LIKE 'sql_%' \n\
|
|
AND name NOT LIKE 'idx_%' \n\
|
|
AND name NOT LIKE 'spatial_ref_sys%' \n\
|
|
AND name NOT LIKE 'spatialite_%' \n\
|
|
AND name NOT LIKE 'geometry_columns%' \n\
|
|
AND name NOT LIKE 'views_%' \n\
|
|
AND name NOT LIKE 'virts_%' \n\
|
|
AND name NOT LIKE 'SpatialIndex' \n\
|
|
AND name NOT LIKE 'ElementaryGeometries' \n\
|
|
;" );
|
|
|
|
var tables = results[ 0 ].values;
|
|
|
|
for ( var t = 0; t < tables.length; t++ )
|
|
{
|
|
var table = tables[ t ][ 0 ];
|
|
|
|
results = db.exec( "SELECT * FROM " + table );
|
|
var result = results[ 0 ];
|
|
|
|
// Columns
|
|
var geomcol = null;
|
|
|
|
for ( var c = 0; c < result.columns.length; c++ )
|
|
{
|
|
if ( result.columns[ c ].toLowerCase() === "geometry" ) { geomcol = c; break; }
|
|
if ( result.columns[ c ].toLowerCase() === "geom" ) { geomcol = c; break; }
|
|
}
|
|
|
|
// Rows
|
|
var rows = result.values;
|
|
|
|
for ( var r = 0; r < rows.length; r++ )
|
|
{
|
|
var row = rows[ r ];
|
|
|
|
// Convert WKB
|
|
var input = row[ geomcol ];
|
|
var output = new Uint8Array( input.length - 43 - 1 + 5 );
|
|
|
|
// Byte Order
|
|
output[ 0 ] = input[ 1 ];
|
|
|
|
// Type
|
|
output[ 1 ] = input[ 39 ];
|
|
output[ 2 ] = input[ 40 ];
|
|
output[ 3 ] = input[ 41 ];
|
|
output[ 4 ] = input[ 42 ];
|
|
|
|
// Geometry
|
|
var geomlen = input.length - 43 - 1;
|
|
|
|
for ( var i = 0; i < geomlen; i++ )
|
|
{
|
|
output[ 5 + i ] = input[ 43 + i ];
|
|
}
|
|
|
|
var wkb = new ol.format.WKB();
|
|
var geom = wkb.readGeometry( output, { featureProjection: self.client.config.map.projection } );
|
|
|
|
features.push( new ol.Feature( { geometry: geom } ) );
|
|
}
|
|
}
|
|
|
|
self.addImportedFeatures( features );
|
|
}
|
|
);
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.createLayerGeopackage = function( title, data )
|
|
{
|
|
var self = this;
|
|
var arr = new Uint8Array( data );
|
|
|
|
window.GeoPackage.setSqljsWasmLocateFile( function( file ) { return self.client.config.import.geopackageLibURL + file; } );
|
|
|
|
window.GeoPackage.GeoPackageAPI.open( arr ).then( function( geoPackage )
|
|
{
|
|
var features = [];
|
|
var format = new ol.format.GeoJSON();
|
|
var tables = geoPackage.getFeatureTables();
|
|
|
|
for ( var t = 0; t < tables.length; t++ )
|
|
{
|
|
var table = tables[ t ];
|
|
var rows = geoPackage.queryForGeoJSONFeaturesInTable( table );
|
|
|
|
for ( var r = 0; r < rows.length; r++ )
|
|
{
|
|
var row = rows[ r ];
|
|
var geom = format.readGeometry( row.geometry, { featureProjection: self.client.config.map.projection } );
|
|
var feature = new ol.Feature( { geometry: geom } );
|
|
features.push( feature );
|
|
}
|
|
}
|
|
|
|
self.addImportedFeatures( features );
|
|
} );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.addImportedFeatures = function( features )
|
|
{
|
|
// Add To Edit Layer
|
|
this.editEventsSilent = true;
|
|
this.editLayer.getSource().addFeatures( features );
|
|
this.editEventsSilent = false;
|
|
this.updateEditOutput();
|
|
|
|
// Zoom Imported Features
|
|
if ( features.length > 0 )
|
|
{
|
|
var extent = features[ 0 ].getGeometry().getExtent();
|
|
|
|
for ( var f = 1; f < features.length; f++ )
|
|
{
|
|
ol.extent.extend( extent, features[ f ].getGeometry().getExtent() );
|
|
}
|
|
|
|
var padding = 40;
|
|
this.view.fit( extent, { duration: 300, padding: [ padding, padding, padding, padding ] } );
|
|
}
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onImportWKT = function( e )
|
|
{
|
|
var parser = new ol.format.WKT();
|
|
var geom = parser.readGeometry( e );
|
|
var feature = new ol.Feature( { geometry: geom } );
|
|
|
|
this.addImportedFeatures( [ feature ] );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onExportPDF = function( e )
|
|
{
|
|
this.exportImage( "pdf", e.resx, e.resy, e.mode, e.margin );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onExportJPEG = function( e )
|
|
{
|
|
this.exportImage( "jpeg", e.resx, e.resy );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onExportPNG = function( e )
|
|
{
|
|
this.exportImage( "png", e.resx, e.resy );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onExportGIF = function( e )
|
|
{
|
|
this.exportImage( "gif", e.resx, e.resy );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onParcelShowPreview = function( e )
|
|
{
|
|
var parser = new ol.format.WKT();
|
|
var geom = parser.readGeometry( e.geom );
|
|
var feature = new ol.Feature( { geometry: geom } );
|
|
|
|
this.parcelLayer.getSource().clear();
|
|
this.parcelLayer.getSource().addFeature( feature );
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.onParcelHidePreview = function( e )
|
|
{
|
|
this.parcelLayer.getSource().clear();
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.getWidth = function()
|
|
{
|
|
return this.map.getSize()[ 0 ];
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.getHeight = function()
|
|
{
|
|
return this.map.getSize()[ 1 ];
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param {format} string Format identifier (jpeg, png, gif)
|
|
* @param {resx} integer Map image x resolution (pixels)
|
|
* @param {resy} integer Map image y resolution (pixels)
|
|
* @param {mode} boolean PDF mode (true = landscape, false = portrait)
|
|
* @param {margin} integer PDF page margin (millimeters)
|
|
*/
|
|
netgis.MapOpenLayers.prototype.exportImage = function( format, resx, resy, mode, margin )
|
|
{
|
|
this.client.invoke( netgis.Events.EXPORT_BEGIN, null );
|
|
|
|
var self = this;
|
|
var root = this.root;
|
|
var map = this.map;
|
|
var config = this.client.config;
|
|
|
|
// Request Logo Image
|
|
var logo = new Image();
|
|
|
|
logo.onload = function()
|
|
{
|
|
//TODO: refactor map render image and image export
|
|
//NOTE: https://github.com/openlayers/openlayers/issues/9100
|
|
//NOTE: scaling / quality bugs when map pixel ratio is not 1.0
|
|
|
|
// Render Target
|
|
var renderContainer = document.createElement( "div" );
|
|
renderContainer.style.position = "fixed";
|
|
renderContainer.style.top = "0px";
|
|
renderContainer.style.left = "0px";
|
|
renderContainer.style.width = resx + "px";
|
|
renderContainer.style.height = resy + "px";
|
|
renderContainer.style.background = "white";
|
|
renderContainer.style.zIndex = -1;
|
|
renderContainer.style.opacity = 0.0;
|
|
renderContainer.style.pointerEvents = "none";
|
|
root.appendChild( renderContainer );
|
|
|
|
map.setTarget( renderContainer );
|
|
|
|
// Request Render
|
|
map.once
|
|
(
|
|
"rendercomplete",
|
|
function()
|
|
{
|
|
var mapCanvas = document.createElement( "canvas" );
|
|
mapCanvas.width = resx;
|
|
mapCanvas.height = resy;
|
|
|
|
var mapContext = mapCanvas.getContext( "2d" );
|
|
mapContext.webkitImageSmoothingEnabled = false;
|
|
mapContext.mozImageSmoothingEnabled = false;
|
|
mapContext.imageSmoothingEnabled = false;
|
|
|
|
// Loop Map Layers
|
|
Array.prototype.forEach.call
|
|
(
|
|
document.querySelectorAll( ".ol-layer canvas" ),
|
|
function( canvas )
|
|
{
|
|
if ( canvas.width > 0 )
|
|
{
|
|
var opacity = canvas.parentNode.style.opacity;
|
|
mapContext.globalAlpha = ( opacity === '' ) ? 1.0 : Number( opacity );
|
|
|
|
var transform = canvas.style.transform;
|
|
var matrix = transform.match( /^matrix\(([^\(]*)\)$/ )[ 1 ].split( "," ).map( Number );
|
|
|
|
CanvasRenderingContext2D.prototype.setTransform.apply( mapContext, matrix );
|
|
|
|
mapContext.drawImage( canvas, 0, 0 );
|
|
}
|
|
}
|
|
);
|
|
|
|
// Watermark Logo
|
|
mapContext.drawImage( logo, 0, 0 );
|
|
|
|
// Timestamp
|
|
mapContext.fillStyle = "#fff";
|
|
mapContext.fillRect( 0, mapCanvas.height - 30, 140, 30 );
|
|
mapContext.fillStyle = "#000";
|
|
mapContext.font = "4mm sans-serif";
|
|
mapContext.fillText( netgis.util.getTimeStamp(), 10, mapCanvas.height - 10 );
|
|
|
|
// Export Map Image
|
|
var link = document.createElement( "a" );
|
|
|
|
switch ( format )
|
|
{
|
|
case "pdf":
|
|
{
|
|
// Dimensions
|
|
var landscape = mode;
|
|
margin = margin ? margin : 0;
|
|
var widthA4 = 297 - margin - margin;
|
|
var heightA4 = 210 - margin - margin;
|
|
var ratio = mapCanvas.width / mapCanvas.height;
|
|
|
|
if ( ! landscape )
|
|
{
|
|
var w = widthA4;
|
|
widthA4 = heightA4;
|
|
heightA4 = w;
|
|
}
|
|
|
|
var width;
|
|
var height;
|
|
|
|
if ( mapCanvas.height > mapCanvas.width )
|
|
{
|
|
// Tall Canvas
|
|
height = heightA4;
|
|
width = height * ratio;
|
|
|
|
if ( width > widthA4 )
|
|
{
|
|
width = widthA4;
|
|
height = width / ratio;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Wide Canvas
|
|
width = widthA4;
|
|
height = width / ratio;
|
|
|
|
if ( height > heightA4 )
|
|
{
|
|
height = heightA4;
|
|
width = height * ratio;
|
|
}
|
|
}
|
|
|
|
var pdf = new jsPDF( landscape ? "l" : "p" );
|
|
|
|
var x = margin;
|
|
x += ( widthA4 - width ) / 2;
|
|
|
|
var y = margin;
|
|
y += ( heightA4 - height ) / 2;
|
|
|
|
// Map Image
|
|
pdf.addImage( mapCanvas.toDataURL( "image/png,1.0", 1.0 ), "PNG", x, y, width, height );
|
|
|
|
// Text
|
|
pdf.setFillColor( 255, 255, 255 );
|
|
pdf.rect( x, y + height - 11, 80, 11, "F" );
|
|
|
|
pdf.setFontSize( 8 );
|
|
pdf.text( "Datum: " + netgis.util.getTimeStamp(), x + 2, y + height - 2 - 4 );
|
|
pdf.text( "Quelle: " + window.location.href, x + 2, y + height - 2 );
|
|
|
|
// Same Tab
|
|
//pdf.output( "save", { filename: config.export.defaultFilename + ".pdf" } );
|
|
|
|
// New Tab (without Name)
|
|
var data = pdf.output( "bloburl", { filename: config.export.defaultFilename + ".pdf" } );
|
|
window.open( data, "_blank" );
|
|
|
|
/*
|
|
// Download (with Name)
|
|
var data = pdf.output( "blob", { filename: config.export.defaultFilename + ".pdf" } );
|
|
var blob = new Blob( [ data ], { type: "octet/stream" } );
|
|
link.setAttribute( "download", "Export.pdf" );
|
|
link.setAttribute( "href", window.URL.createObjectURL( blob ) );
|
|
link.click();
|
|
//window.URL.revokeObjectURL( url );
|
|
*/
|
|
|
|
break;
|
|
}
|
|
|
|
case "jpeg":
|
|
{
|
|
if ( window.navigator.msSaveBlob )
|
|
{
|
|
window.navigator.msSaveBlob( mapCanvas.msToBlob(), config.export.defaultFilename + ".jpg" );
|
|
}
|
|
else
|
|
{
|
|
link.setAttribute( "download", config.export.defaultFilename + ".jpg" );
|
|
link.setAttribute( "href", mapCanvas.toDataURL( "image/jpeg", 1.0 ) );
|
|
link.click();
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case "png":
|
|
{
|
|
if ( window.navigator.msSaveBlob )
|
|
{
|
|
//if ( ! config.export.openNewTab )
|
|
window.navigator.msSaveBlob( mapCanvas.msToBlob(), config.export.defaultFilename + ".png" );
|
|
/*else
|
|
window.open( mapCanvas.msToBlob(), "_blank" );*/
|
|
}
|
|
else
|
|
{
|
|
/*if ( ! config.export.openNewTab )
|
|
{*/
|
|
link.setAttribute( "download", config.export.defaultFilename + ".png" );
|
|
link.setAttribute( "href", mapCanvas.toDataURL( "image/png", 1.0 ) );
|
|
link.click();
|
|
/*}
|
|
else
|
|
window.open( mapCanvas.toDataURL( "image/png", 1.0 ), "_blank" );*/
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case "gif":
|
|
{
|
|
link.setAttribute( "download", config.export.defaultFilename + ".gif" );
|
|
|
|
var gif = new GIF( { workerScript: config.export.gifWebWorker, quality: 1 } );
|
|
gif.addFrame( mapCanvas );
|
|
|
|
gif.on
|
|
(
|
|
"finished",
|
|
function( blob )
|
|
{
|
|
link.setAttribute( "href", window.URL.createObjectURL( blob ) );
|
|
link.click();
|
|
}
|
|
);
|
|
|
|
gif.render();
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// Done
|
|
map.setTarget( root );
|
|
root.removeChild( renderContainer );
|
|
|
|
self.client.invoke( netgis.Events.EXPORT_END, null );
|
|
}
|
|
);
|
|
|
|
// Begin Map Render
|
|
map.renderSync();
|
|
};
|
|
|
|
// Begin Logo Load & Render
|
|
logo.src = config.export.logo;
|
|
};
|
|
|
|
netgis.MapOpenLayers.prototype.splitMultiPolygons = function( layer )
|
|
{
|
|
//TODO: split only selected feature ( parameter )
|
|
|
|
var source = layer.getSource();
|
|
var features = source.getFeatures();
|
|
|
|
var removeFeatures = [];
|
|
var newFeatures = [];
|
|
|
|
// Find Multi Features
|
|
for ( var i = 0; i < features.length; i++ )
|
|
{
|
|
var feature = features[ i ];
|
|
var geom = feature.getGeometry();
|
|
|
|
if ( geom instanceof ol.geom.MultiPolygon )
|
|
{
|
|
var polygons = geom.getPolygons();
|
|
|
|
// Create Single Features
|
|
for ( var j = 0; j < polygons.length; j++ )
|
|
{
|
|
var polygon = polygons[ j ];
|
|
var newFeature = new ol.Feature( { geometry: polygon } );
|
|
newFeatures.push( newFeature );
|
|
}
|
|
|
|
removeFeatures.push( feature );
|
|
}
|
|
}
|
|
|
|
// Remove Multi Features
|
|
for ( var i = 0; i < removeFeatures.length; i++ )
|
|
{
|
|
source.removeFeature( removeFeatures[ i ] );
|
|
}
|
|
|
|
// Add Single Features
|
|
source.addFeatures( newFeatures );
|
|
}; |