ค้นหาเพื่อนบ้านใกล้ตัว

ฉันจำเป็นต้องหาเพื่อนบ้านที่ "ใกล้" ในจุดที่กำหนด

pointSet

มี 10 จุดตามภาพด้านบน เส้นสีแดงคือขอบจาก Delaunay Triangulation โดยมีดาวสีดำเป็นจุดกึ่งกลาง เส้นขอบ เส้นสีน้ำเงินคือ Voronoi tesselation จุดที่ 1 มีเพื่อนบ้านที่ "ใกล้" สามคน ได้แก่ 4, 6 และ 7 แต่ไม่ใช่ 2 และ 3 ซึ่งเกือบจะอยู่ในแนวเดียวกับขอบ 1-7 แต่อยู่ไกลออกไปมาก

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


comment
+1 สำหรับคำถามที่น่าสนใจ เพื่อให้เข้าใจได้ดีขึ้น อะไรคือเพื่อนบ้านใกล้ของ 9?   -  person Jacob    schedule 10.02.2011
comment
@Jacob: เป็นไปได้มากที่สุด 3, 4, 5, 7, 8, 10   -  person Jonas    schedule 10.02.2011
comment
โจนัส คุณแน่ใจหรือว่าวัตถุที่ส่งคืนของเดโลเนย์ไตรมี 1 และ 3 เชื่อมต่ออยู่? ไม่มีบทแทรกที่ระบุว่ามีขอบ delaunay ระหว่างสองจุดถ้าภูมิภาค voronoi ของพวกเขามีความได้เปรียบร่วมกันใช่หรือไม่ ฉันเป็นมือใหม่ในพื้นที่นี้ ดังนั้นบอกฉันหากฉันขาดอะไรไปที่นี่   -  person sundar - Remember Monica    schedule 23.11.2011
comment
@sundar: ฉันวางแผนผลลัพธ์ของ DelaunayTri แล้วใช่ฉันแน่ใจ อาจมีบทแทรกอย่างที่คุณพูด แต่ฉันไม่รู้   -  person Jonas    schedule 23.11.2011
comment
@ Jonas ขอบคุณสำหรับการตอบกลับ คุณช่วยบอกฉันได้ไหมว่าสิ่งเหล่านี้เป็นจุดเดียวในอินพุตของ DelaunayTri หรือถ้านี่เป็นเวอร์ชันซูมเข้าโดยมีจุดด้านนอกบางจุดเหลืออยู่?   -  person sundar - Remember Monica    schedule 24.11.2011
comment
@sundar: นี่เป็นเพียงประเด็นเดียว   -  person Jonas    schedule 24.11.2011
comment
@โจนัส ขอบคุณ ฉันวิเคราะห์ภาพและพิจารณาว่าพื้นที่ของ 1 และ 2 (และ 1 และ 3) มีขอบร่วมกันและกลายเป็นเพื่อนบ้าน 'ใกล้' ในพื้นที่ด้านขวาสุดของภาพนี้ ดังนั้นขอบ delaunay ที่ส่งคืนนั้นถูกต้องทางเทคนิคและระบุจุดที่อยู่ใกล้เพื่อนบ้านด้วยตัวมันเอง   -  person sundar - Remember Monica    schedule 25.11.2011
comment
@sundar: ขอบคุณที่ได้ดูสิ่งนี้ เพื่อจุดประสงค์ในทางปฏิบัติของฉัน ฉันจะไม่ถือว่าพวกเขาอยู่ใกล้เพื่อนบ้าน   -  person Jonas    schedule 25.11.2011


คำตอบ (3)


คุณสามารถใช้แนวคิดแรกในการเลือกขอบที่มีจุดกึ่งกลางตัดกับเส้นโวโรนอยได้โดยใช้ DelaunayTri คลาส และ edges< /a> และ nearestNeighbor วิธีการ นี่คือตัวอย่างที่มีค่า x และ y แบบสุ่ม 10 คู่:

x = rand(10,1);                     %# Random x data
y = rand(10,1);                     %# Random y data
dt = DelaunayTri(x,y);              %# Compute the Delaunay triangulation
edgeIndex = edges(dt);              %# Triangulation edge indices
midpts = [mean(x(edgeIndex),2) ...  %# Triangulation edge midpoints
          mean(y(edgeIndex),2)];
nearIndex = nearestNeighbor(dt,midpts);  %# Find the vertex nearest the midpoints
keepIndex = (nearIndex == edgeIndex(:,1)) | ...  %# Find the edges where the
            (nearIndex == edgeIndex(:,2));       %#   midpoint is not closer to
                                                 %#   another vertex than it is
                                                 %#   to one of its end vertices
edgeIndex = edgeIndex(keepIndex,:);      %# The "good" edges

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

triplot(dt,'r');  %# Plot the Delaunay triangulation
hold on;          %# Add to the plot
plot(x(edgeIndex).',y(edgeIndex).','r-','LineWidth',3);  %# Plot the "good" edges
voronoi(dt,'b');  %# Plot the Voronoi diagram
plot(midpts(:,1),midpts(:,2),'k*');  %# Plot the triangulation edge midpoints

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

มันทำงานอย่างไร...

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

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

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

person gnovice    schedule 10.02.2011
comment
ขอบคุณมาก! ฉันยอมรับว่าฉันไม่แน่ใจว่าทำไมมันถึงใช้งานได้ (เช่นคุณใช้คุณสมบัติใดของ Voronoi tesselation) แต่ใช้งานได้ - person Jonas; 10.02.2011
comment
@Jonas: ฉันได้เพิ่มคำอธิบายว่าวิธีการจำแนกประเภทเพื่อนบ้านที่ใกล้ที่สุดทำงานอย่างไร - person gnovice; 11.02.2011

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

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

person Throwback1986    schedule 10.02.2011
comment
ขอบคุณสำหรับการอ้างอิงไปยังระบบอื่น ฉันหวังว่าฉันจะหลีกหนีจากวิธีแก้ปัญหาของ @gnovice ได้ แต่เป็นการดีที่จะรู้ว่ามีอะไรอยู่บ้างในกรณีที่ฉันทำไม่ได้ - person Jonas; 10.02.2011
comment
ไปงานปาร์ตี้ช้าไปหน่อย แต่แนวคิดนี้ (ความใกล้เคียงตามคู่โวโรน้อย) ได้ถูกนำมาใช้เมื่อเร็ว ๆ นี้เพื่อสร้างรายชื่อที่อยู่ติดกันแบบจำกัด (รายชื่อผู้สมัคร) สำหรับการแก้ปัญหาการกำหนดเส้นทางยานพาหนะตามหลักการเรียนรู้ ดู Fang, Zhixiang, et al. "A Voronoi neighborhood-based search heuristic for distance/capacity constrained very large vehicle routing problems." International Journal of Geographical Information Science 27.4 (2013): 741-764. - person Gaminic; 25.03.2014

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

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

จุดที่มี Y เล็กสามารถย้ายไปที่แถวบนสุดของเมทริกซ์ได้ และจุดที่มี Y มากก็จะย้ายไปที่แถวล่างเช่นกัน สิ่งเดียวกันนี้จะเกิดขึ้นกับจุดที่มีพิกัด X เล็ก ๆ ที่ควรย้ายไปที่คอลัมน์ทางด้านซ้าย และในทางสมมาตร จุดที่มีค่า X มากจะไปที่คอลัมน์ทางขวา

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

คุณสามารถอ่านรายละเอียดเพิ่มเติมสำหรับแนวคิดนี้ได้ในเอกสารต่อไปนี้ (คุณจะพบสำเนา PDF ของแนวคิดนี้ได้ทางออนไลน์): การจำลองฝูงชนขนาดใหญ่มหาศาลบน GPU ตามพฤติกรรมฉุกเฉิน

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

หากคุณต้องการเรียงลำดับแบบเต็ม คุณสามารถเรียกใช้การขนย้ายเลขคู่ดังกล่าวได้หลายครั้ง (ตามที่อธิบายไว้ในหน้า Wikipedia ต่อไปนี้):

http://en.wikipedia.org/wiki/Odd%E2%80%93even_sort

person mgmalheiros    schedule 08.02.2014
comment
หากคุณมีข้อมูลที่เพิ่มขึ้นอย่างรวดเร็ว... สมมติว่ามีคลัสเตอร์สองกลุ่มที่แยกจากกันอย่างดีเคียงข้างกัน และคุณเรียงลำดับเมทริกซ์ของคุณตามที่คุณแนะนำข้างต้น แล้วจุดซ้ายสุดบนกระจุกขวาและจุดขวาสุดของกระจุกซ้ายจะไม่ถือเป็นเพื่อนบ้านผิดๆ หรอกหรือ? - person codekitty; 13.02.2014
comment
@codekitty: ใช่ จุดที่ห่างไกลเหล่านั้นสามารถวางเคียงข้างกันในเมทริกซ์พื้นที่ใกล้เคียงได้ แต่โครงการนี้ช่วยให้คุณค้นหาผู้สมัครสำหรับเพื่อนบ้านที่แท้จริงได้อย่างรวดเร็ว ดังนั้นหลังจากเลือกเซลล์เมทริกซ์ใกล้เคียงแล้ว คุณยังคงต้องทดสอบเซลล์ที่อยู่ในรัศมีอิทธิพลของคุณ (หรือเลือกเซลล์ที่ใกล้ที่สุด) . - person mgmalheiros; 14.02.2014
comment
แน่นอนว่าความหนาแน่นจริงและการกระจายของจุดในอวกาศส่งผลโดยตรงต่อวิธีการรวมเมทริกซ์ ดังนั้น มันจะทำงานได้ดีกว่าสำหรับการกระจายแบบสม่ำเสมอ โดยอุดมคติแล้วสำหรับการจัดเรียงตารางปกติหรือการจัดเรียงจุดแบบรังผึ้ง สำหรับการใช้งานเฉพาะของฉัน (อนุภาคที่อัดแน่น) มันมีประโยชน์มาก... - person mgmalheiros; 14.02.2014
comment
ฉันได้วางตัวอย่างโค้ด C++ ที่นี่ ซึ่งง่ายมาก และรูปภาพสองรูปที่มีจุดรหัสสีในระนาบ (X องค์ประกอบสีแดง, Y คือสีเขียว): ก่อน และ หลัง - person mgmalheiros; 14.02.2014