Still playing with the reticle...

This commit is contained in:
Eric van der Vlist 2022-10-08 23:59:09 +02:00
parent 77f5ab3996
commit 27305c4b21
2 changed files with 105 additions and 14 deletions

View File

@ -1,26 +1,78 @@
import _ from 'lodash';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { Point } from '../../lib/geo'; import { Point } from '../../lib/geo';
import { MapState } from '../../store/map'; import { MapState } from '../../store/map';
import '../../theme/map.css';
const Reticle: React.FC<{}> = () => { const Reticle: React.FC<{}> = () => {
const windowState = useSelector( const windowState = useSelector(
(state: { map: MapState }) => state.map.window (state: { map: MapState }) => state.map.window
); );
const scope = useSelector((state: { map: MapState }) => state.map.scope);
const radius = Math.min(windowState.width, windowState.height) / 4;
const center: Point = {
x: windowState.width / 2,
y: windowState.height / 2,
};
const center: Point = { x: windowState.width / 2, y: windowState.height / 2 }; /**
const radius = Math.min(windowState.width, windowState.height) / 6; * The horizontal distance represented by each square tile, measured along the parallel at a given latitude, is given by:
* Stile = C cos(latitude) / 2 zoomlevel
* As tiles are 256-pixels wide, the horizontal distance represented by one pixel is:
* Spixel = Stile / 256 = C cos(latitude) / 2 (zoomlevel + 8)
* where C means the equatorial circumference of the Earth (40 075 016.686 m 2π 6 378 137.000 m for the reference geoid used by OpenStreetMap).
* see https://wiki.openstreetmap.org/wiki/Zoom_levels
*/
const sTile =
(40075016.686 * Math.cos((scope.center.lat * Math.PI) / 180)) /
2 ** scope.zoom;
const radiusMeters = (sTile * radius) / 256;
const radiusOrder = Math.floor(Math.log10(radiusMeters));
const radiusRoughUnit = radiusMeters / 10 ** radiusOrder;
var radiusBaseUnit, radiusBaseSubUnit;
if (radiusRoughUnit <= 2) {
radiusBaseUnit = 1;
radiusBaseSubUnit = 0.2;
} else if (radiusRoughUnit <= 5) {
radiusBaseUnit = 2;
radiusBaseSubUnit = 0.5;
} else {
radiusBaseUnit = 5;
radiusBaseSubUnit = 1;
}
const nbSubUnits = Math.floor(
radiusMeters / (radiusBaseSubUnit * 10 ** radiusOrder)
);
const nbUnits = Math.floor(
radiusMeters / (radiusBaseUnit * 10 ** radiusOrder)
);
const radiusUnit = radiusOrder < 3 ? 'm' : 'km';
const radiusUnitValue =
radiusOrder < 3
? radiusBaseUnit * 10 ** radiusOrder
: radiusBaseUnit * 10 ** (radiusOrder - 3);
const subUnitPxStep = ((radiusBaseSubUnit * 10 ** radiusOrder) / sTile) * 256;
const unitPxStep = ((radiusBaseUnit * 10 ** radiusOrder) / sTile) * 256;
console.log(
`radiusMeters: ${radiusMeters}, radiusOrder: ${radiusOrder}, radiusUnit: ${radiusBaseUnit}, radiusSubUnit: ${radiusBaseSubUnit}, nbSubUnits: ${nbSubUnits}`
);
return ( return (
<g> <g className='reticle'>
<circle <circle
cx={center.x} cx={center.x}
cy={center.y} cy={center.y}
r={radius} r={radius}
fill='transparent' fill='transparent'
stroke='black' stroke='black'
strokeWidth={2} strokeWidth={1}
/> />
<path <path
d={`M ${center.x - radius},${center.y} d={`M ${center.x - radius},${center.y}
@ -31,9 +83,39 @@ const Reticle: React.FC<{}> = () => {
v ${radius - 3} v ${radius - 3}
m 0,${6} m 0,${6}
v ${radius - 3}`} v ${radius - 3}`}
strokeWidth={1} strokeWidth={0.5}
stroke='red'
/> />
<g id='reticle-east'>
<path stroke='red' className='reticle'
strokeWidth={0.5}
d={_.range(1, nbSubUnits + 1)
.map(
(i) => `M ${center.x + i * subUnitPxStep},${center.y - 10} v 20`
)
.join(' ')}
/>
<path stroke='red' className='reticle'
d={_.range(1, nbUnits + 1)
.map((i) => `M ${center.x + i * unitPxStep},${center.y - 20} v 40`)
.join(' ')}
strokeWidth={0.5}
/>
</g>
<use stroke='red' className='reticle'
href='#reticle-east'
transform={`rotate(90, ${center.x}, ${center.y})`}
/>
<use className='reticle'
href='#reticle-east'
transform={`rotate(180, ${center.x}, ${center.y})`}
/>
<use className='reticle'
href='#reticle-east'
transform={`rotate(-90, ${center.x}, ${center.y})`}
/>
<text x={center.x + unitPxStep - 15} y={center.y - 20}>
{`${radiusUnitValue} ${radiusUnit}`}
</text>
</g> </g>
); );
}; };

View File

@ -43,6 +43,17 @@ path.current {
stroke: rgba(2, 71, 20, 0.8); stroke: rgba(2, 71, 20, 0.8);
} }
.reticle path,
path.reticle,
use.reticle,
.reticle use {
stroke: red;
}
.reticle text {
font-size: 12px;
}
ion-modal { ion-modal {
--height: 50%; --height: 50%;
--border-radius: 16px; --border-radius: 16px;
@ -60,14 +71,13 @@ ion-modal.full-height {
} */ } */
ion-modal ion-toolbar { ion-modal ion-toolbar {
--background: rgba(14,116,144, .7); --background: rgba(14, 116, 144, 0.7);
--color: white; --color: white;
} }
ion-modal.full-height ion-toolbar { ion-modal.full-height ion-toolbar {
--background: rgba(14,116,144, 1); --background: rgba(14, 116, 144, 1);
} }
ion-modal ion-toolbar.secondary { ion-modal ion-toolbar.secondary {
--background: inherit; --background: inherit;
@ -75,10 +85,9 @@ ion-modal ion-toolbar.secondary {
} }
ion-modal ion-content { ion-modal ion-content {
background-color: rgba(255,255,255,.7) background-color: rgba(255, 255, 255, 0.7);
;
} }
.hidden { .hidden {
display: none; display: none;
} }