module Geom2d.Line
(
InfLine
, mkInfLine
, lineF
, parallel
, slope
, root
, intersection
, FinLine
, mkFinLine
, lineLength
)
where
import Geom2d.Point
import Geom2d.Line.Internal
mkInfLine :: (Eq (p a)) => p a -> p a -> Maybe (InfLine p a)
mkInfLine a b
| a == b = Nothing
| otherwise = Just $ InfLine a b
lineF :: (Eq a, Fractional a, Point p) =>
InfLine p a -> Maybe (a -> a)
lineF l@(InfLine p _) =
( \m -> case root l of
Just x0 -> \arg -> m * (arg x0)
Nothing -> const (y p) ) <$>
slope l
parallel :: (Num a, Num (p a), Point p, Eq a) =>
InfLine p a -> InfLine p a -> Bool
parallel (InfLine a b) (InfLine p q) = (b a) `cross` (q p) == 0
slope :: (Fractional a, Point p, Eq a) =>
InfLine p a -> Maybe a
slope (InfLine p q)
| x p == x q = Nothing
| otherwise = Just $ (y q y p) / (x q x p)
root :: (Eq a, Fractional a, Point p) =>
InfLine p a -> Maybe a
root l@(InfLine p _) =
case slope l of
Nothing -> Just $ x p
Just m ->
if m == 0
then Nothing
else Just $ x p (y p * m)
intersection :: (Eq (p a), Num (p a), RealFloat a, Point p) =>
InfLine p a -> InfLine p a -> Maybe (p a)
intersection l1@(InfLine a1 _) l2@(InfLine b1 _)
| l1 == l2 = Nothing
| l1 `parallel` l2 = Nothing
| otherwise =
case slope l1 of
Nothing -> do
x0 <- root l1
f <- lineF l2
return (fromCoords x0 (f x0))
Just ma ->
case slope l2 of
Nothing -> do
x0 <- root l2
f <- lineF l1
return (fromCoords x0 (f x0))
Just mb -> do
let na = y a1 ma * x a1
nb = y b1 mb * x b1
safeDiv num denom | denom == 0 = Nothing
| otherwise = Just (num/denom)
x' <- (nb na) `safeDiv` (ma mb)
f <- lineF l1
return (fromCoords x' (f x'))
mkFinLine :: (Eq (p a)) => p a -> p a -> Maybe (FinLine p a)
mkFinLine a b
| a == b = Nothing
| otherwise = Just (FinLine a b)
lineLength :: (Point p, Num (p a), Floating a) => FinLine p a -> a
lineLength (FinLine a b) = magnitude (b a)