import { useEffect, useMemo } from 'react';
import { CircleMarker, Popup, useMap } from 'react-leaflet';
import proj4 from 'proj4';
import { Node, AdcValues } from '../types';
// Définition de la projection UTM Zone 31N (WGS84)
const UTM31N = "+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs";
const WGS84 = "EPSG:4326";
function utmToLatLon(easting: number, northing: number): [number, number] | null {
if (!easting || !northing || isNaN(easting) || isNaN(northing)) return null;
try {
// Proj4 attend [longitude, latitude] pour le résultat
const [lon, lat] = proj4(UTM31N, WGS84, [easting, northing]);
return [lat, lon];
} catch (e) {
console.error('UTM Conversion error:', e);
return null;
}
}
function getMarkerColor(value: number | undefined, maxVal = 500): string {
if (value === undefined || value <= 0) return '#444444';
const normalized = Math.min(1, Math.sqrt(value) / Math.sqrt(maxVal));
if (normalized < 0.3) return `rgb(0, ${Math.round(normalized * 3.3 * 255)}, 255)`;
if (normalized < 0.6) return `rgb(0, 255, ${Math.round((1 - (normalized - 0.3) * 3.3) * 255)})`;
return `rgb(255, ${Math.round((1 - (normalized - 0.6) * 2.5) * 255)}, 0)`;
}
function getMarkerRadius(value: number | undefined, maxVal = 500): number {
if (value === undefined || value <= 0) return 6;
const normalized = Math.min(1, Math.sqrt(value) / Math.sqrt(maxVal));
return 6 + normalized * 24;
}
interface NodeMarkersProps {
nodes: Node[];
selectedNode: Node | null;
onSelectNode: (node: Node) => void;
adcValues: AdcValues;
showOnlyWithData?: boolean;
}
function NodeMarkers({ nodes, selectedNode, onSelectNode, adcValues, showOnlyWithData = true }: NodeMarkersProps) {
const map = useMap();
const nodesWithLatLon = useMemo(() => {
console.log(`NodeMarkers: Processing ${nodes.length} nodes`);
const results = nodes
.filter(node => node.position && (!showOnlyWithData || node.hasDates))
.map(node => {
const coords = utmToLatLon(node.position!.easting, node.position!.northing);
if (!coords) return null;
return { ...node, lat: coords[0], lon: coords[1] };
})
.filter((n): n is Node & { lat: number; lon: number } => n !== null);
console.log(`NodeMarkers: ${results.length} nodes converted to LatLon`);
if (results.length > 0) {
console.log('Sample node:', results[0].id, results[0].lat, results[0].lon);
}
return results;
}, [nodes, showOnlyWithData]);
useEffect(() => {
if (nodesWithLatLon.length === 0) return;
try {
const lats = nodesWithLatLon.map(n => n.lat);
const lons = nodesWithLatLon.map(n => n.lon);
const bounds: [[number, number], [number, number]] = [
[Math.min(...lats), Math.min(...lons)],
[Math.max(...lats), Math.max(...lons)]
];
map.fitBounds(bounds, { padding: [50, 50] });
} catch (e) {
console.error('fitBounds error:', e);
}
}, [nodesWithLatLon, map]);
const currentMax = useMemo(() => {
const vals = Object.values(adcValues).filter(v => v > 0);
return vals.length > 0 ? Math.max(...vals) : 500;
}, [adcValues]);
return (
<>
DEBUG: Centre de Sète
{nodesWithLatLon.map(node => {
const adcValue = adcValues[node.id];
const isSelected = selectedNode?.id === node.id;
return (
onSelectNode(node) }}
>
Node {node.id}
E: {node.position?.easting.toFixed(0)} N: {node.position?.northing.toFixed(0)}
RMS: {adcValue?.toFixed(2) || 'N/A'}
);
})}
>
);
}
export default NodeMarkers;