Find the intersection of two lines: Difference between revisions

→‎{{header|Python}}: Replaced the Python version with a simple one
(→‎{{header|Python}}: Replaced the Python version with a simple one)
Line 1,361:
Or, one approach to doing this by hand, without importing special libraries:
{{Works with|Python|3.7}}
<lang python>'''Thedef intersectionline_instersect(Ax1, ofAy1, twoAx2, lines.'''Ay2, Bx1, By1, Bx2, By2):
""" returns a (x, y) tuple or None if there is no intersection """
d = (By2 - By1) * (Ax2 - Ax1) - (Bx2 - Bx1) * (Ay2 - Ay1)
if d:
uA = ((Bx2 - Bx1) * (Ay1 - By1) - (By2 - By1) * (Ax1 - Bx1)) / d
uB = ((Ax2 - Ax1) * (Ay1 - By1) - (Ay2 - Ay1) * (Ax1 - Bx1)) / d
else:
return
if not(0 <= uA <= 1 and 0 <= uB <= 1):
return
x = Ax1 + uA * (Ax2 - Ax1)
y = Ay1 + uA * (Ay2 - Ay1)
return x, y
 
if __name__ == '__main__':
from functools import (reduce)
(a, b), (c, d) = (4, 0), (6, 10) # try (4, 0), (6, 4)
(e, f), (g, h) = (0, 3), (10, 7) # for non intersecting test
pt = line_instersect(a, b, c, d, e, f, g, h)
print(pt)</lang>
 
 
# intersection :: Line -> Line -> Either String Point
def intersection(ab):
'''Either the point at which the lines ab and pq
intersect, or a message string indicating that
they are parallel and have no intersection.'''
def delta(f):
return lambda x: f(fst(x)) - f(snd(x))
 
def prodDiff(abcd):
[a, b, c, d] = abcd
return (a * d) - (b * c)
 
def go(pq):
[abDX, pqDX, abDY, pqDY] = ap(
[delta(fst), delta(snd)]
)([ab, pq])
determinant = prodDiff([abDX, abDY, pqDX, pqDY])
 
def point():
[abD, pqD] = map(
lambda xy: prodDiff(
ap([fst, snd])([fst(xy), snd(xy)])
), [ab, pq]
)
return ap(
[lambda abpq: prodDiff(
[abD, fst(abpq), pqD, snd(abpq)]) / determinant]
)(
[(abDX, pqDX), (abDY, pqDY)]
)
return Right(point()) if 0 != determinant else Left(
'( Parallel lines - no intersection )'
)
 
return lambda pq: bindLR(go(pq))(
lambda xs: Right((fst(xs), snd(xs)))
)
 
 
# TEST ----------------------------------------------------
# main :: IO()
def main():
'''Test'''
 
# Left(message - no intersection) or Right(point)
# lrPoint :: Either String Point
lrPoint = intersection(
((4.0, 0.0), (6.0, 10.0))
)(
((0.0, 3.0), (10.0, 7.0))
)
print(
lrPoint['Left'] or lrPoint['Right']
)
 
 
# GENERIC FUNCTIONS ---------------------------------------
 
# Left :: a -> Either a b
def Left(x):
'''Constructor for an empty Either (option type) value
with an associated string.'''
return {'type': 'Either', 'Right': None, 'Left': x}
 
 
# Right :: b -> Either a b
def Right(x):
'''Constructor for a populated Either (option type) value'''
return {'type': 'Either', 'Left': None, 'Right': x}
 
 
# ap (<*>) :: [(a -> b)] -> [a] -> [b]
def ap(fs):
'''The application of each of a list of functions,
to each of a list of values.'''
return lambda xs: reduce(
lambda a, f: a + reduce(
lambda a, x: a + [f(x)], xs, []
), fs, []
)
 
 
# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
def bindLR(m):
'''Either monad injection operator.
Two computations sequentially composed,
with any value produced by the first
passed as an argument to the second.'''
return lambda mf: (
mf(m.get('Right')) if None is m.get('Left') else m
)
 
 
# fst :: (a, b) -> a
def fst(tpl):
'''First member of a pair.'''
return tpl[0]
 
 
# snd :: (a, b) -> b
def snd(tpl):
'''Second member of a pair.'''
return tpl[1]
 
 
# MAIN ---
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>(5.0, 5.0)</pre>
Anonymous user