อัลกอริทึมสำหรับการสร้างรูปสามเหลี่ยมที่อยู่ติดกัน


14

ฉันมีระบบที่คุณสามารถคลิกหนึ่งครั้งเพื่อวางโหนดในฉาก เมื่อคุณวาง 3 โหนดมันจะสร้างรูปสามเหลี่ยม เมื่อคุณวางโหนดใด ๆ ในอนาคตมันจะสร้างรูปสามเหลี่ยมใหม่โดยรวมโหนดนั้นเข้ากับ 2 โหนดที่มีอยู่ใกล้เคียงที่สุด

วิธีนี้ใช้ได้ผลเกือบตลอดเวลา แต่มีข้อบกพร่องเมื่อใช้ใกล้กับสามเหลี่ยมที่มีมุมแหลมมากเพราะหนึ่งใน 2 โหนดที่ใกล้ที่สุดมักไม่ใช่สิ่งที่ควรใช้

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

ตัวอย่างพฤติกรรมจริงและที่ต้องการ

ฉันจะทราบได้อย่างไรว่าจุดยอดที่มีอยู่ 2 อันที่จะใช้เมื่อสร้างสามเหลี่ยมใหม่เพื่อไม่ให้รูปสามเหลี่ยมซ้อนทับเช่นนี้

แก้ไข : การค้นหาขอบที่ใกล้ที่สุดให้ผลลัพธ์ที่ดีกว่าแต่ไม่ใช่การค้นหาที่สมบูรณ์แบบ พิจารณาสถานการณ์นี้:

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

การทดสอบ 'edge edge ที่ใกล้ที่สุด' นั้นคลุมเครือและสามารถคืนค่า AB หรือ AC (เนื่องจากจุดที่ใกล้ที่สุดไปที่ X สำหรับทั้งคู่อยู่ที่ A) ผลลัพธ์ที่ต้องการคือ AC เพื่อสร้างสามเหลี่ยม ACX ที่ไม่มีขอบซ้อนทับกัน ฉันจะมั่นใจผลลัพธ์นี้ได้อย่างไร (ฉันไม่จำเป็นต้องทำการทดสอบการซ้อนทับของขอบแต่ละอันในกรณีที่เป็นไทเกอร์เบรกเกอร์ถ้าเป็นไปได้เพราะฉันกังวลว่าการทดสอบขอบที่ใกล้ที่สุดนั้นไม่จำเป็นว่าจุดที่ 2 นั้นจะมีระยะเท่ากัน


มันไม่ดีพอที่จะดูจุดยอด 5 จุดสุดท้ายแล้วเลือกสองจุดที่ใกล้กับจุดสุดยอดที่วางใหม่หรือไม่ ฉันจะชี้ให้คุณไปที่อัลกอริธึมสำหรับแถบสามเหลี่ยม ( codercorner.com/Strips.htm ) แต่สิ่งเหล่านั้นมักจะใช้สองครั้งล่าสุดหรือสามครั้งล่าสุดข้ามหนึ่งครั้ง
รอยต.

1
สามเหลี่ยมสีเขียวซ้อนทับสีม่วงแดงหรือไม่ เป้าหมายของสิ่งนี้คืออะไร? ผู้ใช้จำเป็นต้องควบคุมตำแหน่งของสามเหลี่ยมที่สร้างขึ้นและวิธีการหรือว่าการจำแนกจุดของคลาวด์เป็นที่ยอมรับหรือไม่?
bummzack

หากต้องการใส่สิ่งนี้ในบริบทกราฟคุณต้องการเชื่อมต่อโหนดของคุณโดยไม่มีขอบซ้อนทับหรือไม่? (สมมติว่ารูปสามเหลี่ยมสีม่วงแดง / สีเขียวจะแบ่งปันขอบ)
MichaelHouse

Roy T: ไม่ - เพียงแค่เลือก 2 ตัวที่ใกล้ที่สุดนั้นผิดเพราะฉันคิดว่าตัวอย่างแสดงให้เห็น มีบางอย่างที่ไม่ชัดเจน? Bummzack - สีเขียวไม่ทับซ้อนกับสีม่วงแดง เป้าหมายคือการสร้างตาข่ายหรือกราฟของสามเหลี่ยมเหล่านี้ ผู้ใช้ต้องการการควบคุมใช่ Byte56 - ใช่ไม่ควรข้ามขอบ
Kylotan

2
ผู้ใช้จะเห็นรูปสามเหลี่ยมแต่ละรูปจริงหรือไม่ หรือมันจะเป็นพื้นผิวต่อเนื่องหนึ่งอัน?
bummzack

คำตอบ:


11

แทนที่จะค้นหาระยะห่างต่ำสุดไปยังโหนดให้ค้นหาระยะห่างต่ำสุดไปที่ขอบ (เช่นส่วนของเส้นที่กำหนดโดยโหนด)

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

MinAngle(newPoint, vertex, edge1, edge2)
{
   newEdgeUnit = norm(newPoint - vertex); // don't actually need to normalize this
   edge1Unit = norm(edge1 - vertex);      // you probably have these from your dist to line tests
   edge2Unit = norm(edge2 - vertex);

   edge1Dot = dot(edge1Unit, newEdgeUnit);
   edge2Dot = dot(edge2Unit, newEdgeUnit);

   // you can simply compare dot products to find the minimum absolute angle
   if (edge1Dot > edge2Dot) return edge1;     // set up this way so you can generalize to an array
   return edge2;
}

** เพื่อหลีกเลี่ยงการเพิ่มรูปสามเหลี่ยมที่เสื่อมลงซึ่งอาจรบกวนการทดสอบ epsilon คุณอาจต้องการวางพื้นที่รอบจุดยอดแต่ละจุดที่ไม่อนุญาตให้เพิ่มจุด (เช่นจุดที่ไม่อนุญาตให้ใช้ในหลาย ๆ epsilon ที่ใช้ด้านบน)


3
+1 - นี่คือ IMHO คำตอบที่ตรงไปตรงมามากขึ้นกว่าคนอื่น ๆ และมีแนวโน้มที่จะให้ผลลัพธ์ที่ถูกต้อง ระยะทางต่อเซ็กเมนต์สามารถคำนวณได้ง่ายเช่นกันด้วยโครงร่างอัจฉริยะ
Steven Stadnicki

เห็นด้วยนี่เป็นวิธีที่สะอาดกว่า อาจเป็นสิ่งที่ฉันจะมาถึงถ้าฉันคิดเกี่ยวกับมันมากขึ้น: /
MichaelHouse

อ่าใกล้มาก! แต่เช่นเดียวกับคำตอบของ Byte56 และไดอะแกรมของจิมมี่บางครั้งก็มีขอบที่เท่ากัน 2 จุดและหนึ่งในนั้นก็ละเมิดข้อ จำกัด ฉันได้อัปเดตคำถามของฉันแล้ว
Kylotan

@Kylotan บางทีในกรณีนั้นเพียงแค่ตรวจสอบว่าทับซ้อนอันใดและเลือกตัวเลือกอื่นจะทำอย่างไร ค้นหาสามเหลี่ยมที่แบ่งปันขอบที่คุณเลือกและตรวจสอบว่าสามเหลี่ยมใหม่ของคุณอยู่ในด้านเดียวกันของขอบนั้นกับสามเหลี่ยมที่มีอยู่หรือไม่
Kevin Reid

@Kylotan คุณแน่ใจหรือไม่ว่ารูปสามเหลี่ยมของคุณมีขดลวดเดียวกันเสมอ ถ้าใช่คุณสามารถแยกแยะขอบที่มีการชี้ปกติจากจุดยอดใหม่ของคุณ (โดยใช้ผลิตภัณฑ์ดอท)
bummzack

6

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

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

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

จิมมี่นำคดีขึ้นมาเพื่อจุดที่คลุมเครือว่าสามเหลี่ยมใหม่จะเป็นเช่นนี้:

สามเหลี่ยมที่ไม่ชัดเจน

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

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

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


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

@ จิมมี่คุณสามารถวาดภาพของสถ
MichaelHouse


อ่าใช่แล้วคุณมีทางเลือกสองทางในการใส่สามเหลี่ยม! ทั้งสองข้างจะได้ผล บางทีคุณสามารถผูกหยุดกับหนึ่งที่มีระยะทางสั้นที่สุดไปยังศูนย์
MichaelHouse

@Kylotan วิธีนี้ไม่ทำงานใช่ไหม คุณพูดถึงความคิดเห็นต่อ Jeff ว่าภาพลักษณ์ของ Jimmy มีสองกรณีและอีกกรณีหนึ่งละเมิดข้อ จำกัด แต่นั่นไม่เป็นความจริง ในภาพของ Jimmy ทั้งสองกรณีจะสร้างสามเหลี่ยมที่ถูกต้องโดยใช้วิธีการของฉัน
MichaelHouse

1

เมื่อมีสามเหลี่ยมสีม่วงแดง ABC ของคุณคุณจะรวมจุดยอด X ใหม่ฉันคิดว่ามันชัดเจนว่าจะมีสองบรรทัดเริ่มต้นที่ D ที่จะไม่ตัดกันระหว่างขอบ ABC สามเหลี่ยมใด ๆ

สองบรรทัดนี้อาจเป็น AX & BX, BX & CX หรือ AX & CX จากนั้นคุณสามารถแก้ปัญหาของคุณในฐานะปัญหาคลาสสิกของ "ทำสองบรรทัดตัดกัน"? จากนั้นคุณสามารถตรวจสอบว่าคู่ของเส้นใดไม่ตัดกับขอบสามเหลี่ยม ABC ใด ๆ ต่อไปนี้ตัวอย่างเช่นวิธีใดวิธีหนึ่งจากคำถามนี้ ดังนั้นคุณจะมีสองขอบใหม่ของสามเหลี่ยมใหม่


สิ่งนี้ดูดี แต่วิธีการที่คุณระบุไว้ดูเหมือนว่าจะมีเพียงสามเหลี่ยมเดียวเท่านั้น มันจะพูดคุยกับหลาย ๆ คนได้อย่างไร?
Kylotan

หืม ... ถ้า X และ ABC ABC ของคุณได้รับการแก้ไขฉันเดาว่ามีเพียงอันเดียวใช่ไหม?
Dan

ระบบสร้างสามเหลี่ยมใหม่สำหรับทุกโหนดหลังจากที่ 2
Kylotan

ขออภัยฉันเข้าใจผิดคำถามของคุณ ขอผมดูว่าผมจะขยายสามเหลี่ยมนี้เป็นสามเหลี่ยมมากมายได้อย่างไร
Dan

ฉันเดาว่าคุณสามารถค้นหาจุดยอดที่ใกล้เคียงที่สุดไปที่ X ซึ่งไม่ข้ามขอบใด ๆ เมื่อเชื่อมต่อกับ X
bummzack

1

การพิจารณาว่าคุณอยู่ในภูมิภาคที่ไม่คลุมเครือ (1, 2, 3 ด้านล่าง) ค่อนข้างง่าย: ปฏิบัติต่อขอบสามเหลี่ยมของคุณเป็นระนาบ 2 มิติแล้วทดสอบด้านใดของจุดที่คุณอยู่ หากคุณอยู่ภายในสองคน แต่อยู่นอกคนนั้นคนนั้นจะตรงกับขอบของรูปสามเหลี่ยมที่ก่อให้เกิดจุดยอดสองจุดกับรูปสามเหลี่ยมใหม่ของคุณ

ภูมิภาค Voronoi ของรูปสามเหลี่ยม

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

โปรดทราบว่าการทดสอบเครื่องบินในแบบ 2D นั้นทำงานในลักษณะเดียวกับในแบบ 3 มิติ: จุดเวกเตอร์จากที่ใดก็ได้บนเครื่องบินไปยังจุดของคุณด้วยระนาบปกติ (ใน 2D นี่คือเส้นตั้งฉากของเส้น)

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


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

@Kylotan เพียงแค่เรียกใช้อัลกอริทึมสำหรับสามเหลี่ยมทั้งหมดและเลือกคุณสมบัติโดยรวมที่ใกล้ที่สุด คุณต้องใช้ตรรกะในการทำลายเสมอไม่ว่าอะไรจะเกิดขึ้น หากคุณจบลงด้วยคุณสมบัติที่ใกล้เคียงที่สุดที่เป็นจุดสุดยอดที่ใช้ร่วมกันคุณควรจะอยู่ในขอบเขตของภูมิภาค (# 1, # 2, # 3) เพียงหนึ่งสามเหลี่ยมดังนั้นบางทีคุณอาจจะเลือก?
John Calsbeek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.