SG-1.0: Small geometry library for dealing with vectors and collision detection

Data.SG.Geometry.TwoDim

Description

A module with types to use in a 2D system, and various helper functions. Several more functions are available for use in the Data.SG.Geometry module.

Synopsis

# Documentation

newtype Point2' a Source

A point in 2D space.

Constructors

 Point2 (a, a)

Instances

 Functor Point2' Applicative Point2' Foldable Point2' Traversable Point2' VectorNum Point2' Coord2 Point2' Coord Point2' IsomorphicVectors Pair Point2' IsomorphicVectors Rel2' Point2' IsomorphicVectors Point2' Pair IsomorphicVectors Point2' Rel2' Geometry Rel2' Point2' Line2' Eq a => Eq (Point2' a) Ord a => Ord (Point2' a) Read a => Read (Point2' a) Show a => Show (Point2' a)

data Rel2' a Source

A relative vector (free vector) in 2D space. The pair are the x and y components, and the last item is the squared magnitude of the vector, which is stored with it to speed up various operations. It is suggested you use `makeRel2` to create one of these, unless the square magnitude is easily apparent, e.g. ```Rel2 (0, 2) 4```

Constructors

 Rel2 (a, a) a

Instances

 Foldable Rel2' VectorNum Rel2' Coord2 Rel2' Coord Rel2' IsomorphicVectors Pair Rel2' IsomorphicVectors Rel2' Pair IsomorphicVectors Rel2' Point2' IsomorphicVectors Point2' Rel2' Geometry Rel2' Point2' Line2' Eq a => Eq (Rel2' a) (Show a, Eq a, Num a) => Num (Rel2' a) Multiplication doesn't make much sense, but the rest do! Ord a => Ord (Rel2' a) Read a => Read (Rel2' a) Show a => Show (Rel2' a)

makeRel2 :: Num a => (a, a) -> Rel2' aSource

Constructs a Rel2' vector.

data Line2' a Source

A line in 2D space. A line is a point, and a free vector indicating direction. A line may be treated by a function as either finite (taking the magnitude of the free vector as the length) or infinite (ignoring the magnitude of the direction vector).

Constructors

 Line2 FieldsgetLineStart2 :: Point2' a getLineDir2 :: Rel2' a

Instances

 Geometry Rel2' Point2' Line2' Eq a => Eq (Line2' a) Read a => Read (Line2' a) Show a => Show (Line2' a)

toAngle :: RealFloat a => Rel2' a -> aSource

Gets the angle, in radians, anti-clockwise from the x-axis. If you pass the all-zero vector, the return value will be zero.

perpendicular2 :: Num a => Rel2' a -> Rel2' aSource

Gets the vector perpendicular to the given 2D vector. If you pass it a vector that is in a clockwise direction around a polygon, the result will always face away from the polygon.

reflectAgainst2 :: (Floating a, Ord a) => Rel2' a -> Rel2' a -> Rel2' aSource

Reflects the first direction vector against the given surface normal. The resulting direction vector should have the same magnitude as the original first parameter. An example:

``` makeRel2 (-3, -4) `reflectAgainst2` makeRel2 (0,1) == makeRel2 (-3, 4)
```

reflectAgainstIfNeeded2 :: (Floating a, Ord a) => Rel2' a -> Rel2' a -> Rel2' aSource

Reflects the first direction vector against the given surface normal. The resulting direction vector should have the same magnitude as the original first parameter.

The reflection is not performed if the given vector points along the same direction as the normal, that is: if once projected onto the normal vector, the component is positive, the original first parameter is returned unmodified. Examples:

``` makeRel2 (-3, -4) `reflectAgainstIfNeeded2` makeRel2 (0,1) == makeRel2 (-3, 4)
makeRel2 (-3, 4) `reflectAgainstIfNeeded2` makeRel2 (0,1) == makeRel2 (-3, 4)
```

intersectLines2 :: Fractional a => Line2' a -> Line2' a -> Maybe (a, a)Source

Given two 2D lines, finds out their intersection. The first part of the result pair is how much to multiply the direction vector of the first line by (and add it to the start point of the first line) to reach the intersection, and the second part is the corresponding item for the second line. So given `Just (a, b) = intersectLines2 la lb`, it should be the case (minus some possible precision loss) that `alongLine a la == alongLine b lb`. If the lines are parallel, Nothing is returned.

Note that this function assumes the lines are infinite. If you want to check for the intersection of two finite lines, check if the two parts of the result pair are both in the range 0 to 1 inclusive.

findAllIntersections2 :: Fractional a => ([Line2' a], [Line2' a]) -> [((Line2' a, a), (Line2' a, a))]Source

Finds all the intersections between a line from the first list and a line from the second list, and how far along that is each line. That is, this is a bit like mapMaybe composed with intersectLines2 on all pairings of a line from the first list and a line from the second list.

intersectLineCircle :: (Ord a, Floating a) => Line2' a -> (Point2' a, a) -> Maybe (a, a)Source

Given a line, and a circle (defined by a point and a radius), finds the points of intersection.

If the line does not intersect the circle, Nothing is returned. If they do intersect, two values are returned that are distances along the line. That is, given `Just (a, b) = intersectLineCircle l c`, the two points of intersection are `(alongLine l a, alongLine l b)`.

The ordering of the two items in the pair is arbitrary, and if the line is a tangent to the circle, the values will be the same.

point2AtZ :: (Geometry rel pt ln, Coord3 rel, Coord3 pt, Fractional a) => ln a -> a -> Maybe (Point2' a)Source

Like `pointAtZ`, but returns a 2D vector instead of a 3D vector