courseLayer.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { lonLatToWorldTile } from '../../utils/projection'
  2. import { worldToScreen, type CameraState } from '../camera/camera'
  3. import { type MapLayer, type LayerRenderContext } from './mapLayer'
  4. import { type MapScene } from '../renderer/mapRenderer'
  5. import { type ScreenPoint } from './trackLayer'
  6. import {
  7. type OrienteeringCourseControl,
  8. type OrienteeringCourseFinish,
  9. type OrienteeringCourseLeg,
  10. type OrienteeringCourseStart,
  11. } from '../../utils/orienteeringCourse'
  12. export interface ProjectedCourseLeg {
  13. fromKind: OrienteeringCourseLeg['fromKind']
  14. toKind: OrienteeringCourseLeg['toKind']
  15. from: ScreenPoint
  16. to: ScreenPoint
  17. }
  18. export interface ProjectedCourseStart {
  19. label: string
  20. point: ScreenPoint
  21. headingDeg: number | null
  22. }
  23. export interface ProjectedCourseControl {
  24. label: string
  25. sequence: number
  26. point: ScreenPoint
  27. }
  28. export interface ProjectedCourseFinish {
  29. label: string
  30. point: ScreenPoint
  31. }
  32. export interface ProjectedCourseLayers {
  33. starts: ProjectedCourseStart[]
  34. controls: ProjectedCourseControl[]
  35. finishes: ProjectedCourseFinish[]
  36. legs: ProjectedCourseLeg[]
  37. }
  38. function buildVectorCamera(scene: MapScene): CameraState {
  39. return {
  40. centerWorldX: scene.exactCenterWorldX,
  41. centerWorldY: scene.exactCenterWorldY,
  42. viewportWidth: scene.viewportWidth,
  43. viewportHeight: scene.viewportHeight,
  44. visibleColumns: scene.visibleColumns,
  45. rotationRad: scene.rotationRad,
  46. }
  47. }
  48. export class CourseLayer implements MapLayer {
  49. projectPoint(point: { point: { lon: number; lat: number } }, scene: MapScene, camera: CameraState): ScreenPoint {
  50. const worldPoint = lonLatToWorldTile(point.point, scene.zoom)
  51. return worldToScreen(camera, worldPoint, false)
  52. }
  53. projectStarts(starts: OrienteeringCourseStart[], scene: MapScene, camera: CameraState): ProjectedCourseStart[] {
  54. return starts.map((start) => ({
  55. label: start.label,
  56. point: this.projectPoint(start, scene, camera),
  57. headingDeg: start.headingDeg,
  58. }))
  59. }
  60. projectControls(controls: OrienteeringCourseControl[], scene: MapScene, camera: CameraState): ProjectedCourseControl[] {
  61. return controls.map((control) => ({
  62. label: control.label,
  63. sequence: control.sequence,
  64. point: this.projectPoint(control, scene, camera),
  65. }))
  66. }
  67. projectFinishes(finishes: OrienteeringCourseFinish[], scene: MapScene, camera: CameraState): ProjectedCourseFinish[] {
  68. return finishes.map((finish) => ({
  69. label: finish.label,
  70. point: this.projectPoint(finish, scene, camera),
  71. }))
  72. }
  73. projectLegs(legs: OrienteeringCourseLeg[], scene: MapScene, camera: CameraState): ProjectedCourseLeg[] {
  74. return legs.map((leg) => ({
  75. fromKind: leg.fromKind,
  76. toKind: leg.toKind,
  77. from: worldToScreen(camera, lonLatToWorldTile(leg.fromPoint, scene.zoom), false),
  78. to: worldToScreen(camera, lonLatToWorldTile(leg.toPoint, scene.zoom), false),
  79. }))
  80. }
  81. projectCourse(scene: MapScene): ProjectedCourseLayers | null {
  82. const course = scene.course
  83. if (!course) {
  84. return null
  85. }
  86. const camera = buildVectorCamera(scene)
  87. return {
  88. starts: this.projectStarts(course.layers.starts, scene, camera),
  89. controls: this.projectControls(course.layers.controls, scene, camera),
  90. finishes: this.projectFinishes(course.layers.finishes, scene, camera),
  91. legs: this.projectLegs(course.layers.legs, scene, camera),
  92. }
  93. }
  94. draw(_context: LayerRenderContext): void {}
  95. }