3

I have 3 cases shown in the image.

In all of them i want to intersect the lines and remove dangles using python in Qgis python console so afterwards i can make a plugin for this work in qgis.In case 1 i want to extend the vertical line to the horizontal line.In case two i want to extend both of the lines so that they intersect each other.In case three i want to remove the extra portion (remove dangles).

I am able to get the coordinates in the variable.

Can anybody tell me how to do this using python code?

enter image description here

7
  • ftr_geom = [] select = self.iface.activeLayer().selectedFeatures() for ftr in select: geom = ftr.geometry() if geom.type() == QGis.Line: f_geom = geom.asPolyline() ftr_geom.append(f_geom) Commented Oct 7, 2014 at 20:33
  • by using this code i can get the coordinates of each of the point of these lines..i just need the logic with code how to resize these lines. Commented Oct 7, 2014 at 20:35
  • what type of data are you using? Shapefiles? PostGIS has functions that can do this. I just saw a great presentation by Leo Hsu at FOSS4G that demonstrated this... Commented Oct 7, 2014 at 20:40
  • I am using shapefiles.I need to create my own tool for this purpose.I also want to learn how to reshape my feature like extend or trim the lines in qgis not in post gis.Please help me Commented Oct 7, 2014 at 22:34
  • Ali Subhan Kazmi, I woud like to know if the problem was resolved. We have the same problem here in Brazil. thanks! Commented May 19, 2016 at 13:51

2 Answers 2

4

You need to think in terms of analytic geometry or vector geometry:

I illustrate the approach with the first example (same with the others) with PyQGIS here but you can also use Shapely.

You need to create a segment in the direction of line1 and calculate the point of intersection with line2.

1) Find the azimuth of line1 (How do I find vector line bearing in QGIS or GRASS?) and project a point in this direction using direction cosines (How to create points in a specified distance along the line in QGIS?)

import math
def azimuth(point1, point2):
   return point1.azimuth(point2) #in degrees
def cosdir_azim(azim):
   azim = math.radians(azim)
   cosa = math.sin(azim)
   cosb = math.cos(azim)
   return cosa,cosb

seg_start, seg_end = line1.asPolyline()
cosa, cosb = cosdir_azim(azimuth(seg_start, seg_end))
lenght = a_distance
result  = QgsPoint(seg_end.x()+(a_distance*cosa), seg_end.y()+(a_distancer*cosb))

enter image description here

segment =QgsGeometry.fromPolyline([seg_end,result])

enter image description here

2) find the intersection and compute the resulting line

inter = segment.intersection(line2) # a point, in green

enter image description here

result =QgsGeometry.fromPolyline([seg_start,inter])

enter image description here

2
  • what is a_distance??i understand your code but not a_distance. Commented Oct 11, 2014 at 11:21
  • ok i got this..now another problem the I faced..I am running my script on two selected features(these two lines).What is this line is drawn in the opposite direction?means segment end is segment start??and what if line one is the horizontal line because i am just selecting there two lines.Please give me a formula that i apply on two lines and it give me the intersection point of those two and if they dont have intersection point return no value Commented Oct 11, 2014 at 11:35
4

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):

  1. intersectionOfTwoLines(line1StartPoint, line1EndPoint, line2StartPoint, line2EndPoint)
  2. 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))
2
  • how to find to intersection point..like in step 1..another problem is i am new to python so if anybody can provide me proper code it will help me better..Thank you Commented Oct 8, 2014 at 16:05
  • @Ali Subhan Kazmi - I edited the answer. Commented Oct 8, 2014 at 19:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.