SOE ex.8.11


{-
  Just reuse the concept of convex function on ex.2.4.
  Here we do not allow sin(theta) = 0
  Which means we do not allow 2 vectors that the angle between is 0 or PI.
-}

isConvex :: [Coordinate] -> Bool
isConvex [] = False
isConvex cs = all (>0) zScalars || all (<0) zScalars
  where
  rays :: [Ray]
  rays = zip cs (tail (cycle cs))
  crossProductZscalar :: Ray -> Ray -> Float
  crossProductZscalar ((x1, y1), (x2, y2)) ((x3, y3), (x4, y4))
    = (x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1)
  zScalars :: [Float]
  zScalars = zipWith crossProductZscalar rays (tail (cycle rays))


area :: Shape -> Float
area (Polygon vs)
  | isConvex vs =
      let trapezoidArea ((x1, y1), (x2, y2)) = 0.5 * (y2 + y1) * (x2 - x1)
      in  abs $ sum $ map trapezoidArea (zip vs (tail (cycle vs)))
  | otherwise   = error "The polygon is not convex."


----- data/type used in this exercise ----
type Coordinate = (Float, Float)
type Ray = (Coordinate, Coordinate)
data Shape = Polygon [Coordinate]

Leave a Reply