javascriptleafletpolygonpolyline

How can I draw multiple polygons inside a polygon object in Leaflet?


I have a marker, polyline and polygons. Marker is placed in random positions and then followed by a polyline.

Simply, I make a real-time location simulator but with random coordinates. Outside of the polygon, the polyline is deleted once in a while.

But if the marker is inside the polygon it should never be deleted. The problem is, in the code I'm using another array for the coordinates of the polyline inside the polygon and when marker exits the polygon and re-enters from another point, it draws a line between those points. This line is not one of the paths that the marker passes so I don't want it to appear. What can i do for this?

Here my html code.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Konum Takibi</title>
   
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> <!-- LEAFLET CSS  -->

    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            width: 100%;
            height: 97vh;
        }
    </style>
    
</head>

<body>
    <button id="toMarker">Marker'a Dön</button>
    <div id="map"></div>
</body>
</html>

<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <!-- LEAFLET JS  -->
<script src="https://rawgit.com/hayeswise/Leaflet.PointInPolygon/master/wise-leaflet-pip.js"></script> <!-- POINT IN POLYGON PLUGIN -->

<script>
 
    var map = L.map('map').setView([41.06977217083655, 28.810151432566624], 18),
        osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map),

        marker = L.marker([0, 0]), polygon, polygon2,
        polyline = L.polyline([[0, 0], [0, 0]], {color: 'black'}),
        innerPolyline = L.polyline([[0, 0], [0, 0]], {color: 'black'}),
        polygonLatlngs = [[[41.06974720137067, 28.80849354558732], 
                           [41.06974720137067, 28.80991027336842], 
                           [41.069372628577014, 28.80991027336842], 
                           [41.069372628577014, 28.810166071440012],
                           [41.06885341523501, 28.810166071440012],
                           [41.06886083259732, 28.80849354558732]],
                        
                          [[41.06749894364841, 28.80433202507794],
                           [41.067358716772375, 28.80825478362011],
                           [41.066479104942516, 28.808220966736027],
                           [41.066612959666045, 28.80428129975705]]],

        coord = [], inCoord = [],
        control = false, sec = 0, min = 0, hour = 0;
      
        lineLength = 30, //LINE COUNT
        intervalRate = 100, //SETINTERVAL
        dist = 30000, 
        sLat = 41.06977217083655, //BEGINNING LAT
        sLon = 28.810151432566624; //BEGINNING LON
        //INSIDE THE POLYGON LAT: 41.069537596154355, LON: 28.809311727683326

    for(i = 0; i < (lineLength + 1); i++) 
        coord.push([sLat, sLon]) //LAST INDEX GUNCEL CURRENT FIRST INDEX OLDER COORD


    if(!navigator.geolocation) console.log("No Browser Support") //NOT NECESSARY FOR NOW
    else {
        drawArea();

        setInterval(() => {
        randomWalk();
        }, intervalRate);

        setInterval(() => {
            clock();
        }, 1000);

    }
    
    function randomWalk(){

        control = polygon.contains(marker.getLatLng());

        if(marker) map.removeLayer(marker);
        marker = L.marker([coord[lineLength][0], coord[lineLength][1]], { title: "User" }).addTo(map);

        for(i = 0; i < lineLength; i++) 
            for(j = 0; j < 2; j++) 
                coord[i][j] = coord[i + 1][j];

        if(polygon.contains(marker.getLatLng())){ //INSIDE POLYGON

            map.removeLayer(polyline);
            map.removeLayer(innerPolyline);

            inCoord.push([coord[lineLength][0], coord[lineLength][1]]); 
            innerPolyline = L.polyline(inCoord, {color: 'rgba(0, 0, 0, 0.6)'}).addTo(map);

            if(marker) map.removeLayer(marker);
            marker = L.marker([inCoord[inCoord.length - 1][0], inCoord[inCoord.length - 1][1]], { title: "User" }).addTo(map);

        } else { //OUTSIDE POLYGON

            if(marker) map.removeLayer(marker);
            marker = L.marker([coord[lineLength][0], coord[lineLength][1]], { title: "User" }).addTo(map);

            map.removeLayer(polyline);
            polyline = L.polyline(coord, {color: 'rgba(255, 0, 0, 0.6)'}).addTo(map);

        }
        
        var latV = (Math.random()) / dist,
            lonV = (Math.random()) / dist,
            direction = Math.floor(Math.random() * 20);
        if(direction > 7) direction = 1// Math.floor(Math.random() * 4); //DUMDUZ GITME IHTIMALINI AZALT
        //console.log("Lat: " + latV + " Lon: " + lonV + " Dir: " + direction);
        switch(direction){
            case 0: coord[lineLength][0] += latV; coord[lineLength][1] += lonV; break; //KUZEYDOGU
            case 1: coord[lineLength][0] -= latV; coord[lineLength][1] -= lonV; break; //GUNEYBATI
            case 2: coord[lineLength][0] += latV; coord[lineLength][1] -= lonV; break; //KUZEYBATI
            case 3: coord[lineLength][0] -= latV; coord[lineLength][1] += lonV; break; //GUNEYDOGU
            case 4: coord[lineLength][0] += latV; break; //KUZEY
            case 5: coord[lineLength][0] -= latV; break; //GUNEY
            case 6: coord[lineLength][1] += lonV; break; //DOGU
            case 7: coord[lineLength][1] -= lonV; break; //BATI
        }

        if(control == false && polygon.contains(marker.getLatLng()) == true){ //INSIDE STEP
            //var holder = [];
            //holder += inCoord;
            //L.polyline(holder, {color: 'rgba(0, 0, 0, 0.6)'}).addTo(map);
            //map.removeLayer(innerPolyline);
            //var loop = inCoord.length;
            //for(i = 0; i < loop; i++) inCoord.pop();
        }
        if(control == true && polygon.contains(marker.getLatLng()) == false){ //OUTSIDE STEP
            //alert(hour + " Saat, " + min + " Dakika, " + sec + " Saniye bölge içerisinde kaldınız."); //HOW MANY SECOND WE STAY INSIDE OF POLYGON?
            sec = 0; min = 0; hour = 0;
        }


        marker.bindPopup("<b>Cihaz Konumu</b><br/>Enlem(Latitude):"+coord[lineLength][0]
        +"<br/> Boylam(Longitude):"+coord[lineLength][1]+"")//.openPopup(); //POP-UP

    }

    function drawArea(){
        var areaIcon = L.icon({
            iconUrl: 'https://img.icons8.com/glyph-neue/64/40C057/marker.png', //ICON ADRESI
            iconSize: [24, 24], //ICON BOYUTU
            iconAnchor: [12,23], //ICON'UN MARKER'A GORE POZISYONU
        });

        polygon = L.polygon(polygonLatlngs, {color: 'rgb(0, 200, 0)'}).addTo(map);

        for(i = 0; i < polygonLatlngs.length; i++)
            for(j = 0; j < polygonLatlngs[i].length; j++)
                L.marker([polygonLatlngs[i][j][0], polygonLatlngs[i][j][1]], {icon: areaIcon}).addTo(map);
        

    }

    function clock(){
        if(polygon.contains(marker.getLatLng())){
            sec++;
            if(sec == 59) { sec = 0; min +=1; }
            if(min == 59) { min = 0; hour +=1; }
        }

    }

    L.DomEvent.on(document.getElementById('toMarker'),'click',(e)=>{ //TO MARKER
        pauseAutoMove = false;
        map.setView([coord[lineLength][0], coord[lineLength][1]], 18);
    })
 
</script>

Here is the problem's screenshot.


Solution

  • I think I found a solution,

    I update inCoord array for three dimensions and I create i1, i2 variables. i1 means index1, i2 means index2

    i1 is only updated when marker exits the polygon. i2 is updated in every new location and resets every time marker exits the polygon. Lastly, an empty element is added to the inCoord array every time the marker exits the polygon.

    Every polyline is element of inCoord, i1 represents them. i2 represents the polyline coordinates.

    Here is the code piece,

     if(polygon.contains(marker.getLatLng())){ //INSIDE THE POLYGON
    
            map.removeLayer(polyline);
            map.removeLayer(innerPolyline);
    
            inCoord[i1][i2] = ([coord[lineLength][0], coord[lineLength][1]]);
            i2++;
    
            innerPolyline = L.polyline(inCoord, {color: 'rgba(0, 0, 0, 0.6)'}).addTo(map);
    
            if(marker) map.removeLayer(marker);
            marker = L.marker(inCoord[i1][inCoord[i1].length - 1]).addTo(map);
    
        }
    
     if(control == true && polygon.contains(marker.getLatLng()) == false){ //GOING OUT
            i1++; i2 = 0; inCoord.push([]);
        }