chaotic3quilibrium icon

Leveraging squants library for Geospatial methods

chaotic3quilibrium | PRO | 11/20/15 10:22:31 PM UTC | 0 ⭐ | 6738 👁️ | Never ⏰ | []
Scala |

3.35 KB

|

None

|

0 👍

/

0 👎

import squants.space.{Radians, Meters}
import squants.{Angle, Length}
 
object Geospatial {
  case class Longitude(angle: Angle) {
    require(
      (Radians(-Math.PI) <= angle) && (angle < Radians(Math.PI)),
      "angle.inRadians must be greater than or equal to -Math.PI and less than Math.PI"
    )
  }
  case class Latitude(angle: Angle) {
    require(
      (Radians(-(Math.PI * 0.5d)) <= angle) && (angle < Radians(Math.PI * 0.5d)),
      "angle.inRadians must be greater than or equal to -(Math.PI * 0.5d) and less than (Math.PI * 0.5d)"
    )
  }
  case class Distance(length: Length) {
    require(
      Meters(0.0d) <= length,
      "length.inMeters must be greater than or equal to 0.0d"
    )
  }
  case class Bearing(angle: Angle) {
    require(
      (Radians(0.0d) <= angle) && (angle < Radians(Math.PI * 2.0d)),
      "angle.inRadians must be greater than or equal to 0.0d and less than (Math.PI * 2.0d)"
    )
  }
 
  case class Coordinate(longitude: Longitude, latitude: Latitude)
 
  def calculateDistance(
    coordinate1: Coordinate,
    coordinate2: Coordinate
  ): (Distance, Bearing, Bearing) = {
    def calculateDistanceUsingLegacyCodeRifeWithDoubles(
      coordinate1LongitudeInRadians: Double,
      coordinate1LatitudeInRadians: Double,
      coordinate2LongitudeInRadians: Double,
      coordinate2LatitudeInRadians: Double
    ): (Double, Double, Double) = {
      //Legacy code encapsulated here only works with meters and radians
      //returns (distance, initial bearing, final bearing)
      (1.0d, 1.0d, 2.0d) //TODO: replace with real calculation results
    }
    val (coordinate1InRadians, coordinate2InRadians) = (
      (coordinate1.longitude.angle.toRadians, coordinate1.latitude.angle.toRadians),
      (coordinate2.longitude.angle.toRadians, coordinate2.latitude.angle.toRadians)
    )
    val (distanceInMeters, bearingInitialInRadians, bearingFinalInRadians) =
      calculateDistanceUsingLegacyCodeRifeWithDoubles(
        coordinate1InRadians._1,
        coordinate1InRadians._2,
        coordinate2InRadians._1,
        coordinate2InRadians._2
      )
    (
      Distance(Meters(distanceInMeters)),
      Bearing(Radians(bearingInitialInRadians)),
      Bearing(Radians(bearingFinalInRadians))
    )
  }
 
  def calculateCoordinate(
    coordinate1: Coordinate,
    bearingInitial: Bearing,
    distance: Distance
  ): Coordinate = {
    def calculateCoordinateUsingLegacyCodeRifeWithDoubles(
      coordinate1Longitude: Double,
      coordinate1Latitude: Double,
      bearingInitialInRadians: Double,
      distanceInMeters: Double
    ): (Double, Double) = {
      //Legacy code encapsulated here only works with meters and radians
      //returns (longitude, latitude)
      (-1.0d, 1.0d) //TODO: replace with real calculation results
    }
    val (coordinate1InRadians, bearingInitialInRadians, distanceInMeters) = (
      (coordinate1.longitude.angle.toRadians, coordinate1.latitude.angle.toRadians),
      bearingInitial.angle.toRadians,
      distance.length.toMeters
    )
    val (longitude, latitude) =
      calculateCoordinateUsingLegacyCodeRifeWithDoubles(
        coordinate1InRadians._1,
        coordinate1InRadians._2,
        bearingInitialInRadians,
        distanceInMeters
      )
    Coordinate(Longitude(Radians(longitude)), Latitude(Radians(latitude)))
  }
}

Comments