-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathch3dir.hs
40 lines (29 loc) · 1.39 KB
/
ch3dir.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import Data.List
import Data.Ord
data Direction = LeftTurn | Straight | RightTurn deriving (Eq, Show)
data Point a = Point {px :: a, py :: a } deriving Show
turn :: (Ord a, Num a) => Point a -> Point a -> Point a -> Direction
turn a b c = case compare (sign a b c) 0 of EQ -> Straight
GT -> LeftTurn
otherwise -> RightTurn
sign (Point ax ay) (Point bx by) (Point cx cy)
= (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)
turns (a:b:c:points) = turn a b c : turns (b:c:points)
turns _ = []
cmpPoints :: (Ord a) => Point a -> Point a -> Ordering
cmpPoints (Point ax ay) (Point bx by)
| ay == by = compare ax bx
| otherwise = compare ay by
-- let in
-- pivot : sortBy (comparing (coTan pivot)) (tail points)
-- where pivot = minimumBy cmpPoints points
coTan pivot point = (px point - px pivot) / (py point - py pivot)
graham :: (Ord a, Num a) => [Point a] -> Maybe [Point a]
graham (x:y:points) = Just (func [y, x] points)
where func fin [] = fin
func xs@(x:y:finished) (t:todo)
| not (null finished) && turn y x t == RightTurn = func (y:finished) (t:todo)
| otherwise = func (t:xs) todo
graham _ = Nothing
gscan points = graham (pivot : sortBy (comparing (coTan pivot)) (tail points))
where pivot = minimumBy cmpPoints points