1111https://en.wikipedia.org/wiki/Axis-aligned_object
1212"""
1313
14+ import math
15+
1416class AxisAlignedLine (object ):
1517 """
1618 Define an axis aligned line.
@@ -50,32 +52,54 @@ def __init__(self, axis, point1, point2):
5052 """
5153 Construct an axis aligned line with the appropriate min and max.
5254
53- :param axis: axis this line is on
55+ :param axis: axis this line is on (for bookkeeping only, may be None)
5456 :type axis: :class:`pygorithm.geometry.vector2.Vector2`
5557 :param point1: one point on this line
5658 :type point1: :class:`numbers.Number`
5759 :param point2: a different point on this line
5860 :type point2: :class:`numbers.Number`
5961 """
6062
61- pass
63+ self .axis = axis
64+ self .min = min (point1 , point2 )
65+ self .max = max (point1 , point2 )
66+
67+ @staticmethod
68+ def _approx (a , b ):
69+ """
70+ Same as math.isclose but supports python < 3.5
71+
72+ :param a: first numeric
73+ :type a: :class:`numbers.Number`
74+ :param b: second numeric
75+ :type b: :class:`numbers.Number`
76+ :returns: if the are close
77+ :rtype: bool
78+ """
79+
80+ if hasattr (math , 'isclose' ):
81+ return math .isclose (a , b )
82+ return abs (a - b ) <= 1e-09 * max (abs (a ), abs (b ))
6283
6384 @staticmethod
6485 def intersects (line1 , line2 ):
6586 """
6687 Determine if the two lines intersect
6788
68- Determine if the two lines are touching and if they are, if
69- they are overlapping. Lines are touching if they share only
70- one end point, whereas they are overlapping if they share
71- infinitely many points.
89+ Determine if the two lines are touching, if they are overlapping, or if
90+ they are disjoint. Lines are touching if they share only one end point,
91+ whereas they are overlapping if they share infinitely many points.
7292
7393 .. note::
7494
7595 It is rarely faster to check intersection before finding intersection if
7696 you will need the minimum translation vector, since they do mostly
7797 the same operations.
7898
99+ .. tip::
100+
101+ This will never return ``True, True``
102+
79103 :param line1: the first line
80104 :type line1: :class:`pygorithm.geometry.axisall.AxisAlignedLine`
81105 :param line2: the second line
@@ -84,7 +108,16 @@ def intersects(line1, line2):
84108 :rtype: (bool, bool)
85109 """
86110
87- pass
111+ if AxisAlignedLine ._approx (line1 .max , line2 .min ):
112+ return True , False
113+ elif AxisAlignedLine ._approx (line1 .min , line2 .max ):
114+ return True , False
115+ elif line1 .max < line2 .min :
116+ return False , False
117+ elif line1 .min > line2 .max :
118+ return False , False
119+
120+ return False , True
88121
89122 @staticmethod
90123 def find_intersection (line1 , line2 ):
@@ -97,22 +130,39 @@ def find_intersection(line1, line2):
97130 direction of the axis by the magnitude of the result.
98131
99132
100- Returns `true, None` if the lines are touching.
133+ Returns `true, (None, touch_point_numeric, touch_point_numeric)` if the lines are touching
134+ and not overlapping.
101135
102136 .. note::
103137
104- Ensure your program correctly handles `true, None`
138+ Ensure your program correctly handles `true, ( None, numeric, numeric) `
105139
106140
107141 :param line1: the first line
108142 :type line1: :class:`pygorithm.geometry.axisall.AxisAlignedLine`
109143 :param line2: the second line
110144 :type line2: :class:`pygorithm.geometry.axisall.AxisAlignedLine`
111- :returns: (touching, mtv against 1)
112- :rtype: (bool, :class:`numbers.Number` or None)
145+ :returns: (touching, ( mtv against 1, intersection min, intersection max) )
146+ :rtype: (bool, ( :class:`numbers.Number` or None, :class:`numbers.Number`, :class:`numbers.Number`) or None)
113147 """
114148
115- pass
149+ if AxisAlignedLine ._approx (line1 .max , line2 .min ):
150+ return True , (None , line2 .min , line2 .min )
151+ elif AxisAlignedLine ._approx (line1 .min , line2 .max ):
152+ return True , (None , line1 .min , line1 .min )
153+ elif line1 .max < line2 .min or line2 .max < line1 .min :
154+ return False , None
155+ else :
156+ opt_1 = line2 .min - line1 .max
157+ opt_2 = line2 .max - line1 .min
158+
159+ res_min = max (line1 .min , line2 .min )
160+ res_max = min (line1 .max , line2 .max )
161+
162+ if abs (opt_1 ) < abs (opt_2 ):
163+ return True , (opt_1 , res_min , res_max )
164+ else :
165+ return True , (opt_2 , res_min , res_max )
116166
117167 @staticmethod
118168 def contains_point (line , point ):
@@ -132,4 +182,10 @@ def contains_point(line, point):
132182 :returns: (if the point is an edge of the line, if the point is contained by the line)
133183 :rtype: (bool, bool)
134184 """
135- pass
185+
186+ if AxisAlignedLine ._approx (line .min , point ) or AxisAlignedLine ._approx (line .max , point ):
187+ return True , False
188+ elif point < line .min or point > line .max :
189+ return False , False
190+ else :
191+ return False , True
0 commit comments