This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

# Collision2D

Collision detection in two dimensions

# Building a Hull

type alias Vec2 = Vec2.Vec2

A vector with x and y components

type Hull = Bounded (List Side)

A collection of sides that together represent a hull. This library interprets the sides as forming the smallest possible convex polygon.

vec2 : Float -> Float -> Vec2

Build a Vec2 given x and y

``````vec2 1 2 -- x = 1, y = 2
``````
fromVectors : List Vec2 -> Hull

Given the vertexes of a polygon, compute a hull. Vertexes must be ordered counter-clockwise around the center of the shape. Only works for convex polygons.

Returns an empty hull if given less than three vertexes.

# Collision Detection

isInside : Vec2 -> Hull -> Bool

Returns `True` if the given position is on or in the given hull. Defaults to `False` if the hull has no sides.

``````hull =
fromVertexes
[ vec2 0 1
, vec2 3 4
, vec2 1 0
]

isInside hull (vec2 1 1) == True

isInside hull (vec2 -1 2) == False

isInside hull (vec2 0 0) == True
``````
isOutside : Vec2 -> Hull -> Bool

Returns `True` if the given position is outside the given hull. The logical inverse of `isInside`.

``````module Collision2D (isOutside, isInside, fromVectors, Hull, Vec2, vec2) where

{-| Collision detection in two dimensions

# Building a Hull
@docs Vec2, Hull, vec2, fromVectors

# Collision Detection
@docs isInside, isOutside
-}

import Vec2

{-| A vector with x and y components
-}
type alias Vec2 =
Vec2.Vec2

{-| Build a Vec2 given x and y

vec2 1 2 -- x = 1, y = 2
-}
vec2 : Float -> Float -> Vec2
vec2 =
Vec2.vec2

{-| Given the vertexes of a polygon, compute a hull. Vertexes must be ordered
counter-clockwise around the center of the shape. Only works for convex polygons.

Returns an empty hull if given less than three vertexes.
-}
fromVectors : List Vec2 -> Hull
fromVectors vertexes =
let
segments =
(List.drop 1 vertexes)
++ (List.take 1 vertexes)
|> List.map2 (,) vertexes
in
if List.length vertexes >= 3 then
fromSegments segments
else
Bounded []

fromSegments : List ( Vec2, Vec2 ) -> Hull
fromSegments segments =
let
toNormal a b =
let
( x, y ) = Vec2.toTuple (Vec2.direction a b)
in
Vec2.fromTuple ( -y, x )

toSide ( a, b ) =
{ keyPoint = a
, normal = toNormal a b
}

isDefined vec =
not (isNaN (Vec2.getX vec) || isNaN (Vec2.getY vec))
in
List.map toSide segments
|> List.filter (.normal >> isDefined)
|> Bounded

{-| Returns `True` if the given position is on or in the given hull.
Defaults to `False` if the hull has no sides.

hull =
fromVertexes
[ vec2 0 1
, vec2 3 4
, vec2 1 0
]

isInside hull (vec2 1 1) == True

isInside hull (vec2 -1 2) == False

isInside hull (vec2 0 0) == True

-}
isInside : Vec2 -> Hull -> Bool
isInside point (Bounded sides) =
let
isBehind side =
Vec2.dot side.normal (Vec2.sub point side.keyPoint) < 1.0e-6
in
not (List.isEmpty sides) && List.all isBehind sides

{-| Returns `True` if the given position is outside the given hull.
The logical inverse of `isInside`.
-}
isOutside : Vec2 -> Hull -> Bool
isOutside point boundary =
not (isInside point boundary)

{-| A collection of sides that together represent a hull. This library
interprets the sides as forming the smallest possible convex polygon.
-}
type Hull
= Bounded (List Side)

{- A side is a straight-line boundary with an inside and an outside. The key
point is a location on the boundary. The
[normal](https://en.wikipedia.org/wiki/Normal_%28geometry%29) is a unit vector
perpendicular to the boundary.

Any point on the side can be a key point, so sides with different key points can
be equivalent sometimes.

Since the sides have no endpoints, infinite-area hulls are possible (e.g. if
there are less than three sides).
-}

type alias Side =
{ keyPoint : Vec2
, normal : Vec2
}
```
```