2022-09-12 13:12:59 +02:00
/* 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 ;
2023-01-31 16:26:59 +01:00
this . importLayerID = 20000 ;
this . editLayerID = 30000 ;
this . labelFont = "4mm Verdana, sans-serif" ;
this . drawBufferRadius = 100.0 ;
this . drawBufferSegments = 3 ;
2022-09-12 13:12:59 +02:00
} ;
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
2023-01-31 16:26:59 +01:00
this . initMap ( ) ;
this . initDefaultLayers ( ) ;
this . initInteractions ( ) ;
2022-09-12 13:12:59 +02:00
// 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 ) ) ;
2023-01-31 16:26:59 +01:00
this . client . on ( netgis . Events . TRACING _ON , this . onTracingOn . bind ( this ) ) ;
this . client . on ( netgis . Events . TRACING _OFF , this . onTracingOff . bind ( this ) ) ;
2022-09-12 13:12:59 +02:00
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 ) ) ;
2023-01-31 16:26:59 +01:00
this . client . on ( netgis . Events . IMPORT _SPATIALITE , this . onImportSpatialite . bind ( this ) ) ;
this . client . on ( netgis . Events . IMPORT _GEOPACKAGE , this . onImportGeopackage . bind ( this ) ) ;
2022-09-12 13:12:59 +02:00
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 ) ) ;
2023-01-31 16:26:59 +01:00
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 ) ) ;
2022-09-12 13:12:59 +02:00
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . initMap = function ( )
2022-09-12 13:12:59 +02:00
{
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 ) ) ;
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . initDefaultLayers = function ( )
2022-09-12 13:12:59 +02:00
{
//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 ) ;
2023-01-31 16:26:59 +01:00
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 } ) ;
2022-09-12 13:12:59 +02:00
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*/ );
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . initInteractions = function ( )
2022-09-12 13:12:59 +02:00
{
// 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 ( )
] ;
2023-01-31 16:26:59 +01:00
this . interactions [ netgis . Modes . DRAW _POINTS ] [ 0 ] . on ( "drawend" , this . onDrawPointsEnd . bind ( this ) ) ;
2022-09-12 13:12:59 +02:00
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 ( )
] ;
2023-01-31 16:26:59 +01:00
this . interactions [ netgis . Modes . DRAW _LINES ] [ 0 ] . on ( "drawend" , this . onDrawLinesEnd . bind ( this ) ) ;
2022-09-12 13:12:59 +02:00
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(),
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 )
{
2023-01-31 16:26:59 +01:00
var layer = null ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
// Create Specific Layer By Type
2022-09-12 13:12:59 +02:00
switch ( data . type )
{
case netgis . LayerTypes . XYZ :
{
2023-01-31 16:26:59 +01:00
layer = this . createLayerXYZ ( data . url ) ;
break ;
2022-09-12 13:12:59 +02:00
}
case netgis . LayerTypes . OSM :
{
2023-01-31 16:26:59 +01:00
layer = this . createLayerOSM ( ) ;
break ;
2022-09-12 13:12:59 +02:00
}
case netgis . LayerTypes . WMS :
{
2023-01-31 16:26:59 +01:00
layer = this . createLayerWMS ( data . url , data . name , data . format , data . username , data . password ) ;
break ;
2022-09-12 13:12:59 +02:00
}
case netgis . LayerTypes . WFS :
{
2023-02-13 09:03:09 +01:00
layer = this . createLayerWFS ( data . url , data . name , this . client . config . map . projection , data . outputFormat , data . username , data . password ) ;
2023-01-31 16:26:59 +01:00
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
2022-09-12 13:12:59 +02:00
(
{
2023-01-31 16:26:59 +01:00
url : url ,
crossOrigin : "anonymous"
2022-09-12 13:12:59 +02:00
}
2023-01-31 16:26:59 +01:00
)
}
) ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
return layer ;
} ;
netgis . MapOpenLayers . prototype . createLayerOSM = function ( )
{
var layer = new ol . layer . Tile
(
{
source : new ol . source . XYZ
2022-09-12 13:12:59 +02:00
(
{
2023-01-31 16:26:59 +01:00
url : "https://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png" ,
crossOrigin : "anonymous"
2022-09-12 13:12:59 +02:00
}
2023-01-31 16:26:59 +01:00
)
}
) ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
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
} ;
2023-02-13 09:03:09 +01:00
// User Auth
2023-01-31 16:26:59 +01:00
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
}
) ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
return layer ;
} ;
2023-02-13 09:03:09 +01:00
netgis . MapOpenLayers . prototype . createLayerWFS = function ( url , typeName , projection , outputFormat , user , password )
2023-01-31 16:26:59 +01:00
{
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 ,
2023-02-13 09:03:09 +01:00
loader : function ( extent , resolution , proj , success , failure )
2023-01-31 16:26:59 +01:00
{
2023-02-13 09:03:09 +01:00
//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 ( ) ;
2023-01-31 16:26:59 +01:00
}
2022-09-12 13:12:59 +02:00
}
2023-01-31 16:26:59 +01:00
) ;
var layer = new ol . layer . Vector
(
{
source : source
}
) ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
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 ;
2022-09-12 13:12:59 +02:00
} ;
netgis . MapOpenLayers . prototype . clearAll = function ( )
{
for ( var i = 0 ; i < this . layers . length ; i ++ )
{
this . map . removeLayer ( this . layers [ i ] ) ;
}
2022-10-07 13:56:43 +02:00
this . layers = [ ] ;
2022-09-12 13:12:59 +02:00
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 ) ;
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . styleEdit = function ( feature )
2022-09-12 13:12:59 +02:00
{
var radius = this . client . config . styles . editLayer . pointRadius ;
2023-01-31 16:26:59 +01:00
var geom = feature . getGeometry ( ) ;
2022-09-12 13:12:59 +02:00
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 } )
}
) ;
2023-01-31 16:26:59 +01:00
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 ]
}
)
) ;
}
2022-09-12 13:12:59 +02:00
return style ;
} ;
netgis . MapOpenLayers . prototype . styleSelect = function ( feature )
{
2023-01-31 16:26:59 +01:00
var geom = feature . getGeometry ( ) ;
2022-09-12 13:12:59 +02:00
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 } )
}
) ;
2023-01-31 16:26:59 +01:00
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 ]
}
)
) ;
}
2022-09-12 13:12:59 +02:00
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 )
}
) ;
return [ style , vertex ] ;
} ;
netgis . MapOpenLayers . prototype . styleSketch = function ( feature )
2023-01-31 16:26:59 +01:00
{
var geom = feature . getGeometry ( ) ;
2022-09-12 13:12:59 +02:00
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 } )
}
) ;
2023-01-31 16:26:59 +01:00
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 ]
}
)
) ;
}
2022-09-12 13:12:59 +02:00
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 )
{
2023-01-31 16:26:59 +01:00
// Leave
2022-09-12 13:12:59 +02:00
switch ( this . mode )
{
case netgis . Modes . BUFFER _FEATURE _EDIT :
{
this . onBufferCancel ( null ) ;
break ;
}
2023-01-31 16:26:59 +01:00
case netgis . Modes . DRAW _POINTS :
case netgis . Modes . DRAW _LINES :
{
this . onDrawBufferOff ( null ) ;
break ;
}
}
// Enter
switch ( mode )
{
2022-09-12 13:12:59 +02:00
}
// 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();
2023-01-31 16:26:59 +01:00
//TODO: https://openlayers.org/en/latest/examples/tracing.html
2022-09-12 13:12:59 +02:00
} ;
netgis . MapOpenLayers . prototype . setSnapOff = function ( )
{
if ( this . snap )
{
this . map . removeInteraction ( this . snap ) ;
this . snap = null ;
//this.snapFeatures = null;
}
} ;
2023-01-31 16:26:59 +01:00
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 ) ;
} ;
2022-09-12 13:12:59 +02:00
/ *
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 ( ) ;
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . onTracingOn = function ( e )
{
this . setTracingOn ( ) ;
} ;
netgis . MapOpenLayers . prototype . onTracingOff = function ( e )
{
this . setTracingOff ( ) ;
} ;
2022-09-12 13:12:59 +02:00
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
/ * f o r ( v a r l = 0 ; l < c o n t e x t . l a y e r s . l e n g t h ; l + + )
{
var data = context . layers [ l ] ;
if ( data . active ) this . onLayerShow ( { id : l } ) ;
} * /
} ;
2023-01-31 16:26:59 +01:00
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 ;
} ;
2022-09-12 13:12:59 +02:00
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 )
{
2023-01-31 16:26:59 +01:00
var pixel = e . pixel ;
var coords = e . coordinate ;
2022-09-12 13:12:59 +02:00
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
(
2023-01-31 16:26:59 +01:00
pixel ,
2022-09-12 13:12:59 +02:00
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
(
2023-01-31 16:26:59 +01:00
pixel ,
2022-09-12 13:12:59 +02:00
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
(
2023-01-31 16:26:59 +01:00
pixel ,
2022-09-12 13:12:59 +02:00
function ( feature , layer ) //TODO: bind to this?
{
if ( layer === self . editLayer )
{
hover = feature ;
feature . setStyle ( styleSelect ) ;
}
return true ;
}
) ;
break ;
}
2023-01-31 16:26:59 +01:00
case netgis . Modes . DRAW _POINTS :
case netgis . Modes . DRAW _LINES :
{
this . updateDrawBufferPreview ( ) ;
break ;
}
2022-09-12 13:12:59 +02:00
}
//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 ;
}
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 ( ) ;
} ;
netgis . MapOpenLayers . prototype . onModifyFeaturesEnd = function ( e )
{
this . updateEditOutput ( ) ;
2023-01-31 16:26:59 +01:00
this . updateEditArea ( ) ;
2022-09-12 13:12:59 +02:00
} ;
2023-01-31 16:26:59 +01:00
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 )
2022-09-12 13:12:59 +02:00
{
2023-01-31 16:26:59 +01:00
var parser = new jsts . io . OL3Parser ( ) ;
var a = parser . read ( srcgeom ) ;
var b = a . buffer ( radius , segments ) ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
var geom = parser . write ( b ) ;
return geom ;
} ;
netgis . MapOpenLayers . prototype . onBufferChange = function ( e )
{
2022-09-12 13:12:59 +02:00
var source = this . editLayer . getSource ( ) ;
var target = this . selected ;
if ( this . sketch )
{
source . removeFeature ( this . sketch ) ;
}
if ( target )
{
2023-01-31 16:26:59 +01:00
var feature = this . createBufferFeature ( target . getGeometry ( ) , e . radius , e . segments ) ;
2022-09-12 13:12:59 +02:00
//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 ;
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . onDrawPointsEnd = function ( e )
{
var preview = this . previewLayer . getSource ( ) . getFeatures ( ) [ 0 ] ;
if ( preview )
{
var src = this . editLayer . getSource ( ) ;
src . addFeature ( preview . clone ( ) ) ;
//TODO: remove sketch point ?
//this.editLayer.getSource().removeFeature( e.feature );
/ * w i n d o w . s e t T i m e o u t ( f u n c t i o n ( ) {
var features = src . getFeatures ( ) ;
src . removeFeature ( features [ features . length - 1 ] ) ;
src . addFeature ( preview . clone ( ) ) ;
} , 10 ) ; * /
/ * e . p r e v e n t D e f a u l t ( ) ;
e . stopPropagation ( ) ;
return false ; * /
}
} ;
netgis . MapOpenLayers . prototype . onDrawLinesEnd = function ( e )
{
var preview = this . previewLayer . getSource ( ) . getFeatures ( ) [ 0 ] ;
if ( ! preview ) return ;
var src = this . editLayer . getSource ( ) ;
src . addFeature ( preview . clone ( ) ) ;
} ;
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 ) ;
} ;
2022-09-12 13:12:59 +02:00
netgis . MapOpenLayers . prototype . onEditLayerAdd = function ( e )
{
2023-01-31 16:26:59 +01:00
////this.updateEditOutput();
2022-09-12 13:12:59 +02:00
this . updateEditLayerItem ( ) ;
2023-01-31 16:26:59 +01:00
this . updateEditOutput ( ) ;
2022-09-12 13:12:59 +02:00
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 ( ) ;
2022-10-05 11:01:11 +02:00
var proj = this . client . config . map . projection ;
2022-09-12 13:12:59 +02:00
var format = new ol . format . GeoJSON ( ) ;
2022-10-05 11:01:11 +02:00
var output = format . writeFeaturesObject ( features , { dataProjection : proj , featureProjection : proj } ) ;
2023-01-31 16:26:59 +01:00
// Projection
2022-10-05 11:01:11 +02:00
output [ "crs" ] =
{
"type" : "name" ,
"properties" : { "name" : "urn:ogc:def:crs:" + proj . replace ( ":" , "::" ) }
} ;
2022-09-12 13:12:59 +02:00
2023-01-31 16:26:59 +01:00
// 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 ;
2022-09-12 13:12:59 +02:00
if ( ! this . editEventsSilent )
2023-01-31 16:26:59 +01:00
{
2022-09-12 13:12:59 +02:00
this . client . invoke ( netgis . Events . EDIT _FEATURES _CHANGE , output ) ;
2023-01-31 16:26:59 +01:00
}
2022-09-12 13:12:59 +02:00
} ;
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" } ) ;
}
} ;
2023-01-31 16:26:59 +01:00
netgis . MapOpenLayers . prototype . updateEditArea = function ( )
{
} ;
2022-09-12 13:12:59 +02:00
netgis . MapOpenLayers . prototype . onEditFeaturesLoaded = function ( e )
{
2022-10-07 13:56:43 +02:00
var json = e ;
var self = this ;
window . setTimeout ( function ( ) { self . createLayerGeoJSON ( "Import" , json ) ; } , 10 ) ;
2022-09-12 13:12:59 +02:00
} ;
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 ) ;
} ;
2023-01-31 16:26:59 +01:00
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 ) ;
} ;
2022-09-12 13:12:59 +02:00
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 ); } )
2022-10-05 11:01:11 +02:00
var projcode = projection . getCode ( ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
switch ( projcode )
{
case "EPSG:3857" :
case "EPSG:4326" :
case this . client . config . map . projection :
{
// Projection OK
break ;
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
default :
{
// Projection Not Supported
console . warn ( "Unsupported Import Projection:" , projcode ) ;
break ;
}
2022-10-07 13:56:43 +02:00
}
2022-09-12 13:12:59 +02:00
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!" ) ;
2022-10-05 11:01:11 +02:00
//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" }*/ );
2022-09-12 13:12:59 +02:00
//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" } );
2022-10-05 11:01:11 +02:00
//var projection = format.readProjection( data );
2022-09-12 13:12:59 +02:00
//var features = format.readFeatures( data, { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } );
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
//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 = [ ] ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
var parser = new DOMParser ( ) ;
var xml = parser . parseFromString ( data , "text/xml" ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
// Features
var featureMembers = xml . getElementsByTagName ( "gml:featureMember" ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
for ( var f = 0 ; f < featureMembers . length ; f ++ )
{
var props = { } ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
var node = featureMembers [ f ] ;
var child = node . children [ 0 ] ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
// Attributes
for ( var a = 0 ; a < child . attributes . length ; a ++ )
{
var attribute = child . attributes [ a ] ;
props [ attribute . nodeName ] = attribute . nodeValue ;
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
for ( var c = 0 ; c < child . children . length ; c ++ )
{
var childNode = child . children [ c ] ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
if ( childNode . nodeName === "ogr:geometryProperty" ) continue ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
var parts = childNode . nodeName . split ( ":" ) ;
var k = parts [ parts . length - 1 ] ;
var v = childNode . innerHTML ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
props [ k ] = v ;
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
// Geometry
var geomprop = child . getElementsByTagName ( "ogr:geometryProperty" ) [ 0 ] ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
//for ( var g = 0; g < geomprop.children.length; g++ )
{
var geom = geomprop . children [ 0 ] ;
var proj = geom . getAttribute ( "srsName" ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
if ( proj && proj !== "EPSG:4326" && proj !== this . client . config . map . projection )
console . warn ( "Unsupported Import Projection:" , proj ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
switch ( geom . nodeName )
{
case "gml:Polygon" :
{
props [ "geometry" ] = this . gmlParsePolygon ( geom , proj ) ;
break ;
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
case "gml:MultiPolygon" :
{
props [ "geometry" ] = this . gmlParseMultiPolygon ( geom , proj ) ;
break ;
}
}
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
var feature = new ol . Feature ( props ) ;
features . push ( feature ) ;
}
2022-09-12 13:12:59 +02:00
this . addImportedFeatures ( features ) ;
} ;
2022-10-05 11:01:11 +02:00
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 ;
} ;
2022-09-12 13:12:59 +02:00
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 ) ;
}
) ;
} ;
2023-01-31 16:26:59 +01:00
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 ) ;
} ) ;
} ;
2022-09-12 13:12:59 +02:00
netgis . MapOpenLayers . prototype . addImportedFeatures = function ( features )
{
// Add To Edit Layer
this . editEventsSilent = true ;
this . editLayer . getSource ( ) . addFeatures ( features ) ;
this . editEventsSilent = false ;
this . updateEditOutput ( ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
// Zoom Imported Features
2022-09-12 13:12:59 +02:00
if ( features . length > 0 )
2022-10-05 11:01:11 +02:00
{
var extent = features [ 0 ] . getGeometry ( ) . getExtent ( ) ;
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
for ( var f = 1 ; f < features . length ; f ++ )
{
ol . extent . extend ( extent , features [ f ] . getGeometry ( ) . getExtent ( ) ) ;
}
2022-10-07 13:56:43 +02:00
2022-10-05 11:01:11 +02:00
var padding = 40 ;
this . view . fit ( extent , { duration : 300 , padding : [ padding , padding , padding , padding ] } ) ;
}
2022-09-12 13:12:59 +02:00
} ;
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 ( ) ;
2023-01-31 16:26:59 +01:00
2022-09-12 13:12:59 +02:00
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 ) ;
2023-01-31 16:26:59 +01:00
// 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 ) ;
2022-09-12 13:12:59 +02:00
// 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
2023-01-31 16:26:59 +01:00
pdf . setFillColor ( 255 , 255 , 255 ) ;
pdf . rect ( x , y + height - 11 , 80 , 11 , "F" ) ;
2022-09-12 13:12:59 +02:00
pdf . setFontSize ( 8 ) ;
2023-01-31 16:26:59 +01:00
pdf . text ( "Datum: " + netgis . util . getTimeStamp ( ) , x + 2 , y + height - 2 - 4 ) ;
2022-09-12 13:12:59 +02:00
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" ) ;
/ * e l s e
window . open ( mapCanvas . msToBlob ( ) , "_blank" ) ; * /
}
else
{
/ * i f ( ! c o n f i g . e x p o r t . o p e n N e w T a b )
{ * /
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 ) ;
} ;