Search code examples
leafletreact-leafletangular-leaflet-directiveleaflet.markercluster

How to place the arc of angle 90 inside the circle of 5km radius using leaflet map in angular and how to change the color of circle


In my angualr project I have created the map with leaflet and created the circle of 5km radius with the coordinates coming from the backend.something like :


 "drone1": {
        "Drone": {
            "Droneid": 1001,
           
            "latlong": [
                {
                    "lat": 12.979377,
                    "lon": 80.195147
                },
                {
                    "lat": 12.957052,
                    "lon": 80.241433
                },
                {
                    "lat": 12.95379,
                    "lon": 80.230627
                },
                {
                    "lat": 12.956634,
                    "lon": 80.18737
                },
                {
                    "lat": 12.952619,
                    "lon": 80.17072
                },
                {
                    "lat": 12.950946,
                    "lon": 80.150122
                },
                {
                    "lat": 12.949356,
                    "lon": 80.134757
                }
            ]
        }

from the above object I have created the circle with 5km radius with index-0 and with index 1 created the drone icon and from the index 2 created the points.

from the second index drone has to move from one place to another if the drone comes inside the circle of 5km it(circle) has to turned to red otherwise blue.

I have done with the above object with moving drone and color changing,but now my requirement is I have another JSON object (drone2) something like:

 "drone2": {
        "Drone": {
            "Droneid": 1002,
            
            "latlong": [
                {
                    "lat": 12.979377,
                    "lon": 80.195147
                },
                {
                    "lat": 13.021618,
                    "lon": 80.140019
                },
                {
                    "lat": 13.000376,
                    "lon": 80.164602
                },
                {
                    "lat": 12.991009,
                    "lon": 80.174901
                },
                {
                    "lat": 12.980304,
                    "lon": 80.184514
                },
                {
                    "lat": 12.965416,
                    "lon": 80.20838
                },
                {
                    "lat": 12.936976,
                    "lon": 80.24117
                }
            ]
        }
    }
}

So for this object also I have to create the circle of 5 km radius and moving from the index the functionality same as above.

but when I am trying the circle color is changing only for one drone for other the color is not changing.

.component.ts

var latlngs = this.drones.drone1.Drone.latlong;
var latlngs02 = this.drones.drone2.Drone.latlong;
var START_IDX = 2;
var latlngIdx = START_IDX; // 0 = Circle, 1 = First position
var marker;
var circlemark;
var circle;
latlngs.forEach((latlong, idx)=>{
    var latlng = L.latLng(latlong.lat,latlong.lon)
    
    if(idx === 0){
      var jammer = {"name":"Jammer 1","lat":latlong.lat,"lon":latlong.lon,"isCollapsed":false};
      var sensor = {"name":"Sensor 1","lat":latlong.lat,"lon":latlong.lon};
      circlemark = L.circle(latlng,{radius:5000}).addTo(map);
     marker = L.marker(latlng,{icon:sensoricon}).addTo(map);
      marker = L.marker(latlng,{icon:jammericon}).addTo(map);
 
    }else if(idx===1){
      marker = L.marker(latlng,{icon:myIcon}).addTo(map);
    }else if(idx>=2){
      var circleMarker = L.circle(latlng,{color: 'red'},{radius:100}).addTo(map)
    }
});
var Quadrant1 = createQuadrant(circlemark,0).addTo(map);
var Quadrant2 = createQuadrant(circlemark,90).addTo(map);
var Quadrant3 = createQuadrant(circlemark,180).addTo(map);
var Quadrant4 = createQuadrant(circlemark,270).addTo(map);


function nextLatLng(){
    if(marker){
        if(latlngIdx === latlngs.length){ 
            latlngIdx = START_IDX;
            
        }
        marker.setLatLng(latlngs[latlngIdx]);
        inQuadrant(Quadrant1,marker);
        inQuadrant(Quadrant2,marker);
        inQuadrant(Quadrant3,marker);
        inQuadrant(Quadrant4,marker);
        
        latlngIdx++;
        
        setTimeout(nextLatLng,TIME); 
    }
}
nextLatLng();

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}

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]);
}

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;
};
function inQuadrant(quadrant,marker){
    var inPolygon = isMarkerInsidePolygon(marker,quadrant);
  if(inPolygon){
    quadrant.setStyle({color: 'red'});
  }else{
    quadrant.setStyle({color: '#3388ff'});
  }
}

I want to place the two drones in the map and are moving from index-2(for index-0placed the circle for index-1 placed the drone icon) and if any of the drone comes inside it has to change the color as red otherwise turned to blue.

Can anyone help me regarding this.


Solution

  • You had the problem, that some variables are used multiple times.

    I created a class for you, now you can easy create new drones with drone1 = new L.Drone(map,latlngs)

      var map = L.map('map').setView([12.979377,80.195147], 12);
    
      L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 180,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
          '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
          'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox.streets'
      }).addTo(map);
      
      
    
      var D1 = {
        "drone1":{
          "Drone":{
                "Droneid":
                  1001,
                "latlong":
                  [
                    {
                      "lat": 12.979377,
                      "lon": 80.195147
                    },
                    {
                      "lat": 12.957052,
                      "lon": 80.241433
                    },
                    {
                      "lat": 12.95379,
                      "lon": 80.230627
                    },
                    {
                      "lat": 12.956634,
                      "lon": 80.18737
                    },
                    {
                      "lat": 12.952619,
                      "lon": 80.17072
                    },
                    {
                      "lat": 12.950946,
                      "lon": 80.150122
                    },
                    {
                      "lat": 12.949356,
                      "lon": 80.134757
                    }
                  ]
              }
          }
      };
      var D2 = {
        "drone2": {
          "Drone": {
            "Droneid": 1002,
    
            "latlong": [
              {
                "lat": 12.979877,
                "lon": 80.195147
              },
              {
                "lat": 13.021618,
                "lon": 80.140019
              },
              {
                "lat": 13.000376,
                "lon": 80.164602
              },
              {
                "lat": 12.991009,
                "lon": 80.174901
              },
              {
                "lat": 12.980304,
                "lon": 80.184514
              },
              {
                "lat": 12.965416,
                "lon": 80.20838
              },
              {
                "lat": 12.936976,
                "lon": 80.24117
              }
            ]
          }
        }
      }
    
      var latlngs = D1.drone1.Drone.latlong;
      var latlngs02 = D2.drone2.Drone.latlong;
    
    
      L.Drone = L.Class.extend({
        START_IDX: 2,
        latlngIdx: this.START_IDX, // 0 : Circle, 1 : First position
        marker: null,
        circle: null,
        TIME: 500,
        latlngs: null,
        droneMarker: null,
        timeout: null,
        initialize(map, data) {
          this.map = map;
          this.addDroneData(data);
          this.showDroneData();
          this.startDroneMoving();
        },
        addDroneData(data) {
          this.latlngs = data;
        },
        showDroneData() {
          this.latlngs.forEach((latlong, idx) => {
            var latlng = L.latLng(latlong.lat, latlong.lon);
    
            if (idx === 0) {
              var jammer = {"name": "Jammer 1", "lat": latlong.lat, "lon": latlong.lon, "isCollapsed": false};
              var sensor = {"name": "Sensor 1", "lat": latlong.lat, "lon": latlong.lon};
              this.circle = L.circle(latlng, {radius: 5000}).addTo(map);
              L.marker(latlng).addTo(map);
              L.marker(latlng).addTo(map);
            } else if (idx === 1) {
              this.droneMarker = L.marker(latlng).addTo(map);
              L.circle(latlng, {color: 'red'}, {radius: 100}).addTo(map)
            } else if (idx >= 2) {
              L.circle(latlng, {color: 'red'}, {radius: 100}).addTo(map)
            }
          });
          this.Quadrant1 = this.createQuadrant(this.circle, 0).addTo(map);
          this.Quadrant2 = this.createQuadrant(this.circle, 90).addTo(map);
          this.Quadrant3 = this.createQuadrant(this.circle, 180).addTo(map);
          this.Quadrant4 = this.createQuadrant(this.circle, 270).addTo(map);
    
    
        },
        startDroneMoving(){
          this.nextLatLng();
        },
        stopDroneMoving(){
          clearTimeout(this.timeout);
        },
        createQuadrant(circle, 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]);
        },
        nextLatLng() {
          if (this.droneMarker) {
            if (!this.latlngIdx || this.latlngIdx === this.latlngs.length) {
              this.latlngIdx = this.START_IDX;
    
            }
            this.droneMarker.setLatLng(this.latlngs[this.latlngIdx]);
            this.inQuadrant(this.Quadrant1); //this.droneMarker
            this.inQuadrant(this.Quadrant2);
            this.inQuadrant(this.Quadrant3);
            this.inQuadrant(this.Quadrant4);
    
            this.latlngIdx++;
    
            this.timeout = setTimeout(()=>{this.nextLatLng()}, this.TIME);
          }
        },
    
        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;
        },
        
    inQuadrant(quadrant) {
      var inPolygon = this.isMarkerInsidePolygon(this.droneMarker, quadrant);
      if (inPolygon) {
        quadrant.setStyle({color: 'red'});
        quadrant.addTo(this.map);
      } else {
        quadrant.removeFrom(this.map);
        quadrant.setStyle({color: '#3388ff'});
      }
    }
      });
      
      
      
      
      
      
      
      
    var drone1 = new L.Drone(map,latlngs);
    var drone2 = new L.Drone(map,latlngs02);
      
      
    #map {
           width: 600px;
           height: 400px;
    }
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
        <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.min.js"></script>
    <div id='map'>

    Also I added the functions drone1.startDroneMoving() and drone1.stopDroneMoving()

    Update

    To show only the red quadrants:

    
        inQuadrant(quadrant) {
          var inPolygon = this.isMarkerInsidePolygon(this.droneMarker, quadrant);
          if (inPolygon) {
            quadrant.setStyle({color: 'red'});
            quadrant.addTo(this.map);
          } else {
            quadrant.removeFrom(this.map);
            quadrant.setStyle({color: '#3388ff'});
          }
        }
    

    Example: https://jsfiddle.net/falkedesign/fu39n1so/