Portability | GHC with TypeFamilies and more |
---|---|
Stability | unstable |
Maintainer | stephen.tetley@gmail.com |
Objects and operations for 2D geometry.
Vector, point, affine frame, 3x3 matrix, and radian
representations, plus a type family DUnit
for parameterizing
type classes with some dimension.
- type family DUnit a :: *
- data Vec2 u = V2 !u !u
- type DVec2 = Vec2 Double
- data Point2 u = P2 !u !u
- type DPoint2 = Point2 Double
- data Frame2 u = Frame2 (Vec2 u) (Vec2 u) (Point2 u)
- type DFrame2 = Frame2 Double
- data Matrix3'3 u = M3'3 !u !u !u !u !u !u !u !u !u
- type DMatrix3'3 = Matrix3'3 Double
- data Radian
- class Pointwise sh where
- class MatrixMult t where
- vec :: Num u => u -> u -> Vec2 u
- hvec :: Num u => u -> Vec2 u
- vvec :: Num u => u -> Vec2 u
- avec :: Floating u => Radian -> u -> Vec2 u
- pvec :: Num u => Point2 u -> Point2 u -> Vec2 u
- direction :: (Floating u, Real u) => Vec2 u -> Radian
- vlength :: Floating u => Vec2 u -> u
- vangle :: (Floating u, Real u, InnerSpace (Vec2 u)) => Vec2 u -> Vec2 u -> Radian
- zeroPt :: Num u => Point2 u
- minPt :: Ord u => Point2 u -> Point2 u -> Point2 u
- maxPt :: Ord u => Point2 u -> Point2 u -> Point2 u
- langle :: (Floating u, Real u) => Point2 u -> Point2 u -> Radian
- ortho :: Num u => Point2 u -> Frame2 u
- displaceOrigin :: Num u => Vec2 u -> Frame2 u -> Frame2 u
- pointInFrame :: Num u => Point2 u -> Frame2 u -> Point2 u
- frame2Matrix :: Num u => Frame2 u -> Matrix3'3 u
- matrix2Frame :: Matrix3'3 u -> Frame2 u
- frameProduct :: (Num u, InnerSpace (Vec2 u)) => Frame2 u -> Frame2 u -> Frame2 u
- standardFrame :: Num u => Frame2 u -> Bool
- identityMatrix :: Num u => Matrix3'3 u
- scalingMatrix :: Num u => u -> u -> Matrix3'3 u
- translationMatrix :: Num u => u -> u -> Matrix3'3 u
- rotationMatrix :: (Floating u, Real u) => Radian -> Matrix3'3 u
- originatedRotationMatrix :: (Floating u, Real u) => Radian -> Point2 u -> Matrix3'3 u
- invert :: Fractional u => Matrix3'3 u -> Matrix3'3 u
- determinant :: Num u => Matrix3'3 u -> u
- transpose :: Matrix3'3 u -> Matrix3'3 u
- req :: Radian -> Radian -> Bool
- toRadian :: Real a => a -> Radian
- fromRadian :: Fractional a => Radian -> a
- d2r :: (Floating a, Real a) => a -> Radian
- r2d :: (Floating a, Real a) => Radian -> a
- circularModulo :: Radian -> Radian
- bezierArc :: Floating u => u -> Radian -> Radian -> Point2 u -> (Point2 u, Point2 u, Point2 u, Point2 u)
- bezierCircle :: (Fractional u, Floating u) => Int -> u -> Point2 u -> [Point2 u]
Type family
Data types
2D Vector - both components are strict.
V2 !u !u |
Functor Vec2 | |
Eq u => Eq (Vec2 u) | |
Show u => Show (Vec2 u) | |
Num u => Monoid (Vec2 u) | |
Num u => VectorSpace (Vec2 u) | |
(Scalar u ~ u, Num u, InnerSpace u) => InnerSpace (Vec2 u) | |
Num u => AdditiveGroup (Vec2 u) | |
Pretty u => Pretty (Vec2 u) | |
Num u => MatrixMult (Vec2 u) | |
Pointwise (Vec2 u) | |
Num u => Translate (Vec2 u) | |
Num u => Scale (Vec2 u) | |
(Floating u, Real u) => RotateAbout (Vec2 u) | |
(Floating u, Real u) => Rotate (Vec2 u) | |
Num u => Transform (Vec2 u) |
2D Point - both components are strict.
Note - Point2 derives Ord so it can be used as a key in Data.Map etc.
P2 !u !u |
Functor Point2 | |
Eq u => Eq (Point2 u) | |
Ord u => Ord (Point2 u) | |
Show u => Show (Point2 u) | |
Num u => AffineSpace (Point2 u) | |
Pretty u => Pretty (Point2 u) | |
Num u => MatrixMult (Point2 u) | |
Pointwise (Point2 u) | |
Num u => Translate (Point2 u) | |
Num u => Scale (Point2 u) | |
(Floating u, Real u) => RotateAbout (Point2 u) | |
(Floating u, Real u) => Rotate (Point2 u) | |
Num u => Transform (Point2 u) |
A two dimensional frame.
The components are the two basis vectors e0
and e1
and
the origin o
.
Typically these names for the elements will be used:
Frame2 (V2 e0x e0y) (V2 e1x e1y) (P2 ox oy)
3x3 matrix, considered to be in row-major form.
(M3'3 a b c d e f g h i)
For instance the rotation matrix is represented as
( cos(a) -sin(a) 0 sin(a) cos(a) 0 0 0 1 )
This seems commplace in geometry texts, but PostScript
represents the current-transformation-matrix
in
column-major form.
The right-most column is considered to represent a coordinate:
( 1 0 x 0 1 y 0 0 1 )
So a translation matrix representing the displacement in x of 40 and in y of 10 would be:
( 1 0 40 0 1 10 0 0 1 )
M3'3 !u !u !u !u !u !u !u !u !u |
type DMatrix3'3 = Matrix3'3 DoubleSource
Radian is represented with a distinct type. Equality and ordering are approximate where the epsilon is 0.0001.
Pointwise type class
class Pointwise sh whereSource
Pointwise is a Functor like type class, except that the container/element relationship is defined via an associated type rather than a type parameter. This means that applied function must be type preserving.
Matrix multiply type class
class MatrixMult t whereSource
Matrix multiplication - typically of points and vectors represented as homogeneous coordinates.
Num u => MatrixMult (Point2 u) | |
Num u => MatrixMult (Vec2 u) |
Vector operations
vec :: Num u => u -> u -> Vec2 uSource
A synonym for the constructor V2
with a Num constraint on
the arguments.
Essentially superfluous, but it can be slightly more typographically pleasant when used in lists of vectors:
[ vec 2 2, vvec 4, hvec 4, vec 2 2 ]
Versus:
[ V2 2 2, vvec 4, hvec 4, V2 2 2 ]
pvec :: Num u => Point2 u -> Point2 u -> Vec2 uSource
The vector between two points
pvec = flip (.-.)
direction :: (Floating u, Real u) => Vec2 u -> RadianSource
Direction of a vector - i.e. the counter-clockwise angle from the x-axis.
vangle :: (Floating u, Real u, InnerSpace (Vec2 u)) => Vec2 u -> Vec2 u -> RadianSource
Extract the angle between two vectors.
Point operations
maxPt :: Ord u => Point2 u -> Point2 u -> Point2 uSource
Component-wise max on points.
maxPt (P2 1 2) (Pt 2 1) = Pt 2 2
langle :: (Floating u, Real u) => Point2 u -> Point2 u -> RadianSource
Calculate the counter-clockwise angle between two points and the x-axis.
Frame operations
ortho :: Num u => Point2 u -> Frame2 uSource
Create a frame with standard (orthonormal bases) at the supplied point.
displaceOrigin :: Num u => Vec2 u -> Frame2 u -> Frame2 uSource
Displace the origin of the frame by the supplied vector.
pointInFrame :: Num u => Point2 u -> Frame2 u -> Point2 uSource
'World coordinate' calculation of a point in the supplied frame.
frame2Matrix :: Num u => Frame2 u -> Matrix3'3 uSource
Concatenate the elements of the frame as columns forming a 3x3 matrix. Points and vectors are considered homogeneous coordinates - triples where the least element is either 0 indicating a vector or 1 indicating a point:
Frame (V2 e0x e0y) (V2 e1x e1y) (P2 ox oy)
becomes
(M3'3 e0x e1x ox e0y e1y oy 0 0 1 )
matrix2Frame :: Matrix3'3 u -> Frame2 uSource
Interpret the matrix as columns forming a frame.
(M3'3 e0x e1x ox e0y e1y oy 0 0 1 )
becomes
Frame (V2 e0x e0y) (V2 e1x e1y) (P2 ox oy)
frameProduct :: (Num u, InnerSpace (Vec2 u)) => Frame2 u -> Frame2 u -> Frame2 uSource
Multiplication of frames to form their product.
standardFrame :: Num u => Frame2 u -> BoolSource
Is the origin at (0,0) and are the basis vectors orthogonal with unit length?
Matrix contruction
identityMatrix :: Num u => Matrix3'3 uSource
Construct the identity matrix:
(M3'3 1 0 0 0 1 0 0 0 1 )
scalingMatrix :: Num u => u -> u -> Matrix3'3 uSource
Construct a scaling matrix:
(M3'3 sx 0 0 0 sy 0 0 0 1 )
translationMatrix :: Num u => u -> u -> Matrix3'3 uSource
Construct a translation matrix:
(M3'3 1 0 x 0 1 y 0 0 1 )
rotationMatrix :: (Floating u, Real u) => Radian -> Matrix3'3 uSource
Construct a rotation matrix:
(M3'3 cos(a) -sin(a) 0 sin(a) cos(a) 0 0 0 1 )
originatedRotationMatrix :: (Floating u, Real u) => Radian -> Point2 u -> Matrix3'3 uSource
Construct a matrix for rotation about some point.
This is the product of three matrices: T R T^-1
(T being the translation matrix, R the rotation matrix and T^-1 the inverse of the translation matrix).
matrix operations
invert :: Fractional u => Matrix3'3 u -> Matrix3'3 uSource
Invert a matrix.
determinant :: Num u => Matrix3'3 u -> uSource
Determinant of a matrix.
Radian operations
req :: Radian -> Radian -> BoolSource
Equality on radians, this is the operation used for (==) in Radian's Eq instance.
fromRadian :: Fractional a => Radian -> aSource
Convert from radians.
circularModulo :: Radian -> RadianSource
Modulate a (positive) angle to be in the range 0..2*pi
Bezier curves
bezierArc :: Floating u => u -> Radian -> Radian -> Point2 u -> (Point2 u, Point2 u, Point2 u, Point2 u)Source
Create an arc - this construction is the analogue of
PostScript's arc
command, but the arc is created as a
Bezier curve so it should span less than 90deg.
CAVEAT - ang2 must be greater than ang1
bezierCircle :: (Fractional u, Floating u) => Int -> u -> Point2 u -> [Point2 u]Source
Make a circle from Bezier curves - n
is the number of
subdivsions per quadrant.