Search code examples
openlayersopenlayers-6

Cannot get circle radius correct in OpenLayers


I have a jsfiddle below where I attempt to create a circle 1600 meters in radius. I don't think that I have the projection right, because this circle is definitely smaller than 1600 meters. Measuring on Google Maps I think it's around 1000 meters instead. What do I need to do to correct this please>

Thank you.

var centerLongitudeLatitude = ol.proj.fromLonLat([-1.733014, 51.982989]);
var layer = new ol.layer.Vector({
  source: new ol.source.Vector({
    projection: 'EPSG:4326',
    features: [new ol.Feature(new ol.geom.Circle(centerLongitudeLatitude, 1600))]
  }),
  style: [
    new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: 'blue',
        width: 3
      }),
      fill: new ol.style.Fill({
        color: 'rgba(0, 0, 255, 0.1)'
      })
    })
  ]
});


var map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    layer
  ],
  view: new ol.View({
    center: ol.proj.fromLonLat([-1.733014, 51.982989]),
    zoom: 14
  })
});
html,
body {
  height: 100%;
  width: 100%;
  padding: 0px;
  margin: 0px;
}

.map {
  height: 100%;
  width: 100%;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.2.1/css/ol.css">
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.2.1/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="map" class="map"></div>


Solution

  • You have an inconsistency between the SRS of the vector layer (EPSG:4326), and the center and of the circle (EPSG:3857). You need to one of the above, not both.

    Try to create the layer without specifying projection, it would use the default view projection, in this case EPSG:3857 (because of OSM).

    UPDATE:

    After building the snippet below, I realize that the proposed change does not affect the result, not sure why just now, so I proposed the use of Polygon.circular as an alternative.

    <!doctype html>
    <html lang="en">
      <head>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/css/ol.css" type="text/css">
        <style>
          .map {
            height: 400px;
            width: 100%;
          }
        </style>
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/build/ol.js"></script>
        <title>Circle features</title>
      </head>
      <body>
        <div id="map" class="map"></div>
    		<script type="text/javascript">
    		// features
        var radius = 1600;
        var center = [-1.733014, 51.982989]
        var fcircle = new ol.Feature({
          geometry: new ol.geom.Circle(
            ol.proj.fromLonLat(center),
            radius
          )
        });
        fcircle.setStyle(new ol.style.Style({
          stroke: new ol.style.Stroke({
            color: 'blue',
            width: 2
          })
        }));
        var fcircular = new ol.Feature({
          geometry: ol.geom.Polygon.circular(center, radius, 64).transform('EPSG:4326', 'EPSG:3857')
        });
        fcircular.setStyle(new ol.style.Style({
          stroke: new ol.style.Stroke({
            color: 'red',
            width: 1
          })
        }));
        // map
        var view = new ol.View({
          center: ol.proj.fromLonLat(center),
          zoom: 14
        });
        var map = new ol.Map({
    			target: 'map',
    			layers: [
    				new ol.layer.Tile({
    					source: new ol.source.OSM()
    				}),
            new ol.layer.Vector({
              source: new ol.source.Vector({
                features: [fcircle, fcircular]
              })
            })
    			],
    			view
    		});
        </script>
      </body>
    </html>