ArcPyを使用してポリラインのエンドポイントを編集しますか?


8

ArcGIS 10を使用して、Pythonでポリラインエンドポイントスナップツールを作成しようとしています。検索カーソルを使用して、値をラインオブジェクトの配列(ラインのフィーチャIDと2つの "EndPoint"オブジェクトを含む)に読み込みます。最後-それぞれのX座標とY座標を含みます)、次に、ポイントのデータ補間を処理して、すべてのポイントに正しい値を与えます。

これまでのところ、その部分は完全に機能します。ただし、シェープファイルに戻って編集しようとすると、変更中のデータは表示されますが、編集できないようです。

次に、フィールドを更新するためのコードを示します。

# --------------------------
#
# Update the file with the new EPs
#
# --------------------------

# Create update cursor
#
rows = arcpy.UpdateCursor(outputDirectory + "\\" + trails_fc + ".shp")

# Enter for loop for each feature/row
#
i = 0
for row in rows:
    # Create the geometry object
    #
    feat = row.getValue(shapefieldname)

    partnum = 0

    if feat.getPart(partnum)[0].X != allLines[i].startEP.x:
        arcpy.AddMessage("Change: " + str(feat.getPart(partnum)[0].X) + " to " + str(allLines[i].startEP.x) )
        feat.getPart(partnum)[0].X = allLines[i].startEP.x

    rows.updateRow(row)

    arcpy.AddMessage("Now is: " + str(feat.getPart(partnum)[0].X))

    i+=1

私の読みはこのようなステートメントで構成されています:

変更:-105.512166832を-105.699533165に変更:-105.512166832

何らかの理由で、行が更新されていません。そして、私にとって、ポリラインの特定のポイントを編集する方法についてのチュートリアルや説明はありません。ポイントシェープファイルのフィールドとしてポイントを編集する方法のみを見つけることができます。

誰かアイデアはありますか?


1
ArcViewライセンスしか持っていませんか?ArcEditor / ArcInfoがある場合、Arc10のSNAPジオプロセシングツールでは実行できない独自のスナップツールを構築して何を達成しようとしているのですか(ArcToolbox> Editing Tools)?(help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//...
RyanKDalton

別の方法もあるかもしれませんが、ツールが完全にオリジナルかどうか、座標の操作方法を理解しようとしています。機能性と同じくらい多くの経験があります。
キバクウルフ

回答:


6

残念ながら、フィーチャの既存のジオメトリに新しい値を直接割り当てることはできません。新しいジオメトリオブジェクトを作成し、その新しいオブジェクトでフィーチャのシェイプフィールドを更新する必要があります。幸い、配列オブジェクトにはreplaceメソッドがあります。したがって、配列内のポイントのX座標を直接変更するのではなく、次のことを行う必要があります。

  • arcpy.Point正しい座標で新しいオブジェクトを作成します(すでにこれを行っているようです)
  • 行のShapeフィールドに格納されている配列オブジェクトのコピーを取得します
  • replaceメソッドを使用して、変更した点で配列内の目的の点を設定します
  • その配列で新しいポリラインオブジェクトを作成する
  • 行オブジェクトのsetValueメソッドを使用して、Shapeフィールドを新しい正しいポリラインで更新します。
  • カーソルオブジェクトのupdateRowメソッドを使用して、変更された行をデータセットに挿入します。

具体的には:

for r in cur:
    ary = r.getValue("SHAPE").getPart(0)
    ary.replace(0,correct_point_object) # first arg 0 replaces the first point in the line
    newLine = arcpy.Polyline(ary)
    r.setValue("SHAPE",newLine)
    cur.updateRow(r)

このreplaceメソッドはインデックスと値を取ることに注意してください。残念ながら、それは配列の最後のポイントへのインデックスとして例えば-1を受け入れません。しかし、あなたは言うことができますmy_array[my_array.count]

X座標を別の場所で事前計算し、後で取得しているようです。これが事実である場合、私はおそらくあなたが全体を行き、正しい座標を計算している間に、各ラインの正しいポイントで新しいポリラインオブジェクトを作成するでしょう。これはおそらくより簡単でクリーンになります。そうすれば、コードはより

row_num = 0
    for r in cur:
        r.setValue(shapeField,correct_geometry_list[row_num])
        cur.updateRow(r)
        row_num += 1

少なくとも私にとっては、これはもう少し明確です...しかしそれは文体です!

追加して編集:

コメントにこれを収めることができませんでした。あなたのコードを見なければ、それがどこに転倒しているのかを知るのは難しい。これは私のために動作する完全にテストされたスクリプトです。参考にしてください。ここでは、2つのパスを実行するのではなく、古いジオメトリから直接新しいジオメトリを計算していることに注意してください。スナップ位置の計算方法によっては、これが可能である場合とできない場合があります。また、今回はreplace、必要に応じて、メソッドを使用するのではなく、古い配列に基づいて新しい配列を構築しています。

import arcpy

def offsetPoint(old_point,X_distance,Y_distance):
    """Trivial function to offset a point - replace with what you're
actually doing."""
    new_point = arcpy.Point(old_point.X+X_distance,
                            old_point.Y+Y_distance)
    return new_point

def offsetFirstPointInLine(line_geom,X_distance,Y_distance):
    """Takes a Polyline geometry object and returns a new Polyline with
the first point of the first part offset by the distance given."""
    array = line_geom.getPart(0)
    first_point = array[0]
    new_point = offsetPoint(first_point,X_distance,Y_distance)

    # Build a new array with your new point in the 0th position, and
    # the rest of the points from the old array.
    new_array = arcpy.Array([new_point]+
                            [array.getObject(x) for x in range(1,array.count)])

    # Then make a new Polyline object with that array.
    new_line = arcpy.Polyline(new_array)
    return new_line

fc = r"C:\Users\student\Documents\ArcGIS\Default.gdb\SomeStorms"

cur = arcpy.UpdateCursor(fc)

for r in cur:
    geom = r.getValue("SHAPE")
    r.setValue("SHAPE",offsetFirstPointInLine(geom,-45000,-5000))
    cur.updateRow(r)

del r,cur

うまくいけば、それはそれをクリアするのに役立ちます。


私はそうかもしれないこの沈没感を持っていました。やり方を説明してくれてありがとう!私はあなたが言ったようにポリライン全体を作成するだけだと思います。そうすれば、前に戻って他の何かを調整したい場合に、より細かく制御できます。
Kivak Wolf

残念ながら、私はそれを機能させることができませんでした。非常に奇妙なことが起こっています。"ary = r.getValue(" SHAPE ")。getPart(0)"を使用し、次にaryからポリラインを作成して値を設定すると、シェープファイルは完全に異なって見えます。これは起こらないはずですよね?
Kivak Wolf

何が悪いのか正確に言うのは難しい。それが役立つ場合に備えて、より完全なソリューションで回答を更新しました。実際には、配列を作成してポイントを変更しているようです。むしろ、新しいポイントを作成し、そのポイントを含むように配列を変更する(または上記のようにそのポイントで新しい配列を作成する)必要があります。
ThomM、2011

ThomM:詳しい説明ありがとうございます!ほんとうにありがとう!昨日見つけたように、私はarcpy.Array()、arcpy.Point()sを作成し、arcpy.Ployline()クラスを正しく使用しています。しかし、arcpy.Ployline()クラスコンストラクターの実際のプログラミングにはバグがある可能性があります。バグレポートを提出しましたが、arcpy.Polyline()のコンストラクターが「破棄」されているか、類似したまだ一意の値を持つarcpy.Point()を無視しているようです。ですから、私の問題はそれがどのように機能するのかを理解していないことだと思っていましたが、それはバグのようです。
Kivak Wolf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.