From f82c94805578fbbd8d5a9bb5866e6e9b838cc52f Mon Sep 17 00:00:00 2001 From: hasufell Date: Sun, 12 Oct 2014 20:37:24 +0200 Subject: [PATCH] ALGO: Improve readability by introducing notcw --- Algebra/Vector.hs | 32 ++++++++++++++++++++++------- Algebra/VectorTypes.hs | 5 +++++ Algorithms/ConvexHull/GrahamScan.hs | 28 ++++++++++++------------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Algebra/Vector.hs b/Algebra/Vector.hs index 864e6a9..2ffcc3d 100644 --- a/Algebra/Vector.hs +++ b/Algebra/Vector.hs @@ -58,16 +58,34 @@ vp2 :: PT -- ^ vector origin vp2 a b = (pt2Vec b) - (pt2Vec a) --- |Checks if 3 points a,b,c build a counterclock wise triangle by --- connecting a-b-c. This is done by computing the determinant and --- checking the algebraic sign. -ccw :: PT -> PT -> PT -> Bool -ccw a b c = - (bx - ax) * +-- |Computes the determinant of 3 points. +det :: PT -> PT -> PT -> Double +det a b c = + (bx - ax) * (cy - ay) - (by - ay) * - (cx - ax) >= 0 + (cx - ax) where (ax, ay) = unp2 a (bx, by) = unp2 b (cx, cy) = unp2 c + + +-- |Get the orientation of 3 points which can either be +-- * clock-wise +-- * counter-clock-wise +-- * collinear +getOrient :: PT -> PT -> PT -> Alignment +getOrient a b c = case compare (det a b c) 0 of + GT -> CW + LT -> CCW + EQ -> CL + + +--- |Checks if 3 points a,b,c do not build a clockwise triangle by +--- connecting a-b-c. This is done by computing the determinant and +--- checking the algebraic sign. +notcw :: PT -> PT -> PT -> Bool +notcw a b c = case getOrient a b c of + CW -> False + _ -> True diff --git a/Algebra/VectorTypes.hs b/Algebra/VectorTypes.hs index dc3ac89..a465d91 100644 --- a/Algebra/VectorTypes.hs +++ b/Algebra/VectorTypes.hs @@ -8,3 +8,8 @@ import Diagrams.TwoD.Types type Vec = R2 type PT = P2 type Coord = (Double, Double) + + +data Alignment = CW + | CCW + | CL diff --git a/Algorithms/ConvexHull/GrahamScan.hs b/Algorithms/ConvexHull/GrahamScan.hs index c49fe84..38978a5 100644 --- a/Algorithms/ConvexHull/GrahamScan.hs +++ b/Algorithms/ConvexHull/GrahamScan.hs @@ -25,14 +25,14 @@ return (scanHalf upperHull restu) ++ === begin scanHalf function === scanHalf (min 3 elem => lowerHull) (min 1 elem => rest) - | isCounterClockWise (last3Elements lowerHull) == True + | isNotClockWise (last3Elements lowerHull) == True = scanHalf (lowerHull + head rest) (tail rest) | otherwise = scanHalf (deleteSndToLastElem lowerHull + head rest) (rest) scanHalf (min 3 elem => lowerHull ) [] - | isCounterClockWise (last3Elements lowerHull) == True + | isNotClockWise (last3Elements lowerHull) == True = return lowerHull | otherwise = scanHalf (deleteSndToLastElem lowerHull) [] @@ -49,26 +49,26 @@ scanHalf lowerHull _ = lowerHull xs = [(100, 100), (200, 450), (250, 250)] ys = [(300, 400), (400, 200)] -ccw (100, 100) (200, 450) (250, 250) => false, pop snd2last of xs +notcw (100, 100) (200, 450) (250, 250) => false, pop snd2last of xs === move first of ys to end of xs xs = [(100, 100), (250, 250), (300, 400)] ys = [(400, 200)] -ccw (100, 100), (250, 250) (300, 400) => true +notcw (100, 100), (250, 250) (300, 400) => true === move first of ys to end of xs xs = [(100, 100), (250, 250), (300, 400), (400, 200)] ys = [] -ccw (250, 250) (300, 400) (400, 200) => false, pop snd2last of xs +notcw (250, 250) (300, 400) (400, 200) => false, pop snd2last of xs === xs = [(100, 100), (250, 250), (400, 200)] ys = [] -ccw (100, 100) (250, 250) (400, 200) => false, pop snd2last of xs +notcw (100, 100) (250, 250) (400, 200) => false, pop snd2last of xs === xs = [(100, 100), (400, 200)] ys = [] @@ -91,13 +91,13 @@ grahamGetCH vs = -> [PT] -- ^ the rest of the points -> [PT] -- ^ all convex hull points for the half scanH hs@(x:y:z:xs) (r':rs') - | ccw z y x = scanH (r':hs) rs' - | otherwise = scanH (x:z:xs) (r':rs') + | notcw z y x = scanH (r':hs) rs' + | otherwise = scanH (x:z:xs) (r':rs') scanH hs@(x:y:z:xs) [] - | ccw z y x = hs - | otherwise = scanH (x:z:xs) [] - scanH hs (r':rs') = scanH (r':hs) rs' - scanH hs _ = hs + | notcw z y x = hs + | otherwise = scanH (x:z:xs) [] + scanH hs (r':rs') = scanH (r':hs) rs' + scanH hs _ = hs -- |Compute all steps of the graham scan algorithm to allow @@ -116,12 +116,12 @@ grahamGetCHSteps vs = where scanH c' hs@(x:y:z:xs) (r':rs') | c' >= c = hs - | ccw z y x = scanH (c' + 1) (r':hs) rs' + | notcw z y x = scanH (c' + 1) (r':hs) rs' | otherwise = scanH (c' + 1) (x:z:xs) (r':rs') scanH _ [x,y] [] = [y,x] scanH c' hs@(x:y:z:xs) [] | c' >= c = hs - | ccw z y x = hs + | notcw z y x = hs | otherwise = scanH (c' + 1) (x:z:xs) [] scanH c' hs (r':rs') | c' >= c = hs