Linear Referencing Module

This module contains functions relating to linear referencing. Requires the Shapely module

Reference links:

exception wayfarer.linearref.IdenticalMeasuresError[source]

A custom exception to indicate the start and end measures are identical

wayfarer.linearref.check_valid_m(m_value, length, tolerance=1e-05)[source]

Check that an m_value is a valid measure for the input length

Parameters:
  • m_value (float) – The measure

  • length (float) – The length of the line

  • tolerance (float) – The tolerance the m-value can be beyond the length of the line

Return type:

bool

Returns:

If the line is valid

>>> check_valid_m(m_value=10, length=20)
True
>>> check_valid_m(m_value=-0.213, length=20)
Traceback (most recent call last):
...
ValueError: The m value (-0.213) must be a positive number
wayfarer.linearref.create_line(line, start_m, end_m, tolerance=1e-05)[source]

Create a new line feature based on a start and end measure This function also handles ring LineStrings (where start and end nodes are the same)

Parameters:
  • line (LineString) – The original LineString

  • start_m (float) – The start measure to split the line

  • end_m (float) – The end measure to split the line

  • tolerance (float) – The tolerance the m-value can be beyond the length of the line

Return type:

LineString

Returns:

A new line based on the original geometry between the two measures

>>> ls = LineString([(0, 0), (0, 100)])
>>> create_line(ls, start_m=0, end_m=50)
<LINESTRING (0 0, 0 50)>
wayfarer.linearref.find_common_vertices(line1, line2)[source]

Find all the points common to both lines and return a list of touching points

Parameters:
  • line1 (LineString) – The first line

  • line1 – The second line

Return type:

list[Point]

Returns:

A list of points shared between the lines

>>> ls1 = LineString([(0, 0), (0, 100)])
>>> ls2 = LineString([(0, 100), (0, 200)])
>>> find_common_vertices(ls1, ls2)
[<POINT (0 100)>]
wayfarer.linearref.get_closest_line(lines, point)[source]

Get the closest line to a point

Return type:

tuple[int, Point]

wayfarer.linearref.get_closest_point_to_measure(line, points, measure)[source]

Returns the point closest to the start measure from the list of points

Parameters:
  • line (LineString) – The LineString

  • points (list[Point]) – A list of points to check

  • measure (float) – A measure along the line

Return type:

Point

Returns:

The measure (m-value) of the point along the line

>>> ls = LineString([(0, 0), (0, 50), (0, 100)])
>>> points = [Point(0, 10), Point(0, 55)]
>>> get_closest_point_to_measure(ls, points, measure=20)
<POINT (0 10)>
>>> get_closest_point_to_measure(ls, points, measure=80)
<POINT (0 55)>
wayfarer.linearref.get_end_point(line, point, common_vertices)[source]

Get the start or end of the line closest to the input point

Parameters:
  • line (LineString) – The input line

  • point (Point) – The input point

  • common_vertices (list[Point]) – Points shared between the two lines

Return type:

Point

Returns:

The end point

>>> ls = LineString([(0, 0), (100, 0)])
>>> point = Point(30, 0)
>>> common_vertices = [Point(0, 0), Point(70, 0)]
>>> get_end_point(ls, point, common_vertices)
<POINT (0 0)>
wayfarer.linearref.get_measure_on_line(line, point)[source]

Return the measure along a line of a point. Note the Shapely function can return a np.float64 value, so we ensure it is converted to a float (see https://github.com/shapely/shapely/issues/2196).

Parameters:
  • line (LineString) – The LineString

  • point (Point) – The point

Return type:

float

Returns:

The measure (m-value) of the point along the line

>>> line = LineString([(0, 0), (100, 0)])
>>> point = Point(50, 0)
>>> get_measure_on_line(line, point)
50.0
wayfarer.linearref.get_measures(line, pt1, pt2)[source]

Snap two points to a line and return the measures

Parameters:
  • line (LineString) – The LineString

  • pt1 (Point) – A first point

  • pt2 (Point) – A second point

Return type:

tuple[float, float]

Returns:

A tuple of the start and end measures

>>> ls = LineString([(0, 0), (100, 0)])
>>> pt1 = Point(4, 0)
>>> pt2 = Point(96, 0)
>>> get_measures(ls, pt1, pt2)
(4.0, 96.0)
wayfarer.linearref.get_nearest_vertex(point, line)[source]

Get the point on the line that is closest to the input point Based on code from gis.stackexchange.com

Parameters:
  • point (Point) – The input point to place along a line

  • line (LineString) – The input line

Return type:

tuple[Point, float]

Returns:

A tuple containing the snapped point along the line and its distance from the original point

>>> point = Point(2, 21)
>>> line = LineString([(0, 0), (0, 50), (0, 100)])
>>> get_nearest_vertex(point, line)
(<POINT (0 21)>, 2.0)
wayfarer.linearref.intersect_point_to_line(point, start_point, end_point)[source]

Get the closest point to the input point, on a straight line created between start point and the end point

>>> point = Point(1, 60)
>>> start_point = Point(0, 0)
>>> end_point = Point(0, 100)
>>> intersect_point_to_line(point, start_point, end_point)
<POINT (0 60)>
Parameters:
  • point (Point) – The input point to place along a line

  • start_point (Point) – The start point of a straight line

  • end_point (Point) – The end point of a straight line

Return type:

Point

Returns:

A point along the straight line, or the closest end point if beyond the start and end points of the line

The function will fail if two points have the same coordinates (as magnitude is 0) with ZeroDivisionError: float division

From the Shapely Manual the definition of a LineString is “Repeated points in the ordered sequence are allowed, but may incur performance penalties and should be avoided. A LineString may cross itself (i.e. be complex and not simple).”

wayfarer.linearref.is_partial(line, start_m, end_m, tolerance=1e-05)[source]

Check if the measures cover a whole LineString or only a part of it

Parameters:
  • line (LineString) – The LineString

  • start_m (float) – The start measure

  • end_m (float) – The end measure

  • tolerance (float) – The tolerance for the measures when comparing the start and end

Return type:

bool

Returns:

Boolean indicating if the measures only partially cover the line

>>> ls = LineString([(0, 0), (0, 100)])
>>> is_partial(ls, start_m=0.5, end_m=101, tolerance=1)
False
wayfarer.linearref.magnitude(pt1, pt2)[source]

Return the magnitude (distance) between two points

Parameters:
  • pt1 (Point) – The first point

  • pt2 (Point) – The second point

Return type:

float

Returns:

The distance between the two points

>>> pt1 = Point(0, 0)
>>> pt2 = Point(100, 100)
>>> round(magnitude(pt1, pt2))
141
wayfarer.linearref.remove_duplicates_in_line(line)[source]

Remove any duplicate coordinates from a LineString Note this does not work with MultiLineStrings

Parameters:

line (LineString) – The LineString

Returns:

A new LineString with any duplicate coordinates removed

>>> ls = LineString([(0, 0), (1, 1), (1,1)])
>>> remove_duplicates_in_line(ls)
<LINESTRING (0 0, 1 1)>
wayfarer.linearref.snap_to_ends(line, start_m, end_m, tolerance=5)[source]

If the measure values are within the set tolerance to the ends of a segment, then “snap” these values to the end.

Parameters:
  • line (LineString) – The LineString

  • start_m (float) – The start measure

  • end_m (float) – The end measure

  • tolerance (float) – The tolerance the m-value can be beyond the length of the line

Return type:

tuple[float, float]

Returns:

A tuple of the new snapped measures

>>> ls = LineString([(0, 0), (0, 100)])
>>> snap_to_ends(ls, start_m=4, end_m=96, tolerance=5)
(0, 100.0)
>>> snap_to_ends(ls, start_m=4, end_m=96, tolerance=4)
(4, 96)