module Data.Geometry.Geometry(
IsPoint2Functor(..)
, IsTransformable(..)
, HasPoints(..)
, Vec3(..)
, Matrix3(..)
, identityMatrix3
, matrix3FromLists
, matrix3FromList
, matrix3ToList
, matrix3ToLists
) where
import Data.Geometry.Point
class IsPoint2Functor g where
p2fmap :: (Point2' a -> Point2' b) -> g a -> g b
class HasPoints g where
points :: g a -> [Point2' a]
instance HasPoints Point2' where
points p = [p]
newtype Vec3 a = Vec3 (a,a,a)
deriving (Show,Eq)
newtype Matrix3 a = Matrix3 (Vec3 (Vec3 a))
deriving (Show,Eq)
instance Functor Vec3 where
fmap f (Vec3 (a,b,c)) = Vec3 (f a, f b, f c)
instance Functor Matrix3 where
fmap f (Matrix3 (Vec3 (a,b,c))) = Matrix3 $ Vec3 (fmap f a, fmap f b, fmap f c)
v3FromList :: [a] -> Vec3 a
v3FromList [a,b,c] = Vec3 (a,b,c)
v3FromList _ = error "v3FromList needs exactly 3 elements."
matrix3FromList :: [a] -> Matrix3 a
matrix3FromList = matrix3FromLists . rtake 3
where
rtake k ss = let (xs,ys) = splitAt k ss in
xs : rtake k ys
matrix3FromLists :: [[a]] -> Matrix3 a
matrix3FromLists = Matrix3 . v3FromList . map v3FromList
v3ToList :: Vec3 a -> [a]
v3ToList (Vec3 (a,b,c)) = [a,b,c]
matrix3ToList :: Matrix3 a -> [a]
matrix3ToList = concat . matrix3ToLists
matrix3ToLists :: Matrix3 a -> [[a]]
matrix3ToLists (Matrix3 (Vec3 (a,b,c))) = map v3ToList [a,b,c]
identityMatrix3 :: Num a => Matrix3 a
identityMatrix3 = matrix3FromLists [ [ 1, 0, 0 ]
, [ 0, 1, 0 ]
, [ 0, 0, 1 ] ]
multiply3 :: Num a => Matrix3 a -> Vec3 a -> Vec3 a
multiply3 (Matrix3 (Vec3 ( Vec3 (a,b,c)
, Vec3 (d,e,f)
, Vec3 (g,h,i)))) (Vec3 (x,y,z)) =
Vec3 ( a*x + b*y + c*z,
d*x + e*y + f*z,
g*x + h*y + i*z)
class IsTransformable g where
transformWith :: Num a => Matrix3 a -> g a -> g a
instance IsTransformable Point2' where
transformWith = transformPoint
transformPoint :: Num a => Matrix3 a -> Point2' a -> Point2' a
transformPoint m (Point2 (x,y)) = Point2 (x',y')
where
v = Vec3 (x,y,1)
Vec3 (x',y',_) = multiply3 m v
tranformPointBased :: (Num a, IsPoint2Functor g) => Matrix3 a -> g a -> g a
tranformPointBased m = p2fmap (transformWith m)
instance IsPoint2Functor g => IsTransformable g where
transformWith = tranformPointBased