content: {-# OPTIONS_GHC -Wall #-}
  {-# LANGUAGE Safe #-}
  
  {- | 
  Module      :  Physics.Learn.CoordinateSystem
  Copyright   :  (c) Scott N. Walck 2012-2018
  License     :  BSD3 (see LICENSE)
  Maintainer  :  Scott N. Walck <walck@lvc.edu>
  Stability   :  experimental
  
  A module for working with coordinate systems.
  -}
  
  module Physics.Learn.CoordinateSystem
      ( CoordinateSystem(..)
      , standardCartesian
      , standardCylindrical
      , standardSpherical
      , newCoordinateSystem
      )
      where
  
  import Physics.Learn.Position
      ( Position
      , cartesian
      , cartesianCoordinates
      , cylindrical
      , cylindricalCoordinates
      , spherical
      , sphericalCoordinates
      )
  
  -- | Specification of a coordinate system requires
  --   a map from coordinates into space, and
  --   a map from space into coordinates.
  data CoordinateSystem
      = CoordinateSystem { toPosition   :: (Double,Double,Double) -> Position  -- ^ a map from coordinates into space
                         , fromPosition :: Position -> (Double,Double,Double)  -- ^ a map from space into coordinates
                         }
  
  -- | The standard Cartesian coordinate system
  standardCartesian :: CoordinateSystem
  standardCartesian = CoordinateSystem cartesian cartesianCoordinates
  
  -- | The standard cylindrical coordinate system
  standardCylindrical :: CoordinateSystem
  standardCylindrical = CoordinateSystem cylindrical cylindricalCoordinates
  
  -- | The standard spherical coordinate system
  standardSpherical :: CoordinateSystem
  standardSpherical = CoordinateSystem spherical sphericalCoordinates
  
  -- | Define a new coordinate system in terms of an existing one.
  --   First parameter is a map from old coordinates to new coordinates.
  --   Second parameter is the inverse map from new coordinates to old coordinates.
  newCoordinateSystem :: ((Double,Double,Double) -> (Double,Double,Double))  -- ^ (x',y',z') = f(x,y,z)
                      -> ((Double,Double,Double) -> (Double,Double,Double))  -- ^ (x,y,z) = g(x',y',z')
                      -> CoordinateSystem  -- ^ old coordinate system
                      -> CoordinateSystem
  newCoordinateSystem f g (CoordinateSystem tp fp)
      = CoordinateSystem (tp . g) (f . fp)
  