I have to iterate over a point and line layer to draw the perpendicular line from each point to the nearest line. The QGIS geoalgorithm "DISTANCE TO NEAREST HUB" isn't helpful because the nearest hub isn't perpendicular.

I found this code, but how can I call the points in the Point Layer and the lines in the Line layer generally? How can I can iterate over them with a loop to find/create the perpendicular line in between?

# basic example with PyQGIS
# the end points of the line
line_start = QgsPoint(50,50)
line_end = QgsPoint(100,150)
# the line
line = QgsGeometry.fromPolyline([line_start,line_end])
# the point
point = QgsPoint(30,120)

enter image description here

def intersect_point_to_line(point, line_start, line_end):
     ''' Calc minimum distance from a point and a line segment and intersection'''
      # sqrDist of the line (PyQGIS function = magnitude (length) of a line **2)
      magnitude2 = line_start.sqrDist(line_end) 
      # minimum distance
      u = ((point.x() - line_start.x()) * (line_end.x() - line_start.x()) + (point.y() - line_start.y()) * (line_end.y() - line_start.y()))/(magnitude2)
      # intersection point on the line
      ix = line_start.x() + u * (line_end.x() - line_start.x())
      iy = line_start.y() + u * (line_end.y() - line_start.y())
      return QgsPoint(ix,iy)

line = QgsGeometry.fromPolyline([point,intersect_point_to_line(point, line_start, line_end)])

enter image description here

  • What is your definition of "nearest line". The line that have the closest node to your point. The line that have the shortest perpendicular to your point. Or for example the line which it's midpoint is closest to the point. – Francisco Puga Aug 24 '16 at 9:20
  • The Line that have the closest node to each point – NewbieInQGIS Aug 24 '16 at 9:27
  • In that case, "the line" could be not perpendicular to the polyline segment and there is a problem in the title of your question. – xunilk Aug 24 '16 at 9:35
  • Oh Sorry, I want "the line which have the shortest perpendicular to my point" – NewbieInQGIS Aug 24 '16 at 9:42

You need a reference to the layers. I do that with QgsMapCanvas class in the next code. PyQGIS also has classes to find 'Closest Segments'. For this reason you can avoid to use your 'intersect_point_to_line' function. I used 'closestSegmentWithContext' of QgsGeometry instead.

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

feat_points = [ feat for feat in layers[0].getFeatures() ]

feat_line = layers[1].getFeatures().next()

geoms = [ feat_line.geometry().closestSegmentWithContext(feat.geometry().asPoint())
          for feat in feat_points ]

#geom is a tupla. I need only second term, geom[1], that is a QgsPoint
for i, geom in enumerate(geoms):
    closest_line = QgsGeometry.fromPolyline([ feat_points[i].geometry().asPoint(), 
                                             geom[1] ])

    print closest_line.exportToWkt()

I employed above code with next layers; where you can have two possible situations.

enter image description here

After running the code, at the Python Console of QGIS were printed two Line Strings in WKT format. By using QuickWKT plugin of QGIS I got:

enter image description here

You can observe that, in one case, second closest segment is not perpendicular.

  • What parts of the code do I need to modify for my layers? – cbunn Feb 16 '17 at 23:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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