module Data.Geometry.SetOperations( AreIntersectable(..)
) where
import Data.List
import Data.Geometry.Point
import Data.Geometry.Line
import Data.Geometry.Circle
import Debug.Trace
class AreIntersectable g h a where
intersectionPoints :: g a -> h a -> [Point2' a]
instance (Ord a, Floating a) => AreIntersectable Circle2' LineSegment2' a where
intersectionPoints c l = filter (`onLineSegment` l) $ circleAndLine c l
instance (Ord a, Floating a) => AreIntersectable Circle2' Polyline2' a where
intersectionPoints c (Polyline2 ls) = concatMap (intersectionPoints c) ls
instance (Ord a, Floating a) => AreIntersectable Circle2' Line2' a where
intersectionPoints c (Line2 l) = circleAndLine c l
circleAndLine :: (Ord a, Floating a) => Circle2' a -> LineSegment2' a -> [Point2' a]
circleAndLine (Circle2 p r) (LineSegment2 s t) = map (|+| p) $ pts discr
where
s'@(Point2 (sx,sy)) = s |-| p
t' = t |-| p
d@(Point2 (dx,dy)) = t' |-| s'
q lamb = s' |+| (lamb |*| d)
a = dx^2 + dy^2
b = 2*(sx*dx + sy*dy)
c = sx^2 + sy^2 r^2
discr = b^2 4*a*c
discr' = sqrt discr
lambda (|+-|) = (b |+-| discr') / (2*a)
pts dscr
| dscr < 0 = []
| dscr == 0 = [q $ lambda (+)]
| otherwise = let lambdas = sort [lambda (), lambda (+)] in
map q lambdas