{-# LANGUAGE PatternGuards #-}
module Graphics.Gloss.Geometry.Line
( segClearsBox
, closestPointOnLine
, closestPointOnLineParam
, intersectLineLine
, intersectSegLine
, intersectSegHorzLine
, intersectSegVertLine
, intersectSegSeg
, intersectSegHorzSeg
, intersectSegVertSeg)
where
import Graphics.Gloss.Data.Point
import Graphics.Gloss.Data.Vector
import qualified Graphics.Gloss.Data.Point.Arithmetic as Pt
segClearsBox
:: Point
-> Point
-> Point
-> Point
-> Bool
segClearsBox :: Point -> Point -> Point -> Point -> Bool
segClearsBox (Float
x1, Float
y1) (Float
x2, Float
y2) (Float
xa, Float
ya) (Float
xb, Float
yb)
| Float
x1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
xa, Float
x2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
xa = Bool
True
| Float
x1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
xb, Float
x2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
xb = Bool
True
| Float
y1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
ya, Float
y2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
ya = Bool
True
| Float
y1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
yb, Float
y2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
yb = Bool
True
| Bool
otherwise = Bool
False
closestPointOnLine
:: Point
-> Point
-> Point
-> Point
{-# INLINE closestPointOnLine #-}
closestPointOnLine :: Point -> Point -> Point -> Point
closestPointOnLine Point
p1 Point
p2 Point
p3
= Point
p1 Point -> Point -> Point
Pt.+ (Float
u Float -> Point -> Point
`mulSV` (Point
p2 Point -> Point -> Point
Pt.- Point
p1))
where u :: Float
u = Point -> Point -> Point -> Float
closestPointOnLineParam Point
p1 Point
p2 Point
p3
{-# INLINE closestPointOnLineParam #-}
closestPointOnLineParam
:: Point
-> Point
-> Point
-> Float
closestPointOnLineParam :: Point -> Point -> Point -> Float
closestPointOnLineParam Point
p1 Point
p2 Point
p3
= (Point
p3 Point -> Point -> Point
Pt.- Point
p1) Point -> Point -> Float
`dotV` (Point
p2 Point -> Point -> Point
Pt.- Point
p1)
Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Point
p2 Point -> Point -> Point
Pt.- Point
p1) Point -> Point -> Float
`dotV` (Point
p2 Point -> Point -> Point
Pt.- Point
p1)
intersectLineLine
:: Point
-> Point
-> Point
-> Point
-> Maybe Point
intersectLineLine :: Point -> Point -> Point -> Point -> Maybe Point
intersectLineLine (Float
x1, Float
y1) (Float
x2, Float
y2) (Float
x3, Float
y3) (Float
x4, Float
y4)
= let dx12 :: Float
dx12 = Float
x1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x2
dx34 :: Float
dx34 = Float
x3 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x4
dy12 :: Float
dy12 = Float
y1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y2
dy34 :: Float
dy34 = Float
y3 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y4
den :: Float
den = Float
dx12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
dy34 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
dy12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
dx34
in if Float
den Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0
then Maybe Point
forall a. Maybe a
Nothing
else let
det12 :: Float
det12 = Float
x1Float -> Float -> Float
forall a. Num a => a -> a -> a
*Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1Float -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x2
det34 :: Float
det34 = Float
x3Float -> Float -> Float
forall a. Num a => a -> a -> a
*Float
y4 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y3Float -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x4
numx :: Float
numx = Float
det12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
dx34 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
dx12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
det34
numy :: Float
numy = Float
det12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
dy34 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
dy12 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
det34
in Point -> Maybe Point
forall a. a -> Maybe a
Just (Float
numx Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
den, Float
numy Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
den)
intersectSegLine
:: Point
-> Point
-> Point
-> Point
-> Maybe Point
intersectSegLine :: Point -> Point -> Point -> Point -> Maybe Point
intersectSegLine Point
p1 Point
p2 Point
p3 Point
p4
| Just Point
p0 <- Point -> Point -> Point -> Point -> Maybe Point
intersectLineLine Point
p1 Point
p2 Point
p3 Point
p4
, Float
t12 <- Point -> Point -> Point -> Float
closestPointOnLineParam Point
p1 Point
p2 Point
p0
, Float
t12 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
0 Bool -> Bool -> Bool
&& Float
t12 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
1
= Point -> Maybe Point
forall a. a -> Maybe a
Just Point
p0
| Bool
otherwise
= Maybe Point
forall a. Maybe a
Nothing
intersectSegHorzLine
:: Point
-> Point
-> Float
-> Maybe Point
intersectSegHorzLine :: Point -> Point -> Float -> Maybe Point
intersectSegHorzLine (Float
x1, Float
y1) (Float
x2, Float
y2) Float
y0
| Float
y1 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
y0, Float
y2 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
y0 = Maybe Point
forall a. Maybe a
Nothing
| Float
y1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y0, Float
y2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
y0 = Maybe Point
forall a. Maybe a
Nothing
| Float
y1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y0, Float
y2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
y0 = Maybe Point
forall a. Maybe a
Nothing
| Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0
= Point -> Maybe Point
forall a. a -> Maybe a
Just (Float
x1, Float
y1)
| Bool
otherwise
= Point -> Maybe Point
forall a. a -> Maybe a
Just ( (Float
y0 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* (Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
x1
, Float
y0)
intersectSegVertLine
:: Point
-> Point
-> Float
-> Maybe Point
intersectSegVertLine :: Point -> Point -> Float -> Maybe Point
intersectSegVertLine (Float
x1, Float
y1) (Float
x2, Float
y2) Float
x0
| Float
x1 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
x0, Float
x2 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
x0 = Maybe Point
forall a. Maybe a
Nothing
| Float
x1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
x0, Float
x2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
x0 = Maybe Point
forall a. Maybe a
Nothing
| Float
x1 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
x0, Float
x2 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
x0 = Maybe Point
forall a. Maybe a
Nothing
| Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1 Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0
= Point -> Maybe Point
forall a. a -> Maybe a
Just (Float
x1, Float
y1)
| Bool
otherwise
= Point -> Maybe Point
forall a. a -> Maybe a
Just ( Float
x0
, (Float
x0 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* (Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y1)
intersectSegSeg
:: Point
-> Point
-> Point
-> Point
-> Maybe Point
intersectSegSeg :: Point -> Point -> Point -> Point -> Maybe Point
intersectSegSeg Point
p1 Point
p2 Point
p3 Point
p4
| Just Point
p0 <- Point -> Point -> Point -> Point -> Maybe Point
intersectLineLine Point
p1 Point
p2 Point
p3 Point
p4
, Float
t12 <- Point -> Point -> Point -> Float
closestPointOnLineParam Point
p1 Point
p2 Point
p0
, Float
t23 <- Point -> Point -> Point -> Float
closestPointOnLineParam Point
p3 Point
p4 Point
p0
, Float
t12 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
0 Bool -> Bool -> Bool
&& Float
t12 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
1
, Float
t23 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
>= Float
0 Bool -> Bool -> Bool
&& Float
t23 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
1
= Point -> Maybe Point
forall a. a -> Maybe a
Just Point
p0
| Bool
otherwise
= Maybe Point
forall a. Maybe a
Nothing
intersectSegHorzSeg
:: Point
-> Point
-> Float
-> Float
-> Float
-> Maybe Point
intersectSegHorzSeg :: Point -> Point -> Float -> Float -> Float -> Maybe Point
intersectSegHorzSeg p1 :: Point
p1@(Float
x1, Float
y1) p2 :: Point
p2@(Float
x2, Float
y2) Float
y0 Float
xa Float
xb
| Point -> Point -> Point -> Point -> Bool
segClearsBox Point
p1 Point
p2 (Float
xa, Float
y0) (Float
xb, Float
y0)
= Maybe Point
forall a. Maybe a
Nothing
| Float
x0 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
xa = Maybe Point
forall a. Maybe a
Nothing
| Float
x0 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
xb = Maybe Point
forall a. Maybe a
Nothing
| Bool
otherwise = Point -> Maybe Point
forall a. a -> Maybe a
Just (Float
x0, Float
y0)
where x0 :: Float
x0 | (Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0 = Float
x1
| Bool
otherwise = (Float
y0 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* (Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
x1
intersectSegVertSeg
:: Point
-> Point
-> Float
-> Float
-> Float
-> Maybe Point
intersectSegVertSeg :: Point -> Point -> Float -> Float -> Float -> Maybe Point
intersectSegVertSeg p1 :: Point
p1@(Float
x1, Float
y1) p2 :: Point
p2@(Float
x2, Float
y2) Float
x0 Float
ya Float
yb
| Point -> Point -> Point -> Point -> Bool
segClearsBox Point
p1 Point
p2 (Float
x0, Float
ya) (Float
x0, Float
yb)
= Maybe Point
forall a. Maybe a
Nothing
| Float
y0 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
ya = Maybe Point
forall a. Maybe a
Nothing
| Float
y0 Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
yb = Maybe Point
forall a. Maybe a
Nothing
| Bool
otherwise = Point -> Maybe Point
forall a. a -> Maybe a
Just (Float
x0, Float
y0)
where y0 :: Float
y0 | (Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0 = Float
y1
| Bool
otherwise = (Float
x0 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Num a => a -> a -> a
* (Float
y2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y1) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
x2 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
x1) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y1