TransWikia.com

How to get the exact Circle that user has drawn using Leaflet.draw.Circle?

Geographic Information Systems Asked by Devdatta Tengshe on January 7, 2021

I have a simple Leaflet map, where The user can draw a Circle, using Leaflet.Draw.

When you use the following code to get the geometry,

map.on(L.Draw.Event.CREATED, function (event) {
        var layer = event.layer;
        console.log(layer.toGeoJSON());
        drawnItems.addLayer(layer);
    });

You get only the center Point. This issue on Github says that it is expected behavior.
The issue says that you can also get the Radius, and build the Geometry yourself.

I tried to do that using Turf, using

 TurfBuffer(t.circle_layer.toGeoJSON(), t.circleBounds.radius, {
          units: 'meters',
        });

The problem is that the circle created, is different from the Geometry shown on the Leaflet Map. (note the Road intersection on the South-East Side of the circle)

Circle on Screen where user is drawing:
enter image description here

Circle, which is result of Turf buffer:
enter image description here

I guess this is due to the radius being in Web Mercator in leaflt-draw.

I would like to get the circle coordinates that the user has actually drawn. How can I get those?

2 Answers

Here is a complete page, showing Turf Circle and Turf Buffer, the buffer shows an issue. Note the circle has steps (Vertices). I'm guessing as there isn't a real GeoJSON circle in the standard.

<!DOCTYPE html>
<html>
<head>
    <title>Turf Circle Example</title>
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css"  />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>

<style>
      html, body,  #map {
        width : 100%;
        height : 100%;
      }
</style>
</head>
<body>
    <div id="map" ></div>
<script>

var map = L.map('map').setView([42.736424, -73.762713], 10);  

var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{ 
            attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
    osm.addTo(map);

    var editableLayers = new L.FeatureGroup();
    map.addLayer(editableLayers);   

    var options = {
        position: 'topleft',
        collapsed: false, 

        edit: {
            featureGroup: editableLayers,
            poly: {
                allowIntersection: false
            }
        },

        draw: {
            polygon: {
                allowIntersection: false,
                showArea: true
            }
        }

    };

    var drawControl = new L.Control.Draw(options);
    map.addControl(drawControl);

    map.on(L.Draw.Event.CREATED, function (e) {
        var layer = e.layer;
        var type = e.layerType;

    if (type === 'circle') {

        var theCenterPt = layer.getLatLng();

        var center = [theCenterPt.lng,theCenterPt.lat]; 
        console.log(center);

        var theRadius = layer.getRadius();

        editableLayers.addLayer(layer);

        // Turf Circle
        var turfCircle;
        var options = {steps: 64, units: 'meters'};  //Change steps to 4 to see what it does.
        var turfCircle = turf.circle(center, theRadius, options);
        var NewTurfCircle = new L.GeoJSON(turfCircle, {color:"black"}).addTo(map);

        //Turf Buffer
        var thepoint = turf.point(center);
        var buffered = turf.buffer(thepoint, theRadius, {units: 'meters'});
        var NewTurfBuffer = new L.GeoJSON(buffered, {color:"red"}).addTo(map);
    }
});

 </script>
</body>
</html>

Correct answer by Bill Chappell on January 7, 2021

I get the code a little different as GeoJSON standard does not include circles.

map.on('draw:created', function (e) {

var type = e.layerType,
    layer = e.layer;
    drawfeatureGroup.addLayer(layer);


if (type === 'circle') {

var theCenterPt = layer.getLatLng();
var theRadius = layer.getRadius();

Now I have the center point and radius to draw a circle in leaflet or using Turf.

If you going to use the circle to see if points from another layer are inside it, this may help, it does not use turf.

    var test = [];

    var counter_points_in_circle = 0;

    // Loop through each point in GeoJSON file  //var allPoints = L.geoJson(data); 
    allPoints.eachLayer(function (layer) {

        // Lat, long of current point
        layer_lat_long = layer.getLatLng();
        // Distance from our circle marker To current point in meters
        distance_from_centerPoint = layer_lat_long.distanceTo(theCenterPt);
        // See if meters is within radius
        if (distance_from_centerPoint <= theRadius) {
            counter_points_in_circle += 1;

             test.push(layer.feature);  
        }

    });
   // alert(counter_points_in_circle);  //Works.
        alert(test.length);   
        alert("results "+JSON.stringify(test));

Example from a click & distance instead of a draw, same concept.

http://www.gistechsolutions.com/leaflet/DEMO/Select/SelectPoints4.html

Answered by Bill Chappell on January 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP