110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { lonLatToWorldTile } from '../../utils/projection'
|
|
import { worldToScreen, type CameraState } from '../camera/camera'
|
|
import { type MapLayer, type LayerRenderContext } from './mapLayer'
|
|
import { type MapScene } from '../renderer/mapRenderer'
|
|
import { type ScreenPoint } from './trackLayer'
|
|
import {
|
|
type OrienteeringCourseControl,
|
|
type OrienteeringCourseFinish,
|
|
type OrienteeringCourseLeg,
|
|
type OrienteeringCourseStart,
|
|
} from '../../utils/orienteeringCourse'
|
|
|
|
export interface ProjectedCourseLeg {
|
|
fromKind: OrienteeringCourseLeg['fromKind']
|
|
toKind: OrienteeringCourseLeg['toKind']
|
|
from: ScreenPoint
|
|
to: ScreenPoint
|
|
}
|
|
|
|
export interface ProjectedCourseStart {
|
|
label: string
|
|
point: ScreenPoint
|
|
headingDeg: number | null
|
|
}
|
|
|
|
export interface ProjectedCourseControl {
|
|
label: string
|
|
sequence: number
|
|
point: ScreenPoint
|
|
}
|
|
|
|
export interface ProjectedCourseFinish {
|
|
label: string
|
|
point: ScreenPoint
|
|
}
|
|
|
|
export interface ProjectedCourseLayers {
|
|
starts: ProjectedCourseStart[]
|
|
controls: ProjectedCourseControl[]
|
|
finishes: ProjectedCourseFinish[]
|
|
legs: ProjectedCourseLeg[]
|
|
}
|
|
|
|
function buildVectorCamera(scene: MapScene): CameraState {
|
|
return {
|
|
centerWorldX: scene.exactCenterWorldX,
|
|
centerWorldY: scene.exactCenterWorldY,
|
|
viewportWidth: scene.viewportWidth,
|
|
viewportHeight: scene.viewportHeight,
|
|
visibleColumns: scene.visibleColumns,
|
|
rotationRad: scene.rotationRad,
|
|
}
|
|
}
|
|
|
|
export class CourseLayer implements MapLayer {
|
|
projectPoint(point: { point: { lon: number; lat: number } }, scene: MapScene, camera: CameraState): ScreenPoint {
|
|
const worldPoint = lonLatToWorldTile(point.point, scene.zoom)
|
|
return worldToScreen(camera, worldPoint, false)
|
|
}
|
|
|
|
projectStarts(starts: OrienteeringCourseStart[], scene: MapScene, camera: CameraState): ProjectedCourseStart[] {
|
|
return starts.map((start) => ({
|
|
label: start.label,
|
|
point: this.projectPoint(start, scene, camera),
|
|
headingDeg: start.headingDeg,
|
|
}))
|
|
}
|
|
|
|
projectControls(controls: OrienteeringCourseControl[], scene: MapScene, camera: CameraState): ProjectedCourseControl[] {
|
|
return controls.map((control) => ({
|
|
label: control.label,
|
|
sequence: control.sequence,
|
|
point: this.projectPoint(control, scene, camera),
|
|
}))
|
|
}
|
|
|
|
projectFinishes(finishes: OrienteeringCourseFinish[], scene: MapScene, camera: CameraState): ProjectedCourseFinish[] {
|
|
return finishes.map((finish) => ({
|
|
label: finish.label,
|
|
point: this.projectPoint(finish, scene, camera),
|
|
}))
|
|
}
|
|
|
|
projectLegs(legs: OrienteeringCourseLeg[], scene: MapScene, camera: CameraState): ProjectedCourseLeg[] {
|
|
return legs.map((leg) => ({
|
|
fromKind: leg.fromKind,
|
|
toKind: leg.toKind,
|
|
from: worldToScreen(camera, lonLatToWorldTile(leg.fromPoint, scene.zoom), false),
|
|
to: worldToScreen(camera, lonLatToWorldTile(leg.toPoint, scene.zoom), false),
|
|
}))
|
|
}
|
|
|
|
projectCourse(scene: MapScene): ProjectedCourseLayers | null {
|
|
const course = scene.course
|
|
if (!course) {
|
|
return null
|
|
}
|
|
|
|
const camera = buildVectorCamera(scene)
|
|
return {
|
|
starts: this.projectStarts(course.layers.starts, scene, camera),
|
|
controls: this.projectControls(course.layers.controls, scene, camera),
|
|
finishes: this.projectFinishes(course.layers.finishes, scene, camera),
|
|
legs: this.projectLegs(course.layers.legs, scene, camera),
|
|
}
|
|
}
|
|
|
|
draw(_context: LayerRenderContext): void {}
|
|
}
|