From b3649597fae7aef20a92deb3e0d0e8c80c745ae5 Mon Sep 17 00:00:00 2001 From: jgk Date: Sun, 4 Apr 2021 18:53:43 +0200 Subject: [PATCH] Add haddocks --- src/Dodge/Base.hs | 2 +- src/Geometry.hs | 6 ----- src/Geometry/Bezier.hs | 12 +++++++++ src/Geometry/Data.hs | 1 - src/Geometry/Vector.hs | 61 +++++++++++++++++++++++++++++++++--------- 5 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/Dodge/Base.hs b/src/Dodge/Base.hs index 4f75a6cab..21cfeb529 100644 --- a/src/Dodge/Base.hs +++ b/src/Dodge/Base.hs @@ -761,7 +761,7 @@ logistic x0 l k x = l / (1 + exp (k*(x0 - x))) wallLOS :: [Point2] -> Point2 -> Point2 -> Bool {-# INLINE wallLOS #-} wallLOS !(x:y:_) !c !p = isRHS c x y || isLHS p x' y' || isLHS c p x || isRHS c p y - where n = 10 *.* (normV . vNormal $ y -.- x) + where n = 10 *.* (safeNormalizeV . vNormal $ y -.- x) x' = x +.+ n y' = y +.+ n diff --git a/src/Geometry.hs b/src/Geometry.hs index 1f2e10cdf..ee96bf004 100644 --- a/src/Geometry.hs +++ b/src/Geometry.hs @@ -117,12 +117,6 @@ errorClosestPointOnLineParam !i !x! y! z | x == y = dist x z | otherwise = closestPointOnLineParam x y z --- | Normalize a vector to be unit length. --- For (0,0) return (0,0). -safeNormalizeV :: Point2 -> Point2 -safeNormalizeV !(0,0) = (0,0) -safeNormalizeV !p = normalizeV p - -- | Test whether a point is on the LHS of a line. -- Returns False if the line is of zero length. isLHS diff --git a/src/Geometry/Bezier.hs b/src/Geometry/Bezier.hs index 55b727007..a67bc374c 100644 --- a/src/Geometry/Bezier.hs +++ b/src/Geometry/Bezier.hs @@ -3,8 +3,15 @@ module Geometry.Bezier import Geometry.Data import Geometry.Vector +{- | A synonym describing a quadratic Bezier curve as three 'Point2's: start, +control and end. + -} type BQuad = (Point2,Point2,Point2) +{- | Split a quadratic Bezier curve into two at a fractional point along the +curve. +If the fraction is not between 0 and 1, this will create backwards curves. + -} splitBezierquad :: BQuad -> Float -> (BQuad,BQuad) splitBezierquad (a,b,c) z = ( ( a @@ -17,11 +24,16 @@ splitBezierquad (a,b,c) z ) ) +{- | Split a quadratic Bezier curve into a given number of straight lines, and + return the list of points defining these lines. + -} bQuadToLine :: BQuad -> Int -> [Point2] bQuadToLine (a,_,c) 0 = [a,c] bQuadToLine x i = let (l,r) = splitBezierquad x 0.5 in bQuadToLine l (i-1) ++ bQuadToLine r (i-1) +{- | Transform a quadratic Bezier curve into a function. + -} bQuadToF :: (Point2,Point2,Point2) -> Float -> Point2 bQuadToF (c,b,a) t = t *.* (t *.* a +.+ (1-t) *.* b) +.+ (1-t) *.* (t *.* b +.+ (1-t) *.* c) diff --git a/src/Geometry/Data.hs b/src/Geometry/Data.hs index 8f985d3b7..9a3adf4ad 100644 --- a/src/Geometry/Data.hs +++ b/src/Geometry/Data.hs @@ -4,7 +4,6 @@ module Geometry.Data , Point4 (..) ) where - type Point2 = (Float,Float) type Point3 = (Float,Float,Float) type Point4 = (Float,Float,Float,Float) diff --git a/src/Geometry/Vector.hs b/src/Geometry/Vector.hs index 26a6d1803..afb0deaf7 100644 --- a/src/Geometry/Vector.hs +++ b/src/Geometry/Vector.hs @@ -2,7 +2,8 @@ module Geometry.Vector where import Geometry.Data - +{- | Moves from to three dimensions, adding zero in z direction. + -} zeroZ :: Point2 -> Point3 {-# INLINE zeroZ #-} zeroZ (x,y) = (x,y,0) @@ -10,6 +11,8 @@ zeroZ (x,y) = (x,y,0) infixl 6 +.+, -.- infixl 7 *.* +{- | 2D coordinate-wise addition. + -} (+.+) :: Point2 -> Point2 -> Point2 {-# INLINE (+.+) #-} (x1, y1) +.+ (x2, y2) = @@ -17,7 +20,8 @@ infixl 7 *.* !x = x1 + x2 !y = y1 + y2 in (x, y) - +{- | 2D coordinate-wise subtraction. + -} (-.-) :: Point2 -> Point2 -> Point2 {-# INLINE (-.-) #-} (x1, y1) -.- (x2, y2) = @@ -25,7 +29,8 @@ infixl 7 *.* !x = x1 - x2 !y = y1 - y2 in (x, y) - +{- | 2D scalar multiplication. + -} (*.*) :: Float -> Point2 -> Point2 {-# INLINE (*.*) #-} a *.* (x2, y2) = @@ -37,6 +42,9 @@ a *.* (x2, y2) = infixl 6 +.+.+, -.-.- infixl 7 *.*.* + +{- | 3D coordinate-wise addition. + -} (+.+.+) :: Point3 -> Point3 -> Point3 {-# INLINE (+.+.+) #-} (x1, y1, z1) +.+.+ (x2, y2, z2) = @@ -46,6 +54,8 @@ infixl 7 *.*.* !z = z1 + z2 in (x, y, z) +{- | 3D coordinate-wise subtraction. + -} (-.-.-) :: Point3 -> Point3 -> Point3 {-# INLINE (-.-.-) #-} (x1, y1, z1) -.-.- (x2, y2, z2) = @@ -55,6 +65,8 @@ infixl 7 *.*.* !z = z1 - z2 in (x, y, z) +{- | 3D scalar multiplication. + -} (*.*.*) :: Point3 -> Point3 -> Point3 {-# INLINE (*.*.*) #-} (x1, y1, z1) *.*.* (x2, y2, z2) = @@ -64,10 +76,15 @@ infixl 7 *.*.* !z = z1 * z2 in (x, y, z) +{- | Normalize a vector to length 1. + -} normalizeV :: Point2 -> Point2 {-# INLINE normalizeV #-} normalizeV p = (1 / magV p) *.* p +{- | Angle between two vectors. +Always positive. + -} angleVV :: Point2 -> Point2 -> Float {-# INLINE angleVV #-} angleVV a b = let ma = magV a @@ -75,20 +92,28 @@ angleVV a b = let ma = magV a d = a `dotV` b in acos $ d / (ma * mb) +{- | Dot product. + -} dotV :: Point2 -> Point2 -> Float {-# INLINE dotV #-} dotV (x,y) (z,w) = x*z + y*w +{- | Given vector, returns the angle, anticlockwise from +ve x-axis, in radians. + -} argV :: Point2 -> Float {-# INLINE argV #-} argV (x,y) = normalizeAngle $ atan2 y x +{- | Determinant of the matrix formed by two vectors. + -} detV :: Point2 -> Point2 -> Float {-# INLINE detV #-} detV (x1, y1) (x2, y2) = x1 * y2 - y1 * x2 --- | Angle in radians, anticlockwise from +ve x-axis. +{- | Given an angle in radians, anticlockwise from +ve x-axis, returns the +corresponding unit vector. +-} unitVectorAtAngle :: Float -> Point2 {-# INLINE unitVectorAtAngle #-} unitVectorAtAngle r @@ -106,36 +131,46 @@ degToRad :: Float -> Float degToRad d = d * pi / 180 {-# INLINE degToRad #-} - -- | Convert radians to degrees radToDeg :: Float -> Float radToDeg r = r * 180 / pi {-# INLINE radToDeg #-} - -- | Normalize an angle to be between 0 and 2*pi radians normalizeAngle :: Float -> Float -normalizeAngle f = f - 2 * pi * floor' (f / (2 * pi)) - where floor' :: Float -> Float - floor' x = fromIntegral (floor x :: Int) {-# INLINE normalizeAngle #-} +normalizeAngle f = f - 2 * pi * floor' (f / (2 * pi)) + where + floor' :: Float -> Float + floor' x = fromIntegral (floor x :: Int) +{- | Rotate vector by pi/2 clockwise. + -} vNormal :: Point2 -> Point2 {-# INLINE vNormal #-} vNormal (x,y) = (y,-x) +{- | Negate a vector. + -} vInverse :: Point2 -> Point2 vInverse (x,y) = (-x,-y) -normV :: Point2 -> Point2 -{-# INLINE normV #-} -normV (0,0) = (0,0) -normV p = (1/magV p ) *.* p +{- | Normalize a vector safely: on (0,0) return (0,0). + -} +safeNormalizeV :: Point2 -> Point2 +{-# INLINE safeNormalizeV #-} +safeNormalizeV (0,0) = (0,0) +safeNormalizeV p = (1/magV p ) *.* p +{- | Magnitude of a vector. + -} magV :: Point2 -> Float {-# INLINE magV #-} magV (x,y) = sqrt $ x^2 + y^2 +{- | Magnitude of the cross product of two vectors. +Identical to detV. +-} crossV :: Point2 -> Point2 -> Float crossV (ax,ay) (bx,by) = ax*by - ay*bx