module Diagrams.ThreeD.Types
(
R3(..), r3, unr3, mkR3
, P3, p3, unp3, mkP3
, T3
, r3Iso, p3Iso
, Direction, direction, fromDirection, angleBetweenDirs
, Spherical(..), Cylindrical(..), HasPhi(..)
) where
import Control.Lens (Iso', Lens', iso, over
, _1, _2, _3, (^.))
import Diagrams.Core
import Diagrams.Angle
import Diagrams.TwoD.Types (R2)
import Diagrams.Coordinates
import Data.AffineSpace.Point
import Data.Basis
import Data.Cross
import Data.VectorSpace
data R3 = R3 !Double !Double !Double
deriving (Eq, Ord, Show, Read)
r3Iso :: Iso' R3 (Double, Double, Double)
r3Iso = iso unr3 r3
r3 :: (Double, Double, Double) -> R3
r3 (x,y,z) = R3 x y z
mkR3 :: Double -> Double -> Double -> R3
mkR3 = R3
unr3 :: R3 -> (Double, Double, Double)
unr3 (R3 x y z) = (x,y,z)
instance AdditiveGroup R3 where
zeroV = R3 0 0 0
R3 x1 y1 z1 ^+^ R3 x2 y2 z2 = R3 (x1 + x2) (y1 + y2) (z1 + z2)
negateV (R3 x y z) = R3 (x) (y) (z)
type instance V R3 = R3
instance VectorSpace R3 where
type Scalar R3 = Double
(*^) = over r3Iso . (*^)
instance HasBasis R3 where
type Basis R3 = Either () (Either () ())
basisValue = r3 . basisValue
decompose = decompose . unr3
decompose' = decompose' . unr3
instance InnerSpace R3 where
(R3 x1 y1 z1) <.> (R3 x2 y2 z2) = x1*x2 + y1*y2 + z1*z2
instance Coordinates R3 where
type FinalCoord R3 = Double
type PrevDim R3 = R2
type Decomposition R3 = Double :& Double :& Double
(coords -> x :& y) ^& z = R3 x y z
coords (R3 x y z) = x :& y :& z
type P3 = Point R3
p3 :: (Double, Double, Double) -> P3
p3 = P . r3
unp3 :: P3 -> (Double, Double, Double)
unp3 = unr3 . unPoint
p3Iso :: Iso' P3 (Double, Double, Double)
p3Iso = iso unp3 p3
mkP3 :: Double -> Double -> Double -> P3
mkP3 x y z = p3 (x, y, z)
type T3 = Transformation R3
instance Transformable R3 where
transform = apply
instance HasCross3 R3 where
cross3 u v = r3 $ cross3 (unr3 u) (unr3 v)
data Direction = Direction R3
_Dir :: Iso' Direction R3
_Dir = iso (\(Direction v) -> v) Direction
instance HasX R3 where
_x = r3Iso . _1
instance HasX P3 where
_x = p3Iso . _1
instance HasY R3 where
_y = r3Iso . _2
instance HasY P3 where
_y = p3Iso . _2
instance HasZ R3 where
_z = r3Iso . _3
instance HasZ P3 where
_z = p3Iso . _3
class Spherical t where
spherical :: Iso' t (Double, Angle, Angle)
class Cylindrical t where
cylindrical :: Iso' t (Double, Angle, Double)
instance Cylindrical R3 where
cylindrical = iso (\(R3 x y z) -> (sqrt (x^(2::Int)+y^(2::Int)), atanA (y/x), z))
(\(r,θ,z) -> R3 (r*cosA θ) (r*sinA θ) z)
instance Spherical R3 where
spherical = iso
(\v@(R3 x y z) -> (magnitude v, atanA (y/x), atanA (v^._r/z)))
(\(r,θ,φ) -> R3 (r*cosA θ*sinA φ) (r*sinA θ*sinA φ) (r*cosA φ))
instance HasR R3 where
_r = spherical . _1
instance HasR P3 where
_r = spherical . _1
instance HasTheta R3 where
_theta = cylindrical . _2
instance HasTheta P3 where
_theta = cylindrical . _2
class HasPhi t where
_phi :: Lens' t Angle
instance HasPhi R3 where
_phi = spherical . _3
instance HasPhi P3 where
_phi = spherical . _3
instance Cylindrical P3 where
cylindrical = _relative origin . cylindrical
instance Spherical P3 where
spherical = _relative origin . spherical
instance HasTheta Direction where
_theta = _Dir . _theta
instance HasPhi Direction where
_phi = _Dir . _phi
direction :: R3 -> Direction
direction = Direction
fromDirection :: Direction -> R3
fromDirection (Direction v) = normalized v
angleBetweenDirs :: Direction -> Direction -> Angle
angleBetweenDirs d1 d2 = angleBetween (fromDirection d1) (fromDirection d2)