การสร้างจุดที่เท่ากันใน QGIS?


22

ฉันกำลังพยายามสร้างจุด (เลเยอร์ใหม่) ตามระยะทางเฉพาะตามแนวถนน (เลเยอร์ที่มีอยู่) ใน QGIS การสร้างคะแนนปกติทุก ๆ เมตรในระดับเขตโดยใช้ ArcGIS Desktop? ให้โซลูชันสำหรับ ArcGIS ทำอย่างไรจึงจะได้สิ่งนี้ใน QGIS? การเพิ่มจุดไปยังจุดเวกเตอร์เลเยอร์โดยใช้ QGIS? อธิบายถึงวิธีการสร้างคะแนน แต่ไม่ได้ทำอะไรเกี่ยวกับระยะทาง


(ฉันใช้วิธีแก้ปัญหาที่เสนอพร้อมมาตรการที่มีความยาวแตกต่างกันสำหรับฉันไม่ทราบถึงการแปลง) @ โซลูชันของ Nathans ทำงานได้ในระดับหนึ่งฉันได้ ...

ป้อนคำอธิบายรูปภาพที่นี่. ที่นี่การประมาณการของจุดเท่ากันเหล่านี้จะแตกต่างจากเส้นเดิม

ฉันได้รับคำแนะนำของ @ underdark

ภาพนี้จุดที่ดูเหมือนจะไม่เท่ากัน ฉันเดาว่ามีปัญหาเกี่ยวกับการฉายภาพทั้งสองอย่างนี้ซึ่งฉันไม่เข้าใจ


1
เปรียบเทียบgis.stackexchange.com/questions/11992/…
underdark

2
คะแนนสองสาม ประการแรกบรรทัดต้องอยู่ใน CRS ที่คาดการณ์ไว้ (ไม่ใช่ lat / lon) ประการที่สองสายของคุณเป็นเส้นหลายเส้นจริงหรือไม่? ฉันไม่คิดว่าวิธีการใด ๆ ที่จะทำงานอย่างถูกต้องในบรรทัดที่ประกอบด้วยสตริงของแต่ละบรรทัด กรงขัง
nhopton

นอกจากนี้เมื่อใช้รหัสของฉันคุณไม่จำเป็นต้องโทรหาimport locateสายมากกว่านี้อีกครั้ง เพียงแค่เรียกมันครั้งเดียวแล้วคุณสามารถโทรได้locate.pointsAlongLine(30)มากเท่าที่คุณต้องการ
นาธาน W

วิธีการอื่น (ระบุว่า Sextant ตามคำแนะนำบางคำตอบที่นี่คือ QGIS <2.0 เท่านั้น) ก็ใช้ปลั๊กอินที่เรียกว่า QChainage
andy

คำตอบ:


14

หมายเหตุ:QChainageขณะนี้มีปลั๊กอิน QGIS มันทำทั้งหมดนี้และอีกมากมาย รหัสด้านล่างล้าสมัยด้วย 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)

คัดลอกและวางโค้ดด้านบนลงในไฟล์ฉันเรียกว่า Loc loc ของฉันใน~./qgis/pythonไดเรกทอรี (เพราะอยู่ในเส้นทาง Python) และทำสิ่งนี้ในคอนโซล Python ภายใน QGIS

 import locate
 locate.pointsAlongLine(30)

ที่จะสร้างเลเยอร์จุดใหม่ที่มีคะแนนทุก ๆ 30 เมตรตามแนวที่เลือกดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

หมายเหตุ: รหัสค่อนข้างหยาบและอาจต้องทำความสะอาด

แก้ไข: QGIS dev build ล่าสุดสามารถทำสิ่งนี้ได้

เปลี่ยนวนลูปใน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

ขอบคุณ @ นาธาน ฉันไม่สามารถรับแพ็คเกจ Shapely สำหรับไพ ธ อนได้ ฉันติดตั้ง python 2.7 แล้ว แต่ตัวติดตั้ง Shapely บอกว่า python 2.7 ไม่ได้อยู่ในรีจิสตรีของฉัน มีอีกวิธีในการติดตั้ง Shapely
Stat-R

ฉันติดตามstackoverflow.com/questions/3652625/…และพิมพ์สองบรรทัดด้านบนเพื่อโทรออกlocateและใช้ แต่ก็ยังไม่ได้รับคะแนนเท่ากัน นอกจากนี้ฉันเป็น Neophyte ใน Python ดังนั้นฉันจึงไม่เข้าใจที่จะเรียกใช้โค้ด (1) python ในไดเรกทอรี qgis หรือ (2) ที่ C: \ Python27 \?
Stat-R

คุณใช้ระบบปฏิบัติการอะไร
Nathan W

Windows 7 Professional
Stat-R

สร้างไฟล์C:\Users\{you user name}\.qgis\pythonไพ ธ อนจากนั้นรีสตาร์ท QGIS ถ้าเปิดและไปที่ ' . Load a line layer, select a line a call ปลั๊กอินlocate.pointsAlongLine(30)
นาธาน 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
Stat-R

ตอนนี้ก็เป็นเช่นนี้: QGIS -> Sextante -> GRASS -> v.to.points
markusN

5

หากคุณต้องการพล็อตโซ่ในช่วงเวลาที่แน่นอนตามแนวถนนคุณสามารถใช้ปลั๊กอิน 'โปรไฟล์จากบรรทัด' เพื่อทำสิ่งนี้ คุณต้องมี DEM ใต้เลเยอร์บรรทัดถนน แต่ขั้นตอนนั้นรวดเร็วและง่ายมาก กรงขัง

ป้อนคำอธิบายรูปภาพที่นี่


นี่เป็นวิธีที่ดีและง่ายเช่นกันขอบคุณ!
Shepherdjo

2

ระวังว่าโมเดลข้อมูล Shapely (Python) / GEOS (C ++) ถูกกำหนดในระนาบ ดังนั้นถ้าคะแนนของคุณประกอบด้วยตำแหน่ง GPS (เส้นรุ้งเส้นแวง) โดยใช้วิธีการออกจะตำแหน่งจีพีเอสที่ระยะทางยุคลิดตามที่กำหนดshapely.geometry.LineString.interpolate(distance)LineString

หุ่นดีinterpolate()ขึ้นอยู่กับgeos::linearref::LengthIndexedLineระดับของ GEOS โดยใช้extractPointวิธีการ

สมมุติว่าการแก้ไขที่เว้นระยะเท่ากันในละติจูด - ลองจิจูด - ระนาบนั้นเพียงพอสำหรับการใช้งานโดยพิจารณาระยะทางที่ค่อนข้างเล็ก อย่างไรก็ตามโดยทั่วไปเราควรพิจารณาระยะทางบนทรงกลมสำหรับแอปพลิเคชัน GIS (ตามที่กำหนดไว้ในWGS84 )

ฉันสามารถคิดถึงวิธีแก้ปัญหาสองวิธีโดยใช้โมดูล Shapely:

  • LineStringคุณสมบัติคือจุดที่กำหนดทั้งหมดและเส้นโค้งที่สอดแทรกเชิงเส้นตรง บางทีคุณสามารถเขียนสมาชิกที่เข้าถึงส่วนโค้งที่สอดแทรกและนำอินทิกรัลบรรทัดต่อไปนี้มาแทนระยะทางแบบยุคลิด ฉันชอบวิธีนี้เพราะใช้เส้นโค้งต่อเนื่องที่ชาญฉลาดชิ้นส่วนจุดที่ต้องการสามารถทำได้โดยการคำนวณจุดตัดของวงกลมที่อยู่ติดกันตามแนวโค้งด้วยรัศมี r = radian_measure(arc_length) = arc_length / Rโดยที่ R เท่ากับรัศมีของโลกในตำแหน่งที่กำหนด
  • รหัสวิธีการแก้ไขของคุณเอง (โดยไม่ต้องสัมผัสรหัสหุ่นดี) โดยใช้ฟังก์ชั่นระยะทางที่เหมาะสม (เช่นสูตร haversine)

เพื่อให้บรรลุนี้ฉันต้องการอ้างถึงคำถาม StackOverflowต่อไปนี้และคำตอบนี้โดยเฉพาะ:

มันเป็นไปได้ที่จะสร้างจุดที่เท่ากันตามแนวโค้ง แต่จะต้องมีคำจำกัดความเพิ่มเติมของสิ่งที่คุณต้องการสำหรับคำตอบที่แท้จริง ขออภัยรหัสที่ฉันเขียนสำหรับงานนี้อยู่ใน MATLAB แต่ฉันสามารถอธิบายแนวคิดทั่วไปได้ มีสามความเป็นไปได้

อย่างแรกคือประเด็นที่ต้องมีระยะทางเท่ากันอย่างแท้จริงจากเพื่อนบ้านในแง่ของระยะทางแบบยุคลิดแบบง่ายหรือไม่? ในการทำเช่นนั้นจะเกี่ยวข้องกับการหาจุดตัด ณ จุดใดก็ได้บนโค้งด้วยวงกลมที่มีรัศมีคงที่ จากนั้นเพียงแค่ก้าวไปตามโค้ง

ถัดไปหากคุณต้องการให้ระยะทางเฉลี่ยเท่ากับระยะทางตามเส้นโค้งถ้าเส้นโค้งเป็นเส้นตรงแบบชิ้นเดียวปัญหาจะง่ายขึ้นอีกครั้ง เพียงแค่ก้าวไปตามโค้งเนื่องจากระยะทางในส่วนของเส้นตรงนั้นสามารถวัดได้ง่าย

สุดท้ายถ้าคุณตั้งใจให้เส้นโค้งเป็นลูกบาศก์อิสระอีกครั้งนี่ไม่ใช่เรื่องยากอย่างเหลือเชื่อ แต่เป็นการทำงานอีกเล็กน้อย นี่คือเคล็ดลับคือ:

  • คำนวณค่าความยาวเชิงเส้นแบบอาร์ทซิกซ์จากจุดหนึ่งไปยังอีกจุดหนึ่งตามแนวโค้ง เรียกมันว่า สร้างคู่ของลูกบาศก์ Splines, x (t), y (t)

  • แยก x และ y เป็นฟังก์ชันของ t เนื่องจากสิ่งเหล่านี้เป็นลูกบาศก์เซ็กเมนต์นี่จึงเป็นเรื่องง่าย ฟังก์ชันอนุพันธ์จะเป็น
    กำลังสอง

  • ใช้ตัวแก้ ode เพื่อเลื่อนไปตามเส้นโค้งโดยรวมฟังก์ชัน arclength ที่แตกต่างกัน ใน MATLAB ODE45 ทำงานได้ดี

ดังนั้นหนึ่งรวม

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

อีกครั้งใน MATLAB สามารถตั้งค่า ODE45 เพื่อระบุตำแหน่งที่ฟังก์ชันข้ามจุดที่ระบุ

หากทักษะ MATLAB ของคุณเป็นไปตามภารกิจคุณสามารถดูรหัสใน interparcเพื่อดูคำอธิบายเพิ่มเติม มันเป็นรหัสความเห็นดีพอสมควร

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


1

Sextante มีเครื่องมือที่อาจใช้ได้ผลกับคุณ Sextante สามารถดาวน์โหลดได้จากที่เก็บปลั๊กอิน Qgis

ค้นหา:
"เครื่องมือสำหรับเลเยอร์บรรทัด"
"เส้นไปยังจุดที่อยู่ติดกัน"


ปลั๊กอินนี้ดูเหมือนจะไม่พร้อมใช้งานสำหรับ QGIS 2 หรือ 3
Martin Burch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.