将点移动到线上(〜邻域)


14

我确实有两个矢量层,其中一个是基于遥感“事件”的点层,第二个是来自本地研究的线层。

就我而言,这些是地震和构造断裂,但我想人们可以简单地选择“车祸和道路”作为一般示例。

因此,我想做的就是将点移动/复制到直线的最近点上,只要它在公差范围内(例如1-2km或0.0xx°),并使用新的点层(已移动+ attr y / n)。

有任何想法吗 ?

Linux,QGIS 1.8


3
将会有一个PostGIS解决方案:PostGIS:线串上到给定点的最接近点
暗处

您是在寻找一种完全自动化的功能来执行此操作,还是可以通过某种形式的捕捉工具来手动执行此操作?
Simbamangu

我问了一个类似的问题,我试图将线对齐到点,但从未找到简单的解决方案。 gis.stackexchange.com/questions/52232/…–
GreyHippo

三角测量和距离匹配呢?
huckfinn 2014年

我发现了有关使用Near在ArcGIS中工作的方法的问题。去寻找接近QGIS 地方,并找到了这个论坛帖子,其中有人建议GRASS v.distance。这使我进入了可能确定方法的本教程。也许现在某个地方有人写了一个插件?
克里斯W

Answers:


13

发布了以下代码片段(在python控制台中测试)

  1. 使用QgsSpatialIndex查找距点最近的线要素
  2. 在这条线上找到离该点最近的点。我使用匀称的包装作为此操作的快捷方式。我发现用于此的QGis方法不足(或者很可能我不太了解它们)
  3. 在捕捉位置添加了橡皮筋
from shapely.wkt import *
from shapely.geometry import *
from qgis.gui import *
from PyQt4.QtCore import Qt
lineLayer = iface.mapCanvas().layer(0)
pointLayer =  iface.mapCanvas().layer(1)
canvas =  iface.mapCanvas()
spIndex = QgsSpatialIndex() #create spatial index object
lineIter =  lineLayer.getFeatures()
for lineFeature in lineIter:
    spIndex.insertFeature(lineFeature)        
pointIter =  pointLayer.getFeatures()
for feature in pointIter:
    ptGeom = feature.geometry()
    pt = feature.geometry().asPoint()
    nearestIds = spIndex.nearestNeighbor(pt,1) # we need only one neighbour
    featureId = nearestIds[0]
    nearestIterator = lineLayer.getFeatures(QgsFeatureRequest().setFilterFid(featureId))
    nearFeature = QgsFeature()
    nearestIterator.nextFeature(nearFeature)
    shplyLineString = shapely.wkt.loads(nearFeature.geometry().exportToWkt())
    shplyPoint = shapely.wkt.loads(ptGeom.exportToWkt())
    #nearest distance from point to line
    dist = shplyLineString.distance(shplyPoint)
    print dist
    #the point on the road where the point should snap
    shplySnapPoint = shplyLineString.interpolate(shplyLineString.project(shplyPoint))
    #add rubber bands to the new points
    snapGeometry = QgsGeometry.fromWkt(shapely.wkt.dumps(shplySnapPoint))
    r = QgsRubberBand(canvas,QGis.Point)
    r.setColor(Qt.red)
    r.setToGeometry(snapGeometry,pointLayer)

编辑: 刚刚发现使用radicalSegmentWithContext的@radouxju方法在更少的代码行中给出了相同的结果。我想知道为什么他们想出这个奇怪的方法名称?应该是最近的PointPointOnGeometry之类的东西。

这样我们就可以避免身材匀称而喜欢

nearFeature = QgsFeature()
nearestIterator.nextFeature(nearFeature)   

closeSegResult = nearFeature.geometry().closestSegmentWithContext(ptGeom.asPoint())
closePoint = closeSegResult[1]
snapGeometry = QgsGeometry.fromPoint(QgsPoint(closePoint[0],closePoint[1])) 

p1 = ptGeom.asPoint()
p2 = snapGeometry.asPoint()

dist = math.hypot(p2.x() - p1.x(), p2.y() - p1.y())
print dist

1
陷入噩梦,试图格式化此python代码..argh!
vinayan 2014年

5

这是一个伪代码开始。我希望这会有所帮助,并希望有人有时间提供完整的代码(我目前没有)

首先要做的是在该点上循环并选择到每个点的阈值距离内的线。可以使用QgsSpatialIndex完成

在第一个循环中,第二件事是在选定的线上循环并找到该线上的最近点。这可以直接基于QgsGeometry :: closestSegmentWithContext完成

双QgsGeometry :: closestSegmentWithContext(const QgsPoint&point,QgsPoint&minDistPoint,int&afterVertex,double * leftOf = 0,double epsilon = DEFAULT_SEGMENT_EPSILON)

搜索最接近给定点的几何段。

参数point指定要搜索的点

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.