Simon Ziegler
Simon Ziegler

Reputation: 25

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>

Upvotes: 0

Views: 1397

Answers (2)

Simon Ziegler
Simon Ziegler

Reputation: 25

Thanks to Mike and cabesuon I have a solution, posted here for future readers.

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

var centerLongitudeLatitude = ol.proj.fromLonLat([-1.733014, 51.982989]);
var viewProjection = map.getView().getProjection();
var pointResolution = ol.proj.getPointResolution(viewProjection , 1, centerLongitudeLatitude );
var radius = 1600 / pointResolution;
var layer = new ol.layer.Vector({
  source: new ol.source.Vector({
    projection: 'EPSG:4326',
    features: [new ol.Feature(new ol.geom.Circle(centerLongitudeLatitude, radius))]
  }),
  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)'
      })
    })
  ]
});

map.addLayer(layer);
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>

Upvotes: 1

cabesuon
cabesuon

Reputation: 5268

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>

Upvotes: 0

Related Questions