module Geometry( Dimension -- Double , Point -- (Dimension, Dimension) , Angle -- Double , Figure -- (abstract) , rect -- Dimension-> Dimension-> Figure , triangle -- Dimension-> Angle-> Dimension-> Figure , poly -- [Point]-> Figure , circle -- Dimension-> Figure , translate -- Point-> Figure-> Figure , scale -- Double-> Figure-> Figure , rotate -- Angle-> Figure-> Figure , draw -- G.Point-> Double-> Figure-> Graphic , rot -- Angle-> Point->Point , rotAround -- Point-> Angle-> Point-> Point , add, sub -- Point-> Point-> Point , intersect -- Figure-> Figure-> Bool , len -- Point -> Dimension , Polar(..) , cart , polar ) where import GraphicsUtils hiding (Point, Angle) import qualified GraphicsUtils as G (Point, Angle) import List (nub) -- import Debug.Trace type Dimension = Double type Point = (Dimension, Dimension) type Angle = Double rect :: Dimension-> Dimension-> Figure triangle :: Dimension-> Angle-> Dimension-> Figure poly :: [Point]-> Figure circle :: Dimension-> Figure translate :: Point-> Figure-> Figure scale :: Double-> Figure-> Figure rotate :: Angle-> Figure-> Figure rotAt :: Point-> Angle-> Figure-> Figure rotAt (px, py) w = translate (px, py) . rotate w . translate (-px, -py) data Figure = Polygon [Point] | Circle Point Double smult :: Double-> Point-> Point smult f (x, y) | f == 1 = (x, y) | otherwise = (f* x, f* y) add :: Point-> Point-> Point add (x1, y1) (x2, y2) = (x1+ x2, y1+ y2) sub :: Point-> Point-> Point sub (x1, y1) (x2, y2) = (x1- x2, y1- y2) rot :: Angle-> Point-> Point rot w (x, y) | w == 0 = (x, y) | otherwise = ( x* cos w- y* sin w, x* sin w+ y* cos w) rotAround :: Point-> Angle-> Point-> Point rotAround p w q = add p (rot w (sub q p)) rect a b = let x2= a/2; y2= b/2 in Polygon [(x2, y2), (-x2, y2), (-x2, -y2), (x2, -y2), (x2, y2)] triangle l1 a l2 = Polygon [(0, 0), (l1, 0), rot a (l2, 0), (0, 0)] poly ps = Polygon (checkclosed ps) where checkclosed [] = [] checkclosed xs = if head xs == last xs then xs else xs++ [head xs] circle r = Circle (0, 0) r rotate a (Polygon ps) = Polygon (map (rot a) ps) rotate a (Circle c r) = Circle (rot a c) r scale s (Polygon ps) = Polygon (map (smult s) ps) scale s (Circle c r) = Circle (smult s c) (r* s) translate p (Polygon ps) = Polygon (map (add p) ps) translate p (Circle c r) = Circle (add p c) r draw :: G.Point-> Double-> Figure-> Graphic draw (wx, wy) s = draw'. scale s where draw' (Polygon ps) = polygon (map (\ (x, y)-> (wx+ round x, wy+ round y)) ps) draw' (Circle (x, y) r) = ellipse (wx+ round (x- r), wy+ round (y- r)) (wx+ round (x+ r), wy+ round (y+ r)) inC :: Point-> Double-> Point-> Bool inC (mx, my) r (px, py) = len (px- mx, py- my) <= r len :: Point-> Double len (x, y)= sqrt (x^2+ y^2) det :: Point-> (Point, Point)-> Int det (cx,cy) ((ax,ay), (bx,by)) = round (signum ((by-ay)*(cx-bx)-(cy-by)*(bx-ax))) sides :: [Point]-> [(Point, Point)] sides [] = [] sides (x:[]) = [] sides (x:xs) = (x, head xs):(sides xs) inP :: [Point]-> Point-> Bool inP ps c = (length. nub. map (det c). sides) ps == 1 contains :: Figure-> Point-> Bool contains (Polygon pts)= inP pts contains (Circle c r) = inC c r intersect :: Figure-> Figure-> Bool intersect (Circle (mx1, my1) r1) (Circle (mx2, my2) r2)= len (mx2- mx1, my2- my1) <= r1+ r2 intersect (Polygon p1) (Polygon p2)= any (inP p1) p2 || any (inP p2) p1 intersect (Polygon p) (Circle c r)= inP p c || any (inC c r) p intersect (Circle c r) (Polygon p)= inP p c || any (inC c r) p data Polar = Polar { angle :: Angle, dist :: Dimension } deriving (Show, Eq) cart :: Polar-> Point cart p = rot (angle p) (dist p, 0) polar :: Point-> Polar polar (x, y) | (x, y) == (0, 0) = Polar {dist= r, angle = 0} -- beliebig | otherwise = Polar {dist= r, angle= asin (y/r)} where r = len (x, y)