Search code examples
openlayers

OpenLayers 4 Draw circle on map. Circle radius in meters and Map using latitude and longitude


I'm not sure why, but the resources available is seems very specific to each scenario and won't help some one else or for a different version.

What I'm trying to do is this: https://openlayers.org/en/latest/examples/custom-circle-render.html. But the example does not seem to work. Further to this, I'd like to draw a circle where the point is specified in degrees(EPSG:4326) and the radius in meters. My map's projection is also EPSG:4326. I have ended up trying to simplify to the following:

    var vectorSource = new ol.source.Vector();
    var map = new ol.Map({
        target: document.getElementById('map'),
        view: new ol.View({
            projection: 'EPSG:4326',
            center: [0, 0],
            zoom: 5
        }),
        layers: [
            new ol.layer.Tile({
                projection: 'EPSG:4326',
                source: new ol.source.OSM()
            }),
            new ol.layer.Vector({
                projection: 'EPSG:4326',
                source: vectorSource,
            }),
        ],
    });

function MapAddRadius() {
        var circle = new ol.geom.Circle(
            ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857'),
            10
        );
        var circleFeature = new ol.Feature(circle);
        vectorSource.addFeature(circleFeature);
    }

This does draw a circle, but it is not the correct size. This leads me to believe that I'm using the wrong projection as the size does correlate to degrees instead of meters. Or there are functions I am unaware of that makes this easier. I know that precision could be an issue, but I'm drawing small circles, like less than 1km, so I'm not too worried about it.

Please point me in the right direction.


Solution

  • ol.geom.Circle requires coordinates and radius to be in the same units, and all geometry must be in the view projection. The custom renderer used in the example is specific to Circle geometry and due to an omission in earlier versions will only work with OpenLayers 6. If you must have a Circle geometry in EPSG:4326 view and radius in meters try

        var circle = new ol.geom.Circle(
            ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857'),
            radius
        ).transform('EPSG:3857', 'EPSG:4326');
    

    or

        var circle = new ol.geom.Circle(
            [lon, lat],
            radius / ol.proj.getPointResolution('EPSG:4326', 1, [lon, lat], 'm')
        )
    

    The second method will scale the radius to approximate to true distance on the ground at northern and southern latitudes.