Search code examples
angulartypescriptleafletreact-leafletangular-leaflet-directive

How to detect marker goes inside and outside of the circle using leaflet open street map in angular


I have used the Leaflet open street map. With the API I have fetched the latitude, longitude array and placed the locations - something like this:

{
  "Drone": {
    "Droneid": 1001,
    "latlong": [
        {
            "lat": 12.989839,
            "lon": 80.198822
        },
        {
            "lat": 13.051832,
            "lon": 80.194480
        },
        {
            "lat": 13.038453,
            "lon": 80.227442
        },
        {
            "lat": 13.009018,
            "lon": 80.242550
        },
        {
            "lat": 12.976903,
            "lon": 80.237056
        },
        {
            "lat": 12.956829,
            "lon": 80.193107
        },
        {
            "lat": 12.980917,
            "lon": 80.150531
        },
        {
            "lat": 13.007680,
            "lon": 80.149158
        },
        {
            "lat": 13.043805,
            "lon": 80.154651
        }
    ]
}
}

From the above array I have placed the circle of 3 km radius with index-0, and placed the drone icon with index-1 and with the remaining index values (lat, long) placed the dots on the map.

And created the movement of drone from one latitude, longitude to another starting from index-2.

.component.ts

var  map = L.map('map').setView([12.0827, 80.2707], 11);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
} ).addTo(map);

var TIME = 2000; 
//var TIME = 1;

var latlngs = this.drones.Drone.latlong;
var START_IDX = 2;
var latlngIdx = START_IDX; // 0 = Circle, 1 = First position
var marker;

latlngs.forEach((latlong, idx)=>{
    var latlng = L.latLng(latlong.lat,latlong.lon)
    if(idx === 0){
      L.circle(latlng,{radius:5000}).addTo(map);
      marker = L.marker(latlng,{icon:sensoricon}).addTo(map)
     // L.circle(latlng,{radius:100}).addTo(map);
      

    }else if(idx===1){
      marker = L.marker(latlng,{icon:myIcon})
      .bindTooltip( this.drones.Drone.Droneid  ).addTo(map)
    }else if(idx>=2){
      //L.circle(latlng,{color: '#3388ff'},{radius:70}).addTo(map)
      var circleMarker = L.circle(latlng,{color: 'red'},{radius:100}).addTo(map)
    }
});

function nextLatLng(){
    if(marker){
        if(latlngIdx === latlngs.length){
            latlngIdx = START_IDX;
            
        }
        marker.setLatLng(latlngs[latlngIdx]);
        //.bindPopup( this.latlngs.lat,this.latlngs.lon  );
        latlngIdx++;
        //function () { marker.slideTo(START_IDX,   {duration:5000}); };
        setTimeout(nextLatLng,TIME); 
    }
}
nextLatLng();

Now I have to make the circle as four quadrants(90 degrees) and if the drone comes inside the circle that particular arc should be turn to red and if the drone comes out of the circle circle should be turn to previous color(blue).

Note:If the drone is moving out of the circle it should be disappear (should not show drone icon)


Solution

  • Create the quadrants with:

    function createQuadrant(circle,degree){
        var degree
        var p1 = L.GeometryUtil.destination(circle.getLatLng(), degree, circle.getRadius());
      var p2 = L.GeometryUtil.destination(circle.getLatLng(), degree+22.5, circle.getRadius());
      var p3 = L.GeometryUtil.destination(circle.getLatLng(), degree+45, circle.getRadius());
      var p4 = L.GeometryUtil.destination(circle.getLatLng(), degree+67.5, circle.getRadius());
      var p5 = L.GeometryUtil.destination(circle.getLatLng(), degree+90, circle.getRadius());
      return L.polygon([circle.getLatLng(),p1,p2,p3,p4,p5]);
    }
    

    And then test if the marker is in the quadrant:

    
    
    function inQuadrant(quadrant,marker){
        var inPolygon = isMarkerInsidePolygon(marker,quadrant);
      if(inPolygon){
        quadrant.setStyle({color: 'red'});
      }else{
        quadrant.setStyle({color: '#3388ff'});
      }
    }
    
    
    function isMarkerInsidePolygon(marker, poly) {
        var inside = false;
        var x = marker.getLatLng().lat, y = marker.getLatLng().lng;
        for (var ii=0;ii<poly.getLatLngs().length;ii++){
            var polyPoints = poly.getLatLngs()[ii];
            for (var i = 0, j = polyPoints.length - 1; i < polyPoints.length; j = i++) {
                var xi = polyPoints[i].lat, yi = polyPoints[i].lng;
                var xj = polyPoints[j].lat, yj = polyPoints[j].lng;
    
                var intersect = ((yi > y) != (yj > y))
                    && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
                if (intersect) inside = !inside;
            }
        }
    
        return inside;
    };
    
    
    var Quadrant1 = createQuadrant(circle,0).addTo(map);
    inQuadrant(Quadrant1,marker);
    

    https://jsfiddle.net/falkedesign/w0ahrxp3/