Algoritma untuk membuat segitiga yang berdekatan

14

Saya memiliki sistem di mana Anda dapat mengklik sekali untuk menempatkan sebuah simpul dalam sebuah adegan. Ketika Anda menempatkan 3 node, itu membentuk segitiga. Ketika Anda menempatkan node masa depan, itu menciptakan segitiga baru dengan menggabungkan node itu ke 2 node terdekat yang ada.

Ini berfungsi dengan baik sebagian besar waktu tetapi cacat ketika digunakan di dekat segitiga dengan sudut yang sangat akut, karena salah satu dari 2 node terdekat sering bukan salah satu yang harus digunakan.

Sebagai contoh, lihat gambar di bawah ini. Segitiga magenta adalah yang pertama ditempatkan. Jika saya klik pada posisi bertanda X, yang saya dapatkan adalah segitiga baru di mana overlay biru berada. Yang saya inginkan adalah segitiga baru di mana overlay hijau berada. (mis. simetris dengan magenta, dalam contoh ini. Klarifikasi: Segitiga hijau dan magenta tidak tumpang tindih - yang hijau memanjang di bawah yang biru ke simpul paling kiri)

Contoh perilaku aktual dan yang diinginkan

Bagaimana saya bisa menentukan 2 simpul yang ada untuk digunakan saat membuat segitiga baru sehingga segitiga tidak ditumpangkan seperti ini?

EDIT : Mencari tepi terdekat memberikan hasil yang lebih baik , tetapi tidak sempurna. Pertimbangkan situasi ini:

masukkan deskripsi gambar di sini

Tes 'tepi terdekat' adalah ambigu, dan dapat mengembalikan AB atau AC (sebagai titik terdekat ke X untuk keduanya adalah pada A). Hasil yang diinginkan adalah AC, untuk membentuk segitiga ACX tanpa ujung yang tumpang tindih. Bagaimana saya bisa memastikan hasil ini? (Saya lebih suka tidak harus melakukan tes tumpang tindih masing-masing tepi sebagai tie-breaker jika memungkinkan karena saya khawatir bahwa tes tepi terdekat tidak harus melihat 2 persis sama, mengingat masalah presisi titik mengambang.)

Kylotan
sumber
Bukankah cukup bagus untuk melihat 5 simpul terakhir yang ditempatkan dan memilih dua yang paling dekat dengan simpul yang baru ditempatkan? Saya akan mengarahkan Anda ke algoritma untuk strip segitiga ( codercorner.com/Strips.htm ) tetapi yang sering hanya menggunakan dua terakhir atau tiga terakhir melewatkan satu.
Roy T.
1
Apakah segitiga hijau tumpang tindih dengan magenta? Apa tujuan dari ini? Apakah pengguna perlu mengontrol di mana dan bagaimana segitiga dibuat atau apakah triangulasi titik-awan dapat diterima?
bummzack
Untuk menempatkan ini dalam konteks grafik, pada dasarnya Anda ingin menghubungkan node Anda, tanpa ada tepi yang tumpang tindih? (Dengan asumsi magenta / segitiga hijau akan berbagi keunggulan)
MichaelHouse
Roy T: tidak - hanya memilih 2 yang terdekat itu salah, seperti yang saya pikir contohnya tunjukkan. Apakah ada sesuatu yang tidak jelas? Bummzack - Yang hijau tidak tumpang tindih dengan magenta. Tujuannya adalah untuk membuat mesh atau grafik dari segitiga ini. Pengguna memang perlu kontrol, ya. Byte56 - ya, tidak ada tepi yang harus disilangkan.
Kylotan
2
Akankah pengguna benar-benar melihat segitiga individual? Atau apakah itu akan menjadi satu permukaan kontinu?
bummzack

Jawaban:

11

Daripada menemukan jarak minimum ke node, cari jarak minimum ke tepi (yaitu segmen garis yang ditentukan oleh node).

Kemudian, jika titik terdekat adalah titik (yang Anda harus menggunakan beberapa tes titik mengambang epsilon **), bandingkan sudut antara garis dari titik baru ke titik dan masing-masing tepi terhubung ke titik itu. Pilih satu dengan sudut absolut minimum:

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;
}

** Untuk menghindari penambahan segitiga yang merosot, yang dapat mengganggu tes epsilon, Anda mungkin ingin menempatkan wilayah di sekitar setiap titik di mana menambahkan poin tidak diizinkan, (seperti melarang poin dalam beberapa beberapa epsilon yang digunakan di atas).

Jeff Gates
sumber
3
+1 - ini adalah IMHO jawaban yang jauh lebih mudah daripada yang lain, dan lebih cenderung memberikan hasil yang benar. Distance-to-segment juga mudah untuk dihitung dengan skema cerdas.
Steven Stadnicki
Setuju, ini adalah metode yang lebih bersih. Mungkin apa yang akan saya tiba jika saya lebih memikirkannya: /
MichaelHouse
Ah, sangat dekat! Tapi, seperti jawaban Byte56 dan diagram Jimmy, kadang-kadang ada 2 sisi yang sama, dan salah satunya melanggar kendala. Saya telah memperbarui pertanyaan saya.
Kylotan
@Kylotan Mungkin dalam kasus itu, cukup memeriksa yang mana yang tumpang tindih dan mengambil opsi lain akan lakukan? Cari segitiga yang berbagi tepi yang Anda pilih, dan periksa apakah segitiga baru Anda berada di sisi yang sama dengan yang ada.
Kevin Reid
@Kylotan Apakah Anda memastikan segitiga Anda selalu memiliki lilitan yang sama? Jika ya, Anda bisa mengesampingkan tepi yang memiliki titik normal yang jauh dari titik baru Anda (menggunakan produk-titik).
bummzack
6

Setelah segitiga pertama ditempatkan, saat menempatkan simpul baru, Anda akan selalu menghasilkan dua tepi baru. Tepi ketiga untuk segitiga baru akan selalu menjadi tepi bersama dengan segitiga sebelumnya. Jika Anda dapat menemukan cara untuk menentukan tepi bersama, Anda akan tahu simpul mana yang harus disambungkan, tetapi itulah bagian yang sulit. Saya percaya satu cara Anda bisa melakukan ini dengan menggambar garis dari titik baru Anda ke pusat masing-masing dari tiga tepi terakhir yang dihasilkan (atau mungkin 3 tepi terdekat).

masukkan deskripsi gambar di sini

Jika garis dari titik Anda ke pusat tepi tidak melewati salah satu dari dua tepi lainnya, Anda memiliki tepi yang Anda bagikan. Tepi yang dibagikan akan memberi tahu Anda dua simpul mana yang harus disambungkan ke simpul baru Anda.

Jimmy membawa kasing untuk titik yang tidak jelas ke mana segitiga baru akan pergi seperti ini:

segitiga ambigu

Itu akan memberi Anda kesempatan untuk memilih antara dua segitiga yang valid. Mungkin yang memutuskan titik tengah mana yang paling dekat.

Mempertimbangkan pembaruan Anda, meski lebih kompleks, solusi saya hanya akan menghasilkan dasi ketika Anda memiliki dua segitiga yang valid. Dengan menggunakan metode ini, contoh gambar kedua Anda akan menghasilkan hasil yang Anda inginkan.

masukkan deskripsi gambar di sini

MichaelHouse
sumber
Ada kemungkinan untuk memiliki situasi di mana dua garis tidak bersinggungan dengan tepi (ketika X lebih dekat ke titik daripada ke tepi)
Jimmy
@ Jimmy, bisakah kamu menggambar situasi seperti ini?
MichaelHouse
Ah ya, maka Anda punya dua pilihan tempat meletakkan segitiga! Kedua belah pihak akan bekerja. Mungkin Anda dapat memutuskan hubungan dengan yang memiliki jarak terdekat ke pusat.
MichaelHouse
@Kylotan apakah solusi ini tidak berfungsi? Anda menyebutkan dalam komentar kepada Jeff bahwa gambar Jimmy memiliki dua kasus dan satu melanggar kendala, tetapi itu tidak benar. Dalam gambar Jimmy, kedua kasing menghasilkan segitiga yang valid menggunakan metode saya.
MichaelHouse
1

Memiliki segitiga ABC magenta Anda, Anda kemudian memasukkan simpul X baru. Saya pikir jelas bahwa akan ada dua garis mulai dari D yang tidak akan berpotongan di antara salah satu tepi ABC segitiga.

Dua baris ini bisa menjadi AX & BX, BX & CX atau AX & CX. Anda kemudian dapat memperlakukan masalah Anda sebagai masalah klasik "do two lines intersect"? Anda kemudian dapat memeriksa pasangan garis mana yang tidak bersinggungan dengan tepi segitiga ABC mana saja yang mengikuti, misalnya, salah satu metode dari pertanyaan ini . Oleh karena itu, Anda akan memiliki dua tepi baru dari segitiga baru.

Dan
sumber
Ini kelihatannya bagus, tetapi cara Anda menyatakan tampaknya menganggap bahwa hanya ada satu segitiga yang ada. Bagaimana itu akan digeneralisasi ke banyak orang?
Kylotan
Hum ... jika X dan segitiga ABC Anda sudah diperbaiki, saya kira hanya ada satu, bukan?
Dan
Sistem membuat segitiga baru untuk setiap node setelah yang kedua.
Kylotan
Maaf, saya salah mengerti pertanyaan Anda. Biarkan saya melihat bagaimana saya dapat memperluas ini ke banyak segitiga.
Dan
Yah saya kira Anda bisa mencari dua simpul terdekat ke X yang tidak melewati batas ketika terhubung ke X?
bummzack
1

Mencari tahu jika Anda berada di salah satu daerah yang tidak ambigu (1, 2, 3 di bawah), cukup mudah: perlakukan setiap tepi segitiga Anda sebagai bidang 2D dan uji sisi mana pesawat pada titik baru Anda berada. Jika Anda berada di dalam dua dari mereka tetapi di luar satu, maka yang sesuai dengan tepi segitiga yang berkontribusi dua simpul untuk segitiga baru Anda.

Daerah Voronoi berbentuk segitiga

Jika Anda berada di dalam satu dan di luar dua, Anda berada dalam kasus ambigu di mana bagian terdekat dari segitiga ke titik baru Anda adalah sudut. Dalam hal ini, Anda bisa membentuk bidang 2D dari titik tengah dari tepi yang berlawanan (yang Anda berada di dalamnya) dan verteks terdekat (yang dibagi oleh dua pesawat yang Anda berada di luar). Anda dapat memilih ujung tergantung pada sisi mana dari pesawat ini titik baru Anda aktif.

Perhatikan bahwa tes bidang dalam 2D ​​bekerja dengan cara yang sama seperti dalam 3D: beri titik vektor dari mana saja pada bidang ke titik Anda dengan bidang normal (dalam 2D, ini garis tegak lurus).

(Kebetulan, daerah yang dibatasi magenta dalam gambar ini disebut daerah Voronoi; mereka adalah area ruang yang mengandung titik-titik yang paling dekat dengan fitur tertentu — tepi atau simpul-segitiga). Sunting: Terminologi saya di sini sebenarnya tidak cukup benar, ini bukan daerah Voronoi.)

John Calsbeek
sumber
Tidak segera jelas bagi saya bagaimana ini digeneralisasikan ke beberapa segitiga dalam adegan - terutama jika fitur terdekat adalah titik yang dapat dibagi oleh lebih dari 1 segitiga.
Kylotan
@Kylotan Jalankan algoritma untuk semua segitiga, dan pilih keseluruhan fitur terdekat. Anda memerlukan logika yang mengikat apa pun yang terjadi. Jika Anda berakhir dengan fitur terdekat sebagai verteks bersama, maka Anda harus berada di wilayah tepi (# 1, # 2, # 3) hanya untuk satu segitiga, jadi mungkin Anda bisa memilih itu?
John Calsbeek