hgeometry-0.12.0.0: src/Data/Geometry/Point/Quadrants.hs
--------------------------------------------------------------------------------
-- |
-- Module : Data.Geometry.Point.Quadrants
-- Copyright : (C) Frank Staals
-- License : see the LICENSE file
-- Maintainer : Frank Staals
--------------------------------------------------------------------------------
module Data.Geometry.Point.Quadrants where
import Control.Lens
import Data.Ext
import Data.Geometry.Point.Class
import Data.Geometry.Point.Internal
import Data.Geometry.Vector
import qualified Data.List as L
import GHC.TypeLits
--------------------------------------------------------------------------------
-- | Quadrants of two dimensional points. in CCW order
data Quadrant = TopRight | TopLeft | BottomLeft | BottomRight
deriving (Show,Read,Eq,Ord,Enum,Bounded)
-- | Quadrants around point c; quadrants are closed on their "previous"
-- boundary (i..e the boundary with the previous quadrant in the CCW order),
-- open on next boundary. The origin itself is assigned the topRight quadrant
quadrantWith :: (Ord r, 1 <= d, 2 <= d, Arity d)
=> Point d r :+ q -> Point d r :+ p -> Quadrant
quadrantWith (c :+ _) (p :+ _) = case ( (c^.xCoord) `compare` (p^.xCoord)
, (c^.yCoord) `compare` (p^.yCoord) ) of
(EQ, EQ) -> TopRight
(LT, EQ) -> TopRight
(LT, LT) -> TopRight
(EQ, LT) -> TopLeft
(GT, LT) -> TopLeft
(GT, EQ) -> BottomLeft
(GT, GT) -> BottomLeft
(EQ, GT) -> BottomRight
(LT, GT) -> BottomRight
-- | Quadrants with respect to the origin
quadrant :: (Ord r, Num r, 1 <= d, 2 <= d, Arity d) => Point d r :+ p -> Quadrant
quadrant = quadrantWith (ext origin)
-- | Given a center point c, and a set of points, partition the points into
-- quadrants around c (based on their x and y coordinates). The quadrants are
-- reported in the order topLeft, topRight, bottomLeft, bottomRight. The points
-- are in the same order as they were in the original input lists.
-- Points with the same x-or y coordinate as p, are "rounded" to above.
partitionIntoQuadrants :: (Ord r, 1 <= d, 2 <= d, Arity d)
=> Point d r :+ q
-> [Point d r :+ p]
-> ( [Point d r :+ p], [Point d r :+ p]
, [Point d r :+ p], [Point d r :+ p]
)
partitionIntoQuadrants c pts = (topL, topR, bottomL, bottomR)
where
(below',above') = L.partition (on yCoord) pts
(bottomL,bottomR) = L.partition (on xCoord) below'
(topL,topR) = L.partition (on xCoord) above'
on l q = q^.core.l < c^.core.l