Можно ли упростить неравенство «расстояние (p1, p2) <расстояние (p1, p3)?»

14

Я работаю над некоторой векторной логикой, поэтому спрашиваю: могу ли я сэкономить время процессора, упростив это неравенство:

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

Я вижу, что vector1это повторяется в обоих случаях.

Филипп Димитровский
источник
10
Просто быстрое примечание: ваш текущий метод очень удобочитаем, и его функция может быть мгновенно понята. Некоторые из этих ответов могут выполнить задание, которое вы просили, но гораздо менее ясно. Это хорошо, если производительность имеет существенное значение, но обязательно прокомментируйте ее правильно, чтобы учесть потерю ясности.
MikeS
3
Чтобы продолжить комментарий @ MikeS, производительность должна иметь существенное значение только в таких случаях, если вы уже провели анализ или профилирование и определили этот вызов как узкое место. Если мы говорим о разнице между 305fps и 303fps, удобство обслуживания превосходит исходную производительность.
Phoshi

Ответы:

24

Да , вы можете упростить это. Во-первых, перестань называть их векторами. Это очки. Давайте назовем их A, Bи C.

Итак, вы хотите это:

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

Замените расстояния квадратами расстояний, а затем точечными произведениями (из определения евклидовой длины . Замените ACна AB + BC(теперь это реальные векторы). Разверните, упростите, множите:

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)

Вот ты где:

dot(AB + AC, BC) > 0

С вашей векторной нотацией:

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

Это несколько дополнений и один точечный продукт вместо двух предыдущих.

Сэм Хоцевар
источник
Можете ли вы объяснить, как вы можете заменить a a + b b = a a + c c версией точечного продукта?
TravisG
2
@TravisG Я не уверен в том, что вы спрашиваете. Если ваш вопрос, почему так dist(A, B)²же, как dot(AB, AB)это, это происходит из самого определения евклидовой длины .
Сэм Хочевар
2
Ясно, что это (несколько) математически упрощает уравнение, но не обязательно «экономит время процессора» для OP. Это приводит к большей сложности и большему количеству вычислений, чем просто удаление квадратного корня из исходных уравнений расстояния.
MichaelHouse
1
Поправьте меня, если я ошибаюсь, но два точечных произведения - это 5 операций на одно точечное произведение плюс два вычитания vec3, что в сумме составляет 16 операций, ваш путь имеет 3 вычитания vec3 плюс сложение, которое составляет 12 операций плюс произведение точек делает 17.
Луис W
2
Интересно, что результатом является скалярное произведение двух противоположных диагоналей параллелограмма. Но это не имеет значения. То, что я хотел сказать, - это то, что от этого полного упрощения нельзя получить огромную сумму ; как уже упоминали другие, это делает приличное количество, чтобы запутать или усложнить то, что вы на самом деле пытаетесь вычислить. Тем не менее, вы определенно хотите использовать первый шаг. Избегать ненужного квадратного корня всегда стоит. Простое сравнение квадратов расстояний одинаково, так как расстояние положительно определено даже в комплексной плоскости.
TASagent
16

Да. Предполагая, что ваша distanceфункция использует квадратный корень, вы можете упростить это, удалив квадратный корень.

При попытке найти большее (или меньшее) расстояние x^2 > y^2все равно остается в силе x > y.

Однако дальнейшие попытки математически упростить уравнение, скорее всего, бессмысленны. Расстояние между vector1и vector2не совпадает с расстоянием между vector1и vector3. Хотя уравнение может быть упрощено математически, как показывает ответ Сэма , форма, в которой оно находится в настоящее время, вероятно, будет такой же простой, как вы получите с точки зрения использования процессора.

MichaelHouse
источник
Мне не хватает повторений, но я бы сказал, что это в корне неверно: «Могу ли я сэкономить время процессора, упростив это неравенство?» Ответ - да.
Я так растерялся,
Ответ только да, если в уравнении расстояния используется квадратный корень. Который я упоминаю.
MichaelHouse
Допустимый момент, я бы отказался от своего заявления. Тем не менее, на 99% гарантируется, что пользователь имеет в виду евклидово расстояние sqrt (сумма (размерная разность в квадрате))
замешательстве
@imsoconfused Справедливо, я изменил порядок своего ответа, чтобы сначала сформулировать наиболее вероятный (99%) сценарий.
MichaelHouse
2
Да, мой опыт показывает, что когда вы работаете с такими вещами, функция DistanceSquared очень полезна. Это так же ясно и позволяет избежать дорогостоящей операции sqrt.
Лорен Печтел
0

Некоторые математики могут помочь.

То, что вы пытаетесь сделать, это:

<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

Из чего можно удалить повторяющиеся переменные и сгруппировать некоторые другие. Операция, которую вы должны проверить:

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

Надеюсь, это поможет.

j4nSolo
источник
-1

Похоже, реальный вопрос заключается в том, как уменьшить количество вычислений для определения ближайшего объекта?

Оптимизация этого часто делается в играх, хотя при всех оптимизациях она должна быть ориентирована на профиль и часто не упрощает вещи.

Способ избежать ненужных вычислений расстояния для определения ближайшего объекта - или всех объектов в определенном диапазоне - состоит в использовании пространственного индекса, например, октодерева .

Это окупается только при наличии большого количества объектов. Всего три объекта вряд ли окупятся и, конечно, не упростят код.

Будет
источник
4
Я думаю, что настоящий вопрос довольно прост, и этот ответ не касается этого. Если вы хотите поразмышлять о более глубоких, неустановленных вопросах ОП, которые действительно следует сделать в качестве комментария, если вы не собираетесь фактически ответить на заданный вопрос.
Я опровергаю это, потому что вызов возможной преждевременной оптимизации не является решением проблемы, когда явная оптимизация не вредит ни читабельности, ни поддерживаемости кода, ни поощряет неясные практики. Если вы действительно можете написать простой и оптимизированный код, почему бы не сделать это? Конечно, это не помешает, даже если у вас план более высокого уровня (ни один разработчик игры никогда не откажется от дополнительных микросекунд на кадр, особенно на консолях).
Теодрон
@teodron: «Когда вы действительно можете написать простой и оптимизированный код, почему бы не сделать это?» - Потому что ОП (а теперь и мы) потратили немало времени на оптимизацию чего-то, что может не дать ему никакой выгоды.
BlueRaja - Дэнни Пфлугхофт
@ BlueRaja-DannyPflughoeft Я согласен с этим, чтобы быть незначительным (следовательно, незначительная оптимизация, если используется для нескольких сотен вызовов на кадр, но если множитель увеличивается до тысяч, вещи, безусловно, изменятся). Тем не менее, мы все свободны, не теряя времени, пытаясь ответить / оптимизировать то, что мы считаем нецелесообразным. ФП спросил одну вещь, люди предположили, что ФП не знал о стратегиях более высокого уровня и методах профилирования. Я лично предпочитаю делать такие замечания в комментариях, а не в ответах. Извините, что так многословен :(.
Теодрон
-3

это зависит от того, что вывод расстояния (v1, v2)

если это десятичное число (число с плавающей запятой или двойное число) над вектором, вполне вероятно, что квадрат расстояний будет намного быстрее

RoughPlace
источник
5
Я не понимаю, какое это floatимеет отношение к чему-либо.
MichaelHouse
я имел в виду плавание над другим вектором, просто не очень хорошо объясненным (и я думаю, что вы это знали)
RoughPlace
5
Я не был намеренно недоразумением. Я все еще не уверен, что вы имеете в виду. Я не знаю, почему функция расстояния будет возвращать вектор.
MichaelHouse