62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { Coordinates, Track } from "@mt/common-types";
|
|
|
|
import { getDistance, getPointDeviation } from "../utils";
|
|
|
|
const APPROXIMATE_DISTANCE = 15; // [meters] half of tramway length (~30 meters)
|
|
|
|
export function usePassedTrackIndex(
|
|
track: Track | null,
|
|
currentPosition: Coordinates | null
|
|
) {
|
|
const [passedTrackIndex, setPassedTrackIndex] = useState<number>(0);
|
|
|
|
useEffect(() => {
|
|
if (!track || !currentPosition) {
|
|
return;
|
|
}
|
|
|
|
let minDistance = getDistance(track[0], currentPosition);
|
|
let newPassedIndex = 0;
|
|
|
|
for (let i = 1; i < track.length; i++) {
|
|
const distance = getDistance(track[i], currentPosition);
|
|
|
|
if (distance < minDistance) {
|
|
newPassedIndex = i;
|
|
minDistance = distance;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Is current position more than APPROXIMATE_DISTANCE far from found track point
|
|
* we need to check that we really reach newPassedIndex. If not — should decrement index
|
|
*/
|
|
if (
|
|
getDistance(track[newPassedIndex], currentPosition) > APPROXIMATE_DISTANCE
|
|
) {
|
|
const prevIndex = Math.max(newPassedIndex - 1, 0);
|
|
const nextIndex = Math.min(newPassedIndex + 1, track.length - 1);
|
|
|
|
const leftDeviation = getPointDeviation(
|
|
track[prevIndex],
|
|
track[newPassedIndex], // Ближайшая точка трека
|
|
currentPosition
|
|
);
|
|
const rightDeviation = getPointDeviation(
|
|
track[newPassedIndex], // Ближайшая точка трека
|
|
track[nextIndex],
|
|
currentPosition
|
|
);
|
|
|
|
if (leftDeviation >= rightDeviation) {
|
|
newPassedIndex--;
|
|
}
|
|
}
|
|
|
|
setPassedTrackIndex(newPassedIndex);
|
|
}, [track, currentPosition]);
|
|
|
|
return { passedTrackIndex };
|
|
}
|