2

I'm trying to draw a circle around some set of coordinates with a radius in meters using OpenLayers 7. The circle center is correct, but the radius ends up being around 10^5 times larger than expected.

For example, when I draw a circle with a 10m radius, I get a huge area:

huge area

instead of the expected tiny street-wide circle:

tiny circle

Here's an example:

<script src="https://cdn.jsdelivr.net/npm/ol@v7.3.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.3.0/ol.css" />
<body>
    <div id="map" style="width: 800px; height: 600px"></div>
    <script>
        class Map {
            map

            constructor(on, initialCoordinate) {
                const { Map, View } = ol
                const { Tile } = ol.layer
                const { useGeographic } = ol.proj
                const { OSM } = ol.source
                const { Fill, Style, Stroke, Text } = ol.style

                // Init target
                const target = document.getElementById(on)
                target.coordinate = initialCoordinate

                // We're working with map coordinates rather than tile coords
                useGeographic()

                // Layers
                // The pin indicating the location the user selected
                const pointLayerSource = new ol.source.Vector({ features: [] })
                const pointLayer = new ol.layer.Vector({
                    source: pointLayerSource,
                })

                // The map itself, sourced from Open Street Map
                const tilesLayer = new Tile({ source: new OSM() })

                // Create the map widget
                this.map = new Map({
                    layers: [tilesLayer, pointLayer],
                    view: new View({
                        center: [-49.0766336, -26.8992512],
                        zoom: 12,
                        maxZoom: 19,
                    }),
                    target,
                })

                if (initialCoordinate) {
                    // Add a pin as a feature so the selected location becomes visible on the map
                    const feature = new ol.Feature({
                        geometry: new ol.geom.Point(initialCoordinate),
                    })
                    pointLayerSource.addFeature(feature)
                    this.center(initialCoordinate)
                }

                // Bind this object to the target
                target.map = this
            }

            center(at) {
                this.map.getView().animate({
                    center: at,
                    zoom: 18,
                })
            }

            drawCircle(center, radius) {
                const map = this.map
                const circle = new ol.geom.Circle(center, radius)
                const circleFeature = new ol.Feature({
                    geometry: circle,
                })
                // Source and vector layer
                const vectorSource = new ol.source.Vector({
                    projection: map.getView().getProjection(),
                    features: [circleFeature],
                })
                const vectorLayer = new ol.layer.Vector({
                    source: vectorSource,
                })
                map.addLayer(vectorLayer)
                this.center(center)
            }
        }
        const map = new Map('map')
        const hugeCircle = map.drawCircle([-49.0766336, -26.8992512], 10)
        const expectedCircle = map.drawCircle([-49.0766336, -26.8992512], 10 * 1e-5)
    </script>
</body>

I tried transforming the radius to account for the projection and what not as suggested on this and similar questions: how to draw circle with radius in openlayers. It hasn't, however, made any difference on final result.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
adolfohw
  • 41
  • 4
  • 1
    You don't show how us `drawCircle()` is called. Please provide a full reproducible example. According to the [docs](https://openlayers.org/en/latest/apidoc/module-ol_geom_Circle-Circle.html) `The radius is in the units of the projection.`. – scai May 02 '23 at 13:32
  • @scai I added an example to the question. I did explore the the map's projection and it seems to me that the radius is already in meters, given that `map.map.getView().getProjection().getUnits()` returns "m", but I might be misunderstanding it. – adolfohw May 02 '23 at 14:10
  • 4
    In `new ol.geom.Circle` the `radius` is in projection units, which, when you specify `useGeographic` is degrees. A workaround would be to use `ol.geom.Polygon.circular` where the radius is always in meters. – Mike May 02 '23 at 14:29

1 Answers1

2

As suggested by Mike (thank you!), calling the function useGeographic made the circle be drawn with the radius in degrees. Adjusting the geometry from

new ol.geom.Circle(center, radius)

to

new ol.geom.Circle(center, radius / ol.proj.Units.METERS_PER_UNIT.degrees)

fixes the issue.

adolfohw
  • 41
  • 4