Posso semplificare la disuguaglianza "distanza (p1, p2) <distanza (p1, p3)?"


14

Sto lavorando su una logica vettoriale, quindi chiedo: posso risparmiare tempo del processore semplificando questa disuguaglianza:

distance(vector1, vector2) < distance(vector1, vector3)

Vedo che vector1si ripete in entrambi i casi.


10
Solo una breve nota: il tuo metodo attuale è molto leggibile e la sua funzione può essere immediatamente compresa. Alcune di queste risposte possono svolgere l'attività richiesta, ma sono molto meno chiare. Questo va bene se le prestazioni sono essenziali, ma assicurati di commentarle correttamente per tenere conto della perdita di chiarezza.
MikeS

3
Per continuare il commento di @ MikeS, le prestazioni dovrebbero essere essenziali in casi come questo se hai già fatto analisi o profilazione e hai identificato questa chiamata come un collo di bottiglia. La manutenibilità supera le prestazioni grezze se parliamo della differenza tra 305 fps e 303 fps.
Foshi,

Risposte:


24

, puoi semplificarlo. Per prima cosa, smetti di chiamarli vettori. Sono punti. Chiamiamoli così A, Be C.

Quindi, vuoi questo:

dist(A, B) < dist(A, C)

Sostituisci le distanze con le distanze al quadrato, quindi con i punti (dalla definizione della lunghezza euclidea . Sostituisci ACcon AB + BC(ora questi sono vettori reali). Espandi, semplifica, fattore:

dist(A, B < dist(A, C
dot(AB, AB) < dot(AC, AC)
dot(AB, AB) < dot(AB + BC, AB + BC)
dot(AB, AB) < dot(AB, AB) + dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC + 2 AB, BC)

Eccoti:

dot(AB + AC, BC) > 0

Con la tua notazione vettoriale:

dot(v2 - v1 + v3 - v1, v3 - v2) > 0

Sono alcune aggiunte e un prodotto punto invece dei precedenti due prodotti punto.


Puoi spiegare come puoi sostituire a a + b b = a a + c c con la versione del prodotto punto?
TravisG,

2
@TravisG Non sono sicuro di quello che stai chiedendo. Se la tua domanda è perché dist(A, B)²è la stessa dot(AB, AB), viene dalla definizione stessa della lunghezza euclidea .
Sam Hocevar,

2
Chiaramente ciò semplifica (in qualche modo) matematicamente l'equazione, ma non "risparmierebbe necessariamente il tempo del processore" per l'OP. Ne risulta una maggiore complessità e più calcoli rispetto alla semplice rimozione della radice quadrata dalle equazioni della distanza originale.
MichaelHouse

1
Correggimi se sbaglio, ma i due prodotti punto sono 5 operazioni per prodotto punto più le due sottostrazioni vec3 che sono un totale di 16 operazioni, a modo tuo hai 3 sottostrazioni vec3 più un'aggiunta che fa 12 operazioni più il prodotto punto fa 17.
Luis W

2
È interessante notare che il risultato è il prodotto punto delle due diagonali opposte di un parallelogramma. Ma questo è irrilevante. Quello che volevo dire è che non c'è molto da guadagnare da questa piena semplificazione; come altri hanno già detto, fa una discreta quantità per offuscare o complicare ciò che stai effettivamente cercando di calcolare. Tuttavia, vuoi sicuramente usare il primo passo. Evitare una radice quadrata non necessaria vale sempre la pena. Il solo confronto dei quadrati delle distanze è lo stesso, poiché la distanza è definita positiva, anche nel piano complesso.
TASagent

16

Sì. Supponendo che la tua distancefunzione usi una radice quadrata, puoi semplificarla rimuovendo la radice quadrata.

Quando si cerca di trovare la distanza maggiore (o minore), x^2 > y^2vale ancora per x > y.

Tuttavia, ulteriori tentativi di semplificare matematicamente l'equazione sono probabilmente inutili. La distanza tra vector1e vector2non è uguale alla distanza tra vector1e vector3. Mentre l'equazione può essere semplificata matematicamente come mostra la risposta di Sam , la forma in cui si trova attualmente è probabilmente tanto semplice quanto otterrai dalla prospettiva di utilizzo del processore.


Non ho abbastanza rappresentante, ma vorrei che sia fondamentalmente errato, credo: "posso risparmiare tempo del processore semplificando questa disuguaglianza?" La risposta è si.
così confuso il

La risposta è sì solo se l'equazione della distanza utilizza una radice quadrata. Che cito.
MichaelHouse

Punto valido, ritirare la mia dichiarazione. Tuttavia, è garantito al 99% che l'utente intende sqrt distanza euclidea (somma (differenze dimensionali al quadrato))
così confuso

@imsoconfused Abbastanza giusto, ho cambiato l'ordine della mia risposta per indicare prima lo scenario più probabile (99%).
MichaelHouse

2
Sì, la mia esperienza è quando hai a che fare con questo genere di cose una funzione DistanceSquared è molto utile. È altrettanto chiaro ed evita la costosa operazione sqrt.
Loren Pechtel,

0

Alcuni calcoli potrebbero aiutare.

Quello che stai cercando di fare è:

<v1, v2> < <v1, v3> =>
sqrt((y2-y1)^2+(x2-x1)^2) < sqrt((y3-y1)^2+(x3-x1)^2) =>
y2^2 - 2*y2y1 + y1^2 + x2^2 - 2*x2x1 + x1^2 < y3^2 - 2*y3y1 + y1^2 + x3^2 - 2*x3x1 + x1^2

Da ciò che è possibile rimuovere variabili ripetute e raggrupparne altre. L'operazione che devi controllare è:

y3^2 - y2^2 - 2*y1(y3-y2) + x3^2 - x2^2 - 2*x1(x3-x2) > 0

Spero che sia d'aiuto.


-1

La vera domanda sembra essere come ridurre il calcolo per determinare l'oggetto più vicino?

Ottimizzazione questo viene spesso eseguita nei giochi, sebbene con tutte le ottimizzazioni dovrebbe essere guidata dal profilo e, spesso, non semplifica le cose.

Il modo per evitare calcoli di distanza non necessari per determinare la cosa più vicina - o tutte le cose entro un certo intervallo - è utilizzare un indice spaziale ad es. Un octree .

Questo paga solo se ci sono molti oggetti. Per soli tre oggetti, è improbabile che ripaghi e certamente non semplifica il codice.


4
Penso che la vera domanda sia abbastanza semplice, e questa risposta non risponde a questo. Se si desidera speculare sulle domande più profonde e non dichiarate del PO che dovrebbero essere fatte come commenti se non si risponde effettivamente alla domanda.

Lo sto ridimensionando perché invocare una possibile ottimizzazione prematura non è una risposta a un problema in cui l' ottimizzazione esplicita non danneggia né la leggibilità, né la manutenibilità del codice, né incoraggia pratiche oscure. Quando puoi effettivamente scrivere codice semplice e ottimizzato, perché non farlo? Certamente non fa male farlo, anche se hai un piano di livello superiore (nessuno sviluppatore di giochi rifiuterà mai alcuni microsecondi extra per frame, specialmente su console).
teodron,

@teodron: "Quando puoi effettivamente scrivere codice semplice e ottimizzato, perché non farlo?" - Perché OP (e ora noi) ha trascorso un periodo di tempo non trascurabile nell'ottimizzazione di qualcosa che potrebbe non dargli alcun beneficio.
BlueRaja - Danny Pflughoeft,

@ BlueRaja-DannyPflughoeft Sono d'accordo con questo per essere un minore (quindi ottimizzazione insignificante se usata per qualche centinaio di chiamate per frame, ma se il fattore di magnitudine aumenta a migliaia, le cose cambieranno sicuramente). Tuttavia, siamo tutti liberi di non perdere tempo cercando di rispondere / ottimizzare qualcosa che riteniamo non fattibile. L'OP ha chiesto una cosa, le persone hanno ipotizzato che l'OP non fosse a conoscenza di strategie e pratiche di profilazione di livello superiore. Personalmente preferisco fare tali osservazioni nei commenti, non nelle risposte. Scusate se sono così
prolisso

-3

dipende da quale sia l'uscita della distanza (v1, v2)

se è un decimale (float o double) su un vettore, è probabile che le distanze al quadrato siano molto più veloci


5
Non vedo cosa floatabbia a che fare con qualcosa.
MichaelHouse

volevo dire un float su un altro vettore non spiegato in modo particolare (e penso che tu lo sapessi)
RoughPlace

5
Non ero intenzionalmente frainteso. Non sono ancora sicuro di cosa intendi. Non so perché una funzione di distanza restituisca un vettore.
MichaelHouse
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.