Total circles area: Difference between revisions

→‎Analytical Solution: changes and comments
(Removed one unused function in the second Haskell entry)
(→‎Analytical Solution: changes and comments)
Line 332:
<lang haskell>{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
import Data.List (sort, zip3)
 
data Vec = Vec Double Double
Line 421:
zipWith Arc (repeat c) $ zipWith Angle2 angs $ tail angs
 
-- if an arc that was part of one circle is inside *another* circle,
-- it will not be part of the zero-winding path, so reject it
inCircle :: (Vec, Circle) -> Circle -> Bool
inCircle (Vec x0 y0, c) (Circle x y r) =
Line 429 ⟶ 431:
where (Arc c _) = arc
 
{-
 
Given a list of arcs, build sets of closed paths from them.
If one arc's end point is no more than 1e-4 from another's
start point, they are considered connected. Since these
start/end points resulted from intersecting circles earlier,
they *should* be exactly the same, but floating point
precision may cause small differences, hence the 1e-4 error
margin. When there are genuinely different intersections
closer than this margin, the method will backfire, badly.
-}
makePaths :: [Arc] -> [[Arc]]
makePaths arcs = joinArcs [] arcs where
Line 435 ⟶ 446:
joinArcs [] (x:xs) = joinArcs [x] xs
joinArcs a (x:xs)
| vDist (arcStart(arcEnd (headlast a)) (arcEndarcStart (lasthead a))) < 1e-34
= a : joinArcs [] (x:xs)
| vDist (arcEnd (last a)) (arcStart x) < 1e-34
= joinArcs (a ++ [x]) xs
| otherwise = joinArcs a (xs ++ [x])
Line 448 ⟶ 459:
area_ (a + arcArea arc) (e ++ [arcCenter arc, arcEnd arc]) as
 
-- slice N-polygon into N-2 triangles
 
polylineArea :: [Vec] -> Double
polylineArea [a, b](v:vs) = 0sum $ map triArea $ zip3 (repeat v) vs (tail vs)
where triArea (a ,b ,c) = ((b `vSub` a) `vCross` (c `vSub` b)) / 2
polylineArea (a:b:c:rest) = triArea a b c + polylineArea (a:c:rest)
where triArea a b c = ((b `vSub` a) `vCross` (c `vSub` b)) / 2
 
 
circlesArea :: [Circle] -> Double
Anonymous user