I can't give you python code (haven't used it for a while), but I hope that I can help you with a logic.
To clarify: "Line" extends in both directions infinitely. If it does have ends it is called a "Line Segment".
You will need to write 2 simple functions (I can post source code in Java if you need it):
- intersectionOfTwoLines(line1StartPoint, line1EndPoint, line2StartPoint, line2EndPoint)
- isPointOnTheLineSegment(segmentStartPoint, segmentEndPoint, point)
Step 1 - find intersection point of 2 lines. Let's call that point P, and call our line segments S1 and S2.
Step 2 - check if P is on S1.
Step 3 - check if P is on S2.
Step 4 - P is on S1 but not on S2 (your case 1). Find the closest node of the S2 to the P and replace that node with the P.
Step 5 - P is on S2 but not on S1 (your case 1). Find the closest node of the S1 to the P and replace that node with the P.
Step 6 - P is not on S1 and not on S2 (your case 2). Find the closest node of the S1 to the P and replace that node with the P. Do the same for the S2.
Step 7 - P is on S1 and on S2 (your case 3). This is little bit tricky. I presume that you will always consider dangle to be the shortest segment of the intersection. If that is the case than you will need to calculate distances from P to the each node of the S1 and S2. Shortest distance will tell you which point to replace with P. For example, if shortest distance is from P to S2 end-node, than you just need to replace end-node of the S2 with P.
Sorry for my bad English.
EDIT
I'm not really python developer, but this should work:
Python 3 code
import math
def intersection_of_two_lines(l1_pt1, l1_pt2, l2_pt1, l2_pt2):
"""Returns point of intersection of two lines.
Keyword arguments:
l1_pt1 -- Line 1 - Point 1.
l1_pt2 -- Line 1 - Point 2.
l2_pt1 -- Line 2 - Point 1.
l2_pt2 -- Line 2 - Point 2.
"""
dx1 = l1_pt1["x"] - l1_pt2["x"]
dx2 = l2_pt1["x"] - l2_pt2["x"]
dy1 = l1_pt1["y"] - l1_pt2["y"]
dy2 = l2_pt1["y"] - l2_pt2["y"]
# Determinant.
d = dx1 * dy2 - dy1 * dx2
if (d == 0):
raise Exception('Lines are parallel.')
a = l1_pt1["x"] * l1_pt2["y"] - l1_pt1["y"] * l1_pt2["x"]
b = l2_pt1["x"] * l2_pt2["y"] - l2_pt1["y"] * l2_pt2["x"]
p = {}
p["x"] = (a * dx2 - dx1 * b) / d
p["y"] = (a * dy2 - dy1 * b) / d
return p
def distance(p1, p2):
"""Returns the distance between two points.
Keyword arguments:
p1 -- Point 1.
p2 -- Point 2.
"""
dx = p1["x"] - p2["x"]
dy = p1["y"] - p2["y"]
return math.sqrt(dx * dx + dy * dy)
def is_point_on_line_segment(p, seg_pt1, seg_pt2):
"""Returns true if point is on line segment.
Keyword arguments:
p -- Point to check.
seg_pt1 -- First point of the line segment.
seg_pt2 -- Second point of the line segment.
"""
d = distance (seg_pt1, seg_pt2)
d1 = distance (p, seg_pt1)
d2 = distance (p, seg_pt2)
if (d == d1 + d2):
return True
return False
# How to use:
# Segment 1
l1_pt1 = {}
l1_pt1["x"] = -10
l1_pt1["y"] = -5
l1_pt2 = {}
l1_pt2["x"] = 10
l1_pt2["y"] = 25
# Segment 2
l2_pt1 = {}
l2_pt1["x"] = 20
l2_pt1["y"] = -10
l2_pt2 = {}
l2_pt2["x"] = -20
l2_pt2["y"] = 30
print(intersection_of_two_lines(l1_pt1, l1_pt2, l2_pt1, l2_pt2))
# Point on segment 1
pt1 = {}
pt1["x"] = 0
pt1["y"] = 10
print(is_point_on_line_segment(pt1, l1_pt1, l1_pt2))
# Point not on segment 1
pt2 = {}
pt2["x"] = 50
pt2["y"] = 10
print(is_point_on_line_segment(pt2, l1_pt1, l1_pt2))