Friedrich wrote (to the Haskell mailing list):

>  o_array :: Shape -> Float
>  o_array (Polygon (v1:vs)) =  
>     let ph = phelp vs
>    in
>      foldr (+) 0.0 (map triangleArea ph)
>      where phelp :: [Vertex] -> [[Vertex]]
>            phelp (v2:v3:vs) = (v1:v2:v3:[]):phelp (v3:vs)
>            phelp _          = []
>
>  what I want is to replace the recursive phelp function with a function
>  using higher order functions. 

In situations like this where you need both an element and the next element
it can be simpler to pass two lists: the original list and its tail.
For example:

o_array :: Shape -> Float
o_array (Polygon (v1:vs))
     =   sum [triangleArea [v1, v2, v3] | (v2, v3) <- zip vs (tail vs) ]

 > My base idea is splitting up List of Vertices into a list of exactly 
 > three vertices calculating that area and adding them all. 

As Ralf mentioned you can compute the area of the triangle without
using square roots:

triangleArea :: [Vertex] -> Float
triangleArea [Vertex x1 y1, Vertex x2 y2, Vertex x3 y3]
     =   0.5 * ((x2*y1-x1*y2) + (x3*y2-x2*y3) + (x1*y3-x3*y1))

This can give an negative area, depending on the direction of the
vertices. See for example <http://www.seanet.com/~ksbrown/kmath201.htm>.

Here's implementation of the original problem without using triangles:

area :: Shape -> Float
area (Polygon vertices)
     =   0.5 * sum [(x1-x2)*(y1+y2)
                   | (Vertex x1 y1, Vertex x2 y2)
                       <- zip vertices (tail vertices ++ [head vertices])]

which is equivalent to your o_array function with the modified triangleArea
(I think).


Cheers,

Ronny Wichers Schreur


Reply via email to