import { describe, expect, it } from "vitest" import { midpoint, projectOntoAxis } from "./hole-geometry" // Testrigg: en rein nord-sør-akse (tee i sør, green 200 m rett nord) -- // lett å regne fasit for. 111_320 m per breddegrad er samme tilnærming // som geo.test.ts allerede bruker. const METERS_PER_DEGREE_LAT = 111_320 const tee = { lat: 59.9, lng: 10.75 } const green = { lat: 59.9 + 200 / METERS_PER_DEGREE_LAT, lng: 10.75 } describe("projectOntoAxis", () => { it("punktet på start (tee) gir alongPercent=0, crossMeters≈0", () => { const { alongPercent, crossMeters } = projectOntoAxis(tee, green, tee) expect(alongPercent).toBeCloseTo(0, 3) expect(crossMeters).toBeCloseTo(0, 3) }) it("punktet på slutt (green) gir alongPercent=100, crossMeters≈0", () => { const { alongPercent, crossMeters } = projectOntoAxis(tee, green, green) expect(alongPercent).toBeCloseTo(100, 0) expect(crossMeters).toBeCloseTo(0, 1) }) it("midtpunktet på aksen gir alongPercent≈50, crossMeters≈0", () => { const mid = midpoint(tee, green) const { alongPercent, crossMeters } = projectOntoAxis(tee, green, mid) expect(alongPercent).toBeCloseTo(50, 0) expect(crossMeters).toBeCloseTo(0, 1) }) it("et punkt rett øst for midtpunktet gir riktig crossMeters mot høyre", () => { // Aksen peker rett nord (bearing 0) -- et punkt rett øst for et punkt // PÅ aksen skal derfor ligge til HØYRE (positiv cross), på samme // langs-posisjon (alongPercent uendret). const mid = midpoint(tee, green) const offsetEast = { lat: mid.lat, lng: mid.lng + 20 / (METERS_PER_DEGREE_LAT * Math.cos((mid.lat * Math.PI) / 180)) } const { alongPercent, crossMeters } = projectOntoAxis(tee, green, offsetEast) expect(alongPercent).toBeCloseTo(50, 0) expect(crossMeters).toBeGreaterThan(19) expect(crossMeters).toBeLessThan(21) }) it("et punkt rett vest for midtpunktet gir negativ crossMeters (venstre)", () => { const mid = midpoint(tee, green) const offsetWest = { lat: mid.lat, lng: mid.lng - 20 / (METERS_PER_DEGREE_LAT * Math.cos((mid.lat * Math.PI) / 180)) } const { crossMeters } = projectOntoAxis(tee, green, offsetWest) expect(crossMeters).toBeLessThan(-19) expect(crossMeters).toBeGreaterThan(-21) }) it("et punkt bak tee (før start) gir negativ alongPercent", () => { const behindTee = { lat: tee.lat - 50 / METERS_PER_DEGREE_LAT, lng: tee.lng } const { alongPercent } = projectOntoAxis(tee, green, behindTee) expect(alongPercent).toBeLessThan(0) }) it("et punkt forbi green gir alongPercent > 100", () => { const beyondGreen = { lat: green.lat + 50 / METERS_PER_DEGREE_LAT, lng: green.lng } const { alongPercent } = projectOntoAxis(tee, green, beyondGreen) expect(alongPercent).toBeGreaterThan(100) }) it("axisStart == axisEnd degraderer grasiøst (ingen NaN/deling på null)", () => { const { alongPercent, crossMeters } = projectOntoAxis(tee, tee, green) expect(Number.isFinite(alongPercent)).toBe(true) expect(Number.isFinite(crossMeters)).toBe(true) }) }) describe("midpoint", () => { it("midtpunktet av et punkt med seg selv er punktet selv", () => { expect(midpoint(tee, tee)).toEqual(tee) }) it("midtpunktet ligger halvveis mellom to punkt", () => { const m = midpoint(tee, green) expect(m.lat).toBeCloseTo((tee.lat + green.lat) / 2, 10) expect(m.lng).toBeCloseTo((tee.lng + green.lng) / 2, 10) }) })