เชื่อมต่อคุณสมบัติของสายและกำหนดความยาวของสายที่ยาวที่สุด


12

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

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

คุณสมบัติเส้น - แม่น้ำ


1
พวกเขาเชื่อมต่อเลยหรือไม่? คุณบอกว่าพวกเขาไม่ข้าม แต่นั่นหมายความว่าพวกเขาไม่แบ่งปันจุดสุดยอดหรือไม่?
Nathanus

1
ขออภัย - ฉันควรจะชัดเจนมากขึ้น พวกเขาแบ่งปันจุดยอด แต่ไม่ข้ามผ่านกันอย่างสมบูรณ์
Radar

คุณรู้หรือไม่ว่าปากแม่น้ำอยู่ที่ไหน แม่น้ำตั้งอยู่บนต้นไม้หรือไม่ (เส้นทางที่ไม่เหมือนกันจากจุดต้นน้ำไปยังปากแม่น้ำ)?
Kirk Kuykendall

3
ที่จริงแล้วคุณไม่ต้องการความยาวของ "เส้นที่ยาวที่สุด" นั่นอาจเป็นเส้นทางจากการเข้าถึงต้นน้ำหนึ่งจนถึงการเข้าถึงต้นน้ำระยะไกลอื่น สิ่งนี้จะเกิดขึ้นเมื่อกระแสหลักสองกิ่งเข้าใกล้ปาก คุณต้องการเส้นทางที่ยาวที่สุดระหว่างปากและปลายทางอื่น ๆ ในสตรีมแทน (ลักษณะนี้ไม่จำเป็นต้องมีการแสดงกระแสเป็นต้นไม้: มันสามารถถักเปียและมีเกาะ)
whuber

@whuber - การประเมินของคุณถูกต้อง - มีความคิดใดที่ฉันจะทำได้โดยใช้เส้นทาง
Radar

คำตอบ:


18

ครั้งแรกพื้นหลังเล็กน้อยเพื่อระบุว่าทำไมจึงไม่ใช่ปัญหายาก การไหลผ่านแม่น้ำรับรองว่าส่วนของมันหากถูกต้องดิจิทัลสามารถมุ่งเน้นในการสร้างกราฟ acyclic (DAG) ในทางกลับกันกราฟสามารถสั่งซื้อได้เป็นเส้นตรงและถ้าหากมันเป็น DAG โดยใช้เทคนิคที่เรียกว่าการจัดเรียงทอพอโลยี การจัดเรียงโทโพโลยีนั้นรวดเร็ว: ความต้องการด้านเวลาและพื้นที่ของมันคือทั้ง O (| E | + | V |) (E = จำนวนขอบ, V = จำนวนจุดยอด) ซึ่งดีเท่าที่จะได้รับ การสร้างการเรียงลำดับแบบเชิงเส้นจะช่วยให้ค้นหาเตียงหลักได้ง่าย

ที่นี่จึงเป็นร่างของอัลกอริทึม ปากลำธารนอนอยู่บนเตียงหลัก ย้ายอัปสตรีมไปตามแต่ละสาขาที่ติดกับปาก (อาจมีมากกว่าหนึ่งหากปากเป็นจุดบรรจบกัน) และพบเตียงใหญ่ซ้ำ ๆ ที่ทอดลงไปสู่กิ่งนั้น เลือกสาขาที่มีความยาวรวมมากที่สุดนั่นคือ "ลิงก์ย้อนกลับ" ของคุณตามเตียงหลัก

จะทำให้เรื่องนี้ชัดเจนฉันมีบางส่วน (ทดสอบ) pseudocode อินพุตเป็นชุดของส่วนของเส้น (หรือส่วนโค้ง) S (ประกอบด้วยสตรีมแบบดิจิทัล) แต่ละอันมีจุดเริ่มต้นที่แตกต่างกันสองจุด (S) และจุดสิ้นสุด (S) และความยาวบวกความยาว (S); และปากแม่น้ำพีซึ่งเป็นจุดที่ เอาท์พุทเป็นลำดับของส่วนรวมกันปากที่มีจุดต้นน้ำที่ห่างไกลที่สุด

เราจะต้องทำงานกับ "กลุ่มที่ทำเครื่องหมายไว้" (S, p) เหล่านี้ประกอบด้วยหนึ่งในกลุ่มSพร้อมกับหนึ่งในสองปลายทางของมัน, p . เราจะต้องค้นหาเซกเมนต์ทั้งหมดSที่ใช้จุดปลายร่วมกับโพรบจุดqทำเครื่องหมายเซกเมนต์เหล่านั้นด้วยจุดสิ้นสุดอื่น ๆและส่งคืนชุด:

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

เมื่อไม่พบเซ็กเมนต์ดังกล่าว Extract จะต้องส่งคืนชุดว่าง เป็นผลข้างเคียง,สารสกัดจากต้องเอาทุกกลุ่มก็จะกลับมาจากชุดA,จึงปรับเปลี่ยนตัวเอง

ฉันไม่ให้การดำเนินการของสารสกัดจาก: GIS ของคุณจะให้ความสามารถในการเลือกกลุ่มSร่วมกันปลายทางกับคิว การทำเครื่องหมายพวกเขาเป็นเพียงเรื่องของการเปรียบเทียบทั้งจุดเริ่มต้น (S) และจุดสิ้นสุด (S) กับqและกลับจุดใดจุดหนึ่งในสองจุดไม่ตรงกัน

ตอนนี้เราพร้อมที่จะแก้ปัญหาแล้ว

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และส่งกลับอาร์เรย์ใหม่

(หากกระแสเป็นต้นไม้จริงๆ: ไม่มีเกาะ, ทะเลสาบ, braids ฯลฯ - จากนั้นคุณสามารถแจกจ่ายด้วยขั้นตอนการคัดลอกAไปที่A0 )

คำถามเดิมตอบโดยการรวมกันของเซกเมนต์ที่ส่งคืนโดย LongestUpstreamReach

เพื่อแสดงภาพลองพิจารณาสตรีมในแผนที่ดั้งเดิม สมมติว่ามันเป็นดิจิทัลเป็นชุดของเจ็ดส่วนโค้ง Arc ไปจากปากที่จุด 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)}

ฉันจะสมมติว่าพวกเขามีความยาว 8, 2, 4, 1, 2, 2, 2 สำหรับaถึงgตามลำดับ จุดยอดปาก 0

รูป

ตัวอย่างแรกคือการเรียกไปยัง Extract (5, {f, g}) มันจะส่งคืนชุดของส่วนที่ทำเครื่องหมายไว้ {(f, 6), (g, 7)} โปรดทราบว่าจุดสุดยอด 5 อยู่ที่จุดบรรจบของส่วนโค้งfและg (ส่วนโค้งทั้งสองที่ด้านล่างของแผนที่) และ (f, 6) และ (g, 7) ทำเครื่องหมายส่วนโค้งเหล่านี้แต่ละจุดด้วยจุดปลายน้ำ

ตัวอย่างถัดไปคือการเรียกใช้ LongestUpstreamReach (0, A) การดำเนินการแรกที่ใช้คือการเรียกไปยัง Extract (0, A) ส่งคืนชุดที่มีเซ็กเมนต์ที่ทำเครื่องหมาย (a, 1) และลบเซ็กเมนต์aออกจากชุดA0ซึ่งตอนนี้เท่ากับ {b, c, d, e, f, g} มีการวนซ้ำหนึ่งรอบโดยที่ (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), ด้วยความยาว 16 ในทั้งสองกรณีสำหรับค่าส่งคืนที่สอง สิ่งนี้แสดงให้เห็นว่า LongestUpstreamReach เพิ่งเคลื่อนทวนกระแสน้ำออกมาจากปากเลือกที่มาบรรจบกันในแต่ละสาขาด้วยระยะทางที่ไกลที่สุดและไปตามเส้นทางของมัน

การใช้งานที่มีประสิทธิภาพมากขึ้นเป็นไปได้เมื่อมี braids และเกาะจำนวนมาก แต่สำหรับจุดประสงค์ส่วนใหญ่จะมีความพยายามเล็กน้อยหาก LongestUpstreamReach ดำเนินการตรงตามที่แสดงเพราะในการบรรจบกันไม่มีการซ้อนทับกันระหว่างการค้นหาในสาขาต่างๆ: การคำนวณ เวลา (และความลึกของสแต็ค) จะเป็นสัดส่วนโดยตรงกับจำนวนรวมของกลุ่ม


+1 ตอนนี้ถ้ามีเพียงพวกเขารู้เรื่องนี้ก่อนตั้งชื่อแม่น้ำมิสซูรี่
Kirk Kuykendall

1
@ Kirk การสำรวจแบบเรียกซ้ำของ American West ในช่วงต้นปี 1800 ไม่ใช่เรื่องง่าย :-)
whuber

สิ่งนี้มีประโยชน์อย่างน่าอัศจรรย์! ฉันจะดูว่าฉันจะได้รับการตั้งค่านี้ภายใน GIS ของฉันและแบ่งปันรหัสที่มีประโยชน์เมื่อฉันใช้งานได้ไหม ไชโย!
Radar

Nice answer whuber
Ragi Yaser Burhum

2

Unsplit สายเครื่องมือจะมีประโยชน์สำหรับสิ่งที่คุณกำลังพยายามที่จะทำถึงแม้ว่าคุณจะต้องทำนายวิธีการบางอย่างเพื่อแยกความแตกต่างสาขาสตรีมจากอีกหนึ่ง (สำหรับเขตละลาย) สิ่งนี้ถือว่าคุณมีใบอนุญาต ArcInfo

หากคุณไม่ได้มีใบอนุญาตดังกล่าวคุณอาจพิจารณา ArcObjects วิธีการ XY ของแต่ละจุดสุดยอด, กรอกIPointCollectionกับพวกเขาแล้วสร้างเป็นIGeometryPolyLineClass


1

คุณสามารถใช้RivEXมันเป็นเครื่องมือ 9.1 ArcGIS (ที่จะทำงานใน 9.3 และ 10) มันมีเครื่องมือสำหรับการระบุปัญหาทอพอโลยีกับเครือข่ายแม่น้ำและเครื่องมือการประมวลผลมากมาย หนึ่งเครื่องมือดังกล่าวพบว่าลำต้นหลัก

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