3

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

4
  • 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. Aug 24, 2016 at 9:20
  • The Line that have the closest node to each point Aug 24, 2016 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, 2016 at 9:35
  • Oh Sorry, I want "the line which have the shortest perpendicular to my point" Aug 24, 2016 at 9:42

1 Answer 1

2

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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