Найдите расстояние между двумя точками самым быстрым способом

Этот код вычисляет расстояние между двумя точками, используя формулу расстояния Math.sqrt ( (x1 – x2)^2 + (y1 – y2) ^2). Моя первая точка имеет координацию mmx и mmy, а вторая - координацию ox и oy. У меня простой вопрос: есть ли какой-нибудь БЫСТРЫЙ способ вычислить это?

private function dist(mmx:int, mmy:int, ox:int, oy:int):Number{
  return Math.sqrt((mmx-ox)*(mmx-ox)+(mmy-oy)*(mmy-oy));
}

Это мой код, спасибо за помощь.

public function moveIT(Xmouse, Ymouse):void{
            f = Point.distance( new Point( Xmouse, Ymouse ), new Point( mainSP.x, mainSP.y ) );// distance between mouse and instance 
            distancePro = Point.distance( pointO, new Point( mainSP.x, mainSP.y ) );// distance from start point 
            if (  f < strtSen ){ // move forward
                tt.stop(); tt.reset(); // delay timer on destination    
                mF = true;  mB = false;
                ag = Math.atan2((Ymouse - mainSP.y),(Xmouse - mainSP.x)); // move-forward angle, between mouse and instance
            }
            if (mF){ /// shoot loop
                if (f > 5){// 5 pixel
                    mainSP.x -= Math.round( (400 /f) + .5 ) * Math.cos(ag);
                    mainSP.y -= Math.round( (400 /f) + .5 ) * Math.sin(ag);
                }
                if (  distancePro > backSen ){// (backSen = max distance)
                    mF = false;         
                    tt.start();// delay timer on destination
                }
            }
            if (mB){ /// return loop
                if ( distancePro < 24 ){//  back angle re-calculation
                    agBACK = Math.atan2((y1 - mainSP.y),(x1 - mainSP.x));                   
                }
                mainSP.x += (Math.cos(agBACK) * rturnSpeed);
                mainSP.y += (Math.sin(agBACK) * rturnSpeed);
                if ( distancePro < 4 ){ // fix position to start point (x1,y1)
                    mB = false;
                    mainSP.x = x1; mainSP.y = y1;
                }
            }
        }
private function scTimer(evt:TimerEvent):void {// timer
            tt.stop();
            agBACK = Math.atan2((y1 - mainSP.y),(x1 - mainSP.x));// move-back angle between start point and instance
            mB = true;
        }

Также: pointO = new Point(x1,y1); установите начальную точку. Я не могу использовать mouseX и mouseY из-за того, что приложение вызывается родительским классом, поэтому я могу просто передать x и y в свой цикл.


person Katax Emperore    schedule 22.09.2011    source источник
comment
У меня такой же простой вопрос: определили ли вы, что скорость этого кода является проблемой?   -  person Oliver Charlesworth    schedule 22.09.2011
comment
.. хорошая мысль, я просто хочу знать, есть ли какой-нибудь другой метод. Например, специальная математическая формула или битовые вычисления над числами.   -  person Katax Emperore    schedule 22.09.2011
comment
Мое приложение похоже на интерактивное шоу в реальном времени с количеством экземпляров. Мне нужна хорошая скорость.   -  person Katax Emperore    schedule 22.09.2011
comment
Конечно. Но распространенная поговорка преждевременная оптимизация — это корень всех зол. Не пытайтесь оптимизировать часть кода, если вы не определили, что она составляет значительную часть вашего общего времени выполнения. Например, если это всего 1% вашего времени выполнения, в этом нет смысла.   -  person Oliver Charlesworth    schedule 22.09.2011
comment
@OliCharlesworth, я полностью с вами согласен, однако в этом случае важно достаточно хорошо знать API, чтобы не изобретать велосипед.   -  person zzzzBov    schedule 22.09.2011


Ответы (3)


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

private var sqrtFunc = Math.sqrt;

private function dist(mmx:int, mmy:int, ox:int, oy:int):Number{
    return sqrtFunc((mmx-ox)*(mmx-ox)+(mmy-oy)*(mmy-oy));
}
person Martin Epsz    schedule 22.09.2011
comment
Я спрошу то же самое, что и у @zzzzBov. Вы проверяли это? Я проверил это, и кажется, что таким образом добавляется около 15% накладных расходов на ссылку через переменную. Можете ли вы показать пример кода, который доказывает, что статическая функция дороже, чем разрешение функции через переменную? Более того, можете ли вы привести пример, доказывающий, что то, что вы сказали, правда? Мне жаль, что я так сильно бросаю вызов, но это второй ответ, который я видел в этой теме, который на самом деле был медленнее, чем то, что ОП просил ускорить. - person Brian Genisio; 24.09.2011
comment
Протестировал на какой-то старой версии флеш плеера. Возможно, в какой-то момент он изменился. Скоро еще раз протестирую и отпишусь здесь. - person Martin Epsz; 26.09.2011

Я думаю, что если вы встраиваете свою функцию вместо фактического вызова функции, это самый быстрый способ.

f = Math.sqrt((Xmouse-mainSP.x)*(Xmouse-mainSP.x)+(Ymouse-mainSP.y)*(Ymouse-mainSP.y)); 
distancePro = Math.sqrt((x1-mainSP.x)*(x1-mainSP.x)+(y1-mainSP.y)*(y1-mainSP.y));

Использование Point.distance НАМНОГО читабельнее, но в несколько раз медленнее. Если вам нужна скорость, вы хотите напрямую встроить свою математику.

person Brian Genisio    schedule 22.09.2011

Используйте Point.distance

d = Point.distance( new Point( x1, y1 ), new Point( x2, y2 ) );

Он будет выполняться в собственном коде, который обычно быстрее интерпретируемого кода.

Если вы находитесь в трехмерном пространстве, используйте Vector3D.distance

Если вы выполняете обнаружение столкновений, сравнивайте длины векторов (2D или 3D) довольно распространены и могут быть ресурсоемкими из-за использования функции sqrt. Если сравнить lengthSquared вместо этого он будет намного более производительным.

person zzzzBov    schedule 22.09.2011
comment
Вы в этом уверены? Я быстро вычислил время двух, и ваш оказался в 4 раза медленнее, чем OP. - person Brian Genisio; 22.09.2011
comment
@KataxEmperorKatax: Вы подтвердили, что это так? Я хотел бы, чтобы кто-нибудь сказал мне, что они это сделали, потому что, когда я тестировал его, я обнаружил, что этот ответ в 4 раза медленнее, чем тот, который вы пытаетесь оптимизировать. - person Brian Genisio; 22.09.2011
comment
@BrianGenisio - если у вас есть какие-либо идеи по оптимизации моей функции, пожалуйста, дайте мне знать .. : ] ,, - person Katax Emperore; 22.09.2011
comment
@KataxEmperorKatax: у меня нет лучшей идеи. Я думаю, что ваша исходная функция является наиболее эффективной. Но я измерил время вызова обеих этих функций по 10 000 раз каждую. В режиме отладки он в 4 раза быстрее, чем Point.distance, а в режиме выпуска — в 10 раз быстрее, чем Point.distance. - person Brian Genisio; 22.09.2011
comment
@ Брайан Генизио, когда вы проводили бенчмаркинг, включали ли вы создание экземпляров объектов Point? Создание большого количества новых объектов отрицательно скажется на бенчмаркинге, и, как правило, для больших наборов данных несколько объектов можно использовать повторно. - person zzzzBov; 22.09.2011
comment
@BrianGenisio - я проверю это снова, .. Теперь с Point.distance кажется более плавным, спасибо за внимание .. : ] ,, - person Katax Emperore; 22.09.2011
comment
@zzzzBov Ну, это не тот код, который у него есть ... он каждый раз обновляет объекты. В любом случае это не имеет значения. Накладные расходы на новые объекты Point не покрывают разницы. Математический способ ведения дел по-прежнему значительно быстрее, чем способ Point.distance. Вот код: gist.github.com/1233935 - person Brian Genisio; 22.09.2011
comment
@KataxEmperorKatax может быть более плавным, потому что ваша новая версия не выполняет вызов функции, а старая версия делала? (dist был описан как вызов функции, но в коде, который вы показываете, он встроен) В любом случае, мы говорим о 4 против 27 MILLIseconds для 10 000 выполнений. Сколько раз вы делаете это, что это имеет значение? - person Brian Genisio; 22.09.2011
comment
@ Брайан Дженизио. Он является частью stage.addEventListener(Event.ENTER_FRAME, FL); и всегда работает. Я думаю, как вы указываете, вызов функции делает это медленным. - person Katax Emperore; 22.09.2011
comment
@BrianGenisio - я использую f = Math.sqrt((Xmouse-mainSP.x)*(Xmouse-mainSP.x)+(Ymouse-mainSP.y)*(Ymouse-mainSP.y)); distancePro = Math.sqrt((x1-mainSP.x)*(x1-mainSP.x)+(y1-mainSP.y)*(y1-mainSP.y)); в своем цикле, он работает быстрее. Ваш пример был действительно полезен (gist.github.com/1233935). Спасибо. - person Katax Emperore; 22.09.2011