CoolFace
Apppublic

Manthan2004/heatmap

sourceHugging Facemitupdated 2y agoView on Hugging Face
0likes
script.js143 linesDownload Raw Back to root
1let storeData = [];2let map = L.map('map').setView([18.5204, 73.8567], 10);3L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);4 5let heatmapMap = L.map('heatmap').setView([18.5204, 73.8567], 10);6L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(heatmapMap);7let heatLayer;8 9document.getElementById('drop-zone').addEventListener('click', () => {10    document.getElementById('csvFileInput').click();11});12 13document.getElementById('csvFileInput').addEventListener('change', (event) => {14    readCSV(event.target.files[0]);15});16 17function getMarkerColor(storeType) {18    return storeType === "Retail" ? "blue" :19           storeType === "Restaurant" ? "green" :20           storeType === "Pharmacy" ? "red" : "orange";21}22 23function readCSV(file) {24    Papa.parse(file, {25        header: true,26        skipEmptyLines: true,27        complete: (result) => {28            storeData = result.data.map(row => ([ 29                parseFloat(row.Latitude), 30                parseFloat(row.Longitude), 31                row["Store Type"], 32                parseFloat(row["Foot Traffic"]) || 1, 33                parseFloat(row["Population Density"]) || 0 // Adding Population Density34            ]));35        }36    });37}38 39function processCSV() {40    if (!storeData.length) return alert("Please upload a CSV file first!");41    storeData.forEach(([lat, lon, storeType, footTraffic]) => {42        L.marker([lat, lon], {43            icon: L.icon({44                iconUrl: `https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-${getMarkerColor(storeType)}.png`,45                iconSize: [25, 41]46            })47        }).addTo(map).bindPopup(`<b>Store Type:</b> ${storeType}<br><b>Foot Traffic:</b> ${footTraffic}`);48    });49}50 51function generateHeatmap() {52    if (heatLayer) heatmapMap.removeLayer(heatLayer);53    if (!storeData.length) return alert("No data found! Upload a CSV first.");54    heatLayer = L.heatLayer(storeData.map(([lat, lon, , footTraffic]) => [lat, lon, footTraffic]), { 55        radius: 25, 56        blur: 15, 57        maxZoom: 10 58    }).addTo(heatmapMap);59}60 61function kMeansClustering(k) {62    if (!storeData.length) return alert("No data to cluster! Upload a CSV first.");63 64    // Function to calculate Euclidean distance65    function euclideanDistance(point1, point2) {66        return Math.sqrt(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2));67    }68 69    // Initialize centroids randomly70    let centroids = [];71    while (centroids.length < k) {72        let randIndex = Math.floor(Math.random() * storeData.length);73        if (!centroids.some(centroid => centroid[0] === storeData[randIndex][0] && centroid[1] === storeData[randIndex][1])) {74            centroids.push(storeData[randIndex].slice(0, 2)); // Only use lat and lon for centroid75        }76    }77 78    let clusters = Array(k).fill().map(() => []);79    let prevCentroids = new Array(k).fill([0, 0]);80 81    // K-Means Loop82    while (JSON.stringify(centroids) !== JSON.stringify(prevCentroids)) {83        clusters = Array(k).fill().map(() => []);84        85        // Assign each point to the nearest centroid86        storeData.forEach(([lat, lon, storeType, footTraffic]) => {87            let closestCentroidIndex = centroids.reduce((closest, centroid, index) => {88                let dist = euclideanDistance([lat, lon], centroid);89                return dist < closest.dist ? { dist, index } : closest;90            }, { dist: Infinity }).index;91            92            clusters[closestCentroidIndex].push([lat, lon, storeType, footTraffic]);93        });94 95        prevCentroids = [...centroids];96 97        // Recalculate centroids98        centroids = clusters.map(cluster => {99            let sumLat = 0, sumLon = 0;100            cluster.forEach(([lat, lon]) => {101                sumLat += lat;102                sumLon += lon;103            });104            return [sumLat / cluster.length, sumLon / cluster.length];105        });106    }107 108    // Display clusters on the map109    clusters.forEach((cluster, clusterIndex) => {110        cluster.forEach(([lat, lon, storeType, footTraffic]) => {111            L.marker([lat, lon], {112                icon: L.icon({113                    iconUrl: `https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-${clusterIndex + 1}.png`,114                    iconSize: [25, 41]115                })116            }).addTo(map).bindPopup(`<b>Store Type:</b> ${storeType}<br><b>Foot Traffic:</b> ${footTraffic}<br><b>Cluster:</b> ${clusterIndex + 1}`);117        });118    });119}120 121function recommendDarkStores() {122    if (!storeData.length) return alert("Please upload a CSV file first!");123 124    // Sort stores by population density and foot traffic to find optimal locations125    const potentialDarkStores = storeData126        .filter(([lat, lon, storeType, footTraffic, popDensity]) => {127            return storeType !== "Retail" && footTraffic < 50 && popDensity > 5000; // Criteria for Dark Store128        })129        .sort((a, b) => b[4] - a[4]); // Sort by Population Density130 131    // Display recommended dark stores on the map132    potentialDarkStores.forEach(([lat, lon, storeType, footTraffic, popDensity], index) => {133        L.marker([lat, lon], {134            icon: L.icon({135                iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-3.png', // Dark Store Marker136                iconSize: [25, 41]137            })138        }).addTo(map).bindPopup(`<b>Recommended Dark Store Location</b><br><b>Population Density:</b> ${popDensity}<br><b>Foot Traffic:</b> ${footTraffic}`);139    });140 141    alert("Dark Store recommendations displayed on the map.");142}143