
Получение координаты точки после поворота. AS3
1
Я не очень силен в тригонометрии, поэтому постоянно приходится искать формулы или же готовые решения к моим проблемам. Будь то движение по окружности, движение к точки по радиусу и т.д.
Одна из таких давних проблем — как найти координату точки, после поворота объекта.

Не найдя решения на скорую руку, я обычно по средствам флеша, запихивал какой нибудь мувиклип внутрь нужного объекта и проверял уже его координаты. Но сейчас понадобилась именно формула.
В общем наткнулся на эту статью и написал функцию для получения координаты.
И так, чтобы получить новую координату точки в startPoint передаем координаты точки при начальном ее положении, то есть как бы она располагалась без поворота объекта ( Cx + Px1, Cy + Py1 ).
В centerPoint точку относительно которой было произведен поворот ( Cx, Cy ).
И в currentAngleRad угол на который был повернут объект в радианах.
Одна из таких давних проблем — как найти координату точки, после поворота объекта.

Не найдя решения на скорую руку, я обычно по средствам флеша, запихивал какой нибудь мувиклип внутрь нужного объекта и проверял уже его координаты. Но сейчас понадобилась именно формула.
В общем наткнулся на эту статью и написал функцию для получения координаты.
<br />
private function getNewPoint ( startPoint:Point, centerPoint:Point, currentAngleRad:Number ) :Point {
var endPoint:Point = new Point ();
startPoint = new Point ( startPoint.x - centerPoint.x, startPoint.y - centerPoint.y );
endPoint.x = startPoint.x * Math.cos( currentAngleRad ) - startPoint.y * Math.sin( currentAngleRad );
endPoint.y = startPoint.x * Math.sin( currentAngleRad) + startPoint.y * Math.cos( currentAngleRad );
endPoint.x += centerPoint.x;
endPoint.y += centerPoint.y;
return endPoint;
}
И так, чтобы получить новую координату точки в startPoint передаем координаты точки при начальном ее положении, то есть как бы она располагалась без поворота объекта ( Cx + Px1, Cy + Py1 ).
В centerPoint точку относительно которой было произведен поворот ( Cx, Cy ).
И в currentAngleRad угол на который был повернут объект в радианах.
- +6
- Nrjwolf
Комментарии (20)
кстати, в некоторых случаях, при получении необходимого угла для передачи в аргументы можно брать угол поворота у контейнера:
где container — это спрайт, который вы поворачиваете
Во-первых, «никакой тригонометрии» — это ты пошутил :) она есть, внутри метода rotate()
Во-вторых, даже если вынести mx в поле класса, у тебя все равно создается новый объект Point при вызове метода transformPoint. И от этого никак не избавиться (привет тормозному Adobe, который никак не научится передавать необязательную ссылку на объект-результат).
Если добавить обязательный (хороший тон да) для таких функций необязательный (пардон за каламбур) параметр endPoint в оба ваших варианта и провести тест, то выяснится, что вариант автора работает как минимум вдвое, а то и почти втрое быстрей.
Код.
У меня выводит что-то такое:
39 110
42 109
43 107
Так то все верно вы с кроликом говорите и про переиспользование матриц и про тригонометрию внутри
Однако твой вариант тоже показателен. По правде сказать, первый вариант выигрывает лишь в нетипичной задаче «поворот тысяч произвольных точек вокруг тысяч произвольных центров на тысячи произвольных углов» или в случае с парой-тройкой точек. На практике же матрицу, которая присутствует в твоем варианте, мы готовим один раз для целой группы точек. Тот же поворот квада аннулирует сразу три вызова троицы «translate-rotate-translate» (а ведь сюда еще может добавиться и scale, и skew). Ну и последним гвоздем относительно первого варианта может стать кастомный класс матрицы, которая таки умеет в метод transformPoint получать не только точку, подлежащую трансформации, но и точку, в которую мы запишем результат. В таком случае в полевых условиях подход как у автора потерпит фиаско.
Вот так все непросто :)
з.ы. навскидку еще приходит в голову третий вариант, использовать Point.polar(), который тоже позволяет «на центрах вертеть» какую-нибудь точку. Только применимо к задаче автора к входному углу надо будет добавлять угол стартовой точки.
это пипец :) Да еще и в EnterFrame???
для таких случаев придумали indentity(); у матрицы, чтоб не создавать каждый раз новый объект.
Если из Point ничего кроме x/y не используется — рекомендую создать свой класс из 2х полей x/y для экономии памяти + снижения обращений к GC (если это в EnterFrame все).
Да и вообще в релиз советую «разворачивать» руками такие методы в точку вызова. А в идеале инлийн использовать.
А inline разве есть в as3? Вручную же разворачивать — путь к проблемам с поддержкой кода.
Что касается сборщика мусора — дело не в том. Он соберет его качественно. Но если мусора будет много — то приостановит runtime до завершения цикла сборки. И многие тормоза вызываются уже не тем, что проц слабый, а тем, что слишком много мусора для GC наплодилось
На самом деле с управляемым кодом выделение памяти может быть очень быстрым, гораздо быстрее чем стандартное выделение памяти на куче в с/с++. По сути это может быть просто return nextFreePtr; nextFreePtr += sizeof(newObject); Да, память будет фрагментироваться, но при очередном проходе сборщика мусора ее можно дефрагментировать.
Ну и в нативном коде на c++ никто не мешает написать custom allocator, и прекрасно пользоваться дальше new/delete не теряя ни производительности, ни удобства написания кода.
А вообще, прошу прощения за холиварность моего комментария.
Никто же не жалуется на то, что Nape самый быстрый среди 2D физики для Flash :) Все радуются этому гениальному движку. Который как раз и разрабатывался с учетом специфики AVM :) Он с ней считался — он получился лидером )
Без препроцессора он не смог бы реализовать в бородатые годы банальный инлайн. Просто в то время не мог стандартный флешовый компилятор сделать то, что он задумал.
И заметь — это все не отменяет правил и рекомендаций по работе с виртуальной машиной флеш плеера. Haxe ничего нового не вписывал в swf файл, чего небыло во флеш плеере.