อัลกอริทึมเพื่อค้นหาจุดที่ทำให้เกิดการผันสำหรับโพลีไลน์


22

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

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


ข้อมูลแหล่งที่มาเป็นรูปหลายเหลี่ยมที่ทำจากส่วนของเส้นและคุณต้องการที่จะแสดงให้เห็นด้วยเส้นโค้งหรือว่ามันมีส่วนโค้ง?
U2ros

ปัจจุบันมันทำจากส่วนของเส้น
Devdatta Tengshe

1
ภาพประกอบในคำถามนี้ดูน่าทึ่งอย่างหนึ่งที่ตีพิมพ์esri.com/news/arcuser/0110/turning.html
whuber

@whuber: การสังเกตที่ชาญฉลาดมาก นั่นคือแหล่งข้อมูลที่ฉันใช้ในการสร้างภาพ
Devdatta Tengshe

คำตอบ:


15

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

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

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

นี่คือRโค้ดที่ใช้งานได้เพื่อแสดงแนวคิดเหล่านี้ เริ่มต้นด้วยสตริงบรรทัดที่แสดงเป็นลำดับของพิกัด:

xy <- matrix(c(5,20, 3,18, 2,19, 1.5,16, 5.5,9, 4.5,8, 3.5,12, 2.5,11, 3.5,3, 
               2,3, 2,6, 0,6, 2.5,-4, 4,-5, 6.5,-2, 7.5,-2.5, 7.7,-3.5, 6.5,-8), ncol=2, byrow=TRUE)

Spline พิกัดxและyแยกจากกันเพื่อให้ได้เส้นโค้งที่กำหนด (พารามิเตอร์จะถูกเรียกtime)

n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")

สอดแทรกเส้นโค้งสำหรับการพล็อตและการคำนวณ:

time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))

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

curvature <- function(t, fx, fy) {
  # t is an argument to spline functions fx and fy.
  xp <- fx(t,1); yp <- fy(t,1)            # First derivatives
  xpp <- fx(t,2); ypp <- fy(t,2)          # Second derivatives
  v <- sqrt(xp^2 + yp^2)                  # Speed
  (xp*ypp - yp*xpp) / v^3                 # (Signed) curvature
  # (Left turns have positive curvature; right turns, negative.)
}

kappa <- abs(curvature(time, fx, fy))     # Absolute curvature of the data

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

curvature.zero <- 2*pi / max(range(xy[,1]), range(xy[,2])) # A small threshold
i.col <- 1 + floor(127 * curvature.zero/(curvature.zero + kappa)) 
palette(terrain.colors(max(i.col)))                        # Colors

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

plot(xy, asp=1, xlab="x",ylab="y", type="n")
tmp <- sapply(2:length(kappa), function(i) lines(rbind(uv[,i-1],uv[,i]), lwd=2, col=i.col[i]))
points(t(sapply(time[diff(kappa < curvature.zero/2) != 0], 
       function(t) c(fx(t), fy(t)))), pch=19, col="Black")
points(xy)

พล็อต

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


บางทีคำศัพท์ที่ฉันใช้ผิด สิ่งที่คุณคิดว่าเป็นสิ่งที่ฉันต้องการ คำตอบของคุณดูมีแนวโน้มและฉันจะต้องทำงานกับ R เพื่อประมวลผล Shapefile ของฉัน
Devdatta Tengshe

3

คุณสามารถใช้เครื่องมือบดอัด สำหรับกรณีนี้คุณเลือกที่จะหนาแน่นตามมุมถัดไปเลือกมุมสูงสุดที่ยอมรับในแนวเส้นตรง จากนั้นให้ใช้จะส่งผลให้กองหลังไปยังเครื่องมือSplit เส้นที่จุด สุดท้ายลบเส้นที่มี shape_length น้อยกว่าความยาวถนนขั้นต่ำ

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

ในภาพนี้เราเห็นสามขั้นตอน:

1- ทำให้เส้นโดยใช้มุมแคบลง ฉันใช้พารามิเตอร์ 10 องศาและเราใช้ splitline ในภาพเส้นโค้งอยู่ในระยะเริ่มต้น

arcpy.Densify_edit("line" , "ANGLE" , "","",10)
arcpy.SplitLine_management("line" , "line_split")

2- เลือกส่วนที่มี shape_length ไม่ซ้ำซ้อน อย่างที่เราเห็นในตารางฉันไม่ได้เลือกความยาวซ้ำซ้อนเหล่านั้น จากนั้นฉันเลือกพวกเขาเป็นคลาสคุณลักษณะใหม่

arcpy.Select_analysis("line_split" , "line_split_selected")

3- เราได้ทำการสกัดจุดยอดที่อยู่ตรงขอบของเส้นตรงซึ่งเป็นจุดเปลี่ยน

arcpy.FeatureVerticesToPoints_management("line_split_selected" , "line_split_pnt" , "DANGLE")

ฉันมีความคิดเห็นและคำถามเดียวกันเกี่ยวกับคำตอบอื่น ๆ ของคุณ: มันเป็นความคิดที่ดี แต่ในขณะเดียวกันก็ไม่ชัดเจนว่ามันจะให้ผลลัพธ์ที่ต้องการหรือไม่ว่าใครควรเลือกมุมเกณฑ์ คุณสามารถแสดงภาพประกอบของผลลัพธ์เพื่อให้ผู้อ่านสามารถประเมินว่าข้อเสนอนี้ทำอะไรได้บ้าง? การให้ตัวอย่างที่ใช้งานได้มีความสำคัญอย่างยิ่งเมื่อแนะนำซอฟต์แวร์ ESRI ซึ่งเป็นส่วนหนึ่งของโซลูชันเนื่องจากอัลกอริทึมของพวกเขามักไม่ได้จัดทำเป็นเอกสารทำให้ไม่สามารถรู้ได้อย่างชัดเจนว่าพวกเขากำลังทำอะไร
whuber

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

เราสามารถตั้งชื่อความคิดและไม่ใช่คำตอบได้
geogeek

1
คุณต้องการให้ฉันย้ายความคิดเห็นเหล่านั้นออกไปไหม? BTW ถ้าคุณต้องการให้ข้อมูลทดสอบคุณสามารถใช้พิกัดที่ฉันโพสต์ไว้ในคำตอบของฉันได้เพราะเป็นข้อมูลที่ใกล้เคียงกับภาพประกอบในคำถาม แต่ทำไมไม่ใช้ข้อมูลทางภูมิศาสตร์ที่คุณมีประโยชน์
whuber

2
ใช่แล้วโซลูชันนี้ทำงานได้ดีกว่าในการแยกข้อมูลแบบเส้นตรง
geogeek

1

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

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

หากเราตั้งชื่อบรรทัดเดิมว่า "line_cur" และอีกบรรทัดหนึ่งคือ "line_gen" เราก็สามารถตัด "line_cur" โดย "line_gen" ผลลัพธ์จะเป็นส่วนตรงของ "line_cur" จากนั้นเราสามารถล้างเซ็กเมนต์ที่สั้นมาก ๆ ได้โดยการลบคิวรี่ sql ซึ่งเลือก Shape_length ที่ยาวกว่าถนนขั้นต่ำสุด


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

ฉันได้ทำการแก้ไขเพื่อรวมรูปภาพรูปภาพอธิบายวิธีที่เครื่องมือนี้สามารถสร้างเส้นตรงที่มีส่วนต่าง ๆ เป็นเส้นตรงดังนั้นเราจึงต้องทำคลิปไปที่บรรทัดเก่าเพื่อแยกส่วนเส้นตรงเก่าออก
geogeek

อะไรไม่ชัดเจนฉันพร้อมที่จะตอบคำถามของคุณหรือไม่
geogeek

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

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