Usted puede ejecutar el código siguiente desde la Consola de Python:
searching_dist = 20 # Set it as you want
lines = QgsMapLayerRegistry.instance().mapLayersByName('line')[0] # Replace 'line' with the name of the line layer
points = QgsMapLayerRegistry.instance().mapLayersByName('points')[0] # Replace 'points' with the name of the point layer
cr = points.crs()
dist_calc = QgsDistanceArea()
dist_calc.setSourceCrs(cr)
dist_calc.setEllipsoid(cr.ellipsoidAcronym())
dist_calc.setEllipsoidalMode(cr.geographicFlag())
# This layer contains all the points created along the line (it isn't an output)
crs = points.crs().toWkt()
temp_pts = QgsVectorLayer('Point?crs='+ crs, 'temp_pts' , 'memory')
prov = temp_pts.dataProvider()
tmp_points = {}
index = QgsSpatialIndex()
for line in lines.getFeatures():
line_geom = line.geometry()
(first_line_point, end_line_point) = (line_geom.interpolate(0).asPoint(), line_geom.interpolate(line.geometry().length()).asPoint())
pt1 = QgsFeature()
pt1.setGeometry(QgsGeometry.fromPoint(first_line_point))
(result, feat) = prov.addFeatures([pt1])
tmp_points[feat[0].id()] = feat[0]
index.insertFeature(feat[0])
pt2 = QgsFeature()
pt2.setGeometry(QgsGeometry.fromPoint(end_line_point))
(result, feat) = prov.addFeatures([pt2])
tmp_points[feat[0].id()] = feat[0]
index.insertFeature(feat[0])
for point in points.getFeatures():
geom = point.geometry()
nearest = index.nearestNeighbor(geom.asPoint(), 1)
tmp_pt_geom = tmp_points[nearest[0]].geometry()
dist = dist_calc.measureLine(geom.asPoint(), tmp_pt_geom.asPoint())
if dist <= searching_dist:
points.dataProvider().changeGeometryValues({point.id(): tmp_pt_geom})
points.triggerRepaint()
Para que funcione, sólo necesita preliminar de la carga del punto y de la línea de las capas en el Panel Capas y, a continuación, escriba sus nombres en caso necesario (he dejado un comentario en el código anterior). Además, es necesario especificar una búsqueda de distancia (yo usé 20
m, establecido como quieras).
Finalmente, el código anterior editar directamente las geometrías dentro de la capa de puntos, así que recuerde de crear una copia de seguridad de sus datos antes de intentarlo.
Como un ejemplo, a partir de esta situación:
usted recibirá este resultado:
y, el zoom más sobre ella (como lo hizo en su pregunta original):
EDITAR
Si desea ajustar los puntos por considerar el final de la línea de nodos, se puede utilizar esta ligeramente editado código:
searching_dist = 20 # Set it as you want
lines = QgsMapLayerRegistry.instance().mapLayersByName('line')[0] # Replace 'line' with the name of the line layer
points = QgsMapLayerRegistry.instance().mapLayersByName('points')[0] # Replace 'points' with the name of the point layer
cr = points.crs()
dist_calc = QgsDistanceArea()
dist_calc.setSourceCrs(cr)
dist_calc.setEllipsoid(cr.ellipsoidAcronym())
dist_calc.setEllipsoidalMode(cr.geographicFlag())
# This layer contains all the points created along the line (it isn't an output)
crs = points.crs().toWkt()
temp_pts = QgsVectorLayer('Point?crs='+ crs, 'temp_pts' , 'memory')
prov = temp_pts.dataProvider()
tmp_points = {}
index = QgsSpatialIndex()
for line in lines.getFeatures():
line_geom = line.geometry()
end_line_point = line_geom.interpolate(line.geometry().length()).asPoint()
pt1 = QgsFeature()
pt1.setGeometry(QgsGeometry.fromPoint(end_line_point))
(result, feat) = prov.addFeatures([pt1])
tmp_points[feat[0].id()] = feat[0]
index.insertFeature(feat[0])
for point in points.getFeatures():
geom = point.geometry()
nearest = index.nearestNeighbor(geom.asPoint(), 1)
tmp_pt_geom = tmp_points[nearest[0]].geometry()
dist = dist_calc.measureLine(geom.asPoint(), tmp_pt_geom.asPoint())
if dist <= searching_dist:
points.dataProvider().changeGeometryValues({point.id(): tmp_pt_geom})
points.triggerRepaint()