GeomPredicates-0.1: Numeric/Geometric/Predicates/Rational.hs
{-# LANGUAGE UnicodeSyntax #-}
module Numeric.Geometric.Predicates.Rational where
import Numeric.Geometric.Primitives
-- | Counter-clockwise orientation test. Classifies p3 in relation to the line formed by p1 and p2.
ccw ∷ Vector2 Rational → Vector2 Rational → Vector2 Rational
→ Ordering -- ^ LT=Right, GT=Left, EQ=Coincident
ccw (x1,y1) (x2,y2) (x3,y3) = compare result 0
where
result = (x1*y2) + (x2*y3) + (x3*y1) - (x1*y3) - (x2*y1) - (x3*y2)
-- | Test the relation of a point to the circle formed by (p1..p3).
incircle ∷ (Vector2 Rational, Vector2 Rational, Vector2 Rational) -- ^ 3 points on the circle, must be in counterclockwise order.
→ Vector2 Rational -- ^ Query point
→ Ordering -- ^ GT=inside, EQ=border, LT=outside
incircle (p1,p2,p3) p4 = compare result 0
where
result = (d p1) * (ccw' p2 p3 p4)
- (d p2) * (ccw' p1 p3 p4)
+ (d p3) * (ccw' p1 p2 p4)
- (d p4) * (ccw' p1 p2 p3)
d (x,y) = (x*x) + (y*y)
ccw' (x1,y1) (x2,y2) (x3,y3) = (x1*y2) + (x2*y3) + (x3*y1) - (x1*y3) - (x2*y1) - (x3*y2)
-- | Test if Point is within the closed interval specified
cintt ∷ Rational -- ^ Lo
→ Rational -- ^ Hi
→ Rational -- ^ Point
→ Bool
cintt x1 x2 p | x1 == x2 = p == x1
| otherwise = t >= 0 && t <= 1
where
t = (u - p) / (-v)
u = x1
v = x2 - x1
-- | Calculate the point of intersecton. Assumes the input lines are already known to be intersecting,
isctp ∷ LineSegment (Vector2 Rational) → LineSegment (Vector2 Rational) → Vector2 Rational
isctp ((ax,ay),(bx,by)) ((cx,cy),(dx,dy)) = (x,y)
where
rtop = (ay-cy)*(dx-cx)-(ax-cx)*(dy-cy)
rbot = (bx-ax)*(dy-cy)-(by-ay)*(dx-cx)
r = rtop/rbot
x = ax + r * (bx - ax)
y = ay + r * (by - ay)