diff --git a/index.html b/index.html
index 7a7b2d4..68e13fc 100644
--- a/index.html
+++ b/index.html
@@ -141,6 +141,44 @@
la nuit, ou bien où l'on séjourne plus longtemps.
+
+
Paramètres de la batterie
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Types de prises
diff --git a/js/lcm_main.js b/js/lcm_main.js
index da05416..7df91a7 100644
--- a/js/lcm_main.js
+++ b/js/lcm_main.js
@@ -4,10 +4,18 @@
* lister les bornes trouvées dans la page
* @type {boolean}
*/
+
+import {lcm_i18n} from './lcm_i18n.js';
+
+ // Détecter la langue du navigateur
+ const currentLanguage = lcm_i18n.detectLanguage();
+ console.log('Langue détectée:', currentLanguage);
+
import lcm_config from './lcm_config.js'
import lcm_utils, { valid_qa_message } from './lcm_utils.js'
import lcm_color_utils from './lcm_color_utils.js'
import { sendToJOSM, createJOSMEditLink } from './lcm_editor.js'
+import routing from './lcm_routing.js'
let geojsondata;
let lastLatLng;
@@ -15,7 +23,16 @@ let searchLocationMarker = null;
let count_hidden_by_filters = 0;
let averageChargeKwh = 26;
+let routePolyline = null;
+let routeMarkers = [];
+let startMarker = null;
+let endMarker = null;
+let startCoords = null;
+let endCoords = null;
+// Déclarer les variables d'itinéraire au début
+let startItinerary = [0, 0];
+let endItinerary = [0, 0];
// serveurs de tuiles: https://wiki.openstreetmap.org/wiki/Tile_servers
// https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png
@@ -31,28 +48,22 @@ let averageChargeKwh = 26;
let map = L.map('map')
L.control.scale().addTo(map)
+setCoordinatesOfLeafletMapFromQueryParameters()
+
/**
* filtres à toggle par des boutons dans la page
* à appliquer à chaque rafraîchissement des points geojson
* TODO: make buttons and filter in refresh circles
*/
let filterStatesAvailable = ['hide', 'show', 'showOnly']
+
-let filters_features = {
- display_unknown_max_power_station: filterStatesAvailable[1]
-}
-let display_type2_sockets = 'show';
-let display_type2_combo_sockets = 'show';
let display_unknown_max_power_station = 'show';
let display_alert_cable_missing = 'show';
-let display_known_max_power_station = 'show';
-let display_type2_combo_sockets_with_cable = 'show';
-let display_lower_than_50kw = 'show';
-let display_higer_than_50kw = 'show';
-let display_lower_than_200kw = 'show';
-let display_higer_than_200kw = 'show';
-let display_chelou = 'show'; // les stations avec une valeur suspecte, plus de 400kW
+const start = map.getCenter();
+const startLat = start.lat;
+const startLon = start.lng;
// Ajouter cette fonction avant searchLocation
function moveToLocation(place) {
@@ -198,7 +209,19 @@ function searchLocation() {
.val(index)
.text(displayText)
.data('place', place);
+
+ // Création du bouton itinéraire
+ const routeBtn = $('
`;
- popupContent += josm_buttons
- // Mettre à jour le contenu de la popup et s'assurer qu'elle est ouverte
+ popupContent += josm_buttons;
clickedMarker.setPopupContent(popupContent);
- // clickedMarker.openPopup(); // Rouvrir pour ajuster la taille si nécessaire
$('#current_station_infos').html(`
Analyse Osmose
${josm_buttons}
${proposedTags}
`);
- // Lier l'événement au bouton JOSM DANS la popup
bindEventsOnJosmRemote(clickedMarker.getPopup().getElement());
})
.catch(error => {
console.error("Erreur lors de la récupération des détails de l'issue Osmose:", error);
clickedMarker.setPopupContent(`Erreur lors du chargement des détails. Voir sur Osmose`);
- // clickedMarker.openPopup();
});
});
osmose_markers.addLayer(osmoseMarker);
});
- updateCounters(); // Mettre à jour l'affichage après le traitement
+ updateCounters();
})
.catch(error => {
console.error('Erreur détaillée lors de la recherche de la liste des issues Osmose:', error);
@@ -1355,11 +1419,19 @@ function searchOsmoseIssues(map) {
// Ajouter un écouteur d'événements pour le changement de visibilité des calques
function init() {
+
+
bindEventsOnJosmRemote();
onMapMoveEnd();
map.on('moveend', onMapMoveEnd);
$('#spinning_icon').hide();
+ // ... dans la gestion du clic sur un résultat Addok ...
+ $('.route-to-place').on('click', function() {
+ const place = $(this).data('place');
+ calculerEtAfficherItineraire(place, 'car');
+ });
+
/**
* boutons de changement de filtres et de rechargement des bornes à l'affichage
*/
@@ -1547,4 +1619,310 @@ function updateFilteredStationsCount() {
} else {
$('#filter_max_output_display').after(filterStats);
}
+}
+// au clic droit, proposer les points d'itinéraire
+map.on('contextmenu', function(e) {
+ // Créer un menu contextuel simple
+ let popup = L.popup()
+ .setLatLng(e.latlng)
+ .setContent(`
+
+
+ `)
+ .openOn(map);
+});
+
+
+// Fonctions globales pour le menu contextuel
+window.setStartMarkerFromPopup = function(latlng) {
+ startItinerary = [latlng[0], latlng[1]]
+
+ setStartMarker({lat: latlng[0], lng: latlng[1]});
+ map.closePopup();
+ if (endItinerary) calculerEtAfficherItineraire();
+};
+window.setEndMarkerFromPopup = function(latlng) {
+ setEndMarker({lat: latlng[0], lng: latlng[1]});
+ endItinerary = [latlng[0], latlng[1]]
+ map.closePopup();
+ if (startItinerary) calculerEtAfficherItineraire();
+};
+
+
+// Déclarer une variable globale pour le tracé
+window.routePolyline = null;
+window.lastRouteDestination = null;
+
+// Ajouter cette fonction avant calculerEtAfficherItineraire
+async function searchChargingStationsAroundPoint(lat, lon, radius = 1500) {
+ const query = `
+ [out:json][timeout:25];
+ (
+ node["amenity"="charging_station"](around:${radius},${lat},${lon});
+ way["amenity"="charging_station"](around:${radius},${lat},${lon});
+ relation["amenity"="charging_station"](around:${radius},${lat},${lon});
+ );
+ out body;
+ >;
+ out skel qt;`;
+
+ const url = `https://overpass-api.de/api/interpreter?data=${encodeURIComponent(query)}`;
+
+ try {
+ const response = await fetch(url);
+ const data = await response.json();
+ return data.elements || [];
+ } catch (error) {
+ console.error('Erreur lors de la recherche des stations de recharge:', error);
+ return [];
+ }
+}
+
+async function calculerEtAfficherItineraire(destination, mode = 'car') {
+ // Récupérer le point de départ (centre de la carte)
+ const startLat = startItinerary[0];
+ const startLon = startItinerary[1];
+ const endLat = endItinerary[0];
+ const endLon = endItinerary[1];
+
+ // Récupérer les paramètres de la batterie
+ const batteryCapacity = parseFloat($('#battery_capacity').val()) || 40;
+ const batteryStartLevel = parseFloat($('#battery_start_level').val()) || 90;
+ const consumptionPerKm = parseFloat($('#consumption_per_km').val()) || 160;
+ const minBatteryLevel = parseFloat($('#min_battery_level').val()) || 15;
+ const chargeToLevel = parseFloat($('#charge_to_level').val()) || 80;
+
+ // Construire l'URL OSRM
+ const url = `https://router.project-osrm.org/route/v1/${mode}/${startLon},${startLat};${endLon},${endLat}?overview=full&geometries=geojson&alternatives=false&steps=false`;
+
+ $('#current_station_infos').html('Calcul de l\'itinéraire en cours…');
+
+ try {
+ const response = await fetch(url);
+ const data = await response.json();
+
+ if (!data.routes || !data.routes.length) {
+ $('#current_station_infos').html('Aucun itinéraire trouvé.');
+ return;
+ }
+
+ const route = data.routes[0];
+ const coords = route.geometry.coordinates.map(c => [c[1], c[0]]); // [lat, lon]
+
+ // Supprimer l'ancien tracé et les marqueurs
+ if (window.routePolyline) {
+ map.removeLayer(window.routePolyline);
+ }
+ if (window.pauseMarkers) {
+ window.pauseMarkers.forEach(marker => map.removeLayer(marker));
+ }
+ if (window.batteryMarkers) {
+ window.batteryMarkers.forEach(marker => map.removeLayer(marker));
+ }
+
+ // Afficher le nouveau tracé sur la carte
+ window.routePolyline = L.polyline(coords, {color: '#0059ce', weight: 5}).addTo(map);
+ // Supprimer le fitBounds qui déplace la vue
+ // map.fitBounds(window.routePolyline.getBounds());
+
+ // Calculer la consommation totale
+ const totalDistanceKm = route.distance / 1000;
+ const totalConsumptionKwh = (totalDistanceKm * consumptionPerKm) / 1000;
+ const batteryStartKwh = (batteryCapacity * batteryStartLevel) / 100;
+ const batteryEndKwh = batteryStartKwh - totalConsumptionKwh;
+ const batteryEndLevel = (batteryEndKwh / batteryCapacity) * 100;
+
+ // Ajouter les marqueurs de niveau de batterie
+ window.batteryMarkers = [];
+ const batteryLevels = [90, 80, 70, 60, 50, 40, 30, 20, 15];
+ let accumulatedDistance = 0;
+ let currentBatteryLevel = batteryStartLevel;
+
+ for (let i = 0; i < coords.length - 1; i++) {
+ const segmentDistance = L.latLng(coords[i]).distanceTo(coords[i + 1]) / 1000; // en km
+ const segmentConsumption = (segmentDistance * consumptionPerKm) / 1000; // en kWh
+ const nextBatteryLevel = ((batteryStartKwh - (accumulatedDistance * consumptionPerKm / 1000)) / batteryCapacity) * 100;
+
+ // Vérifier si on atteint un niveau de batterie à marquer
+ for (const level of batteryLevels) {
+ if (currentBatteryLevel > level && nextBatteryLevel <= level) {
+ const ratio = (level - currentBatteryLevel) / (nextBatteryLevel - currentBatteryLevel);
+ const markerCoords = [
+ coords[i][0] + (coords[i + 1][0] - coords[i][0]) * ratio,
+ coords[i][1] + (coords[i + 1][1] - coords[i][1]) * ratio
+ ];
+
+ const batteryMarker = L.marker(markerCoords, {
+ icon: L.divIcon({
+ className: 'battery-marker',
+ html: `🔋 ${level}%`,
+ iconSize: [30, 30]
+ })
+ }).addTo(map);
+
+ let popupContent = `