libre-charge-map/villes_stats.js
2025-05-19 13:45:19 +02:00

187 lines
7.5 KiB
JavaScript

/**
/**
* compter les stations IRVE par ville et les tags associés
*/
import fs from 'fs';
import fetch from 'node-fetch';
const distanceThreshold = 10; // Distance maximale en km du centre ville
// Liste des 15 plus grandes villes de France avec leurs coordonnées et seuils spécifiques
const cities = [
{ name: "Paris", coords: [48.8566, 2.3522], threshold: 15 }, // Plus grande ville, plus grand rayon
{ name: "Marseille", coords: [43.2965, 5.3700], threshold: 12 },
{ name: "Lyon", coords: [45.7640, 4.8357], threshold: 12 },
{ name: "Toulouse", coords: [43.6047, 1.4442], threshold: 10 },
{ name: "Nice", coords: [43.7055, 7.262], threshold: 10 },
{ name: "Nantes", coords: [47.2184, -1.5536], threshold: 10 },
{ name: "Montpellier", coords: [43.6108, 3.8767], threshold: 8 },
{ name: "Strasbourg", coords: [48.5734, 7.7521], threshold: 8 },
{ name: "Bordeaux", coords: [44.8378, -0.5792], threshold: 8 },
{ name: "Lille", coords: [50.6292, 3.0585], threshold: 8 },
{ name: "Rennes", coords: [48.1141, -1.6778], threshold: 8 },
{ name: "Reims", coords: [49.2583, 4.0316], threshold: 6 },
{ name: "Le Havre", coords: [49.4944, 0.1064], threshold: 6 },
{ name: "Saint-Étienne", coords: [45.4484, 4.3928], threshold: 6 },
{ name: "Toulon", coords: [43.1242, 5.928], threshold: 6 },
{ name: "Rouen", coords: [49.4431, 1.0993], threshold: 6 },
{ name: "Ajaccio", coords: [41.9192, 8.7386], threshold: 6 },
{ name: "Saint-Denis", coords: [-20.8789, 55.4481], threshold: 6 },
{ name: "Brest", coords: [48.3904, -4.4861], threshold: 6 },
{ name: "Cergy", coords: [49.0379, 2.0760], threshold: 6 },
{ name: "Évry", coords: [48.6240, 2.4350], threshold: 6 },
{ name: "Saint-Quentin-en-Yvelines", coords: [48.7704, 2.0150], threshold: 4 },
{ name: "Marne-la-Vallée", coords: [48.8439, 2.7875], threshold: 4 },
{ name: "Melun-Sénart", coords: [48.5711, 2.6298], threshold: 4 },
{ name: "Dieppe", coords: [49.9237, 1.0789], threshold: 4 },
{ name: "Le Mans", coords: [48.0061, 0.1996], threshold: 4 },
{ name: "Orléans", coords: [47.9029, 1.9039], threshold: 4 },
{ name: "Nîmes", coords: [43.8367, 4.3600], threshold: 4 },
{ name: "Aix-en-Provence", coords: [43.5297, 5.4474], threshold: 4 },
{ name: "Tours", coords: [47.3942, 0.6900], threshold: 4 },
{ name: "Limoges", coords: [45.8333, 1.2500], threshold: 4 },
{ name: "Angers", coords: [47.4785, -0.5632], threshold: 4 },
{ name: "Lorient", coords: [47.7479, -2.7795], threshold: 4 },
{ name: "Saint-Nazaire", coords: [47.2862, -2.2133], threshold: 4 },
{ name: "Saint-Malo", coords: [48.6455, -2.0155], threshold: 4 },
{ name: "Saint-Étienne-du-Rouvray", coords: [49.3833, 1.0833], threshold: 4 },
{ name: "Saint-Quentin", coords: [49.8333, 2.8833], threshold: 4 },
];
// Fonction pour charger les données GeoJSON
function loadGeojson(filePath) {
try {
const data = fs.readFileSync(filePath, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('Erreur lors du chargement du fichier GeoJSON:', error.message);
throw new Error(`Impossible de charger le fichier ${filePath}: ${error.message}`);
}
}
// Fonction pour télécharger le fichier si manquant
async function ensureDataFile(filePath) {
if (!fs.existsSync(filePath)) {
console.log('Téléchargement du fichier opendata.json...');
const response = await fetch('https://www.data.gouv.fr/fr/datasets/r/7eee8f09-5d1b-4f48-a304-5e99e8da1e26');
const buffer = await response.arrayBuffer();
fs.writeFileSync(filePath, Buffer.from(buffer));
console.log('Téléchargement terminé');
}
}
// Fonction pour calculer la distance entre deux points en km
function calculateDistance(lat1, lon1, lat2, lon2) {
const R = 6371; // Rayon de la Terre en km
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
// Fonction pour compter le nombre d'éléments IRVE par ville et les tags associés
function countIrveByCityWithTags(irveData, cities, distanceThreshold) {
const irveCountByCity = [];
const allTags = new Map();
const irvePoints = irveData.elements;
// const irvePoints = irveData.features;
// console.log(irveData.elements.length, 'irvePoints dans le fichier', irvePoints.length, 'rayon : ', distanceThreshold, 'km');
// Pour chaque ville
for (const city of cities) {
const cityTagsCount = new Map();
let totalCount = 0;
let totalCapacity = 0;
// Pour chaque point IRVE
for (let i = 0; i < irvePoints.length; i++) {
if (irvePoints[i].lon !== undefined && irvePoints[i].lat !== undefined) {
const distance = calculateDistance(
city.coords[0], // latitude de la ville (premier élément)
city.coords[1], // longitude de la ville (deuxième élément)
irvePoints[i].lat,
irvePoints[i].lon
);
// console.log(irvePoints[i].lon, irvePoints[i].lat, 'distance : ', distance, 'km');
if (distance <= city.threshold) {
totalCount++;
totalCapacity += (irvePoints[i].tags?.capacity * 1) || 0;
const tags = irvePoints[i].tags || {};
for (const [tag, value] of Object.entries(tags)) {
cityTagsCount.set(tag, (cityTagsCount.get(tag) || 0) + 1);
allTags.set(tag, (allTags.get(tag) || 0) + 1);
}
}
}
}
// Créer la feature pour la ville
const cityFeature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: [city.coords[1], city.coords[0]]
},
properties: {
name: city.name,
totalCount: totalCount,
totalCapacity: totalCapacity,
threshold: city.threshold,
tags: Object.fromEntries(cityTagsCount)
}
};
irveCountByCity.push(cityFeature);
console.log(totalCount, totalCapacity, city.name);
}
return irveCountByCity;
}
// Fonction pour sauvegarder les résultats dans un fichier GeoJSON
function saveGeojson(data, filePath) {
const featureCollection = {
type: "FeatureCollection",
features: data
};
fs.writeFileSync(filePath, JSON.stringify(featureCollection, null, 2));
}
// Chemins des fichiers GeoJSON d'entrée et de sortie
const inputFilePath = 'js/openstreetmap.json';
const outputFilePath = 'js/irve_count_by_city_with_tags.geojson';
// Exécution du script
try {
// await ensureDataFile(inputFilePath);
const irveData = loadGeojson(inputFilePath);
// Compter le nombre d'éléments IRVE par ville et les tags associés
const irveCountByCityWithTags = countIrveByCityWithTags(irveData, cities, distanceThreshold);
// Sauvegarder les résultats dans un fichier GeoJSON
saveGeojson(irveCountByCityWithTags, outputFilePath);
// Créer un fichier CSV avec les totaux par ville
const csvContent = irveCountByCityWithTags
.map(city => `${city.properties.name},${city.properties.totalCount},${city.properties.totalCapacity}`)
.join('\n');
const csvHeader = 'Ville,Nombre total de bornes,Capacité totale\n';
fs.writeFileSync('js/irve_totaux_par_ville.csv', csvHeader + csvContent);
console.log('Les totaux par ville ont été sauvés dans js/irve_totaux_par_ville.csv');
console.log(`Les résultats ont été sauvés dans ${outputFilePath}`);
} catch (error) {
console.error('Erreur lors de l\'exécution du script:', error);
}