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;