Files
cmr-mini/miniprogram/engine/layer/courseLayer.ts

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 {}
}