module Data.Geometry.Circle( Circle2'(..) , Disc2'(..) , IsCircleLike(..) , inCircle , insideCircle , onCircle , inDisc , insideDisc ) where import Data.Geometry.Point import Data.Geometry.Geometry --------------------------------------------------------------------- -- | A circle in the plane data Circle2' a = Circle2 (Point2' a) a deriving (Eq,Ord,Show,Read) instance HasPoints Circle2' where points (Circle2 p _) = [p] -- TODO: instance for transformable --------------------------------------------------------------------- -- | A disc in the plane (i.e. a circle inclusiding its contents) newtype Disc2' a = Disc2 { border :: Circle2' a } deriving (Show,Eq,Ord,Read) instance HasPoints Disc2' where points = points . border -- TODO: instance for transformable -------------------------------------------------------------------------------- -- | functions on circles -- | Class expressing functions that circlelike objects all have. Like a center -- and a radius. Minimal implementation is either getCircle or center and radius class IsCircleLike t where getCircle :: t a -> Circle2' a getCircle x = Circle2 (center x) (radius x) center :: t a -> Point2' a center = center . getCircle radius :: t a -> a radius = radius . getCircle distance :: Floating a => Point2' a -> t a -> a distance p = distance p . getCircle distanceToCenter :: Floating a => Point2' a -> t a -> a distanceToCenter p = distanceToCenter p . getCircle instance IsCircleLike Circle2' where center (Circle2 p _) = p radius (Circle2 _ r) = r distanceToCenter p (Circle2 q _) = dist p q distance p c@(Circle2 _ r) = distanceToCenter p c - r instance IsCircleLike Disc2' where getCircle = border -------------------------------------------------------------------------------- -- | Checking if points lie in or on a circle/disc -- | Squared distance to the center l22ToCenter :: Num a => Point2' a -> Circle2' a -> a l22ToCenter p (Circle2 q _) = l22dist p q -- | whether or not p lies in OR on the circle c inCircle :: (Ord a, Num a) => Point2' a -> Circle2' a -> Bool p `inCircle` c = l22ToCenter p c <= (radius c)^2 -- | whether or not p lies strictly inside the circle c insideCircle :: (Num a, Ord a) => Point2' a -> Circle2' a -> Bool p `insideCircle` c = l22ToCenter p c < (radius c)^2 -- | whether or not p lies on the circle onCircle :: (Eq a, Num a) => Point2' a -> Circle2' a -> Bool p `onCircle` c = l22ToCenter p c == (radius c)^2 -- | whether or not a point lies in a disc: this includes its border inDisc :: (Num a, Ord a) => Point2' a -> Disc2' a -> Bool p `inDisc` (Disc2 c) = p `inCircle` c -- | whether or not a point lies strictly inside a disc. insideDisc :: (Num a, Ord a) => Point2' a -> Disc2' a -> Bool p `insideDisc` (Disc2 c) = p `insideCircle` c