teecup/frontend/lib/hole-geometry.ts

40 lines
1.8 KiB
TypeScript
Raw Permalink Normal View History

import { type LatLng, bearingDegrees, haversineMeters } from "./geo"
/**
* Projiserer et vilkårlig punkt ned en fast akse (typisk tee->green),
* for et hull-diagram der "langs hullet" og "til siden" skal vises
* uavhengig av spillerens gangretning -- ren klientberegning, ingen
* Mapbox-kall (samme ADR-048-kostnadskontroll-prinsipp som geo.ts).
*
* `alongPercent`: 0 ved axisStart, 100 ved axisEnd -- IKKE klippet her
* (kan bli <0 eller >100 hvis punktet ligger bak start/forbi slutt),
* klipping skjer kun ved selve visningen.
* `crossMeters`: avstand til siden av aksen. Positiv = til høyre for
* aksens retning (sett fra axisStart mot axisEnd), negativ = venstre --
* samme klokke-positive konvensjon som bearingDegrees.
*/
export function projectOntoAxis(
axisStart: LatLng,
axisEnd: LatLng,
point: LatLng,
): { alongPercent: number; crossMeters: number } {
const axisLength = haversineMeters(axisStart, axisEnd)
if (axisLength === 0) {
return { alongPercent: 0, crossMeters: haversineMeters(axisStart, point) }
}
const axisBearing = bearingDegrees(axisStart, axisEnd)
const pointDistance = haversineMeters(axisStart, point)
const pointBearing = bearingDegrees(axisStart, point)
// Normaliser vinkeldifferansen til (-180, 180] før trigonometri.
const angleDiff = (((pointBearing - axisBearing + 540) % 360) - 180) * (Math.PI / 180)
const along = pointDistance * Math.cos(angleDiff)
const cross = pointDistance * Math.sin(angleDiff)
return { alongPercent: (along / axisLength) * 100, crossMeters: cross }
}
/** Midtpunkt mellom to koordinater (enkel plan-tilnærming -- presist nok
* hull-skala, samme antakelse som resten av geo.ts). */
export function midpoint(a: LatLng, b: LatLng): LatLng {
return { lat: (a.lat + b.lat) / 2, lng: (a.lng + b.lng) / 2 }
}