8

I am using QGIS and I am looking for a script, or a plugin, that can create a large number of perpendicular lines from a point layer to lines in a separate line layer.

So far, I've tried to use the Hub Distance function in MMQGIS (turning the lines into points and then connecting the points to the nearest hub) and the respective tool of the QGIS geoalgorithms. Neither worked. Both take more than 2 hours and create either lines all of the layer or lines that are not perpendicular or connected to the points.

In the picture, you can see the present status of the project. The perpendicular lines should run from the points to the nearest line. In the end, I would like to use intersection points with a line between the points and the country borders to create a buffer of 4-sided polygons that is two polygons deep. I mention this in case that there is an easier way of doing this. enter image description here enter image description here

I know that there are some posts on how to create perpendicular lines, but neither of them solved my problem.

  • 1
    @Germán Carrillo This question is not an exact duplicate of existing question "Drawing perpendicular lines in PyQGIS?" (gis.stackexchange.com/questions/59169/…) because the answer doesn't use 'closestSegmentWithContext' method in a loop for exploring each interaction between points and features line for taking minimum distance to create a line memory layer. It's impossible because this answer only uses points. Please, review it again. – xunilk Mar 20 '17 at 6:27
  • 1
    I still find the other answer a good basis to solve this question. The OP should have mentioned in the original question that he/she was aware of related posts AND tell us why they didn't work for him/her. Nonetheless, good answer, thanks for posting! – Germán Carrillo Mar 20 '17 at 14:25
6

Next script automated creation of perpendicular lines between a point layer and a line layer. The perpendicular segments (features of a memory layer) created run from the points to the nearest feature of line layer.

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

p_lyr = layers[0]
l_lyr = layers[1]

epsg = p_lyr.crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&field=distance:double(20,2)&index=yes"

dist = QgsVectorLayer(uri, 
                      'dist', 
                      'memory')

QgsMapLayerRegistry.instance().addMapLayer(dist)

prov = dist.dataProvider()

lines_features = [ line_feature for line_feature in l_lyr.getFeatures() ] 
points_features = [ point_feature for point_feature in p_lyr.getFeatures() ]

feats = []

for p in points_features:

    minDistPoint = min([l.geometry().closestSegmentWithContext( p.geometry().asPoint() ) for l in lines_features])[1]
    feat = QgsFeature()
    feat.setGeometry(QgsGeometry.fromPolyline([p.geometry().asPoint(), minDistPoint]))
    feat.setAttributes([points_features.index(p),feat.geometry().length()])
    feats.append(feat)

prov.addFeatures(feats)

I tried it out with a situation very similar to presented in the question:

enter image description here

After running the code at the Python Console of QGIS it was obtained:

enter image description here

  • Worked marvelously. I will have to clean it up a bit as I get some misfits like in your example, but otherwise it only took seconds and looks perfect. Thank you very, very much. – Monody Mar 20 '17 at 5:38
2

Here is the same code as in accepted answer only adjusted to work with Python 3.x (or QGIS v3.x):

from qgis.core import QgsProject

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

p_lyr = layers[0]
l_lyr = layers[1]

epsg = p_lyr.crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&field=distance:double(20,2)&index=yes"

dist = QgsVectorLayer(uri,
                      'dist',
                      'memory')

QgsProject.instance().addMapLayer(dist)

prov = dist.dataProvider()

lines_features = [ line_feature for line_feature in l_lyr.getFeatures() ]
points_features = [ point_feature for point_feature in p_lyr.getFeatures() ]

feats = []

for p in points_features:

    minDistPoint = min([l.geometry().closestSegmentWithContext( p.geometry().asPoint() ) for l in lines_features])[1]
    feat = QgsFeature()
    feat.setGeometry(QgsGeometry.fromPolylineXY([p.geometry().asPoint(), minDistPoint]))
    feat.setAttributes([points_features.index(p),feat.geometry().length()])
    feats.append(feat)

prov.addFeatures(feats)

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.