0

I'm trying to create a buffer using OpenLayers with JSTS library.

However, even after transforming geometry from EPSG:4326 to EPSG:3857, the buffer method doesn't create distance in meters as expected.

Take this code snippet, which runs on an OpenLayers Map with view with projection EPSG:3857:

const geoInput = {
    type: 'Point',
    coordinates: [
        14.432940,
        50.077371
    ]
};
const geoJsonFormat = new GeoJSON();
const features = geoJsonFormat.readFeatures(geoInput, {
    dataProjection: 'EPSG:4326',
    featureProjection: 'EPSG:4326'
});
const parser = new jsts.io.OL3Parser();
parser.inject(Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon, Circle);
const originalFeatures = [];
const bufferedFeatures = [];

for(let i = 0; i < features.length; i++) {
    const featGeom = features[i].getGeometry().clone();
    featGeom.transform('EPSG:4326', 'EPSG:3857');
    const bufferedJsts = parser.read(featGeom).buffer(251300); // in km ?
    const buffered = parser.write(bufferedJsts);
    originalFeatures.push(new Feature(featGeom));
    bufferedFeatures.push(new Feature(buffered));
}
const source = new VectorSource();
source.addFeatures(originalFeatures);
source.addFeatures(bufferedFeatures);
const vectorLayer = new VectorLayer({source});

This code snippet tries to put a circle from Prague with a distance of 251 km. The circle obviously doesn't have radius of 251 km, as that's the distance between Prague and Vienna (according to Google Maps) and the buffer doesn't match that.

enter image description here

Even the official example in OpenLayers page doesn't seem like producing correct buffer - https://openlayers.org/en/latest/examples/jsts.html enter image description here

Am I missing something out, or is it a problem report for JSTS library?

  • 1
    It's probably off by about cos(45deg) (sqrt(2)/2 or 0.5ish) due to your latitude- Bottom line don't measure distances in EPSG:3857 – Ian Turton Jul 18 at 13:23
  • So, are you saying that the distance by buffer is correct and the distance measured by Google Maps is wrong? – Stanislav Dušek Jul 18 at 13:30
  • 2
    Both are correct in their own way. You are seeing the difference between true distance calculated using spherical geometry and web mercator projection units on a flat surface. Equivalent to replacing var length = getLength(line); in this example openlayers.org/en/master/examples/measure.html with var length = line.getLength(); – Mike Jul 18 at 13:51
  • I'd be happy to work with EPSG:4326 the whole time to avoid projection issues, but will the buffer function then work with meters? – Stanislav Dušek Jul 18 at 14:01
  • 1
    If you need a buffer or circle stretching from Prague to Vienna you could calculate the radius in projection units new LineString([[14.1854451, 50.0593325], [16.09988, 48.2203445]]).transform('EPSG:4326', 'EPSG:3857').getLength(); Distance rings are rarely true circles in any projection, for example i.stack.imgur.com/kJ5iG.png – Mike Jul 18 at 14:30
1

As it turns out, using Turf library instead of JSTS is simpler and works with meters:

const format = new GeoJSON();
const features = format.readFeatures(geoInput, {
    featureProjection: 'EPSG:3857'
});
const buffered = turf.buffer(geoInput, 251300, {
    units: 'meters'
});
  • 1
    EPSG:3857 is still not a good CRS for distance calculations away from the equator. You can use epsg.io to find a more localized CRS. Search for Czech Republic or Eastern Europe. EPSG:32633 looks promising. – csk Jul 18 at 18:11

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.