From d1da0a110d304da3f7c68a80cd143a8ad71c89a2 Mon Sep 17 00:00:00 2001 From: evlist Date: Tue, 11 Oct 2022 17:38:23 +0200 Subject: [PATCH] Starting to implement avatars for locations (WIP). --- src/components/map/AvatarForLocation.tsx | 49 ++++++++++++++++++++++++ src/components/map/LocationInfo.tsx | 22 +++++------ src/components/map/Reticle.tsx | 25 ++++++------ 3 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 src/components/map/AvatarForLocation.tsx diff --git a/src/components/map/AvatarForLocation.tsx b/src/components/map/AvatarForLocation.tsx new file mode 100644 index 0000000..691fc09 --- /dev/null +++ b/src/components/map/AvatarForLocation.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +import { useSelector } from 'react-redux'; +import { geoPoint, lat2tile, lon2tile, Point } from '../../lib/geo'; + +import { MapState } from '../../store/map'; +import { tileProviders } from './tile'; + +interface AvatarForLocationProps { + location: geoPoint; + zoom?: number; + tileProvider?: string; + size?: number; + name?: string; +} + +const AvatarForLocation: React.FC = ( + props: AvatarForLocationProps +) => { + const size = props.size ? props.size : 42; + const zoom = props.zoom ? Math.round(props.zoom) : 16; + const tileProvider = props.tileProvider ? props.tileProvider : 'osm'; + const location = props.location; + const name = props.name ? props.name : '???'; + + const tilesLocation: Point = { + x: lon2tile(location.lon, zoom), + y: lat2tile(location.lat, zoom), + }; + + + return ( + + + + + + + + + + {name} + + + + ); +}; + +export default AvatarForLocation; diff --git a/src/components/map/LocationInfo.tsx b/src/components/map/LocationInfo.tsx index 3559635..9310e14 100644 --- a/src/components/map/LocationInfo.tsx +++ b/src/components/map/LocationInfo.tsx @@ -32,6 +32,8 @@ import { useSelector } from 'react-redux'; import i18n from '../../i18n'; import { geoPoint } from '../../lib/geo'; import { MapState } from '../../store/map'; +import AvatarForLocation from './AvatarForLocation'; +import { round } from 'lodash'; const LocationInfo: React.FC<{}> = () => { const scope = useSelector((state: { map: MapState }) => state.map.scope); @@ -134,17 +136,15 @@ const LocationInfo: React.FC<{}> = () => { const distDark = (255 * distance) / 3000; const distLight = 1 - distDark; return ( - + + + ); }; diff --git a/src/components/map/Reticle.tsx b/src/components/map/Reticle.tsx index b5716ef..b5f6eac 100644 --- a/src/components/map/Reticle.tsx +++ b/src/components/map/Reticle.tsx @@ -15,6 +15,18 @@ import { import i18n from '../../i18n'; import eventBus from '../../lib/pubsub'; +export const getSTile = (lat: number, zoom: number) => { + /** + * 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 + */ + return (40075016.686 * Math.cos((lat * Math.PI) / 180)) / 2 ** zoom; +}; + const Reticle: React.FC<{}> = () => { const windowState = useSelector( (state: { map: MapState }) => state.map.window @@ -26,18 +38,7 @@ const Reticle: React.FC<{}> = () => { y: windowState.height / 2, }; - /** - * 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 sTile = getSTile(scope.center.lat, scope.zoom); const radiusMeters = (sTile * radius) / 256; const radiusOrder = Math.floor(Math.log10(radiusMeters));