-
-
Notifications
You must be signed in to change notification settings - Fork 489
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic support for WMS layers < 1.3.0, improve bbox handling #5266
base: 3.12.x
Are you sure you want to change the base?
Conversation
if (!(code in proj4.defs) || isDefaultProjection(code)) { | ||
return; | ||
} | ||
return _cachedDefs[code]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to exhaust EPSG.io, so we keep a dictionary of cached Proj4 definitions
/** | ||
* @ngdoc method | ||
* @methodOf gn_map.service:gnMap | ||
* @name gnMap#importProj4js | ||
* | ||
* @description | ||
* Import the proj4js projection that are specified in DB config. | ||
*/ | ||
importProj4js: function() { | ||
proj4.defs('EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0' + | ||
'=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +' + | ||
'towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); | ||
if (proj4 && angular.isArray(gnConfig['map.proj4js'])) { | ||
angular.forEach(gnConfig['map.proj4js'], function(item) { | ||
proj4.defs(item.code, item.value); | ||
}); | ||
} | ||
ol.proj.proj4.register(proj4); | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer used anywhere.
@@ -785,7 +808,7 @@ | |||
advanced: options.advanced, | |||
minResolution: options.minResolution, | |||
maxResolution: options.maxResolution, | |||
cextent: options.extent, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cextent
is only used by GeoNetwork internally, but OpenLayers does not expect this property. Therefore, we replace it by extent
instead.
function(olEvent, target) { | ||
var url = '[no tile URL found]'; | ||
if (olEvent.image) { | ||
if (olEvent.image.getUrl) { | ||
url = olEvent.image.getUrl(); | ||
} else if (olEvent.image.src_) { | ||
url = olEvent.image.src_; | ||
} | ||
} else if (olEvent.tile && olEvent.tile.getKey) { | ||
url = olEvent.tile.getKey(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and improved error handling for WMS ImageLayers
var isLayerAvailableInMapProjection = false; | ||
// OL3 only parse CRS from WMS 1.3 (and not SRS in WMS 1.1.x) | ||
// so a WMS 1.1.x will always failed on this | ||
// https://github.com/openlayers/ol3/blob/master/src/ | ||
// ol/format/wmscapabilitiesformat.js | ||
/* | ||
if (layer.CRS) { | ||
var mapProjection = map.getView().getProjection().getCode(); | ||
for (var i = 0; i < layer.CRS.length; i++) { | ||
if (layer.CRS[i] === mapProjection) { | ||
isLayerAvailableInMapProjection = true; | ||
break; | ||
} | ||
} | ||
} else { | ||
errors.push($translate.instant('layerCRSNotFound')); | ||
console.warn($translate.instant('layerCRSNotFound')); | ||
} | ||
if (!isLayerAvailableInMapProjection) { | ||
errors.push($translate.instant('layerNotAvailableInMapProj')); | ||
console.warn($translate.instant('layerNotAvailableInMapProj')); | ||
} | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This no longer applies.
var bboxProps = gnOwsCapabilities.getWmsLayerExtentFromGetCap(map, getCapLayer, isCustomProj4); | ||
var mapProj = map.getView().getProjection(); | ||
var projCode = bboxProps.epsg; | ||
if (bboxProps.extent && projCode === 'EPSG:4326') { | ||
// If the GetCap CRS list does not include the current map CRS, | ||
// and an extent is returned from GetCap, it must be a WGS84 extent. | ||
// Explicitly set the BBOX layer parameter in this case. | ||
layerParams.BBOX = bboxProps.extent; | ||
} else if (!bboxProps.extent) { | ||
// If no valid extent could be determined, the WMS does not support the projection | ||
// or the WGS84 bounds do not make sense (when reprojecting into a custom projection) | ||
var msg = $translate.instant('layerNotAvailableInMapProj',{proj:projCode}); | ||
if (isCustomProj4) { | ||
msg = $translate.instant('layerWmsInvalidExtent',{proj:projCode}); | ||
} | ||
errors.push(msg); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve extent/BBOX
handling for WMS layers and supply user with more useful error messages when something is (still) not right.
var proj = gnMap.getMapConfig().projection; | ||
if (type === this.VIEWER_MAP) { | ||
gnMap.checkProj4Def(proj); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whenever the viewer map is created, check if the Proj4 definition string is "standard" or custom.
layer.url = url; | ||
layer.CRS = inheritedCrs; | ||
layer.EX_GeographicBoundingBox = layer.EX_GeographicBoundingBox || bbox; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also inherit the geographic bounding box if the "child" does not have that property.
@@ -271,7 +341,7 @@ | |||
}) | |||
.success(function(data) { | |||
try { | |||
defer.resolve(displayFileContent(data, withGroupLayer, url)); | |||
defer.resolve(parseWMSCapabilities(data, withGroupLayer, url)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to be more in line with the other function names.
@@ -390,59 +460,69 @@ | |||
return defer.promise; | |||
}, | |||
|
|||
getLayerExtentFromGetCap: function(map, getCapLayer) { | |||
getWmsLayerExtentFromGetCap: function(map, getCapLayer, isCustomDef) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this function is now being used for WMS layers exclusively, its name should reflect that.
Also added the isCustomDef
parameter.
|
||
getLayerInfoFromCap: function(layerName, capObj, uuid) { | ||
var needles = []; | ||
var layers = capObj.layers || capObj.Layer; | ||
|
||
// Layer name may be a list of comma separated layers | ||
layerList = layerName.split(','); | ||
layersLoop: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused label
var proj = map.getView().getProjection(); | ||
var extent = proj.getExtent(); | ||
if (gnViewerSettings.initialExtent && gnViewerSettings.mapConfig.projection && | ||
gnViewerSettings.mapConfig.projection !== proj.getCode()) { | ||
// Use reprojected initial extent if it is defined | ||
extent = ol.proj.transformExtent( | ||
gnViewerSettings.initialExtent, gnViewerSettings.mapConfig.projection, proj, 8) | ||
} | ||
map.getView().fit(extent, map.getSize()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an initial extent was defined in the viewer settings and its projection is different from the current map projection, use and reproject the initial extent. This makes more sense when switching to EPSG:3857 for instance, where the projection extent usually encapsulates the whole world.
@@ -69,6 +69,8 @@ | |||
this.changeLayerProjection(subLayer, oldProj, | |||
newProj); | |||
}); | |||
} else if (layer instanceof ol.layer.Image) { | |||
gnMap.updateWmsLayerForProj(scope.map, layer, newProj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also update and show WMS layers whenever the projection changes (they were ignored until now).
if (newProj.getExtent()) { | ||
newExtent = newProj.getExtent(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes more sense to stay at the same place and zoom level.
msg: $translate.instant('layerAdded', | ||
{ | ||
layer: layer.get('label'), | ||
extent: layer.get('extent') ? layer.get('extent').toString() : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would throw an error when (c)extent
was null
.
} | ||
|
||
var style = layer.getSource().getParams().STYLES; | ||
$this.addWmsToMapFromCap(map, lyr, style); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the OpenLayers examples and docs, it should be enough to call layer.getSource().updateParams()
to redraw the WMS using the new projection. Unfortunately, that didn't seem to do anything, which is why we're removing and re-adding the layer here.
cextent: gnOwsCapabilities.getLayerExtentFromGetCap(map, | ||
getCapLayer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling the getLayerExtentFromGetCap()
function always returns null
for WMTS layers from what was observed, so it makes no sense to call it at all.
Note: WMTS layers do have an ows:BoundingBox
property sometimes, but this is a deprecated element and it only exists inside TileMatrixSet
elements, which are not being fully parsed by OL.
…r order when re-adding
…ght not be equal to projection), improve error handling
…nitial projection
…lso redraws WMS layers
|
This PR adds basic support for WMS services prior to version 1.3.0, which are not supported by OpenLayers out-of-the-box.
Parse missing properties
Some
GetCapabilities
properties of these older WMS services are ignored by the OL parser. This PR uses thexml2json
lib to scan for and add the missing properties.Improve BBOX creation
WMS requests require a valid bounding box. Unfortunately, even though some EPSG codes might be standard, a user could define their own Proj4 definition for it. Because of that, this could result in an invalid
BBOX
and therefore invalid WMS request.This PR checks if the Proj4 definition set by the user is a custom one. If it is, it will use the geographic bounds of the WMS layer
GetCapabilities
and reproject these to a validBBOX
. If it's not custom, it will use the bounds from theGetCapabilities
CRS list (if a match is found).Maintain WMS layers after projection switch
Currently, WMS layers are not reprojected if the user uses the Projection Switcher in the viewer map. They are simply being ignored and re-appear if the user switches back to the original projection.
This PR tries to re-add all WMS layers once the projection has been switched.