Come si calcola il punto più vicino su 2 curve?


Risposte:


3

Ecco il mio tentativo. I seguenti algoritmi sono tutt'altro che perfetti , ma sono semplici e credo che dovresti iniziare con questo, verificare se funzionano nella tua situazione e passare a qualcosa di più veloce e / o più preciso in seguito.

L'idea è la seguente:

  • Campiona la curva di Bézier, trova il punto più vicino su quel campione
  • Campiona un quartiere intorno al punto trovato, trova un nuovo punto più vicino
  • Continuare fino a quando il punto non cambia più molto

Algoritmo per la distanza dalla curva di Bézier alla linea

La curva di Bézier è parametrizzata da una funzione che F(t)utilizza una serie di punti di controllo e un parametro variabile t. Il numero di punti generatori non è importante.

La linea è parametrizzata da due punti Ae B.

  1. Lascia SAMPLES = 10per esempio

  2. Inizia con t0 = 0et1 = 1

  3. Permettere dt = (t1 - t0) / SAMPLES

  4. Se dt < 1e-10(o qualsiasi altra condizione di precisione che ritieni appropriata), l' algoritmo è finito e la risposta èF(t0) .

  5. Calcola un elenco di SAMPLES + 1punti sulla curva di Bézier:

    • L[0] = F(t0)
    • L[1] = F(t0 + dt)
    • L[2] = F(t0 + 2 * dt)
    • ...
    • L[SAMPLES] = F(t0 + SAMPLES * dt)
  6. Trova il punto Lcon l'indice ipiù vicino alla linea. Utilizzare qualsiasi metodo di distanza punto / linea che si conosce, ad esempio la distanza quadrata ||AB^L[i]A||² / ||AB||²dove ^indica il prodotto incrociato ed ||…||è la distanza.

  7. Se i == 0impostato i = 1; se i == SAMPLES, impostarei = SAMPLES - 1

  8. Let t1 = t0 + (i + 1) * dtandt0 = t0 + (i - 1) * dt

  9. Torna al passaggio 3.

Algoritmo per la distanza dalla curva di Bézier alla curva di Bézier

Questa volta abbiamo due curve di Bézier, parametrizzate da F(t)e G(t).

  1. Lascia SAMPLES = 10per esempio

  2. Inizia con t0 = 0, t1 = 1, s0 = 0es1 = 1

  3. Permettere dt = (t1 - t0) / SAMPLES

  4. Permettere ds = (s1 - s0) / SAMPLES

  5. Se dt < 1e-10(o qualsiasi altra condizione di precisione che ritieni appropriata), l' algoritmo è finito e la risposta èF(t0) .

  6. SE questa è la prima esecuzione del ciclo:

    6.1. Calcola un elenco di SAMPLES + 1punti su F( vedi sopra ).

    6.2. Calcola un elenco di SAMPLES + 1punti su G.

    6.3. Trova la coppia di punti più vicini tra loro.

    6.4. Aggiornamento t0, t1, s0, s1come visto sopra.

  7. ELSE : in alternativa calcola un elenco di punti su F OR un elenco di punti su G, quindi trova quale punto Fè il più vicino G(s0)e aggiorna t0e t1, O quale punto Gè il più vicino F(t0)e aggiorna s0e s1.

  8. Torna al passaggio 3.

Problemi

In base alla progettazione, questi algoritmi convergeranno sempre al minimo locale. Tuttavia, non vi è alcuna garanzia che convergeranno alla soluzione migliore. In particolare, l'algoritmo della curva di Bézier non è affatto buono, e nel caso in cui due curve siano vicine l'una all'altra in molti punti potresti purtroppo perdere la soluzione da un colpo lungo.

Ma come ho detto, prima di iniziare a pensare a soluzioni più solide, dovresti prima sperimentare quelle semplici.


0

1) Traduci tutto in un asse, quindi invece di dover calcolare la lunghezza di un punto in, la 'linea', la 'linea' è, diciamo, l'asse Y.

Quindi, data una curva più bezier, direi che dipende dal numero di punti di controllo.

Se ce ne sono tre (inizio, "controllo" e fine), farei una sorta di scansione (diciamo ciascuno un paio di percentuali e poi perfeziono tra quelli più vicini (con un approccio "binario").

Altri punti proverei la coppia più vicina all'asse Y (tradotto).

Sono sicuro che un ragazzo di matematica può darti la soluzione esatta (in matematica) ma se vuoi trovare la / una soluzione in un videogioco potresti stare meglio con una soluzione leggermente ok poiché la soluzione reale potrebbe contenere diverse risposte ( Non sto nemmeno parlando della potenza di elaborazione).


ps. 2 curve, non ci pensare nemmeno (potresti ottenere qualsiasi cosa (almeno come può ..) in base al numero di punti di controllo)
Valmond


0

Per la curva di Bezier - caso di linea retta, il modo più accurato per trovare la risposta è effettuare le seguenti operazioni:

  1. Trasforma il problema in modo che la linea retta sia sempre orizzontale su Y = 0. Questo viene fatto moltiplicando tutti i punti di controllo per una matrice affine appropriata. (Suppongo che tu abbia familiarità con la rappresentazione delle trasformazioni affine del piano con matrici 3x3 con 3 voci fisse.)
  2. Ispezionare le coordinate Y dei punti di controllo. Se non hanno tutti lo stesso segno, può esserci un incrocio con la linea. Calcola le radici della parte Y della curva di Bezier. Puoi usare qualsiasi metodo di ricerca delle radici per i polinomi, ce ne sono molti in letteratura. Ad esempio, google "marcia dello scafo convesso" - questo è un metodo ragionevolmente buono per i polinomi usati nelle curve di Bezier. Ogni radice che trovi è un valore temporale di un'intersezione con la linea, dove la distanza è zero - il tuo lavoro è finito.
  3. Se tutti i cavi Y hanno lo stesso segno, calcola la derivata della parte Y della curva di Bezier. Puoi ignorare le coordinate X dei punti, poiché non fanno alcuna differenza: la linea di destinazione è orizzontale. Trova le radici di quel derivato. Questi sono i valori temporali in corrispondenza dei quali la curva è localmente più vicina alla linea.
  4. Valuta esplicitamente la curva di Bezier per tutte le radici che hai trovato nel passaggio precedente e riporta la radice che fornisce la distanza minima dalla linea. È inoltre necessario controllare gli endpoint: potrebbero fornire una distanza inferiore rispetto a qualsiasi radice.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.