ラインフィーチャの接続と最長ラインの長さの決定


12

Stream_to_Featureツールを使用して作成した川を表すラインフィーチャ(画像を参照)があります。属性テーブルには、さまざまな行を表す複数のレコードが含まれます。問題は、最長行(視覚的に簡単に区別可能)がテーブル内の単一行として表されず、実際には多くの小さい行で構成されることです。線は互いに交差していないが、触れているように見える。

これらの行をマージし、ArcObjectsまたはArcObjectsに変換できる手動の方法を使用して最長の行の長さを決定するにはどうすればよいですか?さらに良い解決策は、すべての支流を取り除き、川の道だけを一本にしておくことです。

ラインフィーチャ-川


1
彼らはまったく接続していますか?あなたは彼らが交差しないと言ったが、それは彼らが頂点を共有しないことを意味するのか?
ナタヌス

1
申し訳ありませんが、もっと明確にすべきでした。それらは頂点を共有しますが、互いに完全に交差するわけではありません。
レーダー

川の河口がどこにあるか知っていますか?川は常に木(各源流ポイントから口までのユニークなパス)ですか?
カーククイケンドール

3
実際、「最長の線」の長さは必要ありません。これは、あるアップストリームリーチから別のリモートアップストリームリーチへのルートです。これは、ストリームの2つの主要な分岐がその口の近くで結合するときに発生します。代わりに、口とストリーム上の他のエンドポイント間最長ルートが必要です (この特性評価では、ストリームをツリーとして表す必要さえありません。編組して島を作ることができます。)
whuber

@whuber-あなたの評価は正しいです-ルートを使用してこれを達成する方法はありますか?
レーダー

回答:


18

まず、これが難しい問題ではない理由を示すための小さな背景。川の流れにより、そのセグメントが正しくデジタル化されていれば、常に有向非循環グラフ(DAG)を形成できるようになります。次に、トポロジーソートとして知られる手法を使用して、DAGである場合にのみ、グラフを線形に順序付けることができます。トポロジカルソートは高速です。時間とスペースの要件は両方ともO(| E | + | V |)(E =エッジの数、V =頂点の数)で、これは得られるものと同じです。このような線形の順序を作成すると、主要な河川床を簡単に見つけることができます。

ここに、アルゴリズムのスケッチがあります。小川の口はその大きなベッドに沿っています。口に取り付けられた各枝に沿って上流に移動し(口が合流点である場合は複数ある場合があります)、その枝につながる主要なベッドを再帰的に見つけます。合計の長さが最も長いブランチを選択します。これは、主要なベッドに沿った「バックリンク」です。

これを明確にするために、いくつかの(テストされていない)擬似コードを提供します。入力は一連のラインセグメント(またはアーク)S(デジタル化されたストリームを含む)であり、それぞれ2つの異なるエンドポイントstart(S)およびend(S)と正の長さlength(S)を持ちます。そして、河口pがポイントです。出力は、口を最も遠い上流ポイントと結合する一連のセグメントです。

「マークされたセグメント」(S、p)で作業する必要があります。これらは、セグメントSの 1つと、その2つのエンドポイントpの1つで構成されます。プローブポイントqとエンドポイントを共有するすべてのセグメントSを見つけ、それらのセグメントを他のエンドポイントとマークし、セットを返す必要があります。

Procedure Extract(q: point, A: set of segments): Set of marked segments.

そのようなセグメントが見つからない場合、Extractは空のセットを返す必要があります。 副作用として、 ExtractはセットAから返されるすべてのセグメントを削除する必要がありそれによりA自体が変更されます。

Extractの実装は提供していません:GISは、エンドポイントをqと共有するセグメントSを選択する機能を提供します。それらをマークするのは、単にstart(S)とend(S)の両方をqと比較し、2つのエンドポイントのどちらかが一致しないものを返すだけです。

これで問題を解決する準備ができました。

Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
    A0 = A                        // Optional: preserves A
    C = Extract(p, A0)            // Removes found segments from the set A0!
    L = 0; B = empty array
    For each (S,q) in C:          // Loop over the segments meeting point p
        (B0, M) = LongestUpstreamReach(q, A0)
        If (length(S) + M > L) then
            B = append(S, B0)
            L = length(S) + M
        End if
    End for
    Return (B, L)
End LongestUpstreamReach

手順「を追加(S、B0)」棒セグメントSアレイの端部でB0と新しい配列を返します。

(ストリームが本当にツリーである場合:島、湖、三つ編みなどはありません。AA0にコピーするステップを省くことができます。)

元の質問は、LongestUpstreamReachによって返されるセグメントの結合を形成することによって回答されます。

を説明するために、元のマップのストリームを考えてみましょう。7つのアークのコレクションとしてデジタル化されているとします。アークaは、ポイント0(マップの上部、下の図の右側、回転)の口からポイント1の最初の合流点の上流に移動します。これは、8単位の長いアークです。アークbは左(マップ内)に分岐し、短く、約2単位の長さです。弧cは右に分岐し、長さは約4単位などです。マップ上で上から下に向かって「b」、「d」、「f」が左側の分岐を示し、「a」、 「c」、「e」、および「g」の他のブランチ、および頂点0〜7に番号を付けると、グラフをアークのコレクションとして抽象的に表すことができます。

A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}

aからgまでの長さがそれぞれ8、2、4、1、2、2、2であると仮定します。口は頂点0です。

図

最初の例は、Extract(5、{f、g})の呼び出しです。マークされたセグメントのセット{(f、6)、(g、7)}を返します。頂点5はアークfg(マップの下部にある2つのアーク)の合流点にあり、(f、6)と(g、7)はこれらの各アークを上流の端点でマークしていることに注意してください。

次の例は、LongestUpstreamReach(0、A)の呼び出しです。最初に実行するアクションは、Extract(0、A)の呼び出しです。この戻り顕著セグメント(1)を含むセット、それは、セグメント削除A組からA0今{B、C、D、E、F、G}と等しいです。ループの反復が1つあり、(S、q)=(a、1)です。この反復中に、LongestUpstreamReach(1、A0)が呼び出されます。再帰的に、シーケンス(g、e、c)または(f、e、c)のいずれかを返さなければなりません:両方とも有効です。返される長さ(M)は4 + 2 + 2 = 8です(LongestUpstreamReachはA0を変更しないことに注意してください)。ループの最後で、セグメントaストリームベッドに追加され、長さが8 + 8 = 16に増加されました。したがって、最初の戻り値は、シーケンス(g、e、c、a)または(f、e、c、a)のいずれかで構成されます。どちらの場合も、2番目の戻り値の長さは16です。これは、LongestUpstreamReachがどのように口から上流に移動するかを示し、各合流点でこれまでに最も長い距離のブランチを選択し、そのルートに沿って移動したセグメントを追跡します。

多くのブレードとアイランドがある場合、より効率的な実装が可能ですが、ほとんどの目的で、LongestUpstreamReachが示されているとおりに実装されている場合、各合流点でさまざまなブランチの検索にオーバーラップがないため、無駄な労力はほとんどありません:コンピューティング時間(およびスタックの深さ)は、セグメントの総数に直接比例します。


+1今、ミズーリ川に名前を付ける前にこれを知っていた場合のみ。
カーククイケンドール

1
@Kirk 1800年代初期のアメリカ西部の再帰探査は容易ではありませんでした:-)。
whuber

これは驚くほど役に立ちます!GIS内でこのセットアップを取得し、機能するようになったら便利なコードを共有できるかどうかを確認します。乾杯!
レーダー

いい答えwhuber
ラギヤセルバーフム

2

分割されていないラインツールを使用すると、(ディゾルブフィールド用)から別の1本のストリーム枝を区別するためにいくつかの方法を占うする必要がありますが、あなたが、やろうとしているもののために役立つことができます。ただし、これは、ArcInfoライセンスを持っていることを前提としています。

あなたは、このようなライセンスを持っていない場合は、ArcObjectsのは、各頂点のXYを取っ充填近づい検討するかもしれないIPointCollection彼らと、次に作成IGeometryなどPolyLineClass


1

9.1 ArcGISツールであるRivEXを使用できます(9.3および10で動作します)。河川ネットワークと多くの処理ツールでトポロジの問題を識別するためのツールがあります。そのようなツールの1つがメインステムを見つけます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.