简体   繁体   中英

WMS Layer not rendered properly on all zoom levels

I have configured a PostgreSQL v9.5.12 database with the PostGIS v2.4.2 extension. I use GeoServer v2.13.1 to render the tables of the database as WMS Layers and visualise them in a webapp using Openlayers (v4.6.5). The projection used is EPSG:31255 .

However the WMS Layers are not displayed properly on all zoom levels. Sometimes tiles are cut off (see screenshot 1) or not every point in a layer is rendered (see screenshot 2). On some levels, especially when zoomed in, the layer isn't displayed at all. The layers are displayed properly in GeoServer itself and when add them to qGIS.

I use this setup and code for other layers too and it works smoothly, however these layers use a different projection (ESPG:4326).

How can I fix this?

WMS示例1 Screenshot 1 (part of outline on the right side is cut off)

WMS示例2 Screenshot 2 (green dots in between are missing)

EDIT: Here is a code snippet that include the definition of EPSG:31255, without actually using it for the 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

(In the following examples, the positions I used should be somewhere in Austria)

First, let's ensure that the EPSG:31255 is correctly set. As said in the comment, I recommend you to use proj4js, it will make your life easier if you have to deal with projections.

Once you've imported the proj4js library into your app, declare the EPSG:31255 projection as follow:

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");

(You can import a lot of projections in proj4js using epsg.io as a source : https://epsg.io/31255.js )

Hint: Import proj4js before OpenLayers, and it will be used without extra work in OpenLayers.

First case : Deal with one projection for all layers

Now, we need to create or update the OpenLayers map with a view that take this new projection into account.

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'
        })
    });

Now, you may have some hard times setting a correct center, because you must set its coordinates in the EPSG:31255 projection.

To make it easier, I do recommend to use a Transform based on EPSG:4326, for instance.

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
})

Second Case : Dealing with different projections

So what if you have different projections for different layers ?

Simply specify them in your TileWMS (ensure they all have been declared).

let myWMSSource = new ol.source.TileWMS({
    url: myURL,
    params: {
        'LAYERS': 'myCustomLayer'
    },
    serverType: 'geoserver',
    projection: 'EPSG:31255' // Declare the projection the source is in.
});

OpenLayers should automatically reproject them in your map projection.

Concrete example: Using your layer on top of an OSM Map

/** 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()
    ])
});

The usual cause of issues like this is using a standard WMS as the base for a TileWMS layer. This can cause all sorts of issues both in the client and the server.

Make use of the provided WMTS or TMS endpoints to request tiles from GeoServer/GeoWebCache. For example this page shows how to do it right.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM