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



This module has types and functions for dealing with collision detection on simple 2D shapes.



data Shape' a Source

A type for simple 2D convex shapes. It is expected that you will define a synonym in your own application such as type Shape = Shape' Double, hence the funny name.



A rectangle with a centre, and a width (distance from the centre to the left or right side of the rectangle) and a height (distance from the centre to the top or bottom side of the rectangle. So the rectangle with corners (1,1) and (3,2) is Rectangle (Point2 (2,1.5)) (1, 0.5). Technically a rectangle is a polygon, of course, but a rectangle (which is axis-aligned) can be processed faster by most algorithms.


shapeCentre :: Point2' a
rectSize :: (a, a)

A circle with a centre and a radius.


shapeCentre :: Point2' a
circSize :: a

A polygon with a centre, and a list of points. The points are relative vectors from the centre of the polygon, and are expected to be in clockwise order. For example, the triangle with corners (1,1) (3,3) and (3,1) could be Polygon (Point2 (2.5, 1.5)) [Rel2 (-1.5,-0.5), Rel2 (0.5,1.5), Rel2 (-1.5, 1.5)].

Note that whereabouts the centre is inside the polygon is up to you (it does not have to be the geometric average of the points), but it should at least be inside the polygon, or else some algorithms will behave strangely with it.

The list of points should have at least 3 points in it, or else some algorithms will behave strangely.

If your points are not in clockwise order (with the X-Y axes being how they are in graphs, not on screens), funny things will happen with the collision detection.


shapeCentre :: Point2' a
polyPoints :: [Rel2' a]


Eq a => Eq (Shape' a) 
Ord a => Ord (Shape' a) 
Read a => Read (Shape' a) 
Show a => Show (Shape' a) 

moveShape :: Num a => Rel2' a -> Shape' a -> Shape' aSource

Moves a shape by a given vector (by moving the centre).

rotateShape :: forall a. Floating a => a -> Shape' a -> Shape' aSource

Given an angle in radians, rotates the shape by that angle in an anti-clockwise direction. A circle will remain untouched, a polygon will have its points rotated, and a rectangle will become a polygon and get rotated (even if you pass 0 as the angle).

scaleShape :: Num a => a -> Shape' a -> Shape' aSource

Scales the size of the shape (for all edges, from the centre) by the given factor.

shapePoints :: Num a => Shape' a -> [Point2' a]Source

Given a shape, gets a list of points that make up the vertices of the shape. For circles, this list will be empty.

boundingBox :: (Num a, Ord a) => Shape' a -> (Point2' a, Point2' a)Source

Gives back the bounding box of a shape in terms of the minimum X-Y and the maximum X-Y corners of the bounding box.

overlap :: (Floating a, Ord a) => Shape' a -> Shape' a -> Maybe (Rel2' a, Rel2' a)Source

Checks for overlap between the two shapes. If they do not collide, returns Nothing. If they do collide, gives back suggested angles away from each other. These are not necessarily the shortest direction to separate the two shapes, but should be decent for doing collision resolution (by using them as surface normals, or push-away vectors)

The first vector returned is the direction in which the first shape should head (or the surface normal to bounce the first shape off), whereas the second vector returned is the direction in which the second shape should head (or the surface normal to bounce the second shape off).

This function includes an initial quick test, followed by a more detailed test if necessary.

intersectLineShape :: forall a. (Floating a, Ord a) => Line2' a -> Shape' a -> Maybe (a, a)Source

Given a line and a shape, finds all possible intersections of the line with the shape. Since the shapes are convex, continuous 2D shapes, there will either be no intersections or two (which could be the same point). The returned value is distance along the line in multiples of the direction vector (the return value is the same idea as intersectLineCircle).