WMS 层未在所有缩放级别上正确呈现
WMS Layer not rendered properly on all zoom levels
我已经使用 PostGIS v2.4.2 扩展配置了 PostgreSQL v9.5.12 数据库。我使用 GeoServer v2.13.1 将数据库表呈现为 WMS 图层,并使用 Openlayers (v4.6.5) 在 webapp 中将它们可视化。使用的投影是 EPSG:31255。
但是,WMS 图层并未在所有缩放级别上正确显示。有时,图块会被切断(参见屏幕截图 1),或者图层中的每个点都不会被渲染(参见屏幕截图 2)。在某些级别上,尤其是在放大时,图层根本不显示。这些层在 GeoServer 本身以及将它们添加到 qGIS 时正确显示。
我也将此设置和代码用于其他层,并且工作顺利,但是这些层使用不同的投影 (ESPG:4326)。
我该如何解决这个问题?
截图一(右侧部分轮廓被截掉)
截图2(中间的绿点不见了)
编辑:
这是一个代码片段,其中包含 EPSG:31255 的定义,但并未实际将其用于 wmsSource。
// proj4js custom projection
proj4.defs("EPSG:31255","+proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1 +x_0=0 +y_0=-5000000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs");
var proj31255 = ol.proj.get('EPSG:31255');
proj31255.setExtent([-115771.3204, 130037.7189, 115359.4571, 408002.5351]);
var wmsSource = new ol.source.TileWMS({
url: geoserver_getcapabilities_url + geoserver_workspace + '/wms?',
params: {
'LAYERS': wms_layer_name
},
serverType: 'geoserver',
//projection: 'EPSG:31255'
});
var wmsLayer = new ol.layer.Tile({
source: wmsSource,
name: 'selected_wms_layer',
visible: true
});
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var view = new ol.View({
center: map_centre,
zoom: initial_zoom_level,
projection: 'EPSG:3857'
});
/** Set-up the map */
var map = new ol.Map({
target: 'map',
layers: [osmLayer, wmsLayer, point_layer],
overlays: [overlay],
view: view,
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
controls: ol.control.defaults().extend([
new ol.control.OverviewMap()
])
});
TL;DR : An excellent working example is available on the OpenLayers WebSite
(以下例子中,我使用的位置应该是奥地利某地)
首先,让我们确保 EPSG:31255 设置正确。正如评论中所说,我建议您使用 proj4js,如果您必须处理投影,它会让您的生活更轻松。
将 proj4js 库导入应用后,按如下方式声明 EPSG:31255 投影:
proj4.defs("EPSG:31255","+proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1 +x_0=0 +y_0=-5000000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs");
(您可以使用 epsg.io as a source : https://epsg.io/31255.js 在 proj4js 中导入大量投影)
Hint: Import proj4js before OpenLayers, and it will be used without
extra work in OpenLayers.
第一种情况:对所有层处理一个投影
现在,我们需要创建或更新 OpenLayers 地图,其中的视图考虑了这个新投影。
let myMap = new ol.Map({
target: myDOMElement,
layers: [...],
view: new ol.View({
center: ol.proj.fromLonLat([50163.181015, 255280.097217]),
zoom: 5,
projection: 'EPSG:31255'
})
});
现在,您可能很难设置正确的中心,因为您必须在 EPSG:31255 投影中设置其坐标。
为了更简单,我建议使用基于 EPSG:4326 的转换。
view: new ol.View({
// Converts from coordinates known in EPSG:4326 to coordinates in EPSG:31255
center: ol.proj.transform([13.7548828125, 47.43896484375], 'EPSG:4326', 'EPSG:31255'),
zoom: 5,
projection: 'EPSG:31255' // Projection you want the map to use
})
第二种情况:处理不同的投影
如果你对不同的图层有不同的投影怎么办?
只需在您的 TileWMS 中指定它们(确保它们都已声明)。
let myWMSSource = new ol.source.TileWMS({
url: myURL,
params: {
'LAYERS': 'myCustomLayer'
},
serverType: 'geoserver',
projection: 'EPSG:31255' // Declare the projection the source is in.
});
OpenLayers 应该会自动将它们重新投影到您的地图投影中。
具体示例:在 OSM 地图上使用您的图层
/** Set a source */
let myWMSSource = new ol.source.TileWMS({
url: myURL,
params: {
'LAYERS': 'myCustomLayer'
},
serverType: 'geoserver',
projection: 'EPSG:31255'
});
/** Create a custom tile layer */
let myLayerTile = new ol.layer.Tile({
source: myWMSSource,
name: 'MyTile',
visible: true
});
/**
* Create a layer using OSM.
* Note that ol.source.OSM uses EPSG:3857
*/
let OSMLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
/** Set-up the map */
let myMap = new ol.Map({
target: DOMElement,
layers: [OSMLayer, myLayerTile],
view: new ol.View({
center: ol.proj.fromLonLat([1549123.872774, 6044640.196792]),
zoom: 1,
projection: 'EPSG:3857'
}),
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
controls: ol.control.defaults().extend([
new ol.control.OverviewMap()
])
});
此类问题的常见原因是使用标准 WMS 作为 TileWMS
图层的基础。这可能会导致客户端和服务器出现各种问题。
使用提供的 WMTS 或 TMS 端点从 GeoServer/GeoWebCache 请求图块。例如,此 page 显示了如何正确执行此操作。
我已经使用 PostGIS v2.4.2 扩展配置了 PostgreSQL v9.5.12 数据库。我使用 GeoServer v2.13.1 将数据库表呈现为 WMS 图层,并使用 Openlayers (v4.6.5) 在 webapp 中将它们可视化。使用的投影是 EPSG:31255。
但是,WMS 图层并未在所有缩放级别上正确显示。有时,图块会被切断(参见屏幕截图 1),或者图层中的每个点都不会被渲染(参见屏幕截图 2)。在某些级别上,尤其是在放大时,图层根本不显示。这些层在 GeoServer 本身以及将它们添加到 qGIS 时正确显示。
我也将此设置和代码用于其他层,并且工作顺利,但是这些层使用不同的投影 (ESPG:4326)。
我该如何解决这个问题?
编辑: 这是一个代码片段,其中包含 EPSG:31255 的定义,但并未实际将其用于 wmsSource。
// proj4js custom projection
proj4.defs("EPSG:31255","+proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1 +x_0=0 +y_0=-5000000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs");
var proj31255 = ol.proj.get('EPSG:31255');
proj31255.setExtent([-115771.3204, 130037.7189, 115359.4571, 408002.5351]);
var wmsSource = new ol.source.TileWMS({
url: geoserver_getcapabilities_url + geoserver_workspace + '/wms?',
params: {
'LAYERS': wms_layer_name
},
serverType: 'geoserver',
//projection: 'EPSG:31255'
});
var wmsLayer = new ol.layer.Tile({
source: wmsSource,
name: 'selected_wms_layer',
visible: true
});
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var view = new ol.View({
center: map_centre,
zoom: initial_zoom_level,
projection: 'EPSG:3857'
});
/** Set-up the map */
var map = new ol.Map({
target: 'map',
layers: [osmLayer, wmsLayer, point_layer],
overlays: [overlay],
view: view,
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
controls: ol.control.defaults().extend([
new ol.control.OverviewMap()
])
});
TL;DR : An excellent working example is available on the OpenLayers WebSite
(以下例子中,我使用的位置应该是奥地利某地)
首先,让我们确保 EPSG:31255 设置正确。正如评论中所说,我建议您使用 proj4js,如果您必须处理投影,它会让您的生活更轻松。
将 proj4js 库导入应用后,按如下方式声明 EPSG:31255 投影:
proj4.defs("EPSG:31255","+proj=tmerc +lat_0=0 +lon_0=13.33333333333333 +k=1 +x_0=0 +y_0=-5000000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232 +units=m +no_defs");
(您可以使用 epsg.io as a source : https://epsg.io/31255.js 在 proj4js 中导入大量投影)
Hint: Import proj4js before OpenLayers, and it will be used without extra work in OpenLayers.
第一种情况:对所有层处理一个投影
现在,我们需要创建或更新 OpenLayers 地图,其中的视图考虑了这个新投影。
let myMap = new ol.Map({
target: myDOMElement,
layers: [...],
view: new ol.View({
center: ol.proj.fromLonLat([50163.181015, 255280.097217]),
zoom: 5,
projection: 'EPSG:31255'
})
});
现在,您可能很难设置正确的中心,因为您必须在 EPSG:31255 投影中设置其坐标。
为了更简单,我建议使用基于 EPSG:4326 的转换。
view: new ol.View({
// Converts from coordinates known in EPSG:4326 to coordinates in EPSG:31255
center: ol.proj.transform([13.7548828125, 47.43896484375], 'EPSG:4326', 'EPSG:31255'),
zoom: 5,
projection: 'EPSG:31255' // Projection you want the map to use
})
第二种情况:处理不同的投影
如果你对不同的图层有不同的投影怎么办?
只需在您的 TileWMS 中指定它们(确保它们都已声明)。
let myWMSSource = new ol.source.TileWMS({
url: myURL,
params: {
'LAYERS': 'myCustomLayer'
},
serverType: 'geoserver',
projection: 'EPSG:31255' // Declare the projection the source is in.
});
OpenLayers 应该会自动将它们重新投影到您的地图投影中。
具体示例:在 OSM 地图上使用您的图层
/** Set a source */
let myWMSSource = new ol.source.TileWMS({
url: myURL,
params: {
'LAYERS': 'myCustomLayer'
},
serverType: 'geoserver',
projection: 'EPSG:31255'
});
/** Create a custom tile layer */
let myLayerTile = new ol.layer.Tile({
source: myWMSSource,
name: 'MyTile',
visible: true
});
/**
* Create a layer using OSM.
* Note that ol.source.OSM uses EPSG:3857
*/
let OSMLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
/** Set-up the map */
let myMap = new ol.Map({
target: DOMElement,
layers: [OSMLayer, myLayerTile],
view: new ol.View({
center: ol.proj.fromLonLat([1549123.872774, 6044640.196792]),
zoom: 1,
projection: 'EPSG:3857'
}),
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true,
controls: ol.control.defaults().extend([
new ol.control.OverviewMap()
])
});
此类问题的常见原因是使用标准 WMS 作为 TileWMS
图层的基础。这可能会导致客户端和服务器出现各种问题。
使用提供的 WMTS 或 TMS 端点从 GeoServer/GeoWebCache 请求图块。例如,此 page 显示了如何正确执行此操作。