module Geom2d.Line.Internal where
import Test.QuickCheck
import Data.Maybe
import Data.AEq
import Geom2d.Point
import Geom2d.Translate
import Geom2d.Distance
import Control.Monad
data InfLine p a = InfLine (p a) (p a) deriving (Show, Read)
instance Functor p => Functor (InfLine p) where
fmap f (InfLine a b) = InfLine (fmap f a) (fmap f b)
instance (Eq (p a), Arbitrary (p a)) => Arbitrary (InfLine p a) where
arbitrary = do p1 <- arbitrary
p2 <- arbitrary `suchThat` (/= p1)
return $ InfLine p1 p2
instance (Eq (p a), Eq a, RealFloat a, Num (p a), Point p) =>
Eq (InfLine p a) where
a@(InfLine a1 _) == b@(InfLine b1 _)
| slope a /= slope b = False
| isNothing (slope a) = x a1 == x b1
| otherwise = case root a of
Just _ -> fromMaybe False ( (==) <$> root a <*> root b )
Nothing -> y a1 == y b1
where slope (InfLine m n) | x (n m) == 0 = Nothing
| otherwise = Just $ y (n m) / x (n m)
root l@(InfLine p q) | y p == y q = Nothing
| otherwise =
(do dy <- slope l
return (x q (y q / dy))) `mplus`
Just (x p)
instance Translate p => Translate (InfLine p) where
translate m (InfLine p q) = InfLine (m `translate` p) (m `translate` q)
data FinLine p a =
FinLine (p a) (p a) deriving (Show,Read)
instance (Eq (p a)) => Eq (FinLine p a) where
(FinLine a1 b1) == (FinLine a2 b2) =
(a1 == a2 && b1 == b2) ||
(a1 == b2 && b1 == a2)
instance (Eq (p a), Arbitrary (p a)) => Arbitrary (FinLine p a) where
arbitrary = do p1 <- arbitrary
p2 <- arbitrary `suchThat` (/= p1)
return $ FinLine p1 p2
instance Translate p => Translate (FinLine p) where
translate v (FinLine p q) = FinLine (v `translate` p) (v `translate` q)
instance AEq (p a) => AEq (FinLine p a) where
(FinLine a1 b1) ~== (FinLine a2 b2) =
(a1 ~== a2 && b1 ~== b2) ||
(a1 ~== b2 && b1 ~== a2)
instance (Point p) =>
Distance (FinLine p) p where
distance (FinLine a b) p =
sqrt (dx*dx + dy*dy)
where dx = ax + (u * qx) px
dy = ay + (u * qy) py
qx = bx ax
qy = by ay
s = qx^(2::Int) + qy^(2::Int)
u' = ((px ax)*qx + (py ay)*qy)/s
u | u' > 1 = 1
| u' < 0 = 0
| otherwise = u'
py = y p
px = x p
ax = x a
ay = y a
bx = x b
by = y b
instance (Point p) =>
Distance p (FinLine p) where
distance = flip distance