SegSeg (seg_seg v1.0.0)
Calculates the type of relationship between two line segments AB and CD and the location of intersection (if applicable).
Link to this section Summary
Functions
Returns a tuple representing the segment-segment intersection with three elements
Link to this section Types
intersection_result()
@type intersection_result() :: {boolean(), intersection_type(), point() | nil}
intersection_type()
@type intersection_type() :: :interior | :disjoint | :edge | :vertex
point()
Link to this section Functions
intersection(a, b, c, d, options \\ [])
Returns a tuple representing the segment-segment intersection with three elements:
- Boolean
true
if the two segments intersect at all,false
if they are disjoint - An atom representing the classification of the intersection:
:interior
- the segments intersect at a point that is interior to both:vertex
- the segments intersect at an endpoint of one or both segments:edge
- the segments are parallel, collinear, and overlap for some non-zero length:disjoint
- no intersection exists between the two segments
- A tuple
{x, y}
representing the point of intersection if the intersection is classified as:interior
or:vertex
, otherwisenil
.
float-precision-issues
Float Precision Issues
It is possible that floating point math imprecision can cause incorrect results for
certain inputs. In situations where this may cause issues, an epsilon
options is
available. When set to true
intersection comparisons are made with a very small epsilon
based on the minimum
of the lengths of the provided segment times a very small number (currently 0.0000000001). epsilon
can also be set to a specific number that will be used as the epsilon value.
This eliminates most rounding error, but of course could cause false results in certain
situations. This currently only effects :vertex
results but might be expanded to :edge
in the future.
SegSeg.intersection({4, 3}, {4, 7}, {6.05, 9.05}, {3.95, 6.95}) #=> {true, :interior, {4.0, 6.999999999999998}}
SegSeg.intersection({4, 3}, {4, 7}, {6.05, 9.05}, {3.95, 6.95}, epsilon: true) #=> {true, :vertex, {4, 7}}
examples
Examples
iex> SegSeg.intersection({2, -3}, {4, -1}, {2, -1}, {4, -3})
{true, :interior, {3.0, -2.0}}
iex> SegSeg.intersection({-1, 3}, {2, 4}, {-1, 4}, {-1, 5})
{false, :disjoint, nil}
iex> SegSeg.intersection({-1, 0}, {0, 2}, {0, 2}, {1, -1})
{true, :vertex, {0, 2}}
iex> SegSeg.intersection({-1, 0}, {0, 2}, {1, 4}, {-1, 0})
{true, :edge, nil}
# This doesn't behave as expected because of floating point error.
iex> SegSeg.intersection({4, 3}, {4, 7}, {6.05, 9.05}, {3.95, 6.95})
{true, :interior, {4.0, 6.999999999999998}}
# Adding the default epsilon causes this to act more as expected.
iex> SegSeg.intersection({4, 3}, {4, 7}, {6.05, 9.05}, {3.95, 6.95}, epsilon: true)
{true, :vertex, {4, 7}}
# Specifying a very small epsilon shows the floating point error again.
iex> SegSeg.intersection({4, 3}, {4, 7}, {6.05, 9.05}, {3.95, 6.95}, epsilon: 0.00000000000000000001)
{true, :interior, {4.0, 6.999999999999998}}