courseLayer.ts 3.5 KB

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