{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module HGeometry.Line.LineEQ
( LineEQ(LineEQ, MkLineEQ)
, evalAt'
, module HGeometry.Line.NonVertical.Class
) where
import Control.DeepSeq
import Control.Lens((^.), coerced)
import GHC.Generics(Generic)
import HGeometry.Ext
import HGeometry.HyperPlane.Class
import HGeometry.HyperPlane.Internal
import HGeometry.HyperPlane.NonVertical
import HGeometry.Intersection
import HGeometry.Line.Class
import HGeometry.Line.Intersection
import HGeometry.Line.NonVertical.Class
import HGeometry.Point
import HGeometry.Properties(NumType, Dimension)
import HGeometry.Vector
import Text.Read
newtype LineEQ r = MkLineEQ (NonVerticalHyperPlane 2 r)
deriving newtype (LineEQ r -> LineEQ r -> Bool
(LineEQ r -> LineEQ r -> Bool)
-> (LineEQ r -> LineEQ r -> Bool) -> Eq (LineEQ r)
forall r. Eq r => LineEQ r -> LineEQ r -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall r. Eq r => LineEQ r -> LineEQ r -> Bool
== :: LineEQ r -> LineEQ r -> Bool
$c/= :: forall r. Eq r => LineEQ r -> LineEQ r -> Bool
/= :: LineEQ r -> LineEQ r -> Bool
Eq,Eq (LineEQ r)
Eq (LineEQ r) =>
(LineEQ r -> LineEQ r -> Ordering)
-> (LineEQ r -> LineEQ r -> Bool)
-> (LineEQ r -> LineEQ r -> Bool)
-> (LineEQ r -> LineEQ r -> Bool)
-> (LineEQ r -> LineEQ r -> Bool)
-> (LineEQ r -> LineEQ r -> LineEQ r)
-> (LineEQ r -> LineEQ r -> LineEQ r)
-> Ord (LineEQ r)
LineEQ r -> LineEQ r -> Bool
LineEQ r -> LineEQ r -> Ordering
LineEQ r -> LineEQ r -> LineEQ r
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall r. Ord r => Eq (LineEQ r)
forall r. Ord r => LineEQ r -> LineEQ r -> Bool
forall r. Ord r => LineEQ r -> LineEQ r -> Ordering
forall r. Ord r => LineEQ r -> LineEQ r -> LineEQ r
$ccompare :: forall r. Ord r => LineEQ r -> LineEQ r -> Ordering
compare :: LineEQ r -> LineEQ r -> Ordering
$c< :: forall r. Ord r => LineEQ r -> LineEQ r -> Bool
< :: LineEQ r -> LineEQ r -> Bool
$c<= :: forall r. Ord r => LineEQ r -> LineEQ r -> Bool
<= :: LineEQ r -> LineEQ r -> Bool
$c> :: forall r. Ord r => LineEQ r -> LineEQ r -> Bool
> :: LineEQ r -> LineEQ r -> Bool
$c>= :: forall r. Ord r => LineEQ r -> LineEQ r -> Bool
>= :: LineEQ r -> LineEQ r -> Bool
$cmax :: forall r. Ord r => LineEQ r -> LineEQ r -> LineEQ r
max :: LineEQ r -> LineEQ r -> LineEQ r
$cmin :: forall r. Ord r => LineEQ r -> LineEQ r -> LineEQ r
min :: LineEQ r -> LineEQ r -> LineEQ r
Ord,LineEQ r -> ()
(LineEQ r -> ()) -> NFData (LineEQ r)
forall r. NFData r => LineEQ r -> ()
forall a. (a -> ()) -> NFData a
$crnf :: forall r. NFData r => LineEQ r -> ()
rnf :: LineEQ r -> ()
NFData)
deriving stock ((forall x. LineEQ r -> Rep (LineEQ r) x)
-> (forall x. Rep (LineEQ r) x -> LineEQ r) -> Generic (LineEQ r)
forall x. Rep (LineEQ r) x -> LineEQ r
forall x. LineEQ r -> Rep (LineEQ r) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall r x. Rep (LineEQ r) x -> LineEQ r
forall r x. LineEQ r -> Rep (LineEQ r) x
$cfrom :: forall r x. LineEQ r -> Rep (LineEQ r) x
from :: forall x. LineEQ r -> Rep (LineEQ r) x
$cto :: forall r x. Rep (LineEQ r) x -> LineEQ r
to :: forall x. Rep (LineEQ r) x -> LineEQ r
Generic)
pattern LineEQ :: r -> r -> LineEQ r
pattern $bLineEQ :: forall r. r -> r -> LineEQ r
$mLineEQ :: forall {r} {r}. LineEQ r -> (r -> r -> r) -> ((# #) -> r) -> r
LineEQ a b = MkLineEQ (NonVerticalHyperPlane (Vector2 a b))
{-# COMPLETE LineEQ #-}
type instance NumType (LineEQ r) = r
type instance Dimension (LineEQ r) = 2
instance (Show r) => Show (LineEQ r) where
showsPrec :: Int -> LineEQ r -> ShowS
showsPrec Int
k (LineEQ r
a r
b) = Bool -> ShowS -> ShowS
showParen (Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
appPrec) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
String -> ShowS
showString String
"LineEQ "
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> r -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
appPrecInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) r
a
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' '
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> r -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
appPrecInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) r
b
appPrec :: Int
appPrec :: Int
appPrec = Int
10
instance (Read r) => Read (LineEQ r) where
readPrec :: ReadPrec (LineEQ r)
readPrec = ReadPrec (LineEQ r) -> ReadPrec (LineEQ r)
forall a. ReadPrec a -> ReadPrec a
parens (Int -> ReadPrec (LineEQ r) -> ReadPrec (LineEQ r)
forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
appPrec (ReadPrec (LineEQ r) -> ReadPrec (LineEQ r))
-> ReadPrec (LineEQ r) -> ReadPrec (LineEQ r)
forall a b. (a -> b) -> a -> b
$ do
Ident "LineEQ" <- ReadPrec Lexeme
lexP
a <- step readPrec
b <- step readPrec
return (LineEQ a b))
instance ( MkHyperPlaneConstraints 2 r
) => HyperPlane_ (LineEQ r) 2 r where
onHyperPlane :: forall point.
(Point_ point 2 r, Eq r, Num r) =>
point -> LineEQ r -> Bool
onHyperPlane = point -> LineEQ r -> Bool
forall line (d :: Nat) point r.
(HasOnLine line d, Point_ point d r, Num r, Eq r, r ~ NumType line,
d ~ Dimension line) =>
point -> line -> Bool
forall point r.
(Point_ point 2 r, Num r, Eq r, r ~ NumType (LineEQ r),
2 ~ Dimension (LineEQ r)) =>
point -> LineEQ r -> Bool
onLine
instance ( MkHyperPlaneConstraints 2 r
, Fractional r, Eq r
) => ConstructableHyperPlane_ (LineEQ r) 2 r where
hyperPlaneFromEquation :: HyperPlaneFromEquationConstraint (LineEQ r) 2 r =>
Vector (2 + 1) r -> LineEQ r
hyperPlaneFromEquation = NonVerticalHyperPlane 2 r -> LineEQ r
forall r. NonVerticalHyperPlane 2 r -> LineEQ r
MkLineEQ
(NonVerticalHyperPlane 2 r -> LineEQ r)
-> (Vector 3 r -> NonVerticalHyperPlane 2 r)
-> Vector 3 r
-> LineEQ r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall hyperPlane (d :: Nat) r.
(ConstructableHyperPlane_ hyperPlane d r,
HyperPlaneFromEquationConstraint hyperPlane d r) =>
Vector (d + 1) r -> hyperPlane
hyperPlaneFromEquation @(NonVerticalHyperPlane 2 r)
{-# INLINE hyperPlaneFromEquation #-}
fromPointAndNormal :: forall point.
(Point_ point 2 r, Num r) =>
point -> Vector 2 r -> LineEQ r
fromPointAndNormal point
p = NonVerticalHyperPlane 2 r -> LineEQ r
forall r. NonVerticalHyperPlane 2 r -> LineEQ r
MkLineEQ (NonVerticalHyperPlane 2 r -> LineEQ r)
-> (Vector 2 r -> NonVerticalHyperPlane 2 r)
-> Vector 2 r
-> LineEQ r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. point -> Vector 2 r -> NonVerticalHyperPlane 2 r
forall point.
(Point_ point 2 r, Num r) =>
point -> Vector 2 r -> NonVerticalHyperPlane 2 r
forall hyperPlane (d :: Nat) r point.
(ConstructableHyperPlane_ hyperPlane d r, Point_ point d r,
Num r) =>
point -> Vector d r -> hyperPlane
fromPointAndNormal point
p
{-# INLINE fromPointAndNormal #-}
instance ( MkHyperPlaneConstraints 2 r, Num r
) => NonVerticalHyperPlane_ (LineEQ r) 2 r where
evalAt :: forall point.
(Num r, 1 <= 2, Point_ point (2 - 1) r) =>
point -> LineEQ r -> r
evalAt point
p = r -> LineEQ r -> r
forall r. Num r => r -> LineEQ r -> r
evalAt' (r -> LineEQ r -> r) -> r -> LineEQ r -> r
forall a b. (a -> b) -> a -> b
$ point
ppoint -> Getting r point r -> r
forall s a. s -> Getting a s a -> a
^.Getting r point r
forall (d :: Nat) point r.
(1 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int point r
xCoord
hyperPlaneCoefficients :: Lens' (LineEQ r) (Vector 2 r)
hyperPlaneCoefficients = (Vector 2 r -> f (Vector 2 r)) -> LineEQ r -> f (LineEQ r)
forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
Iso (LineEQ r) (LineEQ r) (Vector 2 r) (Vector 2 r)
coerced
instance HasOnLine (LineEQ r) 2 where
onLine :: forall point r.
(Point_ point 2 r, Num r, Eq r, r ~ NumType (LineEQ r),
2 ~ Dimension (LineEQ r)) =>
point -> LineEQ r -> Bool
onLine point
q LineEQ r
l = r -> LineEQ r -> r
forall r. Num r => r -> LineEQ r -> r
evalAt' (point
qpoint -> Getting r point r -> r
forall s a. s -> Getting a s a -> a
^.Getting r point r
forall (d :: Nat) point r.
(1 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int point r
xCoord) LineEQ r
l r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== point
qpoint -> Getting r point r -> r
forall s a. s -> Getting a s a -> a
^.Getting r point r
forall (d :: Nat) point r.
(2 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int point r
yCoord
{-# INLINE onLine #-}
type instance Intersection (LineEQ r) (LineEQ r) =
Maybe (LineLineIntersection (LineEQ r))
instance (Eq r) => HasIntersectionWith (LineEQ r) (LineEQ r) where
(LineEQ r
a r
b) intersects :: LineEQ r -> LineEQ r -> Bool
`intersects` (LineEQ r
a' r
b') = r
a r -> r -> Bool
forall a. Eq a => a -> a -> Bool
/= r
a' Bool -> Bool -> Bool
|| r
b r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
b'
instance (Eq r, Fractional r)
=> IsIntersectableWith (LineEQ r) (LineEQ r) where
l :: LineEQ r
l@(LineEQ r
a r
b) intersect :: LineEQ r -> LineEQ r -> Intersection (LineEQ r) (LineEQ r)
`intersect` (LineEQ r
a' r
b')
| r
a r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
a' = if r
b r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
b' then LineLineIntersectionG r (LineEQ r)
-> Maybe (LineLineIntersectionG r (LineEQ r))
forall a. a -> Maybe a
Just (LineEQ r -> LineLineIntersectionG r (LineEQ r)
forall r line. line -> LineLineIntersectionG r line
Line_x_Line_Line LineEQ r
l) else Maybe (LineLineIntersectionG r (LineEQ r))
Intersection (LineEQ r) (LineEQ r)
forall a. Maybe a
Nothing
| Bool
otherwise = let x :: r
x = (r
b'r -> r -> r
forall a. Num a => a -> a -> a
-r
b) r -> r -> r
forall a. Fractional a => a -> a -> a
/ (r
ar -> r -> r
forall a. Num a => a -> a -> a
-r
a')
in LineLineIntersectionG r (LineEQ r)
-> Maybe (LineLineIntersectionG r (LineEQ r))
LineLineIntersectionG r (LineEQ r)
-> Intersection (LineEQ r) (LineEQ r)
forall a. a -> Maybe a
Just (LineLineIntersectionG r (LineEQ r)
-> Intersection (LineEQ r) (LineEQ r))
-> (Point 2 r -> LineLineIntersectionG r (LineEQ r))
-> Point 2 r
-> Intersection (LineEQ r) (LineEQ r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point 2 r -> LineLineIntersectionG r (LineEQ r)
forall r line. Point 2 r -> LineLineIntersectionG r line
Line_x_Line_Point (Point 2 r -> Intersection (LineEQ r) (LineEQ r))
-> Point 2 r -> Intersection (LineEQ r) (LineEQ r)
forall a b. (a -> b) -> a -> b
$ r -> r -> Point 2 r
forall r. r -> r -> Point 2 r
Point2 r
x (r -> LineEQ r -> r
forall r. Num r => r -> LineEQ r -> r
evalAt' r
x LineEQ r
l)
type instance Intersection (LineEQ r :+ extra) (LineEQ r :+ extra') =
Maybe (LineLineIntersection (LineEQ r :+ extra))
instance (HasIntersectionWith (LineEQ r :+ extra) (LineEQ r :+ extra'), Fractional r, Eq r)
=> IsIntersectableWith (LineEQ r :+ extra) (LineEQ r :+ extra') where
LineEQ r :+ extra
l intersect :: (LineEQ r :+ extra)
-> (LineEQ r :+ extra')
-> Intersection (LineEQ r :+ extra) (LineEQ r :+ extra')
`intersect` LineEQ r :+ extra'
m = LineLineIntersectionG r (LineEQ r)
-> LineLineIntersectionG r (LineEQ r :+ extra)
tag (LineLineIntersectionG r (LineEQ r)
-> LineLineIntersectionG r (LineEQ r :+ extra))
-> Maybe (LineLineIntersectionG r (LineEQ r))
-> Maybe (LineLineIntersectionG r (LineEQ r :+ extra))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (LineEQ r :+ extra
l(LineEQ r :+ extra)
-> Getting (LineEQ r) (LineEQ r :+ extra) (LineEQ r) -> LineEQ r
forall s a. s -> Getting a s a -> a
^.Getting (LineEQ r) (LineEQ r :+ extra) (LineEQ r)
forall core extra core' (f :: * -> *).
Functor f =>
(core -> f core') -> (core :+ extra) -> f (core' :+ extra)
core) LineEQ r -> LineEQ r -> Intersection (LineEQ r) (LineEQ r)
forall g h. IsIntersectableWith g h => g -> h -> Intersection g h
`intersect` (LineEQ r :+ extra'
m(LineEQ r :+ extra')
-> Getting (LineEQ r) (LineEQ r :+ extra') (LineEQ r) -> LineEQ r
forall s a. s -> Getting a s a -> a
^.Getting (LineEQ r) (LineEQ r :+ extra') (LineEQ r)
forall core extra core' (f :: * -> *).
Functor f =>
(core -> f core') -> (core :+ extra) -> f (core' :+ extra)
core)
where
tag :: LineLineIntersectionG r (LineEQ r)
-> LineLineIntersectionG r (LineEQ r :+ extra)
tag = \case
Line_x_Line_Point Point 2 r
p -> Point 2 r -> LineLineIntersectionG r (LineEQ r :+ extra)
forall r line. Point 2 r -> LineLineIntersectionG r line
Line_x_Line_Point Point 2 r
p
Line_x_Line_Line LineEQ r
_lCore -> (LineEQ r :+ extra) -> LineLineIntersectionG r (LineEQ r :+ extra)
forall r line. line -> LineLineIntersectionG r line
Line_x_Line_Line LineEQ r :+ extra
l
type instance Intersection (LineEQ r) (HyperPlane 2 r) =
Maybe (LineLineIntersection (LineEQ r))
instance (Eq r, Fractional r
) => HasIntersectionWith (LineEQ r) (HyperPlane 2 r) where
(LineEQ r
a r
_) intersects :: LineEQ r -> HyperPlane 2 r -> Bool
`intersects` (HyperPlane (Vector3 r
_ r
a' r
b'))
= r
b' r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
0 Bool -> Bool -> Bool
|| r
a r -> r -> Bool
forall a. Eq a => a -> a -> Bool
/= (r
a'r -> r -> r
forall a. Fractional a => a -> a -> a
/ (-r
b'))
instance (Eq r, Fractional r)
=> IsIntersectableWith (LineEQ r) (HyperPlane 2 r) where
l :: LineEQ r
l@(LineEQ r
a r
b) intersect :: LineEQ r
-> HyperPlane 2 r -> Intersection (LineEQ r) (HyperPlane 2 r)
`intersect` (HyperPlane (Vector3 r
c' r
a' r
b'))
| r
b' r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
0 = r -> Maybe (LineLineIntersectionG r (LineEQ r))
point (r -> Maybe (LineLineIntersectionG r (LineEQ r)))
-> r -> Maybe (LineLineIntersectionG r (LineEQ r))
forall a b. (a -> b) -> a -> b
$ r
c'r -> r -> r
forall a. Fractional a => a -> a -> a
/ (-r
a')
| r
a r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
d' = if r
b r -> r -> Bool
forall a. Eq a => a -> a -> Bool
== r
e' then LineLineIntersectionG r (LineEQ r)
-> Maybe (LineLineIntersectionG r (LineEQ r))
forall a. a -> Maybe a
Just (LineEQ r -> LineLineIntersectionG r (LineEQ r)
forall r line. line -> LineLineIntersectionG r line
Line_x_Line_Line LineEQ r
l) else Maybe (LineLineIntersectionG r (LineEQ r))
Intersection (LineEQ r) (HyperPlane 2 r)
forall a. Maybe a
Nothing
| Bool
otherwise = r -> Maybe (LineLineIntersectionG r (LineEQ r))
point (r -> Maybe (LineLineIntersectionG r (LineEQ r)))
-> r -> Maybe (LineLineIntersectionG r (LineEQ r))
forall a b. (a -> b) -> a -> b
$ (r
e'r -> r -> r
forall a. Num a => a -> a -> a
-r
b) r -> r -> r
forall a. Fractional a => a -> a -> a
/ (r
ar -> r -> r
forall a. Num a => a -> a -> a
-r
d')
where
d' :: r
d' = r
a'r -> r -> r
forall a. Fractional a => a -> a -> a
/(-r
b')
e' :: r
e' = r
c'r -> r -> r
forall a. Fractional a => a -> a -> a
/(-r
b')
point :: r -> Maybe (LineLineIntersectionG r (LineEQ r))
point r
x = LineLineIntersectionG r (LineEQ r)
-> Maybe (LineLineIntersectionG r (LineEQ r))
forall a. a -> Maybe a
Just (LineLineIntersectionG r (LineEQ r)
-> Maybe (LineLineIntersectionG r (LineEQ r)))
-> (Point 2 r -> LineLineIntersectionG r (LineEQ r))
-> Point 2 r
-> Maybe (LineLineIntersectionG r (LineEQ r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point 2 r -> LineLineIntersectionG r (LineEQ r)
forall r line. Point 2 r -> LineLineIntersectionG r line
Line_x_Line_Point (Point 2 r -> Maybe (LineLineIntersectionG r (LineEQ r)))
-> Point 2 r -> Maybe (LineLineIntersectionG r (LineEQ r))
forall a b. (a -> b) -> a -> b
$ r -> r -> Point 2 r
forall r. r -> r -> Point 2 r
Point2 r
x (r -> LineEQ r -> r
forall r. Num r => r -> LineEQ r -> r
evalAt' r
x LineEQ r
l)
type instance Intersection (HyperPlane 2 r) (HyperPlane 2 r) =
Maybe (LineLineIntersection (HyperPlane 2 r))
evalAt' :: Num r => r -> LineEQ r -> r
evalAt' :: forall r. Num r => r -> LineEQ r -> r
evalAt' r
x (LineEQ r
a r
b) = r
ar -> r -> r
forall a. Num a => a -> a -> a
*r
x r -> r -> r
forall a. Num a => a -> a -> a
+ r
b