From 37b38115ae3a90591897edb5dce325b72a8176c3 Mon Sep 17 00:00:00 2001 From: hasufell Date: Sun, 12 Oct 2014 19:19:44 +0200 Subject: [PATCH] ALGO: fix algorithm to show collinear points as part of the hull There was also a bug to be fixed when doing this. We missed an important pattern match case which casued wrong results. --- Algebra/Vector.hs | 2 +- Algorithms/ConvexHull/GrahamScan.hs | 34 ++++++++++++++++++----------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/Algebra/Vector.hs b/Algebra/Vector.hs index b5ada50..864e6a9 100644 --- a/Algebra/Vector.hs +++ b/Algebra/Vector.hs @@ -66,7 +66,7 @@ ccw a b c = (bx - ax) * (cy - ay) - (by - ay) * - (cx - ax) > 0 + (cx - ax) >= 0 where (ax, ay) = unp2 a (bx, by) = unp2 b diff --git a/Algorithms/ConvexHull/GrahamScan.hs b/Algorithms/ConvexHull/GrahamScan.hs index ce6f546..da2abd3 100644 --- a/Algorithms/ConvexHull/GrahamScan.hs +++ b/Algorithms/ConvexHull/GrahamScan.hs @@ -29,7 +29,7 @@ scanHalf (min 3 elem => lowerHull) (min 1 elem => rest) = scanHalf (lowerHull + head rest) (tail rest) | otherwise = scanHalf (deleteSndToLastElem lowerHull + head rest) - (tail rest) + (rest) scanHalf (min 3 elem => lowerHull ) [] | isCounterClockWise (last3Elements lowerHull) == True @@ -37,6 +37,10 @@ scanHalf (min 3 elem => lowerHull ) [] | otherwise = scanHalf (deleteSndToLastElem lowerHull) [] +scanHalf lowerHull (min 1 elem => rest) = scanHalf (lowerHull + head rest) + (tail rest) + + scanHalf lowerHull _ = lowerHull === end scanHalf function === @@ -87,12 +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 (r':x:z:xs) rs' + | ccw 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 xs _ = xs + | ccw 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 @@ -110,12 +115,15 @@ grahamGetCHSteps vs = | otherwise = [] where scanH c' hs@(x:y:z:xs) (r':rs') - | c' >= c = hs - | ccw z y x = scanH (c' + 1) (r':hs) rs' - | otherwise = scanH (c' + 1) (r':x:z:xs) rs' - scanH _ [x,y] [] = [y,x] + | c' >= c = hs + | ccw 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 - | otherwise = scanH (c' + 1) (x:z:xs) [] + | c' >= c = hs + | ccw z y x = hs + | otherwise = scanH (c' + 1) (x:z:xs) [] + scanH c' hs (r':rs') + | c' >= c = hs + | otherwise = scanH (c' + 1) (r':hs) rs' scanH _ xs _ = xs