นี่คือรหัสหลอกที่จะเริ่มต้นด้วย ฉันหวังว่านี่จะช่วยได้และใครบางคนจะมีเวลาให้รหัสเต็ม (ฉันยังไม่มีในขณะนี้)
สิ่งแรกที่ต้องทำคือการวนรอบจุดและเลือกบรรทัดที่อยู่ภายในระยะทางขีด จำกัด ของแต่ละจุด Thi สามารถทำได้ด้วย QgsSpatialIndex
ภายในลูปแรกสิ่งที่สองที่ต้องทำคือการวนลูปในบรรทัดที่เลือกและค้นหาจุดที่ใกล้ที่สุดในบรรทัด ซึ่งสามารถทำได้โดยตรงตาม QgsGeometry :: closestSegmentWithContext
double QgsGeometry :: closestSegmentWithContext (const QgsPoint & point, QgsPoint & minDistPoint, int & afterVertex, double * leftOf = 0, epsilon คู่ = DEFAULT_SEGMENT_EPSILON)
ค้นหาส่วนที่ใกล้ที่สุดของรูปทรงเรขาคณิตไปยังจุดที่กำหนด
จุดพารามิเตอร์ระบุจุดที่ต้องการค้นหา
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: ส่งคืนถ้าจุดอยู่ทางด้านซ้ายของด้านขวาของส่วน (<0 หมายถึงซ้าย> 0 หมายถึงด้านขวา) epsilon epsilon สำหรับการจัดกลุ่ม (เพิ่มใน 1.8)
ขั้นตอนที่สาม (ภายในวงแรก) จะประกอบด้วยในการปรับปรุงรูปทรงเรขาคณิตของจุดที่มีรูปทรงเรขาคณิตของminDistPointด้วยระยะทางที่เล็กที่สุด
อัปเดตด้วยรหัสบางส่วน (ใน 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)