Scurry.Geo (Scurry v3.0.0)

View Source

Geometry functions related to lines relevant for 2D map pathfinding.

Summary

Types

A line is represented by two vertices of type vector/0

A polygon is represented by a list of vector/0, each being a tuple of {x, y} coordinates, both number/0. To be properly defined, the vertices of the polygon must be non-closed and clockwise.

A vector is represented as a tuple {x, y}, it's x and y components, both number/0. These are used for vector math in Scurry.Vector and as 2D points in Scurry.Polygon and Scurry.PolygonMap.

Functions

Get the distance from a point to a line/segment.

Get the distance squared from point to line.

Check if two lines intersect

Determine if, where and how two lines intersect.

Types

line()

@type line() :: {vector(), vector()}

A line is represented by two vertices of type vector/0

polygon()

@type polygon() :: [vector()]

A polygon is represented by a list of vector/0, each being a tuple of {x, y} coordinates, both number/0. To be properly defined, the vertices of the polygon must be non-closed and clockwise.

vector()

@type vector() :: {x :: number(), y :: number()}

A vector is represented as a tuple {x, y}, it's x and y components, both number/0. These are used for vector math in Scurry.Vector and as 2D points in Scurry.Polygon and Scurry.PolygonMap.

Functions

distance_to_segment(line, point)

@spec distance_to_segment(vector(), line()) :: float()

Get the distance from a point to a line/segment.

This is the square root of distance_squared/2.

Params

  • line (line/0) the line to compute the distance to.
  • point (vector/0) the point to compute the distance to line for.

Returns

The distance beween the given point and line.

Examples

iex> Geo.distance_to_segment({{2, 0}, {2, 2}}, {0, 1})
2.0

distance_to_segment_squared(line, point)

@spec distance_to_segment_squared(vector(), line()) :: float()

Get the distance squared from point to line.

Params

  • line (line/0) the line to compute the distance squared to.
  • point (vector/0) the point to compute the distance squared to line for.

Returns

The square of the distance beween the given point and line.

Examples

iex> Geo.distance_to_segment_squared({{2, 0}, {2, 2}}, {0, 1})
4.0

do_lines_intersect?(line1, line2)

@spec do_lines_intersect?(line(), line()) :: boolean()

Check if two lines intersect

This is a simpler version of line_segment_intersection/2, which is typically a better choice since it handles endpoints and segment overlap too.

This is kept/provided for historic purposes.

Params

  • line1 (line/0) a line to check for intersection with
  • line2 (line/0) a line to check if it intersects with line1.

Returns

true if they intersect, false otherwise.

Note

This doesn't handle segment overlap or points touching. Use line_segment_intersection/2 instead for that level of detail.

line_segment_intersection(line1, line2)

@spec line_segment_intersection(line(), line()) ::
  :none
  | :parallel
  | :on_segment
  | {:point_intersection, vector()}
  | {:intersection, vector()}

Determine if, where and how two lines intersect.

This function computes whether two lines intersect (cross each other) touch on an endpoint or are on top of each other.

Params

  • line1 (line/0) a line segment
  • line2 (line/0) a line segment to check where and how it intersects with line1.

Returns

  • :none no intersection.
  • :parallel the lines are parallel and do not intersect.
  • :on_segment one line is on the other. They may extend past each other's endpoints.
  • {:point_intersection, vector} either line has an endpoint on the other line. This means they just touch at the returned vector.
  • {:intersection, vector} the lines intersect at the returned vector.

Examples

iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 0}, {3, 0}})
:parallel
iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 2}, {3, 2}})
:on_segment
iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 2}, {5, 2}})
:on_segment
iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 0}, {2, 1}})
:none
iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 0}, {2, 2}})
{:point_intersection, {2.0, 2.0}}
iex> Geo.line_segment_intersection({{1, 2}, {4, 2}}, {{2, 0}, {2, 3}})
{:intersection, {2.0, 2.0}}