Creare linee da coordinate di coppia di punti con ArcPy?


11

Ho alcune coordinate di coppia di punti (punti iniziale e finale) che devo trasformare in linee. Fino ad ora, ho usato un'appendice di entrambe le coordinate in a pippo.Point(), a pippo.CalculateGeometry()per definire la geometria di ciascun piont e pippo.append(defined geometry)per identificare la coppia di punti, quindi PointsToLine per ottenere la mia linea. Questo è abbastanza costoso da fare per centinaia di linee.

C'è un modo più breve per farlo?

Ad esempio, posizionare il punto iniziale e finale di ciascuna linea in diversi campi di una singola tabella e importare le linee direttamente senza passare per la geometria dei punti.

Risposte:


8

Questo legge una tabella (foglio Excel in questo caso, ma potrebbe essere qualsiasi tipo di tabella) che assomiglia a questo:

inserisci qui la descrizione dell'immagine

S_X è punto X iniziale, E_X punto X finale, lo stesso per Y. Esaminiamo la tabella di input, quindi per ogni riga, impostiamo l'inizio / fine X / Y in un punto, aggiungiamo quel punto a un array, quindi creiamo una polilinea dall'array di due punti. Quindi inserire nella featureclass. Risciacqua e ripeti.

import arcpy

in_rows = arcpy.SearchCursor(r"D:\Temp\Lines.xls\Sheet1$")

point = arcpy.Point()
array = arcpy.Array()

featureList = []
cursor = arcpy.InsertCursor(r"D:\Temp\Lines.shp")
feat = cursor.newRow()

for in_row in in_rows:
    # Set X and Y for start and end points
    point.X = in_row.S_X
    point.Y = in_row.S_Y
    array.add(point)
    point.X = in_row.E_X
    point.Y = in_row.E_Y
    array.add(point)   
    # Create a Polyline object based on the array of points
    polyline = arcpy.Polyline(array)
    # Clear the array for future use
    array.removeAll()
    # Append to the list of Polyline objects
    featureList.append(polyline)
    # Insert the feature
    feat.shape = polyline
    cursor.insertRow(feat)
del feat
del cursor

E ottieni le tue linee:

inserisci qui la descrizione dell'immagine


Grazie, proverò a stimare la durata della mia analisi .. era esattamente quello che stavo cercando di fare :-)
Annalisa Minelli,

Per la riga point.X = in_row.S_X restituisce un errore che dice che il valore di input non è numerico. Ho provato a renderlo int o float o anche numerico ma non funziona perché il campo non è un numero è Non-tipo. Qualsiasi aiuto?
Federico Gómez,

5

La scorsa settimana ho creato uno script Python (non usando ArcPy), che prende punti che stanno creando la geometria delle linee del bus (un punto shp) secondo un campo numerico sequenziale ("SEQ"). Puoi facilmente modificarlo per prendere le coordinate da un campo della stessa funzione (usando il valore del campo invece della geometria).

# -*- coding: utf-8 -*-
###############################################################################
from sys import argv
import osgeo.ogr
import os, os.path
###############################################################################

script, srcSHP = argv

#-- Open source shapefile
shapefile = osgeo.ogr.Open(srcSHP)
layer = shapefile.GetLayer(0)
spatialRef = layer.GetSpatialRef()

#-- Output directory
outDir = os.path.dirname(srcSHP)
outDirName = os.path.basename(outDir)

driver = osgeo.ogr.GetDriverByName("ESRI Shapefile")
outFile = driver.CreateDataSource(os.path.join(outDir,outDirName + "_lines.shp"))
outLayer = outFile.CreateLayer("layer", spatialRef)

#-- Adding fields to the output shapefile
fieldDef = osgeo.ogr.FieldDefn("line_no", osgeo.ogr.OFTString)
fieldDef.SetWidth(12)
outLayer.CreateField(fieldDef)

fieldDef = osgeo.ogr.FieldDefn("From_SEQ", osgeo.ogr.OFTReal)
outLayer.CreateField(fieldDef)

fieldDef = osgeo.ogr.FieldDefn("To_SEQ", osgeo.ogr.OFTReal)
outLayer.CreateField(fieldDef)

#-- Going through each feature, one by one
#-- The last point is the end of the line so I don't want to iterate through that one
for i in range(layer.GetFeatureCount()-1):
    lString = osgeo.ogr.Geometry(osgeo.ogr.wkbLineString)  

    feature1 = layer.GetFeature(i)
    feature2 = layer.GetFeature(i+1)

    # When it's a new line, the sequential number restart to 1, so we don't want that line
    if feature1.GetField("SEQ") < feature2.GetField("SEQ"):
        geom1 = feature1.GetGeometryRef()
        geom2 = feature2.GetGeometryRef()

        geom1x = geom1.GetX()
        geom1y = geom1.GetY()
        geom2x = geom2.GetX()
        geom2y = geom2.GetY()

        lString.AddPoint(geom1x, geom1y)
        lString.AddPoint(geom2x, geom2y)     # Adding the destination point

        #-- Adding the information from the source file to the output
        feat = osgeo.ogr.Feature(outLayer.GetLayerDefn())
        feat.SetGeometry(lString)
        feat.SetField("line_no", feature1.GetField("line_no"))
        feat.SetField("From_SEQ", feature1.GetField("SEQ"))
        feat.SetField("To_SEQ", feature2.GetField("SEQ"))
        outLayer.CreateFeature(feat)

print "The End"

Ogni coppia di punti creerà una singola linea. Potrebbe esserci un modo più elegante per farlo, ma ha creato 3900 linee in circa 15 secondi, quindi funziona per me ...


Grazie, sembra esattamente un'enorme elaborazione .. questo dovrebbe essere davvero utile per me. Proverò e poi il feedback. grazie per ora.
Annalisa Minelli,


1

questo è solo un aggiornamento della risposta di @ ChadCooper, perché i cursori "da" ora stanno vantaggiosamente sostituendo i cursori precedenti:

with arcpy.da.SearchCursor(input_table,[orig_namefield,x1,y1,x2,y2] ) as in_rows:
    with arcpy.da.InsertCursor(output_lines,["SHAPE@",name_field]) as cursor:
        for row in in_rows:
            # build array for line segment
            array = arcpy.Array([arcpy.Point(row[1],row[2]),arcpy.Point(row[3],row[4])])
            # Create a Polyline object based on the array of points
            polyline = arcpy.Polyline(array)
            # Insert the feature
            cursor.insertRow([polyline,row[0]])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.