在QGIS中创建等距点?


22

我试图在QGIS中沿道路(现有层)的特定距离创建点(新层)。使用ArcGIS Desktop在县级每米建立常规点吗? 提供ArcGIS解决方案。如何在QGIS中实现这一目标?使用QGIS向点矢量层添加点吗?解释了如何创建点,但不对距离做任何事情。


(由于不知道转换,我以不同的长度度量应用了建议的解决方案)@Nathans的解决方案在某种程度上有效,我得到了...

在此处输入图片说明。在这里,这些等距点的投影与原始线不同。

有了@underdark的建议,我得到了

这个图片点似乎不等距。我猜这两个都存在一些我不理解的投影问题。



2
有两点。首先,生产线必须位于预计的CRS中(而不是经纬度)。其次,您的线是真正的折线吗?我认为任何方法都不能在包含一串单独行的行上正常工作。缺口。
nhopton 2012年

同样,在我的代码中,您无需import locate多次调用该行。只需拨打一次,那么你可以调用locate.pointsAlongLine(30)尽可能多的,因为你需要
弥敦道W ^

另一种方法(假设某些答案建议的Sextant仅是QGIS <2.0),也可以使用称为QChainage的插件。
安迪2014年

Answers:


14

注意:现在有一个QGIS插件QChainage。它可以做所有这些以及更多。以下代码在QGIS 2.0及更高版本中已过期。

这是一些Python代码,您可以将它们粘贴在文件中并在QGIS中使用:

QGIS的API中确实有一种方法可以进行线性引用,但是我无法使其正常工作,但是我将与代码作者联系,查看我是否做错了什么。

现在,您将需要造型优美的 Python库,无论如何都应该安装该库,因为它很容易携带。它还在http://toblerity.github.com/shapely/manual.html上提供了出色的文档。

这是我在以下示例中使用的部分http://toblerity.github.com/shapely/manual.html#interoperation

以下大多数代码是QGIS样板代码,仅用于创建要素,图层,从wkb和wkt转换回来。核心位是point = line.interpolate(currentdistance)沿直线返回一定距离的点。我们只是将其包装成一个循环,直到用完为止。

import qgis
from qgis.core import *
from PyQt4.QtCore import QVariant
from shapely.wkb import loads
from shapely.wkt import dumps

vl = None
pr = None

def createPointsAt(distance, geom):
    if distance > geom.length():
        print "No Way Man!"
        return

    length = geom.length()
    currentdistance = distance
    feats = []  

    while currentdistance < length: 
        line = loads(geom.asWkb())
        point = line.interpolate(currentdistance)
        fet = QgsFeature()
        fet.setAttributeMap( { 0 : currentdistance } )
        qgsgeom = QgsGeometry.fromWkt(dumps(point))
        fet.setGeometry(qgsgeom)
        feats.append(fet)
        currentdistance = currentdistance + distance

    pr.addFeatures(feats)
    vl.updateExtents()

def pointsAlongLine(distance):
    global vl
    vl = QgsVectorLayer("Point", "distance nodes", "memory")
    global pr
    pr = vl.dataProvider()  
    pr.addAttributes( [ QgsField("distance", QVariant.Int) ] )
    layer = qgis.utils.iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        createPointsAt(distance, geom)

    QgsMapLayerRegistry.instance().addMapLayer(vl)

将上面的代码复制并粘贴到目录中的文件我的locate.py中~./qgis/python(因为它位于Python路径中),然后在QGIS的Python控制台中执行此操作。

 import locate
 locate.pointsAlongLine(30)

这将创建一个新的点层,沿着选定的线每30米处有一个点,如下所示:

在此处输入图片说明

注意:代码很粗糙,可能需要清理。

编辑:最新的QGIS开发人员版本现在可以本地执行此操作。

将while循环更改createPointsAt为:

 while currentdistance < length: 
    point = geom.interpolate(distance)
    fet = QgsFeature()
    fet.setAttributeMap( { 0 : currentdistance } )
    fet.setGeometry(point)
    feats.append(fet)
    currentdistance = currentdistance + distance

您可以删除

from shapely.wkb import loads
from shapely.wkt import dumps

谢谢@内森。我无法为我的python获取Shapely软件包。我安装了python 2.7,但是Shapely安装程序说python 2.7不在我的注册表中。还有另一种安装Shapely的方法。
Stat-R

我遵循stackoverflow.com/questions/3652625/…并键入了以上两行以进行调用locate和使用,但仍然没有得到等距点。另外,我是Python的新手,所以我不知道在哪里运行代码(1)在qgis目录中的python或(2)在C:\ Python27 \处的代码?
Stat-R

您在什么操作系统上?
内森·W

Windows 7 Professional
Stat-R

在中创建python文件,C:\Users\{you user name}\.qgis\python然后重新打开QGIS(如果已打开),然后转到“插件-> Python控制台. Load a line layer, select a line a call 导入定位”和locate.pointsAlongLine(30)
Nathan W

5

您可以使用QGIS GRASS插件v.to.points工具定期创建沿线的点

# convert line to points; dmax = distance between points
v.to.points -i -v -t in=road out=road_pts type=line dmax=90

我将dmax设置为100,每个的最终投影如下。(我不知道CRS是如何自行分配的。)CRS of Original Shape file, the line = EPSG:26915 - NAD83 / UTM zone 15N, CRS of Grass line vector obtained using v.in.ogr = EPSG:4269 - NAD83, CRS of Grass points vector obtained using v.to.points = EPSG:4326 - WGS 84
2012年

现在也像这样:QGIS-> Sextante-> GRASS-> v.to.points
markusN 2012年

5

如果要沿道路线以固定间隔绘制桩号,则可以使用“轮廓线”插件来完成。您需要在道路线层下创建DEM,但是该过程非常快速且非常简单。缺口。

在此处输入图片说明


这也是一个非常好的和简单的方法,谢谢!
Shepherdjo

2

请注意,Shapely(Python)/ GEOS(C ++)数据模型是在平面中定义的。因此,如果您的点由GPS位置(纬度,经度)组成,则使用的shapely.geometry.LineString.interpolate(distance)方法将沿给定的欧氏距离输出GPS位置LineString

Shapely的interpolate()方法基于GEOS的geos::linearref::LengthIndexedLineextractPoint

假设在纬度-经度平面中等距的插值对于考虑相对较小距离的应用程序就足够了。但是,一般来说,应该考虑GIS应用程序在球体上的距离(如WGS84中所定义)。

我可以想到使用Shapely模块的两种解决方法:

  • LineString属性均具有给定的点和沿其线性插值的曲线。也许您可以编写一个访问插值曲线的成员,并用以下直线积分代替欧几里德距离。我之所以喜欢这种方法,是因为使用分段连续曲线可以通过计算沿曲线的相邻圆与半径的交点来获得所需点 r = radian_measure(arc_length) = arc_length / R,其中R等于给定位置处的地球半径。
  • 使用适当的距离函数(例如,haversine公式)编写自己的插值方法(无需触摸Shapely代码)。

为此,我想参考下面的StackOverflow问题,尤其是这个答案

可以沿曲线生成等距点。但是,对于真正的答案,必须有更多的定义。抱歉,但是我为此任务编写的代码在MATLAB中,但是我可以描述一些一般性的想法。有三种可能性。

首先,就简单的欧几里得距离而言,这些点是否与邻居真正等距?为此,需要找到曲线上任意点具有固定半径的圆的交点。然后沿着曲线前进。

接下来,如果您打算将距离指的是沿曲线本身的平均距离,则如果曲线是分段线性曲线,则问题仍然很容易解决。只需沿着曲线步进即可,因为线段上的距离易于测量。

最后,如果您打算使曲线成为三次样条曲线,那么这并不是很难,但是需要做更多的工作。这里的窍门是:

  • 计算沿曲线从点到点的分段线性弧长。称它为t。生成一对三次样条曲线x(t),y(t)。

  • 将x和y微分为t的函数。由于这些是立方段,因此很容易。导数函数将是分段
    二次的。

  • 使用ode求解器沿曲线移动,集成差分弧长函数。在MATLAB中,ODE45运作良好。

因此,一个整合

sqrt((x')^2 + (y')^2)

同样,在MATLAB中,可以设置ODE45来标识函数与某些指定点交叉的位置。

如果您的MATLAB技能能够胜任该任务,则可以查看interparc中的代码以 获取更多说明。这是注释合理的代码。

3http//www.mathworks.com/matlabcentral/fileexchange/34874-interparc


1

Sextante有一个可能适合您的工具。可以从Qgis插件存储库下载Sextante。

查找:
“线层工具”
“线到等距点”


这个插件似乎并没有可用于QGIS 2或3
马丁·伯奇
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.