hgeometry-0.1.0.0: src/Data/Geometry/Circle.hs
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
-- | whether or not p lies in OR on the circle c
inCircle :: (Ord a, Floating a) => Point2' a -> Circle2' a -> Bool
p `inCircle` c = distanceToCenter p c <= radius c
-- | whether or not p lies strictly inside the circle c
insideCircle :: (Floating a, Ord a) => Point2' a -> Circle2' a -> Bool
p `insideCircle` c = distanceToCenter p c < radius c
-- | whether or not p lies on the circle
onCircle :: (Eq a, Floating a) => Point2' a -> Circle2' a -> Bool
p `onCircle` c = distanceToCenter p c == radius c
-- | whether or not a point lies in a disc: this includes its border
inDisc :: (Floating 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.
p `insideDisc` (Disc2 c) = p `insideCircle` c