Search code examples
javascriptopenlayersproximity

How to create a circle based on the point on the map in Openlayers


I am trying to create a circle based on the point/coordinate a user clicks. I know how to create a point and a found a function to create a circle based on the point (like a buffer/range ring) but it seems to only work with x,y points (0,0). I tried converting my lon and lat coordinates to X and Y using ol.proj.transform but it doesn't rendered a circle at all.

Link with the function to create circle

This is what I am trying to create

enter image description here

function createCircle(circleCenterX, circleCenterY, circleRadius, pointsToEnd) {
            let angleToAdd = 360 / pointsToEnd;
            let coords = [];
            let angle = 0;
            for (let i = 0; i < pointsToEnd; i++) {
                angle += angleToAdd;
                let coordX = circleCenterX + circleRadius * Math.cos(angle * Math.PI / 180);
                let coordY = circleCenterY + circleRadius * Math.sin(angle * Math.PI / 180);
                coords.push([coordX, coordY]);
            }
            return coords;
        }

        function addMarker(coordinates) {
            console.log(coordinates);
            var marker = new ol.Feature(new ol.geom.Point([708683.3598450683, 1850098.1965979263]));
            marker.setStyle(new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({
                        color: 'red'
                    })
                })
            }));
            vectorSource.addFeature(marker);
        }

        function addCircle(coords) {
            // var lonlat1 = ol.proj.transform([coords[0], coords[1]], 'EPSG:4326','EPSG:3857');
            // console.log('var lonlat1',lonlat1)
            var circleCoords = createCircle(708683.3598450683, 1850098.1965979263, 20, 180);
            console.log(circleCoords);
            var polygon = new ol.geom.Polygon([circleCoords]);
            polygon.transform('EPSG:4326', 'EPSG:3857');
            polygon = new ol.Feature(polygon);
            vectorSource.addFeature(polygon);
        }

jsfiddle


Solution

  • Your problem is the addMarker function takes coordinates in the EPSG:3857 projection, the addCircle function takes them in the EPSG:4326 projection.

    If you want to pass in the same coordinates, you have to make them consistent.

    The circle doesn't appear for [708683.3598450683, 1850098.1965979263] because that is way off the map (the maximum value for latitude is 90 degrees).

    addCircle(ol.proj.toLonLat([708683.3598450683, 1850098.1965979263]));
    addMarker([708683.3598450683, 1850098.1965979263]);
    

    updated fiddle with the same center (but in different projections)

    screenshot of resulting map

    code snippet:

    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([0, 0]),
        zoom: 3
      })
    });
    var layer = new ol.layer.Vector({
      source: new ol.source.Vector({
        projection: 'EPSG:4326',
        features: []
      }),
    });
    map.addLayer(layer);
    var vectorSource = layer.getSource();
    
    function createCircle(circleCenterX, circleCenterY, circleRadius, pointsToEnd) {
      let angleToAdd = 360 / pointsToEnd;
      let coords = [];
      let angle = 0;
      for (let i = 0; i < pointsToEnd; i++) {
        angle += angleToAdd;
        let coordX = circleCenterX + circleRadius * Math.cos(angle * Math.PI / 180);
        let coordY = circleCenterY + circleRadius * Math.sin(angle * Math.PI / 180);
        coords.push([coordX, coordY]);
      }
      return coords;
    }
    
    function addMarker(coordinates) {
      console.log(coordinates);
      var marker = new ol.Feature(new ol.geom.Point(coordinates));
      marker.setStyle(new ol.style.Style({
        image: new ol.style.Circle({
          radius: 5,
          fill: new ol.style.Fill({
            color: 'red'
          })
        })
      }));
      vectorSource.addFeature(marker);
    }
    
    function addCircle(coords) {
      // var lonlat1 = ol.proj.transform([0, 0], 'EPSG:4326','EPSG:3857');
      // console.log('var lonlat1',lonlat1)
      var circleCoords = createCircle(coords[0], coords[1], 20, 180);
      console.log(circleCoords);
      var polygon = new ol.geom.Polygon([circleCoords]);
      polygon.transform('EPSG:4326', 'EPSG:3857');
      polygon = new ol.Feature(polygon);
      vectorSource.addFeature(polygon);
    }
    
    addCircle(ol.proj.toLonLat([708683.3598450683, 1850098.1965979263]));
    addMarker([708683.3598450683, 1850098.1965979263]);
    html,
    body {
      height: 100%;
      width: 100%;
      padding: 0px;
      margin: 0px;
    }
    
    .map {
      height: 100%;
      width: 100%;
    }
    <script src="https://openlayers.org/en/v6.4.3/build/ol.js"></script>
    <link rel="stylesheet" type="text/css" href="https://openlayers.org/en/v6.4.3/css/ol.css" />
    <div id="map" class="map"></div>