Correct algorithm for centering tiles.

This commit is contained in:
Eric van der Vlist 2022-09-06 11:39:27 +02:00
parent 9e8aec244e
commit 4e26d94843
4 changed files with 23 additions and 96 deletions

View File

@ -1,55 +0,0 @@
import React from 'react';
import { PigeonProps, Point } from 'pigeon-maps';
import GPX from 'gpx-parser-builder';
import { round } from 'lodash';
const GPXFigure: React.FC<PigeonProps> = (props: PigeonProps) => {
const gpx = GPX.parse(localStorage.getItem('gpx'));
const dirtyLatLngToPixel = (point: Point) => {
if (props.mapState === undefined) {
return undefined;
}
const latRange = props.mapState.bounds.ne[0] - props.mapState.bounds.sw[0];
const lonRange = props.mapState.bounds.ne[1] - props.mapState.bounds.sw[1];
const x = round(
((point[0] - props.mapState.bounds.sw[0]) * props.mapState.width) /
lonRange
);
const y = round(
((point[1] - props.mapState.bounds.sw[1]) * props.mapState.height) /
latRange
);
return [x, props.mapState.height - y];
};
const trkToPolyline = (gpxData: any) => {
const latLongs: string[] = gpxData.trk[0].trkseg[0].trkpt.map(
(trkpt: any) => {
if (props.latLngToPixel === undefined) {
return '';
}
const point: Point = [trkpt.$.lat, trkpt.$.lon];
const pixelPoint = dirtyLatLngToPixel(point);
if (pixelPoint === undefined) {
return '';
}
return pixelPoint.join(' ');
}
);
console.log('latLongs: ' + latLongs);
return latLongs.join(' ');
};
return (
<polyline
points={trkToPolyline(gpx)}
stroke='black'
strokeWidth='3'
fill='none'
></polyline>
);
};
export default GPXFigure;

View File

@ -1,27 +0,0 @@
import React from 'react';
import { Overlay, PigeonProps } from 'pigeon-maps';
import GPXFigure from './gpx-figure';
const GPXOverlay: React.FC<PigeonProps> = (props: PigeonProps) => {
return (
<Overlay >
{props.mapState && props.mapState.width > 0 && (
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox={'0 0 ' + props.mapState.width + ' ' + props.mapState.height}
width={props.mapState.width}
height={props.mapState.height}
>
<GPXFigure
mapState={props.mapState}
latLngToPixel={props.latLngToPixel}
/>
</svg>
)}
</Overlay>
);
};
export default GPXOverlay;

View File

@ -1,7 +1,6 @@
import _, { round } from 'lodash';
import react, { useState, useEffect } from 'react';
import GPXOverlay from './gpx-overlay';
import Tile from './tile';
import '../theme/map.css';
@ -24,13 +23,13 @@ const lat2tile = (lat: number, zoom: number) => {
Math.PI) /
2) *
Math.pow(2, zoom);
const floor = Math.floor(real);
return [floor, real - floor];
};
const floor = Math.floor(real);
return [floor, real - floor];
};
const Map: react.FC = () => {
const initialCenter: [number, number] = [43.57029965, 3.94242897];
const initialZoom: number = 15;
const initialZoom: number = 17;
const [center, setCenter] = useState(initialCenter);
const [zoom, setZoom] = useState(initialZoom);
@ -51,12 +50,16 @@ const Map: react.FC = () => {
const nbTilesY = _.ceil(dimensions.height / tileSize) + 2;
const nbTilesX = _.ceil(dimensions.width / tileSize) + 2;
const [tileCenterY, deltaY] = lat2tile(center[0], zoom);
const [tileCenterX, deltaX] = lon2tile(center[1], zoom);
const [tileCenterY, reminderY] = lat2tile(center[0], zoom);
const [tileCenterX, reminderX] = lon2tile(center[1], zoom);
const firstTileY = tileCenterY - _.ceil(nbTilesY / 2);
const firstTileX = tileCenterX - _.ceil(nbTilesX / 2);
const locationY = ((tileCenterY + reminderY - firstTileY ) * tileSize) ;
const locationX = ((tileCenterX + reminderX - firstTileX ) * tileSize) ;
const targetLocationY = dimensions.height / 2;
const targetLocationX = dimensions.width / 2;
const deltaY = - targetLocationY + locationY;
const deltaX = - targetLocationX + locationX;
return (
<div className='tiles'>
@ -69,8 +72,8 @@ const Map: react.FC = () => {
ix={ix}
x={firstTileX + ix}
y={firstTileY + iy}
deltaX ={deltaX}
deltaY ={deltaY}
deltaX={deltaX}
deltaY={deltaY}
zoom={zoom}
/>
))}

View File

@ -26,12 +26,18 @@ const Tile: React.FC<{
height: tileSize + 'px',
transform:
'translate3d(' +
(props.ix - props.deltaX -1) * tileSize +
(props.ix * tileSize - props.deltaX) +
'px, ' +
(props.iy - props.deltaY -1) * tileSize +
(props.iy * tileSize - props.deltaY) +
'px, 0px)',
};
return <img src={tileProvider(props.zoom, props.x, props.y)} style={style} />;
return (
<img
src={tileProvider(props.zoom, props.x, props.y)}
style={style}
alt=''
/>
);
};
export default Tile;