đây là một mã giả để bắt đầu. Tôi hy vọng điều này có ích và ai đó sẽ có thời gian để cung cấp mã đầy đủ (hiện tại tôi không có)
Điều đầu tiên cần làm là lặp trên điểm và chọn các đường nằm trong khoảng cách ngưỡng đến từng điểm. Thi có thể được thực hiện với QssSpatial Index
Trong vòng lặp đầu tiên, điều thứ hai cần làm là lặp trên các dòng đã chọn và tìm điểm gần nhất trên dòng. Điều này có thể được thực hiện trực tiếp dựa trên QssGeometry :: nearSegmentWithContext
double QssGeometry :: nearSegmentWithContext (const QssPoint & point, QssPoint & minDistPoint, int & afterVertex, double * leftOf = 0, double epsilon = DEFAULT_SEGMENT_EPSILON)
Tìm kiếm phân đoạn hình học gần nhất với điểm đã cho.
Điểm tham số Chỉ định điểm tìm kiếm
minDistPoint Receives the nearest point on the segment
afterVertex Receives index of the vertex after the closest segment. The vertex before the closest segment is always afterVertex -
1 leftOf Out: Trả về nếu điểm nằm ở bên trái của phân khúc (<0 có nghĩa là bên trái,> 0 có nghĩa là bên phải) epsilon epsilon để chụp phân đoạn (được thêm vào 1.8)
bước thứ ba (trong vòng lặp đầu tiên) sẽ bao gồm việc cập nhật hình dạng của điểm với hình dạng của minDistPoint với khoảng cách nhỏ nhất
cập nhật với một số mã (trên QGIS3)
pointlayer = QgsProject.instance().mapLayersByName('point')[0] #iface.mapCanvas().layer(0)
lineLayer = QgsProject.instance().mapLayersByName('lines')[0] # iface.mapCanvas().layer(1)
epsg = pointlayer.crs().postgisSrid()
uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer&field=distance:double(20,2)&field=left:integer&index=yes"
snapped = QgsVectorLayer(uri,'snapped', 'memory')
prov = snapped.dataProvider()
testIndex = QgsSpatialIndex(lineLayer)
i=0
feats=[]
for p in pointlayer.getFeatures():
i+=1
mindist = 10000.
near_ids = testIndex.nearestNeighbor(p.geometry().asPoint(),4) #nearest neighbor works with bounding boxes, so I need to take more than one closest results and further check all of them.
features = lineLayer.getFeatures(QgsFeatureRequest().setFilterFids(near_ids))
for tline in features:
closeSegResult = tline.geometry().closestSegmentWithContext(p.geometry().asPoint())
if mindist > closeSegResult[0]:
closePoint = closeSegResult[1]
mindist = closeSegResult[0]
side = closeSegResult[3]
feat = QgsFeature()
feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(closePoint[0],closePoint[1])))
feat.setAttributes([i,mindist,side])
feats.append(feat)
prov.addFeatures(feats)
QgsProject.instance().addMapLayer(snapped)