packages feed

Cartesian 0.1.0.1 → 0.2.0.0

raw patch · 16 files changed

+771/−485 lines, 16 filesdep +template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: template-haskell

API changes (from Hackage documentation)

- Cartesian.Lenses: centre :: Lens' (BoundingBox f_a79V) (Complex f_a79V)
- Cartesian.Lenses: size :: Lens' (BoundingBox f_a79V) (Complex f_a79V)
- Cartesian.Plane.BoundingBox: fromCornerAndSize :: RealFloat f => Complex f -> Complex f -> BoundingBox f
- Cartesian.Plane.BoundingBox: fromCorners :: RealFloat f => Complex f -> Complex f -> BoundingBox f
- Cartesian.Plane.BoundingBox: fromSides :: RealFloat f => f -> f -> f -> f -> BoundingBox f
- Cartesian.Plane.BoundingBox: intersect :: (RealFloat f, Ord f) => BoundingBox f -> BoundingBox f -> Maybe (BoundingBox f)
- Cartesian.Plane.BoundingBox.Lenses: bottom :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: bottompad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: centre :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
- Cartesian.Plane.BoundingBox.Lenses: left :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: leftpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: makeBoundingBoxSideLens :: RealFloat f => (BoundingBox f -> f) -> (BoundingBox f -> f -> (f, f, f, f)) -> Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: right :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: rightpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: size :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
- Cartesian.Plane.BoundingBox.Lenses: top :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.BoundingBox.Lenses: toppad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
- Cartesian.Plane.Utilities: dotmap :: (a -> b) -> Complex a -> Complex b
- Cartesian.Plane.Utilities: dotwise :: (a -> a -> b) -> Complex a -> Complex a -> Complex b
- Cartesian.Plane.Utilities: flipx :: Complex Double -> Complex Double
- Cartesian.Plane.Utilities: flipy :: Complex Double -> Complex Double
- Cartesian.Plane.Utilities: imag :: Double -> Complex Double
- Cartesian.Plane.Utilities: real :: Double -> Complex Double
- Cartesian.Space: Line :: (Vector num) -> (Vector num) -> Line num
- Cartesian.Space: Vector :: num -> num -> num -> Vector num
- Cartesian.Space: coefficients :: (Fractional a, Eq a) => Line a -> Maybe (a, a)
- Cartesian.Space: data Line num
- Cartesian.Space: data Vector num
- Cartesian.Space: dot :: Floating a => Vector a -> Vector a -> a
- Cartesian.Space: dotwise :: (a -> b -> c) -> Vector a -> Vector b -> Vector c
- Cartesian.Space: euclidean :: Floating a => Vector a -> Vector a -> a
- Cartesian.Space: instance (GHC.Float.Floating a, GHC.Classes.Eq a) => GHC.Num.Num (Cartesian.Space.Vector a)
- Cartesian.Space: intersect :: Num a => Line a -> Line a -> Maybe (Vector a)
- Cartesian.Space: intersects :: Num a => Line a -> Line a -> Bool
- Cartesian.Space: mag :: (Floating a, Eq a) => Vector a -> a
- Cartesian.Space: magnitude :: (Floating a, Eq a) => Vector a -> a
- Cartesian.Space: overlap :: Real a => (a, a) -> (a, a) -> Maybe (a, a)
- Cartesian.Space: vector :: Num a => a -> a -> a -> Vector a
+ Cartesian.Plane.Lenses: bottom :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: bottompad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: centre :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
+ Cartesian.Plane.Lenses: left :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: leftpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: makeBoundingBoxSideLens :: RealFloat f => (BoundingBox f -> f) -> (BoundingBox f -> f -> (f, f, f, f)) -> Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: right :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: rightpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: size :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
+ Cartesian.Plane.Lenses: top :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Plane.Lenses: toppad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+ Cartesian.Space.Types: Line :: (Vector3D f) -> (Vector3D f) -> Line f
+ Cartesian.Space.Types: Vector3D :: f -> f -> f -> Vector3D f
+ Cartesian.Space.Types: data Line f
+ Cartesian.Space.Types: data Vector3D f
+ Cartesian.Space.Types: instance (GHC.Float.Floating v, GHC.Classes.Eq v) => GHC.Num.Num (Cartesian.Space.Types.Vector3D v)
+ Cartesian.Space.Types: instance Cartesian.Internal.Types.HasX (Cartesian.Space.Types.Vector3D f) f
+ Cartesian.Space.Types: instance Cartesian.Internal.Types.HasY (Cartesian.Space.Types.Vector3D f) f
+ Cartesian.Space.Types: instance Cartesian.Internal.Types.HasZ (Cartesian.Space.Types.Vector3D f) f
+ Cartesian.Space.Types: instance Cartesian.Internal.Types.Vector Cartesian.Space.Types.Vector3D

Files

Cartesian.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.1.0.1
+version:             0.2.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            Coordinate systems
@@ -48,18 +48,21 @@ 
 library
   -- Modules exported by the library.
-  exposed-modules:     Cartesian.Lenses, Cartesian.Plane, Cartesian.Space,
-                       Cartesian.Plane.Utilities, Cartesian.Plane.Types, Cartesian.Plane.BoundingBox, Cartesian.Plane.BoundingBox.Lenses
+  exposed-modules:     Cartesian.Plane,       Cartesian.Space, Cartesian.Types,
+                       Cartesian.Plane.Types, Cartesian.Plane.Lenses,
+                       Cartesian.Space.Types, Cartesian.Space.Lenses
 
   -- Modules included in this library but not exported.
-  -- other-modules:
 
+  other-modules:       Cartesian.Internal.Types, Cartesian.Internal.Lenses, Cartesian.Internal.Core, Cartesian.Internal.Utils
+
   -- LANGUAGE extensions used by modules in this package.
   other-extensions:    TemplateHaskell, RankNTypes
 
   -- Other library packages from which modules are imported.
   build-depends:       base <= 4.8.1.0,
-                       lens <= 4.13.0.0
+                       lens <= 4.13.0.0,
+                       template-haskell
 
   -- Directories containing source files.
   hs-source-dirs:      src
README.md view
@@ -1,4 +1,15 @@ Cartesian
 =========
+Functions and types for working with three-dimensional coordinate systems.
 
-Functions and types for working with three-dimensional coordinate systems+For now, all functions assume a coordinate system where right is +X, up is +Y and forwards is +Z.
+
+Contributors
+------------
+Jonatan H Sundqvist
+
+
+TODO
+----
+- Use typeclass for Vectors (would save a lot of boilerplate)
+- Allow functions to operate on any Vector-like type (including eg. Complex)
+ src/Cartesian/Internal/Core.hs view
@@ -0,0 +1,144 @@+-- |
+-- Module      : Cartesian.Internal.Core
+-- Description : Defines basic functionality that is shared between Plane and Space
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 31 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Internal.Core (module Cartesian.Internal.Core,
+                                module Cartesian.Internal.Types) where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Data.List    (sort)
+import Control.Lens ((%~))
+
+import Cartesian.Internal.Types
+import Cartesian.Internal.Lenses
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Functions
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- | Finds the overlap between two ranges (lower bound, upper bound).
+overlap :: (Ord n) => (n, n) -> (n, n) -> Maybe (n, n)
+overlap (a, b) (c, d)
+  | min (a, b) (c, d) /= (a', b') = Just (b', c')
+  | otherwise                     = Nothing
+  where [a', b', c', d'] = sort [a, b, c, d]
+
+-- Vectors ---------------------------------------------------------------------------------------------------------------------------------
+
+-- | Applies a function to each component in a vector
+dotmap :: Vector v => (a -> b) -> v a -> v b
+dotmap f v = vzip (const . f) v v
+
+
+-- | Performs component-wise operations
+dotwise :: Vector v => (a -> b -> c) -> v a -> v b -> v c
+dotwise = vzip -- Hmmm. Dotwise isn't really a fold is it?
+
+
+-- | Dot product of two vectors
+dot :: (Vector v, Floating f) => v f -> v f -> f
+dot a b = vfold (+) 0 $ dotwise (*) a b
+-- dot (Vector x y z) (Vector x' y' z') = (x * x') + (y * y') + (z * z') -- TODO: Refactor with Num instance (?)
+
+
+-- | Euclidean distance between two points
+euclidean :: (Vector v, Floating f) => v f -> v f -> f
+euclidean a b = sqrt $ dot a b
+
+
+-- |
+magnitude :: (Vector v, Floating f) => v f -> f
+magnitude v = euclidean v v
+
+mag :: (Vector v, Floating f) => v f -> f
+mag = magnitude
+
+
+-- | Angle (in radians) between the positive X-axis and the vector
+-- argument :: (Floating a, Eq a) => Vector a -> a
+-- argument (Vector 0 0 0) = 0
+-- argument (Vector x y z) = atan $ y/x
+
+
+-- arg :: (Floating a, Eq a) => Vector a -> a
+-- arg = argument
+
+
+-- | Vector -> (magnitude, argument)
+-- polar :: (Floating a, Eq a) => Vector a -> (a, a)
+-- polar v@(Vector x y) = (magnitude v, argument v)
+
+
+
+-- | Intersect
+-- TODO: Math notes, MathJax or LaTex
+-- TODO: Intersect for curves (functions) and single points (?)
+-- TODO: Polymorphic, typeclass (lines, shapes, ranges, etc.) (?)
+-- intersect :: Num a => Line a -> Line a -> Maybe (Vector a)
+-- intersect _ _ = error "Not implemented" -- Nothing
+--
+--
+-- -- |
+-- intersects :: Num a => Line a -> Line a -> Bool
+-- intersects a b = case intersect a b of
+-- 	Just _  -> True
+-- 	Nothing -> False
+--
+--
+-- -- | Yields the overlap of two closed intervals (n ∈ R)
+-- -- TODO: Normalise intervals (eg. (12, 5) -> (5, 12))
+-- overlap :: Real a => (a, a) -> (a, a) -> Maybe (a, a)
+-- overlap a b
+-- 	| leftmost /= (α, β) = Just $ (β, γ) --
+-- 	| otherwise                                  = Nothing --
+-- 	where [α, β, γ, _] = sort [fst a, snd a, fst b, snd b] -- That's right.
+-- 	      leftmost     = minimumBy (comparing fst) [a, b]  --
+--
+--
+-- -- |
+-- -- TODO: Intersect Rectangles
+--
+--
+--
+-- -- | Coefficients for the linear function of a Line (slope, intercept). The Z-component is ignored.
+-- -- Fails for vertical and horizontal lines.
+-- --
+-- -- TODO: Use Maybe (?)
+-- --
+-- coefficients :: (Fractional a, Eq a) => Line a -> Maybe (a, a)
+-- coefficients (Line (Vector ax ay _) (Vector bx by _))
+-- 	| ax == bx  = Nothing
+-- 	| ay == ay  = Nothing
+-- 	| otherwise = let slope = (by - ay)/(bx - ax) in Just (slope, ay - slope*ax)
+ src/Cartesian/Internal/Lenses.hs view
@@ -0,0 +1,145 @@+-- |
+-- Module      : Cartesian.Internal.Lenses
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 31 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE RankNTypes            #-}
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Internal.Lenses where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Data.List     (isSuffixOf)
+import Control.Monad (mfilter)
+import Control.Lens
+
+import Language.Haskell.TH
+
+import Cartesian.Internal.Types
+import Cartesian.Internal.Utils
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Lenses
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- Vector ----------------------------------------------------------------------------------------------------------------------------------
+
+-- | Focus on the X component
+x :: HasX v f => Lens v v f f
+x = lens getX setX
+
+
+-- | Focus on the Y component
+y :: HasY v f => Lens v v f f
+y = lens getY setY
+
+
+-- | Focus on the Z component
+z :: HasZ v f => Lens v v f f
+z = lens getZ setZ
+
+-- BoundingBox -----------------------------------------------------------------------------------------------------------------------------
+
+-- TODO: Relative lenses (eg. padding)
+-- TODO: Validate (eg. make sure that left < right)
+-- TODO: Type-changing lenses (?)
+
+
+-- | Ugh...
+makeLensesWith (lensRules & lensField .~ (\_ _ name -> [TopName (mkName $ dropSuffix "Of" (nameBase name))])) (''BoundingBox) -- TODO: 'Of'
+
+
+-- |
+-- TODO: Rename (?)
+offset :: (Fractional f) => (Getter v f) -> (f -> f -> f) -> BoundingBox v -> f
+offset axis towards box = towards (box^.centre.axis) (0.5 * box^.size.axis)
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+-- pad :: f -> (Getter v f) -> f -> BoundingBox v
+-- pad by axis direction = _
+
+
+-- | Moves one side of a BoundingBox along the given 'axis' so that its new position is at 'to'. The 'towards' parameter is expected to be
+--   either (-) and (+), indicating which side along the axis we're dealing with.
+-- TODO: Turn this into a lens function (?)
+-- TODO: Polish description
+-- TODO: Loosen constraint on f
+side :: (Fractional f) => Lens v v f f -> (f -> f -> f) -> Lens (BoundingBox v) (BoundingBox v) f f
+side axis towards = lens get set
+  where
+    get = offset axis towards
+    set box to = let newsize = abs (to - towards centre' (-(box^.size.axis)*0.5))
+                     centre' = box^.centre.axis --
+                 in BoundingBox { sizeOf=(box^.size) & axis .~ newsize, centreOf=(box^.centre) & axis .~ (to `towards` negate (newsize*0.5)) } -- TODO: Refactor. And then refactor some more.
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+width :: (HasX v f) => Lens (BoundingBox v) (BoundingBox v) f f
+width = size.x
+
+
+height :: (HasY v f) => Lens (BoundingBox v) (BoundingBox v) f f
+height = size.y
+
+
+depth :: (HasZ v f) => Lens (BoundingBox v) (BoundingBox v) f f
+depth = size.z
+
+-- So much boilerplate it makes me cry -----------------------------------------------------------------------------------------------------
+
+-- type SideLens = (Fractional f, HasX v f) => Lens (BoundingBox v) (BoundingBox v) f f
+
+left :: (Fractional f, HasX v f) => Lens (BoundingBox v) (BoundingBox v) f f
+left = side x (-)
+
+
+right :: (Fractional f, HasX v f) => Lens (BoundingBox v) (BoundingBox v) f f
+right = side x (+)
+
+
+bottom :: (Fractional f, HasY v f) => Lens (BoundingBox v) (BoundingBox v) f f
+bottom = side y (-)
+
+
+top :: (Fractional f, HasY v f) => Lens (BoundingBox v) (BoundingBox v) f f
+top = side y (+)
+
+
+front :: (Fractional f, HasZ v f) => Lens (BoundingBox v) (BoundingBox v) f f
+front = side z (-)
+
+
+back :: (Fractional f, HasZ v f) => Lens (BoundingBox v) (BoundingBox v) f f
+back = side z (+)
+ src/Cartesian/Internal/Types.hs view
@@ -0,0 +1,81 @@+-- |
+-- Module      : Cartesian.Internal.Types
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 31 2015
+
+-- TODO | - Use TemplateHaskell (?)
+--        - Strictness
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+{-# LANGUAGE TemplateHaskell        #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE FunctionalDependencies #-}
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Internal.Types where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Types
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- Types -----------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+-- TODO: Anchors (eg. C, N, S, E W and combinations thereof, perhaps represented as relative Vectors)
+data BoundingBox v = BoundingBox { centreOf :: v, sizeOf :: v }
+
+-- Classes ---------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+-- TODO: Use GADT instead (?)
+-- TODO: Reduce boilerplate, figure out deriving, choose interface carefully
+class Vector v where
+  vfold :: (f' -> f  -> f')  -> f'  -> v f  -> f'
+  vzip  :: (f  -> f' -> f'') -> v f -> v f' -> v f''
+
+
+-- |
+class HasX a f | a -> f where
+  getX :: a -> f
+  setX :: a -> f -> a
+
+
+-- |
+class HasY a f | a -> f where
+  getY :: a -> f
+  setY :: a -> f -> a
+
+
+-- |
+class HasZ a f | a -> f where
+  getZ :: a -> f
+  setZ :: a -> f -> a
+
+-- Instances -------------------------------------------------------------------------------------------------------------------------------
+ src/Cartesian/Internal/Utils.hs view
@@ -0,0 +1,51 @@+-- |
+-- Module      : Cartesian.Internal.Utils
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created November 2 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Internal.Utils where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Data.List     (isSuffixOf)
+import Control.Monad (mfilter)
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Functions
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- | Removes the given suffix if it exists, does nothing otherwise
+-- TODO: Move to utils module or use existing implementation
+-- TODO: Refactor
+dropSuffix :: (Eq a) => [a] -> [a] -> [a]
+dropSuffix su xs = maybe xs (take (length xs - length su)) $ mfilter (su `isSuffixOf`) (Just xs)
− src/Cartesian/Lenses.hs
@@ -1,59 +0,0 @@--- |
--- Module      : Cartesian.Lenses
--- Description :
--- Copyright   : (c) Jonatan H Sundqvist, 2015
--- License     : MIT
--- Maintainer  : Jonatan H Sundqvist
--- Stability   : experimental|stable
--- Portability : POSIX (not sure)
---
-
--- Created August 30 2015
-
--- TODO | -
---        -
-
--- SPEC | -
---        -
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- GHC Pragmas
---------------------------------------------------------------------------------------------------------------------------------------------
-{-# LANGUAGE TemplateHaskell #-}
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- API
---------------------------------------------------------------------------------------------------------------------------------------------
-module Cartesian.Lenses where
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- We'll need these
---------------------------------------------------------------------------------------------------------------------------------------------
-import qualified Control.Lens as L
-
-import qualified Cartesian.Plane.Types as Plane
--- import qualified Cartesian.Space.Types as Space
-
--- import qualified Cartesian.Plane as Plane
--- import qualified Cartesian.Space as Space
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Invoke the Templates!
---------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------
-L.makeLenses ''Plane.BoundingBox
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
src/Cartesian/Plane.hs view
@@ -71,9 +71,9 @@ -- TODO: How to treat points that lie on an edge
 inside :: Num n => Polygon n -> Vector n -> Bool
 inside (p:olygon) (Vector x y) = undefined
-	where
-		lines   = (p:olygon)++[p] -- Close the loop
-		-- between (Line (Vector ax ay) (Vector bx by)) = _
+  where
+    lines   = (p:olygon)++[p] -- Close the loop
+    -- between (Line (Vector ax ay) (Vector bx by)) = _
 
 
 
@@ -82,14 +82,14 @@ --------------------------------------------------------------------------------------------------------------------------------------------
 -- | abs v * signum v == v
 instance (Floating a, Eq a) => Num (Vector a) where
-	-- TODO: Helper method to reduce boilerplate for component-wise operations
-	(+) = dotwise (+)
-	(-) = dotwise (-)
-	(*) = dotwise (*) -- TODO: Is this really correct?
-	fromInteger n = Vector (fromInteger n) 0
-	signum (Vector 0 0) = Vector 0 0
-	signum v@(Vector x y) = Vector (x/mag v) (y/mag v)
-	abs a  = Vector (euclidean a a) 0
+  -- TODO: Helper method to reduce boilerplate for component-wise operations
+  (+) = dotwise (+)
+  (-) = dotwise (-)
+  (*) = dotwise (*) -- TODO: Is this really correct?
+  fromInteger n = Vector (fromInteger n) 0
+  signum (Vector 0 0) = Vector 0 0
+  signum v@(Vector x y) = Vector (x/mag v) (y/mag v)
+  abs a  = Vector (euclidean a a) 0
 
 
 
@@ -171,18 +171,18 @@ -- |
 intersects :: RealFrac r => Line r -> Line r -> Bool
 intersects a b = case intersect a b of
-	Just _  -> True
-	Nothing -> False
+  Just _  -> True
+  Nothing -> False
 
 
 -- | Yields the overlap of two closed intervals (n ∈ R)
 -- TODO: Normalise intervals (eg. (12, 5) -> (5, 12))
 overlap :: Real a => (a, a) -> (a, a) -> Maybe (a, a)
 overlap a b
-	| leftmost /= (α, β) = Just (β, γ) --
-	| otherwise          = Nothing     --
-	where [α, β, γ, _] = sort [fst a, snd a, fst b, snd b] -- That's right.
-	      leftmost     = minimumBy (comparing fst) [a, b]  --
+  | leftmost /= (α, β) = Just (β, γ) --
+  | otherwise          = Nothing     --
+  where [α, β, γ, _] = sort [fst a, snd a, fst b, snd b] -- That's right.
+        leftmost     = minimumBy (comparing fst) [a, b]  --
 
 
 -- |
@@ -198,9 +198,9 @@ --
 coefficients :: (Fractional a, Eq a) => Line a -> Maybe (a, a)
 coefficients (Line (Vector ax ay) (Vector bx by))
-	| ax == bx  = Nothing
-	| ay == ay  = Nothing
-	| otherwise = let slope' = (by - ay)/(bx - ax) in Just (slope', ay - slope'*ax)
+  | ax == bx  = Nothing
+  | ay == ay  = Nothing
+  | otherwise = let slope' = (by - ay)/(bx - ax) in Just (slope', ay - slope'*ax)
 
 
 -- Linear functions -------------------------------------------------------------------------------
@@ -208,5 +208,5 @@ -- TODO: Use Epsilon (?)
 solve :: (Fractional n, Eq n) => Linear n -> Linear n -> Maybe n
 solve f g
-	| slope f == slope g = Nothing
-	| otherwise          = Just $ (intercept f - intercept g)/(slope f - slope g)
+  | slope f == slope g = Nothing
+  | otherwise          = Just $ (intercept f - intercept g)/(slope f - slope g)
− src/Cartesian/Plane/BoundingBox.hs
@@ -1,85 +0,0 @@--- |
--- Module      : Cartesian.Plane.BoundingBox
--- Description :
--- Copyright   : (c) Jonatan H Sundqvist, 2015
--- License     : MIT
--- Maintainer  : Jonatan H Sundqvist
--- Stability   : experimental|stable
--- Portability : POSIX (not sure)
---
-
--- Created September 7 2015
-
--- TODO | - Corner lenses
---        -
-
--- SPEC | -
---        -
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- GHC Pragmas
---------------------------------------------------------------------------------------------------------------------------------------------
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- API
---------------------------------------------------------------------------------------------------------------------------------------------
-module Cartesian.Plane.BoundingBox (module Cartesian.Plane.Types,
-                                    module Cartesian.Plane.BoundingBox,
-                                    module Cartesian.Plane.BoundingBox.Lenses) where
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- We'll need these
---------------------------------------------------------------------------------------------------------------------------------------------
-import Data.Complex
-import Data.Functor ((<$>))
-import Data.List (sort)
-
-import Control.Lens
-
-import Cartesian.Plane.Types
-import Cartesian.Plane.BoundingBox.Lenses
-import Cartesian.Plane.Utilities
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Functions
---------------------------------------------------------------------------------------------------------------------------------------------
-
--- Convenience constructors ----------------------------------------------------------------------------------------------------------------
-
--- |
--- TODO: Better name (?)
--- TODO: Don't make assumptions about WHICH corners they are (✓)
-fromCorners :: RealFloat f => Complex f -> Complex f -> BoundingBox f
-fromCorners nw@(n:+w) se@(s:+e) = let size = dotmap abs (se-nw) in BoundingBox { _centre=dotwise min nw se+size*(0.5:+0.0), _size=size }
-
-
--- | Creates a bounding box from a topleft and size vector.
-fromCornerAndSize :: RealFloat f => Complex f -> Complex f -> BoundingBox f
-fromCornerAndSize nw size' = BoundingBox { _centre=nw+size'*0.5, _size=size' }
-
-
--- | Top Left Bottom Right
-fromSides :: RealFloat f => f -> f -> f -> f -> BoundingBox f
-fromSides top left bottom right = fromCorners (left:+top) (right:+bottom)
-
--- Booleans --------------------------------------------------------------------------------------------------------------------------------
-
--- |
-intersect :: (RealFloat f, Ord f) => BoundingBox f -> BoundingBox f -> Maybe (BoundingBox f)
-intersect a b = do
-  (left', right')  <- overlap (a^.left, a^.right)  (b^.left, b^.right)
-  (top',  bottom') <- overlap (a^.top,  a^.bottom) (b^.top,  b^.bottom)
-  return $ fromSides top' left' bottom' right'
-  where
-    overlap (a, b) (c, d)
-      | min (a, b) (c, d) == (a', b') = Just (b', c')
-      | otherwise                     = Nothing
-      where [a', b', c', d'] = sort [a, b, c, d]
− src/Cartesian/Plane/BoundingBox/Lenses.hs
@@ -1,128 +0,0 @@--- |
--- Module      : Cartesian.BoundingBox.Lenses
--- Description :
--- Copyright   : (c) Jonatan H Sundqvist, 2015
--- License     : MIT
--- Maintainer  : Jonatan H Sundqvist
--- Stability   : experimental|stable
--- Portability : POSIX (not sure)
---
-
--- Created October 21 2015
-
--- TODO | -
---        -
-
--- SPEC | -
---        -
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- GHC Pragmas
---------------------------------------------------------------------------------------------------------------------------------------------
-{-# LANGUAGE RankNTypes #-}
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- API
---------------------------------------------------------------------------------------------------------------------------------------------
-module Cartesian.Plane.BoundingBox.Lenses where
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- We'll need these
---------------------------------------------------------------------------------------------------------------------------------------------
-import Data.Complex (Complex ((:+)))
-import Data.Functor ((<$>))
-import Control.Lens
-
-import Cartesian.Plane.Types
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Lenses
---------------------------------------------------------------------------------------------------------------------------------------------
-
-
--- |
--- TODO: Make sure invariants remain true (eg. left < right)
--- TODO: Make coordinate-system independent (eg. direction of axes)
-makeBoundingBoxSideLens :: RealFloat f => (BoundingBox f -> f) -> (BoundingBox f -> f -> (f, f, f, f)) -> Lens (BoundingBox f) (BoundingBox f) f f
-makeBoundingBoxSideLens oldside newsides f s@(BoundingBox { _centre=(cx:+cy), _size=(dx:+dy) }) = assemble <$> f (oldside s)
-  where
-    assemble newside = let (nleft, nright, ntop, nbottom) = newsides s newside
-                           newsize                        = (nright-nleft):+(nbottom-ntop)
-                       in BoundingBox { _centre=(nleft:+ntop)+(newsize*(0.5:+0.0)), _size=newsize }
-
--- Core lenses -----------------------------------------------------------------------------------------------------------------------------
-
--- |
-centre :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
-centre f s = let assemble new = s { _centre=new } in assemble <$> f (_centre s)
-
-
--- |
-size :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
-size f s = let assemble new = s { _size=new } in assemble <$> f (_size s)
-
--- Side lenses (absolute) ------------------------------------------------------------------------------------------------------------------
-
--- |
-left :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-left = makeBoundingBoxSideLens
-         (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  }) -> cx - dx/2)
-         (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (newside, cx+dx/2, cy-dy/2, cy+dy/2))
-
-
--- |
-right :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-right = makeBoundingBoxSideLens
-          (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  })         -> cx + dx/2)
-          (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, newside, cy-dy/2, cy+dy/2))
-
-
--- |
-top :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-top = makeBoundingBoxSideLens
-        (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy - dy/2)
-        (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, newside, cy+dy/2))
-
-
--- |
-bottom :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-bottom = makeBoundingBoxSideLens
-           (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy + dy/2)
-           (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2, newside))
-
--- Side lenses (relative) ------------------------------------------------------------------------------------------------------------------
-
--- |
-leftpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-leftpad = makeBoundingBoxSideLens
-            (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  }) -> cx - dx/2)
-            (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2+newside, cx+dx/2, cy-dy/2, cy+dy/2))
-
-
--- |
-rightpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-rightpad = makeBoundingBoxSideLens
-             (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  })         -> cx + dx/2)
-             (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2+newside, cy-dy/2, cy+dy/2))
-
-
--- |
-toppad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-toppad = makeBoundingBoxSideLens
-          (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy - dy/2)
-          (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2+newside, cy+dy/2))
-
-
--- |
-bottompad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
-bottompad = makeBoundingBoxSideLens
-              (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy + dy/2)
-              (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2, cy+dy/2+newside))
+ src/Cartesian/Plane/Lenses.hs view
@@ -0,0 +1,127 @@+-- |
+-- Module      : Cartesian.Plane.Lenses
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 21 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+{-# LANGUAGE RankNTypes #-}
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Plane.Lenses where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Data.Complex
+import Data.Functor ((<$>))
+import Control.Lens
+
+import Cartesian.Plane.Types
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Lenses
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+-- TODO: Make sure invariants remain true (eg. left < right)
+-- TODO: Make coordinate-system independent (eg. direction of axes)
+makeBoundingBoxSideLens :: RealFloat f => (BoundingBox f -> f) -> (BoundingBox f -> f -> (f, f, f, f)) -> Lens (BoundingBox f) (BoundingBox f) f f
+makeBoundingBoxSideLens oldside newsides f s@(BoundingBox { _centre=(cx:+cy), _size=(dx:+dy) }) = assemble <$> f (oldside s)
+  where
+    assemble newside = let (nleft, nright, ntop, nbottom) = newsides s newside
+                           newsize                        = (nright-nleft):+(nbottom-ntop)
+                       in BoundingBox { _centre=(nleft:+ntop)+(newsize*(0.5:+0.0)), _size=newsize }
+
+-- Core lenses -----------------------------------------------------------------------------------------------------------------------------
+
+-- |
+centre :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
+centre f s = let assemble new = s { _centre=new } in assemble <$> f (_centre s)
+
+
+-- |
+size :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) (Complex f) (Complex f)
+size f s = let assemble new = s { _size=new } in assemble <$> f (_size s)
+
+-- Side lenses (absolute) ------------------------------------------------------------------------------------------------------------------
+
+-- |
+left :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+left = makeBoundingBoxSideLens
+         (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  }) -> cx - dx/2)
+         (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (newside, cx+dx/2, cy-dy/2, cy+dy/2))
+
+
+-- |
+right :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+right = makeBoundingBoxSideLens
+          (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  })         -> cx + dx/2)
+          (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, newside, cy-dy/2, cy+dy/2))
+
+
+-- |
+top :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+top = makeBoundingBoxSideLens
+        (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy - dy/2)
+        (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, newside, cy+dy/2))
+
+
+-- |
+bottom :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+bottom = makeBoundingBoxSideLens
+           (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy + dy/2)
+           (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2, newside))
+
+-- Side lenses (relative) ------------------------------------------------------------------------------------------------------------------
+
+-- |
+leftpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+leftpad = makeBoundingBoxSideLens
+            (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  }) -> cx - dx/2)
+            (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2+newside, cx+dx/2, cy-dy/2, cy+dy/2))
+
+
+-- |
+rightpad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+rightpad = makeBoundingBoxSideLens
+             (\(BoundingBox { _centre=cx:+_,  _size=dx:+_  })         -> cx + dx/2)
+             (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2+newside, cy-dy/2, cy+dy/2))
+
+
+-- |
+toppad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+toppad = makeBoundingBoxSideLens
+          (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy - dy/2)
+          (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2+newside, cy+dy/2))
+
+
+-- |
+bottompad :: RealFloat f => Lens (BoundingBox f) (BoundingBox f) f f
+bottompad = makeBoundingBoxSideLens
+              (\(BoundingBox { _centre=_:+cy,  _size=_:+dy  }) -> cy + dy/2)
+              (\(BoundingBox { _centre=cx:+cy, _size=dx:+dy }) newside -> (cx-dx/2, cx+dx/2, cy-dy/2, cy+dy/2+newside))
− src/Cartesian/Plane/Utilities.hs
@@ -1,71 +0,0 @@--- |
--- Module      : Cartesian.Plane.Utilities
--- Description :
--- Copyright   : (c) Jonatan H Sundqvist, 2015
--- License     : MIT
--- Maintainer  : Jonatan H Sundqvist
--- Stability   : experimental|stable
--- Portability : POSIX (not sure)
---
-
--- Created September 8 2015
-
--- TODO | - Uses lenses for Complex type (?)
---        -
-
--- SPEC | -
---        -
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- GHC Pragmas
---------------------------------------------------------------------------------------------------------------------------------------------
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- API
---------------------------------------------------------------------------------------------------------------------------------------------
-module Cartesian.Plane.Utilities where
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- We'll need these
---------------------------------------------------------------------------------------------------------------------------------------------
-import Data.Complex
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Functions
---------------------------------------------------------------------------------------------------------------------------------------------
--- | Applies a function to each component in a vector
-dotmap :: (a -> b) -> Complex a -> Complex b
-dotmap f (re:+im) = f re :+ f im
-
-
--- |
-dotwise :: (a -> a -> b) -> Complex a -> Complex a -> Complex b
-dotwise f (re:+im) (re':+im') = f re re':+ f im im'
-
-
--- | Negates the real component (X)
-flipx :: Complex Double -> Complex Double
-flipx (x:+y) = (-x):+y
-
-
--- | Negates the imaginary component (Y)
-flipy :: Complex Double -> Complex Double
-flipy (x:+y) = x:+(-y)
-
-
--- | Creates a number on the real line (where the imaginary part is 0)
-real :: Double -> Complex Double
-real = (:+ 0)
-
-
--- | Creates a number on the imaginary line (where the real part is 0)
-imag :: Double -> Complex Double
-imag = (0 :+)
src/Cartesian/Space.hs view
@@ -19,6 +19,7 @@ -- TODO | - Haddock header, sections, full coverage
 --        - Separate 2D and 3D modules (✓)
 --        - Factor out common functionality for Space.hs and Plane.hs
+--        - Use existing vector type (eg. Linear.V3)
 
 -- SPEC | -
 --        -
@@ -35,123 +36,10 @@ import Data.List (sort, minimumBy)
 import Data.Ord  (comparing)
 
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Types
---------------------------------------------------------------------------------------------------------------------------------------------
-
--- |
-data Vector num = Vector num num num -- TODO: Constraints on argument types (cf. GADT) (?)
-
-
--- |
-data Line num = Line (Vector num) (Vector num)
-
-
--- | Why the hell did I write this useless function?
-vector :: Num a => a -> a -> a -> Vector a
-vector = Vector -- SublimeHaskell prefers the eta-reduced version (point-free)
-
-
-
---------------------------------------------------------------------------------------------------------------------------------------------
--- Instances
---------------------------------------------------------------------------------------------------------------------------------------------
-
--- |
-instance (Floating a, Eq a) => Num (Vector a) where
-	-- TODO: Helper method to reduce boilerplate for component-wise operations
-	(+) = dotwise (+)
-	(-) = dotwise (-)
-	(*) = dotwise (*) -- TODO: Is this really correct?
-	fromInteger n = Vector (fromInteger n) 0 0
-	signum v@(Vector x y z) = Vector (x/mag v) (y/mag v) (z/mag v) -- TODO: Proper way of implementing this function for vectors
-	abs v                   = Vector (mag v)   (0)       (0)
+import Cartesian.Space.Types
 
 
 
 --------------------------------------------------------------------------------------------------------------------------------------------
 -- Functions
 --------------------------------------------------------------------------------------------------------------------------------------------
-
--- Vector math -----------------------------------------------------------------------------------------------------------------------------
--- | Performs component-wise operations
-dotwise :: (a -> b -> c) -> Vector a -> Vector b -> Vector c
-dotwise f (Vector x y z) (Vector x' y' z') = Vector (f x x') (f y y') (f z z')
-
-
--- | Dot product of two vectors
-dot :: Floating a => Vector a -> Vector a -> a
-dot (Vector x y z) (Vector x' y' z') = (x * x') + (y * y') + (z * z') -- TODO: Refactor with Num instance (?)
-
-
--- | Euclidean distance between two points
-euclidean :: Floating a => Vector a -> Vector a -> a
-euclidean a b = sqrt $ dot a b
-
-
--- |
-magnitude :: (Floating a, Eq a) => Vector a -> a
-magnitude v = euclidean v v
-
-mag :: (Floating a, Eq a) => Vector a -> a
-mag = magnitude
-
-
--- | Angle (in radians) between the positive X-axis and the vector
--- argument :: (Floating a, Eq a) => Vector a -> a
--- argument (Vector 0 0 0) = 0
--- argument (Vector x y z) = atan $ y/x
-
-
--- arg :: (Floating a, Eq a) => Vector a -> a
--- arg = argument
-
-
--- | Vector -> (magnitude, argument)
--- polar :: (Floating a, Eq a) => Vector a -> (a, a)
--- polar v@(Vector x y) = (magnitude v, argument v)
-
---------------------------------------------------------------------------------------------------------------------------------------------
-
--- | Intersect
--- TODO: Math notes, MathJax or LaTex
--- TODO: Intersect for curves (functions) and single points (?)
--- TODO: Polymorphic, typeclass (lines, shapes, ranges, etc.) (?)
-intersect :: Num a => Line a -> Line a -> Maybe (Vector a)
-intersect _ _ = error "Not implemented" -- Nothing
-
-
--- |
-intersects :: Num a => Line a -> Line a -> Bool
-intersects a b = case intersect a b of
-	Just _  -> True
-	Nothing -> False
-
-
--- | Yields the overlap of two closed intervals (n ∈ R)
--- TODO: Normalise intervals (eg. (12, 5) -> (5, 12))
-overlap :: Real a => (a, a) -> (a, a) -> Maybe (a, a)
-overlap a b
-	| leftmost /= (α, β) = Just $ (β, γ) --
-	| otherwise                                  = Nothing --
-	where [α, β, γ, _] = sort [fst a, snd a, fst b, snd b] -- That's right.
-	      leftmost     = minimumBy (comparing fst) [a, b]  --
-
-
--- |
--- TODO: Intersect Rectangles
-
-
-
--- | Coefficients for the linear function of a Line (slope, intercept). The Z-component is ignored.
--- Fails for vertical and horizontal lines.
---
--- TODO: Use Maybe (?)
---
-coefficients :: (Fractional a, Eq a) => Line a -> Maybe (a, a)
-coefficients (Line (Vector ax ay _) (Vector bx by _))
-	| ax == bx  = Nothing
-	| ay == ay  = Nothing
-	| otherwise = let slope = (by - ay)/(bx - ax) in Just (slope, ay - slope*ax)
+ src/Cartesian/Space/Lenses.hs view
@@ -0,0 +1,44 @@+-- |
+-- Module      : Cartesian.Space.Lenses
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 31 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Space.Lenses where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Cartesian.Space.Types
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Lenses
+--------------------------------------------------------------------------------------------------------------------------------------------
+ src/Cartesian/Space/Types.hs view
@@ -0,0 +1,91 @@+-- |
+-- Module      : Cartesian.Space.Types
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created October 31 2015
+
+-- TODO | - Use Linear.V3 instead of defining my own vector type (?)
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances     #-}
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Space.Types where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+import Control.Lens
+
+import Cartesian.Internal.Types
+import Cartesian.Internal.Lenses
+import Cartesian.Internal.Core
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Types
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+data Vector3D f = Vector3D f f f -- TODO: Constraints on argument types (cf. GADT) (?)
+
+
+-- |
+data Line f = Line (Vector3D f) (Vector3D f)
+
+
+-- |
+-- data BoundingBox f = BoundingBox { _centre :: Vector f, _size :: Vector f }
+
+-- Instances -------------------------------------------------------------------------------------------------------------------------------
+
+-- |
+-- TODO: Refactor. A lot.
+instance Vector Vector3D where
+  vfold f a (Vector3D x' y' z')                        = f (f (f a x') y') z'
+  vzip  f   (Vector3D x' y' z') (Vector3D x'' y'' z'') = Vector3D (f x' x'') (f y' y'') (f z' z'')
+
+-- |
+instance (Floating v, Eq v) => Num (Vector3D v) where
+  -- TODO: Helper method to reduce boilerplate for component-wise operations
+  (+) = dotwise (+)
+  (-) = dotwise (-)
+  (*) (Vector3D x y z) (Vector3D x' y' z') = undefined -- TODO: Is this really correct?
+  fromInteger n = Vector3D (fromInteger n) 0 0
+  signum v@(Vector3D x' y' z') = Vector3D (x'/(abs v^.x)) (y'/(abs v^.x)) (z'/(abs v^.x)) -- TODO: Proper way of implementing this function for vectors
+  abs (Vector3D x' y' z')      = Vector3D (sqrt $ (x'**2) + (y'**2) + (z'**2)) (0) (0)
+
+
+instance HasX (Vector3D f) f where
+  getX (Vector3D x' _  _)     = x'
+  setX (Vector3D _  y' z') x' = Vector3D x' y' z'
+
+instance HasY (Vector3D f) f where
+  getY (Vector3D y' _ _)     = y'
+  setY (Vector3D x' _ z') y' = Vector3D x' y' z'
+
+instance HasZ (Vector3D f) f where
+  getZ (Vector3D z' _  _)    = z'
+  setZ (Vector3D x' y' _) z' = Vector3D x' y' z'
+ src/Cartesian/Types.hs view
@@ -0,0 +1,44 @@+-- |
+-- Module      : Cartesian.Types
+-- Description :
+-- Copyright   : (c) Jonatan H Sundqvist, 2015
+-- License     : MIT
+-- Maintainer  : Jonatan H Sundqvist
+-- Stability   : experimental|stable
+-- Portability : POSIX (not sure)
+--
+
+-- Created _ _ 2015
+
+-- TODO | -
+--        -
+
+-- SPEC | -
+--        -
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- GHC Pragmas
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- API
+--------------------------------------------------------------------------------------------------------------------------------------------
+module Cartesian.Types where
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- We'll need these
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+-- Functions
+--------------------------------------------------------------------------------------------------------------------------------------------