2020-07-06 16:16:34 +02:00
|
|
|
import numpy as np
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from mujoco_maze.maze_env_utils import Line
|
|
|
|
|
|
|
|
|
2020-07-14 17:59:54 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"l1, l2, p, ans",
|
|
|
|
[
|
|
|
|
((0.0, 0.0), (4.0, 4.0), (1.0, 3.0), 2.0 ** 0.5),
|
|
|
|
((-3.0, -3.0), (0.0, 1.0), (-3.0, 1.0), 2.4),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_distance(l1, l2, p, ans):
|
|
|
|
line = Line(l1, l2)
|
2021-06-03 13:29:54 +02:00
|
|
|
point = complex(*p)
|
2020-07-14 17:59:54 +02:00
|
|
|
assert abs(line.distance(point) - ans) <= 1e-8
|
|
|
|
|
|
|
|
|
2020-07-06 16:16:34 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"l1p1, l1p2, l2p1, l2p2, none",
|
|
|
|
[
|
|
|
|
((0.0, 0.0), (1.0, 0.0), (0.0, -1.0), (1.0, 1.0), False),
|
|
|
|
((1.0, 1.0), (2.0, 3.0), (-1.0, 1.5), (1.5, 1.0), False),
|
|
|
|
((1.5, 1.5), (2.0, 3.0), (-1.0, 1.5), (1.5, 1.0), True),
|
|
|
|
((0.0, 0.0), (2.0, 0.0), (1.0, 0.0), (1.0, 3.0), False),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_intersect(l1p1, l1p2, l2p1, l2p2, none):
|
|
|
|
l1 = Line(l1p1, l1p2)
|
|
|
|
l2 = Line(l2p1, l2p2)
|
|
|
|
i1 = l1.intersect(l2)
|
|
|
|
i2 = line_intersect(l1p1, l1p2, l2p1, l2p2)
|
|
|
|
if none:
|
|
|
|
assert i1 is None and i2 is None
|
|
|
|
else:
|
|
|
|
assert i1 is not None
|
2020-07-14 17:59:54 +02:00
|
|
|
i1 = np.array([i1.real, i1.imag])
|
2020-07-06 16:16:34 +02:00
|
|
|
np.testing.assert_array_almost_equal(i1, np.array(i2))
|
|
|
|
|
|
|
|
|
|
|
|
def line_intersect(pt1, pt2, ptA, ptB):
|
|
|
|
"""
|
|
|
|
Taken from https://www.cs.hmc.edu/ACM/lectures/intersections.html
|
|
|
|
Returns the intersection of Line(pt1,pt2) and Line(ptA,ptB).
|
|
|
|
"""
|
|
|
|
import math
|
|
|
|
|
|
|
|
DET_TOLERANCE = 0.00000001
|
|
|
|
|
|
|
|
# the first line is pt1 + r*(pt2-pt1)
|
|
|
|
# in component form:
|
|
|
|
x1, y1 = pt1
|
|
|
|
x2, y2 = pt2
|
|
|
|
dx1 = x2 - x1
|
|
|
|
dy1 = y2 - y1
|
|
|
|
|
|
|
|
# the second line is ptA + s*(ptB-ptA)
|
|
|
|
x, y = ptA
|
|
|
|
xB, yB = ptB
|
|
|
|
dx = xB - x
|
|
|
|
dy = yB - y
|
|
|
|
|
|
|
|
DET = -dx1 * dy + dy1 * dx
|
|
|
|
|
|
|
|
if math.fabs(DET) < DET_TOLERANCE:
|
|
|
|
return None
|
|
|
|
|
|
|
|
# now, the determinant should be OK
|
|
|
|
DETinv = 1.0 / DET
|
|
|
|
|
|
|
|
# find the scalar amount along the "self" segment
|
|
|
|
r = DETinv * (-dy * (x - x1) + dx * (y - y1))
|
|
|
|
|
|
|
|
# find the scalar amount along the input line
|
|
|
|
s = DETinv * (-dy1 * (x - x1) + dx1 * (y - y1))
|
|
|
|
|
|
|
|
# return the average of the two descriptions
|
|
|
|
xi = (x1 + r * dx1 + x + s * dx) / 2.0
|
|
|
|
yi = (y1 + r * dy1 + y + s * dy) / 2.0
|
|
|
|
if r >= 0 and 0 <= s <= 1:
|
|
|
|
return xi, yi
|
|
|
|
else:
|
|
|
|
return None
|