@mytec: iter7 ready for test
This commit is contained in:
41
frontend/src/components/map/ElevationDisplay.tsx
Normal file
41
frontend/src/components/map/ElevationDisplay.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useElevation } from '@/hooks/useElevation.ts';
|
||||
|
||||
/**
|
||||
* Shows cursor coordinates + elevation (meters ASL) at the bottom-left of the map.
|
||||
* Uses the Open-Elevation API with debounced requests.
|
||||
*/
|
||||
export default function ElevationDisplay() {
|
||||
const { elevation, position, loading } = useElevation();
|
||||
|
||||
if (!position) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '40px',
|
||||
left: '10px',
|
||||
background: 'rgba(0,0,0,0.8)',
|
||||
color: 'white',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
zIndex: 1000,
|
||||
pointerEvents: 'none',
|
||||
lineHeight: 1.6,
|
||||
fontFamily: 'monospace',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{position.lat.toFixed(5)}, {position.lon.toFixed(5)}
|
||||
</div>
|
||||
<div>
|
||||
{loading
|
||||
? 'Elev: ...'
|
||||
: elevation !== null
|
||||
? `Elev: ${elevation}m ASL`
|
||||
: 'Elev: N/A'}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -84,18 +84,23 @@ export default function Heatmap({ points, visible, opacity = 0.7 }: HeatmapProps
|
||||
|
||||
const { radius, blur, maxIntensity } = getHeatmapParams(mapZoom);
|
||||
|
||||
// Debug: log RSRP stats and heatmap params
|
||||
if (import.meta.env.DEV) {
|
||||
// Debug: log RSRP stats and heatmap params (detailed per spec)
|
||||
if (import.meta.env.DEV && heatData.length > 0) {
|
||||
const rsrpValues = points.map((p) => p.rsrp);
|
||||
const intensityValues = heatData.map((d) => d[2]);
|
||||
console.log('Heatmap Debug:', {
|
||||
pointCount: points.length,
|
||||
const normalizedSample = points.slice(0, 5).map((p) => ({
|
||||
rsrp: p.rsrp,
|
||||
normalized: rsrpToIntensity(p.rsrp),
|
||||
}));
|
||||
console.log('🔍 Heatmap Debug:', {
|
||||
zoom: mapZoom,
|
||||
totalPoints: points.length,
|
||||
rsrpRange: `${Math.min(...rsrpValues).toFixed(1)} to ${Math.max(...rsrpValues).toFixed(1)} dBm`,
|
||||
intensityRange: `${Math.min(...intensityValues).toFixed(3)} to ${Math.max(...intensityValues).toFixed(3)}`,
|
||||
mapZoom,
|
||||
radius,
|
||||
blur,
|
||||
maxIntensity,
|
||||
maxIntensity, // Should ALWAYS be 0.75
|
||||
sample: normalizedSample,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import SiteMarker from './SiteMarker.tsx';
|
||||
import MapExtras from './MapExtras.tsx';
|
||||
import CoordinateGrid from './CoordinateGrid.tsx';
|
||||
import MeasurementTool from './MeasurementTool.tsx';
|
||||
import ElevationDisplay from './ElevationDisplay.tsx';
|
||||
|
||||
interface MapViewProps {
|
||||
onMapClick: (lat: number, lon: number) => void;
|
||||
@@ -54,6 +55,9 @@ export default function MapView({ onMapClick, onEditSite, children }: MapViewPro
|
||||
const setShowGrid = useSettingsStore((s) => s.setShowGrid);
|
||||
const measurementMode = useSettingsStore((s) => s.measurementMode);
|
||||
const setMeasurementMode = useSettingsStore((s) => s.setMeasurementMode);
|
||||
const showElevationInfo = useSettingsStore((s) => s.showElevationInfo);
|
||||
const showElevationOverlay = useSettingsStore((s) => s.showElevationOverlay);
|
||||
const setShowElevationOverlay = useSettingsStore((s) => s.setShowElevationOverlay);
|
||||
const addToast = useToastStore((s) => s.addToast);
|
||||
const mapRef = useRef<LeafletMap | null>(null);
|
||||
|
||||
@@ -89,8 +93,18 @@ export default function MapView({ onMapClick, onEditSite, children }: MapViewPro
|
||||
zIndex={100}
|
||||
/>
|
||||
)}
|
||||
{/* Elevation color overlay (Stamen Terrain via Stadia Maps) */}
|
||||
{showElevationOverlay && (
|
||||
<TileLayer
|
||||
attribution='© Stamen Design'
|
||||
url="https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}.png"
|
||||
opacity={0.5}
|
||||
zIndex={97}
|
||||
/>
|
||||
)}
|
||||
<MapClickHandler onMapClick={onMapClick} />
|
||||
<MapExtras />
|
||||
{showElevationInfo && <ElevationDisplay />}
|
||||
<CoordinateGrid visible={showGrid} />
|
||||
<MeasurementTool
|
||||
enabled={measurementMode}
|
||||
@@ -159,6 +173,16 @@ export default function MapView({ onMapClick, onEditSite, children }: MapViewPro
|
||||
>
|
||||
Ruler
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowElevationOverlay(!showElevationOverlay)}
|
||||
className={`bg-white dark:bg-dark-surface shadow-lg rounded px-3 py-2 text-sm
|
||||
hover:bg-gray-50 dark:hover:bg-dark-border transition-colors
|
||||
text-gray-700 dark:text-dark-text min-h-[36px]
|
||||
${showElevationOverlay ? 'ring-2 ring-amber-500' : ''}`}
|
||||
title={showElevationOverlay ? 'Hide elevation colors' : 'Show elevation color overlay'}
|
||||
>
|
||||
Elev
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -111,7 +111,7 @@ export default function SiteMarker({ site, onEdit }: SiteMarkerProps) {
|
||||
</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
{site.antennaType === 'sector' && (
|
||||
{site.antennaType === 'sector' && (site.beamwidth ?? 65) < 360 && (
|
||||
<Polygon
|
||||
positions={generateSectorWedge(site)}
|
||||
pathOptions={{
|
||||
|
||||
Reference in New Issue
Block a user