Tes andal untuk persimpangan dua kurva Bezier

9

Bagaimana cara mencari tahu apakah dua kurva Bezier planar berpotongan? Dengan "andal" maksud saya tes akan menjawab "ya" hanya ketika kurva berpotongan, dan "tidak" hanya ketika mereka tidak berpotongan. Saya tidak perlu tahu parameter apa yang ditemukan pada persimpangan. Saya juga ingin menggunakan angka floating-point dalam implementasi.

Saya menemukan beberapa jawaban pada StackOverflow yang menggunakan kurva-kotak terikat untuk tes: ini bukan apa yang saya cari karena tes tersebut dapat melaporkan persimpangan bahkan jika kurva tidak memotong.

Hal terdekat yang saya temukan sejauh ini adalah " irisan pembatas " oleh Sederberg dan Meyers tetapi "hanya" membedakan antara persimpangan paling-paling-satu dan dua-atau-lebih, sedangkan saya ingin tahu apakah ada paling-nol dan satu atau lebih persimpangan.

Ecir Hana
sumber
Saya tidak yakin itu ada, menentukan wetehr atau ada kemungkinan untuk 0-1 atau 2 atau lebih cukup sepele tetapi formulasi tidak benar-benar membuatnya mudah untuk memastikan 0 atau 1 tanpa benar-benar memeriksa.
joojaa
Apa persyaratan runtime? Sebuah solusi yang seharusnya dapat menghasilkan hasil yang cukup akurat adalah dengan memperkirakan kedua kurva dengan sejumlah besar segmen lurus pendek dan kemudian memotongnya secara berpasangan. Tapi itu menghabiskan banyak waktu dan memori.
Dragonseel
@ Archonseel Yah, saya akan senang untuk solusi apa pun, sungguh, tetapi karena Anda bertanya O (1) akan menyenangkan. Tetapi mendekati kurva dengan segmen garis mengarah ke masalah yang sama seperti tes untuk kotak tumpang tindih tumpang tindih ...
Ecir Hana
Masalah menarik. Saya tidak berpikir ada jawaban yang mudah tetapi saya ingin salah. Apakah Anda memiliki tautan untuk makalah Sederberg dan Meyers?
Daniel M Gessel
@DanielMGessel Ya, lihat hasil edit di atas.
Ecir Hana

Jawaban:

6

Cara alternatif untuk merumuskan masalah adalah dengan mendefinisikan fungsi yang memberikan jarak antara titik pada dua kurva, sebagai fungsi dari parameter kurva. Kemudian cobalah mencari minimum global dari fungsi ini. Jika kurva bersilangan, minimum akan menjadi nol; kalau tidak minimum akan menjadi jarak positif.

Untuk menjadi eksplisit, diberikan sepasang kurva 2D yang didefinisikan oleh , tentukan jarak-kuadrat sebagaic1,c2:[0,1]R2

f(kamu,v):[0,1]2R0|c2(v)-c1(kamu)|2

Untuk kurva kubik, fungsi kemudian menjadi polinomial tingkat enam dalam dua variabel. Anda kemudian dapat menerapkan teknik optimasi numerik seperti metode simpleks atau keturunan gradien konjugat . Sayangnya fungsi tersebut dapat memiliki beberapa minimum lokal (ini bukan cembung), jadi pengoptimalan tidak mudah. Mungkin ada metode optimasi yang lebih khusus yang tersedia untuk polinomial, tetapi ini bukan bidang keahlian bagi saya.f

Nathan Reed
sumber
Mengapa polinomial tingkat 6, dan bukan ke-3, jika kita berbicara tentang Beziers kubik? Dan dua metode yang Anda tautkan, apakah mereka dapat menemukan solusi hanya di , yang bertentangan dengan seluruh R 2 ? [0,1]2R2
Ecir Hana
1
@EcirHana Tingkat ke-6 karena jarak kuadratnya. (Anda dapat melakukan root-square, tetapi tidak lagi polinomial, dan tidak akan mulus di nol). Perhatikan bahwa adalah ruang parameter, bukan ruang tempat splines hidup, yaitu ini adalah splines dengan titik akhir. Bagaimanapun, metode akan bekerja dengan baik di R 2 , tetapi mereka hanya "melakukan perjalanan menuruni bukit" dari perkiraan awal dan menemukan minimum lokal; sesuatu yang lebih diperlukan untuk memeriksa seluruh wilayah parameter dan menemukanminimumglobal. Membatasi ruang parameter mungkin membantu di sana. [0,1]R2
Nathan Reed
1
Nathan - formulasi yang bagus! Saya berkarat, tapi: Saya pikir Anda bisa membagi setiap kurva lebih dari 5 segmen, di mana atau y mengubah arah dalam kurva. xxyx , sebagai fungsi mengubah arah paling banyak dua kali (akar turunan) memecah kurva menjadi 3 segmen, 2 di antaranya dapat dibagi lagi oleh perubahan arah y . Sekarang Anda memiliki, bukan segmen lurus, tetapi segmen yang "tidak terlalu melengkung". Saya pikir jika Anda memulai pencarian Anda pada 25 poin, dipilih oleh pasangan segmen, Anda dapat selalu menemukan minimum global, tetapi saya tidak bisa melihat bagaimana membuktikan (atau menyangkal) itu. csayay
Daniel M Gessel
@ Nathan: Saya sudah mempertimbangkan itu tetapi, setelah menghabiskan banyak waktu menulis kode untuk menemukan minima dalam format kompresi tekstur, semuanya tampak agak mengerikan.
Simon F
5

[Penafian: Saya pikir yang berikut ini harus berfungsi tetapi belum benar-benar mengkodekannya sendiri]

Saya tidak bisa memikirkan metode "sepele" untuk menghasilkan jawaban ya / tidak, tetapi berikut ini akan menjadi pendekatan yang masuk akal untuk solusi praktis untuk pertanyaan itu.

Anggap kurva kita masing-masing adalah A (s) dan B (t) dengan titik kontrol { A0, A1..An } dan { B0, .. Bm }.

Menurut saya, mengingat sepasang Beziers 2D yang ingin kami tentukan apakah berpotongan atau tidak, ada enam hal yang perlu dipertimbangkan:

  1. Kasus di mana kita bisa "sepele" menentukan mereka tidak berpotongan.

  2. Kasus di mana mereka berpotongan beberapa kali dan kita dapat "dengan mudah" menentukan mereka pasti berpotongan setidaknya sekali (tapi kita tidak benar-benar peduli di mana persimpangan itu terjadi)

  3. Salah satu Beziers adalah degenerasi, yaitu titik (yang akan terjadi jika semua titik kontrol identik). Kita dapat berasumsi kita sudah menangani kasus di mana keduanya merupakan poin.

  4. Satu atau lebih kurva ditutup, mis. A0 == An. Untuk membuat hidup lebih sederhana, kami akan membagi kurva tersebut dan mulai lagi.

  5. Ada banyak titik persimpangan karena setiap subset dari "induk" Bezier dan mereka tumpang tindih.

  6. Kami tidak yakin tentang kasus-kasus di atas dan perlu penyelidikan lebih lanjut

Untuk saat ini kami akan mengabaikan 3 dan 4, tetapi kembali lagi nanti.

Kasus 1

Saat Anda mengisyaratkan dalam pertanyaan Anda, jika masing-masing kotak pembatas dari titik kontrol A dan B ), tidak berpotongan, maka kurva tidak dapat berpotongan. Jelas ini adalah tes penolakan cepat tetapi terlalu konservatif. Seperti yang mungkin Anda ketahui, dengan kurva Bezier, cembung cembung pada titik kontrolnya membentuk ikatan yang lebih erat. Dengan demikian kita dapat menggunakan teknik sumbu pemisah untuk memutuskan apakah lambung A dan B tidak berpotongan. (misalnya seperti yang ditunjukkan di Wikipedia :)

masukkan deskripsi gambar di sini

Kasus 2

Jika uji kasus 1 gagal, Anda dapat memeriksa keberadaan "sepele" persimpangan. Sekarang mungkin ada cara yang lebih baik untuk melakukan ini, tetapi pendekatan berikut, yang relatif murah, terjadi pada saya:

Pertimbangkan hanya kurva A:

"Garis lemak" batas Bezier

SEBUAH0SEBUAHnSEBUAH0SEBUAHn¯SEBUAH0SEBUAHn¯

Jika kita melakukan hal yang sama dengan kurva B kita mendapatkan kasus (mungkin) berikut: masukkan deskripsi gambar di sini

SEBUAH0SEBUAHnB0Bm

Kasus 6

SEBUAH1,SEBUAH2,B1,B2 . Ini relatif mudah (dibiarkan sebagai latihan untuk pembaca) tetapi sangat sepele untuk Beziers kuadratik :

(SEBUAH1,B1),(SEBUAH2,B1)...(SEBUAH2,B2)

Kasus 3 & 5

Di sinilah menjadi sedikit lebih membosankan.

Jika "case 3" berhasil melewati tes "case 1", menurut saya Anda harus menyelesaikan untuk persimpangan yang sebenarnya. Mengingat bahwa ada proses sederhana untuk memetakan titik kontrol N dari Bezier, A (s), ke titik N-1 dari Bezier, A '(s), mewakili turunan pertamanya maka (asalkan dilakukan perawatan untuk relatif jarang, apa yang disebut situasi "merosot" di mana turunan pertama tidak nol), maka iterasi Newton (pada satu dimensi) dapat digunakan untuk menemukan solusi potensial.
Perhatikan juga bahwa, karena titik kontrol A '(s) terikat pada nilai turunan, ada potensi untuk melakukan eliminasi awal beberapa kasus.

Kasus 5 tampaknya relatif tidak mungkin, jadi mungkin hanya jika setelah beberapa kali rekursi tidak ada bukti konklusif, orang dapat mencoba setiap titik akhir A terhadap kurva B dan sebaliknya. Ini hanya akan memberikan bukti persimpangan - bukan bukti non-persimpangan.

Simon F
sumber
Ya, tetapi secara pribadi saya lebih tertarik pada kasus di mana tentang kasus di mana Bm dan / atau B0 keduanya dalam volume max A dan min terikat tetapi tidak menembusnya maka Anda perlu membaginya dan dalam skenario terburuk menghitung persimpangan titik. Cara yang lebih baik adalah dengan menggunakan kotak batas minimum yang juga dikenal sebagai pendekatan garis tebal.
joojaa
Mengingat bahwa, dengan setiap subdivisi biner, perbedaan antara kurva dan segmen yang menghubungkan titik akhir turun oleh faktor yang masuk akal (dan, dari atas kepala saya, saya pikir itu mungkin 4x untuk kuadratika) pasti batasnya akan untuk menyatu ke pita "tipis" cukup cepat.
Simon F
Ya tapi skenario terburuknya adalah bahwa bezier lainnya dimulai dari yang lain.
joojaa
Maksud Anda, misalnya, An == B0 . Apakah Anda mendefinisikannya sebagai persimpangan atau tidak?
Simon F
Tidak lebih seperti B0 adalah Di suatu tempat di kurva. Atau bahkan persimpangan yang minimal
joojaa