2

This is my project as beginner to learn how to use OpenLayers and GeoServer.

I'm using GeoServer version 2.19.0 to share my shapefile with so many polygon in it. Using EPSG:4326 as the projection, I can show it all using OpenLayers 6.5 without much hassle. But, showing all the polygon at once to user is not good, so I try to make filter using bbox loading strategy, hoping it would render only visible layer which inside of current map view.

But my code doesn't work like the way I needed, the GeoJSON vector doesn't rendered based on the view extent.

At first I think if the projection was the culprit, so I transform the coordinates of 'extent' to EPSG:4326, since my shapefile used it as the projection.

    var extentProjected = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326')

And then using bbox feature in GeoServer WFS service, I send the query.

        'http://localhost:8080/geoserver/ows?service=WFS&version=1.1.0&' +
        'request=getFeature&typeName=katingan:Indo_Desa_region&maxFeatures=3000&' +
        'outputFormat=application/json&' +
        'bbox=' + extentProjected.join(',')

It doesn't work, GeoServer sent blank features of GeoJSON.

After that, I change the query and set explicitly the SRS in it to this:

var url = 'http://localhost:8080/geoserver/ows?service=WFS&version=1.1.0&' +
        'request=getFeature&typeName=katingan:Indo_Desa_region&maxFeatures=3000&' +
        'outputFormat=application/json&srsName=EPSG:4326&' +
        'bbox=' + extent.join(',') + ',EPSG:3857'

It work, the layer shown but can't be filtered when I zoom to specific area of map.

Here's my shapefile: download shapefile

and Here's my code:

var vectorSource = new ol.source.Vector({
    format: new ol.format.GeoJSON(),
    url: function(extent) {
        // var extentProjected = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326')
        
        var url = 'http://localhost:8080/geoserver/ows?service=WFS&version=1.1.0&' +
            'request=getFeature&typeName=katingan:Indo_Desa_region&maxFeatures=3000&' +
            'outputFormat=application/json&srsName=EPSG:4326&' +
            'bbox=' + extent.join(',') + ',EPSG:3857'
            console.log(extent, url)
        return (
            url
        )
    },
    strategy: ol.loadingstrategy.bbox
})
var vector = new ol.layer.Vector ({
    source: vectorSource,
    style: new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 255, 1.0)',
            width: 2,
        })
    })
})
var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      vector
    ],
    view: new ol.View({
      center: ol.proj.fromLonLat([113.91794724978148, -2.217485671684518]),
      zoom: 4
    })
});

Do you have any clues for me, so the map rendered faster, and it doesn't always show all the GeoJSON layer at once?

6
  • don't use GeoJSON for large and complex data use a WMS image layer instead – Ian Turton Apr 22 at 15:08
  • Thank you, I need to use geoJSON because I want to get the properties of my layer. Can we achieve the same way with WMS? – yan Apr 22 at 15:12
  • that depends on what you wan to do with them, just display a tooltip or style the layer then fine - if you need something more complex then you'll need a different approach altogether if you can't handle the data – Ian Turton Apr 22 at 15:24
  • WFS 1.1.0 expects EPSG:4326 coordinates to be in Lat/Lon order so for the bbox instead of extentProjected.join try [extentProjected[1], extentProjected[0], extentProjected[3], extentProjected[2]].join – Mike Apr 22 at 15:30
  • @Mike Thank you, It works for the some of the map parts. But sometimes when I zoom it, GeoServers gave me java.lang.IllegalArgumentException: Invalid ordinate index: 3 error message. – yan Apr 22 at 15:45
1

after trying with WFS and also clustering my MultiPolygon shapefile, I found the answer to my own questions, and the answer is: the use of VectorTile.

After installing Vector Tile Extension successfully in GeoServer, and then setting my Layer following the documented step in here, and then with OpenLayer I use ol.source.VectorTile as the source of my ol.layer.VectorTile, I get a nice result.

And here the code:

var style_simple = new ol.style.Style({
    fill: new ol.style.Fill({
      color: '#ADD8E6'
    }),
    stroke: new ol.style.Stroke({
      color: '#880000',
      width: 1
    })
  })
  
function simpleStyle(feature) {
    return style_simple
}
let projection_epsg_no = '900913' // '4326'  

let mapLayer = 'katingan:Indo_Desa_region'

let vectorTileSource = new ol.source.VectorTile({
    tilePixelRatio: 1, // oversampling when > 1
    tileGrid: ol.tilegrid.createXYZ({maxZoom: 19}),
    format: new ol.format.MVT(),
    url: 'http://localhost:8080/geoserver/gwc/service/tms/1.0.0/' + mapLayer +
        '@EPSG%3A'+projection_epsg_no+'@pbf/{z}/{x}/{-y}.pbf'
})

var vector = new ol.layer.VectorTile ({
    source: vectorTileSource,
    style: simpleStyle
})

var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      vector
    ],
    view: new ol.View({
      center: ol.proj.fromLonLat([113.91794724978148, -2.217485671684518]),
      zoom: 8
    })
});

Be careful with projections, I'm just starting to learn about them, and they actually make me scratch my head a lot more.

2
  • WMS is also a valid alternative. For querying and get feature infos attributes, you can use WmsGetFeatureInfo query from OpenLayers. Size of network exchange lighter than with vector tiles. You set the styles on the Geoserver side or by calling the WMS layer and a reference to a remote style. PS: not better than your approach but at least another way to do the job. It can be a better fit if using custom projections and not spherical Mercator (EPSG:3857). – ThomasG77 Apr 25 at 22:53
  • Thank you @ThomasG77, I really need to try another project to exercise next time, need to explore more about the WMS feature. I'm thinking to load my shapefile above as the tile pictures, and add another vector of points above the each polygon with the same properties, then clustered it so I don't need to load all the points at once. – yan Apr 26 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.