{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Use camelCase" #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.HalfLine
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Half-lines in \(d\)-dimensional space.
--
--------------------------------------------------------------------------------
module HGeometry.HalfLine
  ( HalfLine(..)
  , asOrientedLine
  , halfLineThrough
  , LineHalfLineIntersection(..)
  , HasDirection(..)
  ) where

import Control.Lens
import GHC.Generics (Generic)
import GHC.TypeLits
import HGeometry.HalfSpace
import HGeometry.HyperPlane
import HGeometry.Intersection
import HGeometry.Interval.Class
import HGeometry.Line.Intersection
import HGeometry.Line.Class
import HGeometry.Line.PointAndVector
import HGeometry.Point
import HGeometry.Properties
import HGeometry.Vector
import Text.Read
import Data.Type.Ord

--------------------------------------------------------------------------------

-- | A Halfline in R^d
data HalfLine point = HalfLine !point
                               !(Vector (Dimension point) (NumType point))

type instance Dimension (HalfLine point) = Dimension point
type instance NumType   (HalfLine point) = NumType point

deriving instance ( Eq point, Eq (Vector d r)
                  , d ~ Dimension point, r ~ NumType point) => Eq (HalfLine point)

instance ( Show point, Show r, d ~ Dimension point, r ~ NumType point
         , KnownNat d, Has_ Additive_ d r
         ) => Show (HalfLine point) where
  showsPrec :: Int -> HalfLine point -> ShowS
showsPrec Int
k (HalfLine point
p Vector (Dimension point) (NumType point)
v) = 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
"HalfLine "
                               ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> point -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
appPrecInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) point
p
                               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 -> Vector d r -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
appPrecInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Vector d r
Vector (Dimension point) (NumType point)
v

-- instance ( Show r, KnownNat d, Has_ Additive_ d r
--          ) => Show (HalfLine d r) where

appPrec :: Int
appPrec :: Int
appPrec = Int
10

instance ( Read r, Read point, Has_ Additive_ d r, KnownNat d
         , d ~ Dimension point, r ~ NumType point
         ) => Read (HalfLine point) where
  readPrec :: ReadPrec (HalfLine point)
readPrec = ReadPrec (HalfLine point) -> ReadPrec (HalfLine point)
forall a. ReadPrec a -> ReadPrec a
parens (Int -> ReadPrec (HalfLine point) -> ReadPrec (HalfLine point)
forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
appPrec (ReadPrec (HalfLine point) -> ReadPrec (HalfLine point))
-> ReadPrec (HalfLine point) -> ReadPrec (HalfLine point)
forall a b. (a -> b) -> a -> b
$ do
                        Ident "HalfLine" <- ReadPrec Lexeme
lexP
                        p <- step readPrec
                        v <- step readPrec
                        pure (HalfLine p v))

instance HasStart (HalfLine point) point where
  start :: Lens' (HalfLine point) point
start = (HalfLine point -> point)
-> (HalfLine point -> point -> HalfLine point)
-> Lens' (HalfLine point) point
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(HalfLine point
p Vector (Dimension point) (NumType point)
_) -> point
p) (\(HalfLine point
_ Vector (Dimension point) (NumType point)
v) point
p -> point -> Vector (Dimension point) (NumType point) -> HalfLine point
forall point.
point -> Vector (Dimension point) (NumType point) -> HalfLine point
HalfLine point
p Vector (Dimension point) (NumType point)
v)
  {-# INLINE start #-}

instance HasDirection (HalfLine point) where
  direction :: forall (d :: Nat) r.
(Dimension (HalfLine point) ~ d, NumType (HalfLine point) ~ r) =>
Lens' (HalfLine point) (Vector d r)
direction = (HalfLine point -> Vector d r)
-> (HalfLine point -> Vector d r -> HalfLine point)
-> Lens (HalfLine point) (HalfLine point) (Vector d r) (Vector d r)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(HalfLine point
_ Vector (Dimension point) (NumType point)
v) -> Vector d r
Vector (Dimension point) (NumType point)
v) (\(HalfLine point
p Vector (Dimension point) (NumType point)
_) Vector d r
v -> point -> Vector (Dimension point) (NumType point) -> HalfLine point
forall point.
point -> Vector (Dimension point) (NumType point) -> HalfLine point
HalfLine point
p Vector d r
Vector (Dimension point) (NumType point)
v)
  {-# INLINE direction #-}

instance Point_ point d r => HasSupportingLine (HalfLine point) where
  supportingLine :: HalfLine point
-> LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
supportingLine (HalfLine point
p Vector (Dimension point) (NumType point)
v) = Point d r -> Vector d r -> LinePV d r
forall (d :: Nat) r. Point d r -> Vector d r -> LinePV d r
LinePV (point
ppoint -> Getting (Point d r) point (Point d r) -> Point d r
forall s a. s -> Getting a s a -> a
^.Getting (Point d r) point (Point d r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point d r)
asPoint) Vector d r
Vector (Dimension point) (NumType point)
v
  {-# INLINE supportingLine #-}

--------------------------------------------------------------------------------

instance ( Point_ point d r, Ord r, Num r
         , HasOnLine (LinePV d r) d
         , Has_ Metric_ d r
         , Has_ Metric_ (d+1) r, Has_ Vector_ (1+d) r
         , d < d+1, d <= d + 1 -- TODO: these constraints are silly
         ) => Point d r `HasIntersectionWith` HalfLine point where
  Point d r
q intersects :: Point d r -> HalfLine point -> Bool
`intersects` HalfLine point
hl = Point d r
q Point d r -> LinePV d 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 d r, Num r, Eq r, r ~ NumType (LinePV d r),
 d ~ Dimension (LinePV d r)) =>
point -> LinePV d r -> Bool
`onLine` LinePV d r
l Bool -> Bool -> Bool
&& Point d r
q Point d r -> HalfSpaceF (HyperPlane d r) -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` Sign -> HyperPlane d r -> HalfSpaceF (HyperPlane d r)
forall boundingHyperPlane.
Sign -> boundingHyperPlane -> HalfSpaceF boundingHyperPlane
HalfSpace Sign
Positive HyperPlane d r
h
    where
      l :: LinePV d r
l@(LinePV Point d r
p Vector d r
v) = HalfLine point -> LinePV d r
forall point (d :: Nat) r.
Point_ point d r =>
HalfLine point -> LinePV d r
asOrientedLine HalfLine point
hl
      h :: HyperPlane d r
h              = Point d r -> Vector d r -> HyperPlane d r
forall point.
(Point_ point d r, Num r) =>
point -> Vector d r -> HyperPlane d r
forall hyperPlane (d :: Nat) r point.
(ConstructableHyperPlane_ hyperPlane d r, Point_ point d r,
 Num r) =>
point -> Vector d r -> hyperPlane
fromPointAndNormal Point d r
p Vector d r
v :: HyperPlane d r


instance (Ord r, Num r, Point_ point 2 r
         ) => HasIntersectionWith (LinePV 2 r) (HalfLine point) where
  l :: LinePV 2 r
l@(LinePV Point 2 r
_ Vector 2 r
u) intersects :: LinePV 2 r -> HalfLine point -> Bool
`intersects` (HalfLine point
q Vector (Dimension point) (NumType point)
w) = case point
q point -> LinePV 2 r -> SideTest
forall r point.
(Ord r, Num r, Point_ point 2 r) =>
point -> LinePV 2 r -> SideTest
`onSide` LinePV 2 r
l of
      SideTest
OnLine    -> Bool
True
      SideTest
LeftSide  -> (point
q point -> Vector 2 r -> point
forall point (d :: Nat) r.
(Affine_ point d r, Num r) =>
point -> Vector d r -> point
.+^ Vector 2 r
Vector (Dimension point) (NumType point)
w) point -> LinePV 2 r -> SideTest
forall r point.
(Ord r, Num r, Point_ point 2 r) =>
point -> LinePV 2 r -> SideTest
`onSide` LinePV 2 r
l' SideTest -> SideTest -> Bool
forall a. Eq a => a -> a -> Bool
== SideTest
RightSide
      SideTest
RightSide -> (point
q point -> Vector 2 r -> point
forall point (d :: Nat) r.
(Affine_ point d r, Num r) =>
point -> Vector d r -> point
.+^ Vector 2 r
Vector (Dimension point) (NumType point)
w) point -> LinePV 2 r -> SideTest
forall r point.
(Ord r, Num r, Point_ point 2 r) =>
point -> LinePV 2 r -> SideTest
`onSide` LinePV 2 r
l' SideTest -> SideTest -> Bool
forall a. Eq a => a -> a -> Bool
== SideTest
LeftSide
    where
      l' :: LinePV 2 r
l' = Point 2 r -> Vector 2 r -> LinePV 2 r
forall (d :: Nat) r. Point d r -> Vector d r -> LinePV d r
LinePV (point
qpoint -> Getting (Point 2 r) point (Point 2 r) -> Point 2 r
forall s a. s -> Getting a s a -> a
^.Getting (Point 2 r) point (Point 2 r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point 2 r)
asPoint) Vector 2 r
u
    -- we construct a line l' parallel to l that goes through the startPoint of our
    -- ray/halfline.
    --
    -- Now if the start point was left of l, going in the direction of the ray we must end
    -- up right of l'. Symmetrically, if the starting point was right of the ray, we must
    -- go left to intersect instead.

type instance Intersection (LinePV 2 r) (HalfLine point) =
  Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))

-- | Data type representing the intersection of a Line and a HalfLine
data LineHalfLineIntersection point halfLine =
      Line_x_HalfLine_Point    point
    | Line_x_HalfLine_HalfLine halfLine
  deriving (Int -> LineHalfLineIntersection point halfLine -> ShowS
[LineHalfLineIntersection point halfLine] -> ShowS
LineHalfLineIntersection point halfLine -> String
(Int -> LineHalfLineIntersection point halfLine -> ShowS)
-> (LineHalfLineIntersection point halfLine -> String)
-> ([LineHalfLineIntersection point halfLine] -> ShowS)
-> Show (LineHalfLineIntersection point halfLine)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall point halfLine.
(Show point, Show halfLine) =>
Int -> LineHalfLineIntersection point halfLine -> ShowS
forall point halfLine.
(Show point, Show halfLine) =>
[LineHalfLineIntersection point halfLine] -> ShowS
forall point halfLine.
(Show point, Show halfLine) =>
LineHalfLineIntersection point halfLine -> String
$cshowsPrec :: forall point halfLine.
(Show point, Show halfLine) =>
Int -> LineHalfLineIntersection point halfLine -> ShowS
showsPrec :: Int -> LineHalfLineIntersection point halfLine -> ShowS
$cshow :: forall point halfLine.
(Show point, Show halfLine) =>
LineHalfLineIntersection point halfLine -> String
show :: LineHalfLineIntersection point halfLine -> String
$cshowList :: forall point halfLine.
(Show point, Show halfLine) =>
[LineHalfLineIntersection point halfLine] -> ShowS
showList :: [LineHalfLineIntersection point halfLine] -> ShowS
Show,LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
(LineHalfLineIntersection point halfLine
 -> LineHalfLineIntersection point halfLine -> Bool)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine -> Bool)
-> Eq (LineHalfLineIntersection point halfLine)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall point halfLine.
(Eq point, Eq halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$c== :: forall point halfLine.
(Eq point, Eq halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
== :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$c/= :: forall point halfLine.
(Eq point, Eq halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
/= :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
Eq,ReadPrec [LineHalfLineIntersection point halfLine]
ReadPrec (LineHalfLineIntersection point halfLine)
Int -> ReadS (LineHalfLineIntersection point halfLine)
ReadS [LineHalfLineIntersection point halfLine]
(Int -> ReadS (LineHalfLineIntersection point halfLine))
-> ReadS [LineHalfLineIntersection point halfLine]
-> ReadPrec (LineHalfLineIntersection point halfLine)
-> ReadPrec [LineHalfLineIntersection point halfLine]
-> Read (LineHalfLineIntersection point halfLine)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall point halfLine.
(Read point, Read halfLine) =>
ReadPrec [LineHalfLineIntersection point halfLine]
forall point halfLine.
(Read point, Read halfLine) =>
ReadPrec (LineHalfLineIntersection point halfLine)
forall point halfLine.
(Read point, Read halfLine) =>
Int -> ReadS (LineHalfLineIntersection point halfLine)
forall point halfLine.
(Read point, Read halfLine) =>
ReadS [LineHalfLineIntersection point halfLine]
$creadsPrec :: forall point halfLine.
(Read point, Read halfLine) =>
Int -> ReadS (LineHalfLineIntersection point halfLine)
readsPrec :: Int -> ReadS (LineHalfLineIntersection point halfLine)
$creadList :: forall point halfLine.
(Read point, Read halfLine) =>
ReadS [LineHalfLineIntersection point halfLine]
readList :: ReadS [LineHalfLineIntersection point halfLine]
$creadPrec :: forall point halfLine.
(Read point, Read halfLine) =>
ReadPrec (LineHalfLineIntersection point halfLine)
readPrec :: ReadPrec (LineHalfLineIntersection point halfLine)
$creadListPrec :: forall point halfLine.
(Read point, Read halfLine) =>
ReadPrec [LineHalfLineIntersection point halfLine]
readListPrec :: ReadPrec [LineHalfLineIntersection point halfLine]
Read,Eq (LineHalfLineIntersection point halfLine)
Eq (LineHalfLineIntersection point halfLine) =>
(LineHalfLineIntersection point halfLine
 -> LineHalfLineIntersection point halfLine -> Ordering)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine -> Bool)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine -> Bool)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine -> Bool)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine -> Bool)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine)
-> (LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine
    -> LineHalfLineIntersection point halfLine)
-> Ord (LineHalfLineIntersection point halfLine)
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Ordering
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
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 point halfLine.
(Ord point, Ord halfLine) =>
Eq (LineHalfLineIntersection point halfLine)
forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Ordering
forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
$ccompare :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Ordering
compare :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Ordering
$c< :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
< :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$c<= :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
<= :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$c> :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
> :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$c>= :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
>= :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine -> Bool
$cmax :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
max :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
$cmin :: forall point halfLine.
(Ord point, Ord halfLine) =>
LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
min :: LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
-> LineHalfLineIntersection point halfLine
Ord,(forall x.
 LineHalfLineIntersection point halfLine
 -> Rep (LineHalfLineIntersection point halfLine) x)
-> (forall x.
    Rep (LineHalfLineIntersection point halfLine) x
    -> LineHalfLineIntersection point halfLine)
-> Generic (LineHalfLineIntersection point halfLine)
forall x.
Rep (LineHalfLineIntersection point halfLine) x
-> LineHalfLineIntersection point halfLine
forall x.
LineHalfLineIntersection point halfLine
-> Rep (LineHalfLineIntersection point halfLine) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall point halfLine x.
Rep (LineHalfLineIntersection point halfLine) x
-> LineHalfLineIntersection point halfLine
forall point halfLine x.
LineHalfLineIntersection point halfLine
-> Rep (LineHalfLineIntersection point halfLine) x
$cfrom :: forall point halfLine x.
LineHalfLineIntersection point halfLine
-> Rep (LineHalfLineIntersection point halfLine) x
from :: forall x.
LineHalfLineIntersection point halfLine
-> Rep (LineHalfLineIntersection point halfLine) x
$cto :: forall point halfLine x.
Rep (LineHalfLineIntersection point halfLine) x
-> LineHalfLineIntersection point halfLine
to :: forall x.
Rep (LineHalfLineIntersection point halfLine) x
-> LineHalfLineIntersection point halfLine
Generic,(forall a b.
 (a -> b)
 -> LineHalfLineIntersection point a
 -> LineHalfLineIntersection point b)
-> (forall a b.
    a
    -> LineHalfLineIntersection point b
    -> LineHalfLineIntersection point a)
-> Functor (LineHalfLineIntersection point)
forall a b.
a
-> LineHalfLineIntersection point b
-> LineHalfLineIntersection point a
forall a b.
(a -> b)
-> LineHalfLineIntersection point a
-> LineHalfLineIntersection point b
forall point a b.
a
-> LineHalfLineIntersection point b
-> LineHalfLineIntersection point a
forall point a b.
(a -> b)
-> LineHalfLineIntersection point a
-> LineHalfLineIntersection point b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall point a b.
(a -> b)
-> LineHalfLineIntersection point a
-> LineHalfLineIntersection point b
fmap :: forall a b.
(a -> b)
-> LineHalfLineIntersection point a
-> LineHalfLineIntersection point b
$c<$ :: forall point a b.
a
-> LineHalfLineIntersection point b
-> LineHalfLineIntersection point a
<$ :: forall a b.
a
-> LineHalfLineIntersection point b
-> LineHalfLineIntersection point a
Functor)


instance ( Ord r, Fractional r, Point_ point 2 r
         ) => IsIntersectableWith (LinePV 2 r) (HalfLine point) where
  LinePV 2 r
l intersect :: LinePV 2 r
-> HalfLine point -> Intersection (LinePV 2 r) (HalfLine point)
`intersect` HalfLine point
hl = LinePV 2 r
LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
m LinePV 2 r -> LinePV 2 r -> Intersection (LinePV 2 r) (LinePV 2 r)
forall g h. IsIntersectableWith g h => g -> h -> Intersection g h
`intersect` LinePV 2 r
l Maybe (LineLineIntersectionG r (LinePV 2 r))
-> (LineLineIntersectionG r (LinePV 2 r)
    -> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point)))
-> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Line_x_Line_Point Point 2 r
p
        | Point 2 r
p Point 2 r -> LinePV 2 r -> SideTest
forall r point.
(Ord r, Num r, Point_ point 2 r) =>
point -> LinePV 2 r -> SideTest
`onSide` LinePV 2 r -> LinePV 2 r
forall r. Num r => LinePV 2 r -> LinePV 2 r
perpendicularTo LinePV 2 r
LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
m SideTest -> SideTest -> Bool
forall a. Eq a => a -> a -> Bool
== SideTest
LeftSide -> LineHalfLineIntersection (Point 2 r) (HalfLine point)
-> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a. a -> Maybe a
Just (LineHalfLineIntersection (Point 2 r) (HalfLine point)
 -> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point)))
-> LineHalfLineIntersection (Point 2 r) (HalfLine point)
-> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a b. (a -> b) -> a -> b
$ Point 2 r -> LineHalfLineIntersection (Point 2 r) (HalfLine point)
forall point halfLine.
point -> LineHalfLineIntersection point halfLine
Line_x_HalfLine_Point Point 2 r
p
        | Bool
otherwise                                -> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a. Maybe a
Nothing
      Line_x_Line_Line LinePV 2 r
_                           -> LineHalfLineIntersection (Point 2 r) (HalfLine point)
-> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a. a -> Maybe a
Just (LineHalfLineIntersection (Point 2 r) (HalfLine point)
 -> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point)))
-> LineHalfLineIntersection (Point 2 r) (HalfLine point)
-> Maybe (LineHalfLineIntersection (Point 2 r) (HalfLine point))
forall a b. (a -> b) -> a -> b
$ HalfLine point
-> LineHalfLineIntersection (Point 2 r) (HalfLine point)
forall point halfLine.
halfLine -> LineHalfLineIntersection point halfLine
Line_x_HalfLine_HalfLine HalfLine point
hl
    where
      m :: LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
m = HalfLine point
-> LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
forall t.
HasSupportingLine t =>
t -> LinePV (Dimension t) (NumType t)
supportingLine HalfLine point
hl
    -- the left side is suposedly the halfplane containing the halfLine

--------------------------------------------------------------------------------

instance ( Point_ point d r
         , Has_ Metric_ d r
         , Ord r, Fractional r
         , MkHyperPlaneConstraints d r
         ) => HasSquaredEuclideanDistance (HalfLine point) where
  pointClosestTo :: forall r (d :: Nat) point.
(r ~ NumType (HalfLine point), d ~ Dimension (HalfLine point),
 Num r, Point_ point d r) =>
point -> HalfLine point -> Point d r
pointClosestTo point
q hl :: HalfLine point
hl@(HalfLine point
p Vector (Dimension point) (NumType point)
v)
      | Point d r
r Point d r -> HalfSpace d r -> Bool
forall g h. HasIntersectionWith g h => g -> h -> Bool
`intersects` HalfSpace d r
h = Point d r
r
      | Bool
otherwise        = Point d r
p'
    where
      p' :: Point d r
p' = point
ppoint -> Getting (Point d r) point (Point d r) -> Point d r
forall s a. s -> Getting a s a -> a
^.Getting (Point d r) point (Point d r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point d r)
asPoint
      r :: Point d r
r  = point -> LinePV d r -> Point d r
forall g r (d :: Nat) point.
(HasSquaredEuclideanDistance g, r ~ NumType g, d ~ Dimension g,
 Num r, Point_ point d r) =>
point -> g -> Point d r
forall r (d :: Nat) point.
(r ~ NumType (LinePV d r), d ~ Dimension (LinePV d r), Num r,
 Point_ point d r) =>
point -> LinePV d r -> Point d r
pointClosestTo point
q (HalfLine point
-> LinePV (Dimension (HalfLine point)) (NumType (HalfLine point))
forall t.
HasSupportingLine t =>
t -> LinePV (Dimension t) (NumType t)
supportingLine HalfLine point
hl)
      h :: HalfSpace d r
h  = Sign -> HyperPlane d r -> HalfSpace d r
forall boundingHyperPlane.
Sign -> boundingHyperPlane -> HalfSpaceF boundingHyperPlane
HalfSpace Sign
Positive (Point d r -> Vector d r -> HyperPlane d r
forall point.
(Point_ point d r, Num r) =>
point -> Vector d r -> HyperPlane d r
forall hyperPlane (d :: Nat) r point.
(ConstructableHyperPlane_ hyperPlane d r, Point_ point d r,
 Num r) =>
point -> Vector d r -> hyperPlane
fromPointAndNormal Point d r
p' Vector d r
Vector (Dimension point) (NumType point)
v) :: HalfSpace d r
  -- main idea: compute the point closest to the supporting line of the halfline.  if this
  -- point lies in the halfspace h defined by the ray (e.g. for which the ray is the
  -- normal), then we've actually found the point closest to the ray. Otherwise the origin
  -- of the ray is simply the closest point.



--------------------------------------------------------------------------------

-- | Given two points p and q, create a halfline from p through q.
--
-- >>> halfLineThrough (Point2 5 10) (Point2 10 30 :: Point 2 Int)
-- HalfLine (Point2 5 10) (Vector2 5 20)
halfLineThrough     :: (Point_ point d r, Num r) => point -> point -> HalfLine point
halfLineThrough :: forall point (d :: Nat) r.
(Point_ point d r, Num r) =>
point -> point -> HalfLine point
halfLineThrough point
p point
q = point -> Vector (Dimension point) (NumType point) -> HalfLine point
forall point.
point -> Vector (Dimension point) (NumType point) -> HalfLine point
HalfLine point
p (point
q point -> point -> Vector d r
forall point (d :: Nat) r.
(Affine_ point d r, Num r) =>
point -> point -> Vector d r
.-. point
p)


-- | Convert the Halfline into an oriented line.
asOrientedLine                :: (Point_ point d r) => HalfLine point -> LinePV d r
asOrientedLine :: forall point (d :: Nat) r.
Point_ point d r =>
HalfLine point -> LinePV d r
asOrientedLine (HalfLine point
p Vector (Dimension point) (NumType point)
v) = Point d r -> Vector d r -> LinePV d r
forall (d :: Nat) r. Point d r -> Vector d r -> LinePV d r
LinePV (point
ppoint -> Getting (Point d r) point (Point d r) -> Point d r
forall s a. s -> Getting a s a -> a
^.Getting (Point d r) point (Point d r)
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point d r)
asPoint) Vector d r
Vector (Dimension point) (NumType point)
v