Puis-je simplifier l'inégalité «distance (p1, p2) <distance (p1, p3)?»

14

Je travaille sur une logique vectorielle, alors je demande: puis-je gagner du temps au processeur en simplifiant cette inégalité:

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

Je vois que cela vector1se répète dans les deux cas.

Filip Dimitrovski
la source
10
Juste une petite note: votre méthode actuelle est très lisible et sa fonction peut être instantanément comprise. Certaines de ces réponses peuvent accomplir la tâche que vous avez demandée, mais elles sont beaucoup moins claires. C'est bien si les performances sont essentielles, mais assurez-vous de les commenter correctement pour tenir compte de la perte de clarté.
MikeS
3
Pour continuer le commentaire de @ MikeS, les performances ne devraient être essentielles dans des cas comme celui-ci que si vous avez déjà effectué une analyse ou un profilage et identifié cet appel comme un goulot d'étranglement. La maintenabilité dépasse les performances brutes si nous parlons de la différence entre 305fps et 303fps.
Phoshi

Réponses:

24

Oui , vous pouvez simplifier cela. Tout d'abord, arrêtez de les appeler vecteurs. Ce sont des points. Appelons-les A, Bet C.

Donc, vous voulez ceci:

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

Remplacez les distances par des distances au carré, puis par des produits scalaires (à partir de la définition de la longueur euclidienne . Remplacez ACpar AB + BC(maintenant ce sont de vrais vecteurs). Développez, simplifiez, factorisez:

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)

Te voilà:

dot(AB + AC, BC) > 0

Avec votre notation vectorielle:

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

C'est quelques ajouts et un produit scalaire au lieu des deux précédents produits scalaires.

sam hocevar
la source
Pouvez-vous expliquer comment remplacer a a + b b = a a + c c par la version du produit scalaire?
TravisG
2
@TravisG Je ne suis pas sûr de ce que vous demandez. Si votre question est pourquoi dist(A, B)²est la même chose que dot(AB, AB), cela vient de la définition même de la longueur euclidienne .
sam hocevar
2
Il est clair que cela simplifie (quelque peu) mathématiquement l'équation, mais ne permettrait pas nécessairement de "gagner du temps processeur" pour l'OP. Il en résulte plus de complexité et de calculs que la simple suppression de la racine carrée des équations de distance d'origine.
MichaelHouse
1
Corrigez-moi si je me trompe, mais les deux produits scalaires sont 5 opérations par produit scalaire plus les deux soustractions vec3, ce qui représente un total de 16 opérations, votre chemin a 3 soustractions vec3 plus un ajout qui fait 12 opérations plus le produit scalaire fait 17.
Luis W
2
Chose intéressante, le résultat est le produit scalaire des deux diagonales opposées d'un parallélogramme. Mais ce n'est pas pertinent. Ce que je voulais dire, c'est qu'il n'y a pas énormément à gagner de cette simplification complète ; comme d'autres l'ont mentionné, cela fait une quantité décente pour obscurcir ou compliquer ce que vous essayez de calculer. Cependant, vous voulez certainement utiliser la première étape. Éviter une racine carrée inutile en vaut toujours la peine. La comparaison des carrés des distances est identique, car la distance est définie positive, même dans le plan complexe.
TASagent
16

Oui. En supposant que votre distancefonction utilise une racine carrée, vous pouvez simplifier cela en supprimant la racine carrée.

Lorsque vous essayez de trouver la plus grande (ou la plus petite) distance, cela x^2 > y^2vaut toujours pour x > y.

Cependant, de nouvelles tentatives de simplification mathématique de l'équation sont probablement inutiles. La distance entre vector1et vector2n'est pas la même que la distance entre vector1et vector3. Bien que l'équation puisse être simplifiée mathématiquement comme le montre la réponse de Sam , la forme dans laquelle elle se trouve actuellement est probablement aussi simple que celle que vous obtiendrez du point de vue de l'utilisation du processeur.

MichaelHouse
la source
Je n'ai pas assez de représentants, mais je dirais que c'est fondamentalement incorrect, je crois: "puis-je gagner du temps au processeur en simplifiant cette inégalité?" La réponse est oui.
Je suis tellement confus
La réponse est seulement oui si l'équation de distance utilise une racine carrée. Ce que je mentionne.
MichaelHouse
Point valable, je retire ma déclaration. Cependant, il est garanti à 99% que l'utilisateur signifie la distance euclidienne sqrt (somme (différences dimensionnelles au carré))
je suis tellement confus
@imsoconfused Assez bien, j'ai changé l'ordre de ma réponse pour énoncer le scénario le plus probable (99%) en premier.
MichaelHouse
2
Oui, mon expérience est que lorsque vous traitez ce genre de choses, une fonction DistanceSquared est très utile. C'est tout aussi clair et évite l'opération sqrt coûteuse.
Loren Pechtel
0

Quelques maths pourraient aider.

Ce que vous essayez de faire, c'est:

<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

De ce que vous pouvez supprimer les variables répétées et en regrouper d'autres. L'opération que vous devez vérifier est:

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

J'espère que cela aide.

j4nSolo
la source
-1

La vraie question semble être de savoir comment réduire le calcul pour déterminer l'objet le plus proche?

L'optimisation est souvent effectuée dans les jeux, bien qu'avec toutes les optimisations, elle devrait être guidée par le profil et, souvent, ne simplifie pas les choses.

La façon d'éviter les calculs de distance inutiles pour déterminer la chose la plus proche - ou toutes les choses dans une certaine plage - est d'utiliser un index spatial, par exemple un octree .

Cela ne vaut que s'il y a un grand nombre d'objets. Pour seulement trois objets, il est peu probable que cela rapporte et ne simplifie certainement pas le code.

Volonté
la source
4
Je pense que la vraie question est assez simple, et cette réponse ne répond pas à cela. Si vous vouliez spéculer sur les questions plus profondes et non énoncées du PO qui devraient vraiment être faites comme un commentaire si vous ne répondez pas réellement à la question posée.
Je ne suis pas d'accord avec cela car invoquer une éventuelle optimisation prématurée n'est pas une réponse à un problème où l' optimisation explicite ne nuit ni à la lisibilité, ni à la maintenabilité du code, ni n'encourage les pratiques obscures. Lorsque vous pouvez réellement écrire du code simple et optimisé, pourquoi ne pas le faire? Cela ne fait certainement pas de mal de le faire, même si vous avez un plan de niveau supérieur (aucun développeur de jeux ne refusera jamais quelques microsecondes supplémentaires par image, en particulier sur les consoles).
teodron
@teodron: "Quand vous pouvez réellement écrire du code simple et optimisé, pourquoi ne pas le faire?" - Parce que OP (et maintenant, nous) a passé un temps non négligeable à optimiser quelque chose qui ne peut lui apporter aucun avantage.
BlueRaja - Danny Pflughoeft
@ BlueRaja-DannyPflughoeft Je suis d'accord avec cela pour être mineur (d'où une optimisation insignifiante si elle est utilisée pour quelques centaines d'appels par image, mais si le facteur de grandeur augmente à des milliers, les choses changent sûrement). Cependant, nous sommes tous libres de ne pas perdre de temps à essayer de répondre / optimiser quelque chose que nous jugeons non viable. Le PO a demandé une chose, les gens ont supposé que le PO n'était pas au courant des stratégies de niveau supérieur et des pratiques de profilage. Personnellement, je préfère faire de telles remarques dans les commentaires, pas dans les réponses. Désolé d'être si bavard :(.
teodron
-3

cela dépend de la sortie de la distance (v1, v2)

s'il s'agit d'une décimale (float ou double) sur un vecteur, il est probable que les distances au carré soient beaucoup plus rapides

RoughPlace
la source
5
Je ne vois pas ce que cela floata à voir avec quoi que ce soit.
MichaelHouse
je voulais dire un flotteur sur un autre vecteur tout simplement pas expliqué particulièrement bien (et je pense que vous le saviez)
RoughPlace
5
Je n'ai pas intentionnellement mal compris. Je ne sais toujours pas ce que tu veux dire. Je ne sais pas pourquoi une fonction de distance retournerait un vecteur.
MichaelHouse