Source code for Muscat.GeometricalTools.LineTools

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
from typing  import Tuple

import numpy as np

from Muscat.Types import ArrayLike

[docs]def SegmentIntersection(P0: ArrayLike, P1: ArrayLike, Px: ArrayLike, Py: ArrayLike)-> Tuple[np.ndarray]: """function to compute the intersection of 2 lines if no intersection then an empty tuple is returned if the second line is colinear to the first, return the point of the second line inside the first line Parameters ---------- P0 : ArrayLike first point defining the first line P1 : ArrayLike second point defining the first line Px : ArrayLike first point defining the second line Py : ArrayLike second point defining the second line Returns ------- tuple[np.ndarray] a tuple containing the intersection points """ P0 = np.asarray(P0) P1 = np.asarray(P1) Px = np.asarray(Px) Py = np.asarray(Py) p = P0 r = P1 - p q = Px s = Py - q cross1 = np.cross(r, s) cross2 = np.cross(p - q, r) if cross1 == 0 and cross2 == 0: t0 = (q - p).dot(r) / r.dot(r) t1 = (q + s - p).dot(r) / r.dot(r) if t0 > 0 and t0 < 1: if t1 >= 0 and t1 <= 1: return (p + t0 * r, p + t1 * r) else: return (p + t0 * r,) else: if t1 >= 0 and t1 <= 1: return (p + t1 * r,) else: return tuple() elif cross1 == 0 and cross2 != 0: return tuple() t = np.cross(q - p, s) / cross1 u = cross2 / np.cross(s, r) if cross1 != 0 and t >= 0 and t <= 1 and u >= 0 and u <= 1: return (p + t * r,) else: return tuple()
[docs]def CheckIntegrity(GUI: bool = False): P0 = [0, 0] # No intersect P1 = [2, 8] Px = [8, 0] Py = [0, 20] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), ()) P0 = [0, 10] # Intersect P1 = [2, 0] Px = [10, 0] Py = [0, 5] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), ((np.array([10 / 9, 40 / 9]),))) P0 = [0, 0] # Parallel, vertical P1 = [0, 10] Px = [2, 0] Py = [2, 10] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), ()) P0 = [0, 0] # Parallel, diagonal P1 = [5, 5] Px = [2, 0] Py = [7, 5] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), ()) P0 = [0, 0] # Collinear, overlap P1 = [5, 5] Px = [2, 2] Py = [7, 7] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), (np.array([2, 2]),)) P0 = [0, 0] # Collinear, full overlap P1 = [5, 5] Px = [2, 2] Py = [4, 4] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), (np.array([2, 2]), np.array([4, 4]))) P0 = [0, 0] # Collinear, overlap (opposite directions) P1 = [5, 5] Px = [7, 7] Py = [2, 2] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), (np.array([2, 2]),)) P0 = [0, 0] # Collinear, no overlap P1 = [5, 5] Px = [7, 7] Py = [10, 10] np.testing.assert_equal(SegmentIntersection(P0, P1, Px, Py), ()) return "ok"
if __name__ == "__main__": # pragma: no cover print(CheckIntegrity(GUI=True))