All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lucuma.core.model.ObjectTracking.scala Maven / Gradle / Ivy

There is a newer version: 0.108.0
Show newest version
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package lucuma.core.model

import cats.Eq
import cats.data.NonEmptyList
import cats.derived.*
import cats.syntax.all.*
import lucuma.core.math.Coordinates
import lucuma.core.model.syntax.tracking.*
import lucuma.core.util.NewType

import java.time.Instant

// Tag to indicate the coordinates have been corrected for proper motion
object CoordinatesAtVizTime extends NewType[Coordinates]
type CoordinatesAtVizTime = CoordinatesAtVizTime.Type

/**
 * Generic representation to track an object. It is generalization of SiderealTracking but allows
 * tracking "virtual" objects like the center of an asterism
 */
sealed trait ObjectTracking derives Eq:
  def at(i: Instant): Option[CoordinatesAtVizTime]
  def baseCoordinates: Coordinates

object ObjectTracking:

  case class SiderealObjectTracking(tracking: SiderealTracking) extends ObjectTracking derives Eq:
    def at(i: Instant): Option[CoordinatesAtVizTime] =
      tracking.at(i).map(CoordinatesAtVizTime(_))
    def baseCoordinates: Coordinates                 = tracking.baseCoordinates

  case class SiderealAsterismTracking(trackings : NonEmptyList[SiderealTracking]) extends ObjectTracking derives Eq:
    def at(i: Instant): Option[CoordinatesAtVizTime] =
      trackings.centerOfAt(i).map(CoordinatesAtVizTime(_))
    def baseCoordinates: Coordinates                 = trackings.centerOf

  case class ConstantTracking(coordinates: Coordinates) extends ObjectTracking derives Eq:
    def at(i: Instant): Option[CoordinatesAtVizTime] = CoordinatesAtVizTime(coordinates).some
    def baseCoordinates: Coordinates = coordinates


  def fromTarget(target: Target): ObjectTracking = target match
    case t: Target.Sidereal => SiderealObjectTracking(t.tracking)
    case _                  => sys.error("Only sidereal targets supported")

  def fromAsterism(targets: NonEmptyList[Target]): ObjectTracking = 
    val trackingList = targets.toList.traverse(Target.sidereal.getOption).flatMap(NonEmptyList.fromList)
    trackingList.fold(sys.error("Only sidereal targets supported")) { sidereals =>
      if (sidereals.length === 1) SiderealObjectTracking(sidereals.head.tracking)
      else SiderealAsterismTracking(sidereals.map(_.tracking))
    }

  def constant(coordinates: Coordinates): ObjectTracking =
    ConstantTracking(coordinates)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy