Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Алгоритм поворота объекта маркером относительно точки (http://www.flasher.ru/forum/showthread.php?t=146622)

FieryWall 13.11.2010 11:32

Алгоритм поворота объекта маркером относительно точки
 
Здравствуйте уважаемые as программисты. Такой вопрос: какой обычно применяют алгоритм поворота объекта угловым маркером вокруг заданной точки, как например это реализовано в инструменте Free Transform Tool .fla файла?

medvedya2 13.11.2010 12:02

если я правильно понял.
mtx и mty точка относительно которой вращать
angle угол в радианнах
Код AS3:

        graphic.rotation=angle * 180 / Math.PI;
                                x1=(graphic.x-mtx)*Math.cos(angle)-(graphic.y-mty)*Math.sin(angle)+mtx;
                                y1=(graphic.x-mtx)*Math.sin(angle)+(graphic.y-mty)*Math.cos(angle)+mty;
                                graphic.x=x1;
                                graphic.y=y1;

Напишите по понятней что должно получиться.

FieryWall 13.11.2010 13:17

Вот такое надо реализовать
http://xmages.net/storage/10/1/0/5/0...d/1df0b51c.jpg
если бы точка трансформации стояла в центре - то квадрат вращался бы вокруг своей оси

samana 13.11.2010 15:16

Может поможет такой вариант. Тут создаётся прямоугольник, который постоянно крутиться, а клик по сцене - задаёт новую точку вокруг которой он будет крутится.
Код AS3:

package 
{
        import fl.motion.MatrixTransformer;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Matrix;
        import flash.geom.Point;
 
        /**
        * ...
        * @author Samana
        */

        public class Main extends Sprite
        {
                //точка трансформации для mc
                private var center:Point = new Point(300, 300);
                //матрица
                private var matrix:Matrix = new Matrix();
                //угол на который будет поворачиваться mc
                private var ang:Number = 3;
                //сам спрайт mc
                private var mc:Sprite;
 
                public function Main():void
                {
                        //нарисовал спрайт прямоугольник
                        mc = new Sprite();
                        mc.graphics.beginFill(0x00FFcc);
                        mc.graphics.drawRect(0, 0, 150, 80);
                        mc.graphics.endFill();
                        //передвинул сюда
                        mc.x = 300;
                        mc.y = 300;
 
                        addChild(mc);
 
                        stage.addEventListener(MouseEvent.CLICK, newPoint)
                        stage.addEventListener(Event.ENTER_FRAME,rotate)
                }
                private function newPoint(e:MouseEvent):void
                {
                        //новая точка трансформации для поворота
                        center.x = mouseX;
                        center.y = mouseY;
                }
 
                private function rotate(e:Event):void
                {
                        //беру текущую матрицу mc
                        matrix = mc.transform.matrix;
                        //задаю нувую точку для поворота матрицы, и угол
                        MatrixTransformer.rotateAroundExternalPoint(matrix, center.x, center.y, ang);
                        //применяю изменившуюся матрицу к mc
                        mc.transform.matrix = matrix;
                }
        }
}


Wolsh 13.11.2010 15:57

Алгоритм прост.
Код AS3:

package  ru.wolsh.display
{
        import flash.display.DisplayObject;
        import flash.geom.Point;
 
/* * * * * * * * * *
*                  *
*  @author wolsh  *
*                  *
\* * * * * * * * * */

        public function pointRotate (object:DisplayObject, center:Point, angle:Number) : void
        {
                var ra:Number = angle * Math.PI / 180;
 
                var dX:Number = center.x - object.x;
                var dY:Number = center.y - object.y;
 
                var dg:Number = Math.sqrt(dX * dX + dY * dY);
                var da:Number = Math.asin(dX / dg);
 
                object.rotation = angle;
 
                object.x = center.x - dg * Math.sin(da - ra);
                object.y = center.y - dg * Math.cos(da - ra);
        }
}


-De- 13.11.2010 16:12

Wolsh, то же, что и в 2, только хуже. Например из-за Math.asin(dX / dg)

Wolsh 13.11.2010 19:29

Согласен. Тогда так
Код AS3:

package  ru.wolsh.display
{
        import flash.display.DisplayObject;
        import flash.geom.Point;
 
/* * * * * * * * * *
*                  *
*  @author wolsh  *
*                  *
\* * * * * * * * * */

        public function pointRotate (object:DisplayObject, center:Point, angle:Number) : void
        {
                var r:Number = angle * Math.PI / 180;
                var s:Number = Math.sin(r);
                var c:Number = Math.cos(r);
                var dX:Number = object.x - center.x;
                var dY:Number = object.y - center.y;
 
                object.rotation = angle;
                object.x = center.x + dX * c - dY * s;
                object.y = center.y + dX * s + dY * c;
        }
}


FieryWall 13.11.2010 21:48

А можете пожалуйста прокомментировать? Я практик, мне надо, очень надо :umnik2:

-De- 13.11.2010 22:08

Ваш ВУЗ гуманитарный? Матрицы поворота должны на 2-м курсе проходить.
А так - гуглить преобразование поворота, матрицы поворота, аффинные преобразования.
Тут только аккуратное их применение. Начала аналита ж.

FieryWall 13.11.2010 22:31

Цитата:

Сообщение от -De- (Сообщение 949608)
Ваш ВУЗ гуманитарный? Матрицы поворота должны на 2-м курсе проходить.
А так - гуглить преобразование поворота, матрицы поворота, аффинные преобразования.
Тут только аккуратное их применение. Начала аналита ж.

Вы абсолютно правы))) Я как раз на втором курсе :rolleyes:

Добавлено через 2 часа 8 минут
Мне как бы надо что бы для поворота надо было градус курсора относительно Point, т.е. градус объекта равен градус курсора. А в ваших примерах используется значение на которое изменяется градус объекта, это не подходит для реализации такого поворота.

bav 14.11.2010 01:29

Позвольте оффтопик: FieryWall, ради всего святого, полужирное начертание шрифта не предназначено для набора абзацев.

FieryWall 14.11.2010 01:39

Извинтиляюсь :D

8exe8 14.11.2010 18:02

Скажите, а с текстом такое можно делать и если нужно сделать анимацию перемещения при нажатии на кнопку, причем две разные кнопки и перемещение в две разные точки то как? или даже при нажатии на одну кнопку делать допустим размытие, а при нажатии на другую уменьшение и перемещение

FieryWall 14.11.2010 18:05

Если текст не динамичен то его можно зарекомендовать как Мувик и проделать с ним подобное :confused:

Добавлено через 5 минут
Цитата:

Сообщение от Wolsh (Сообщение 949553)
Алгоритм прост.
Код AS3:

package  ru.wolsh.display
{
        import flash.display.DisplayObject;
        import flash.geom.Point;
 
/* * * * * * * * * *
*                  *
*  @author wolsh  *
*                  *
\* * * * * * * * * */

        public function pointRotate (object:DisplayObject, center:Point, angle:Number) : void
        {
                var ra:Number = angle * Math.PI / 180;
 
                var dX:Number = center.x - object.x;
                var dY:Number = center.y - object.y;
 
                var dg:Number = Math.sqrt(dX * dX + dY * dY);
                var da:Number = Math.asin(dX / dg);
 
                object.rotation = angle;
 
                object.x = center.x - dg * Math.sin(da - ra);
                object.y = center.y - dg * Math.cos(da - ra);
        }
}


То как это реализовать? У меня объект летает вокруг Point-а как бешеный!!! :eek:

samana 14.11.2010 19:49

А почему вам не подошел этот способ?
obj-объект который нужно повернуть
point-относительно какой точки
angle-на сколько градусов, относительно текущего поворота.
Код AS3:

public function rotate(obj:DisplayObject,point:Point,angle:Number):void 
                {
                        var matrix:Matrix = obj.transform.matrix;
                        MatrixTransformer.rotateAroundExternalPoint(matrix, point.x, point.y, angle);
                        obj.transform.matrix = matrix;
                }


OFFmind 14.11.2010 20:27

Может оффтопик:

Почему бы не использовать класс TransformTool от senocular. Это если важен только результат, а не сам принцип... просто сам недавно сталкивался с подобной проблемой, используя этот можно в Runtime изменять объект как в стандартом Flash редакторе.

А для поворота при нажатии кнопки идеально подходит TweenLite.

Еще раз извините, если это офф-топ, и тут главное - реализовать своими руками)))

FieryWall 14.11.2010 21:38

Цитата:

Сообщение от samana (Сообщение 949724)
А почему вам не подошел этот способ?
obj-объект который нужно повернуть
point-относительно какой точки
angle-на сколько градусов, относительно текущего поворота.
Код AS3:

public function rotate(obj:DisplayObject,point:Point,angle:Number):void 
                {
                        var matrix:Matrix = obj.transform.matrix;
                        MatrixTransformer.rotateAroundExternalPoint(matrix, point.x, point.y, angle);
                        obj.transform.matrix = matrix;
                }


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

8exe8 14.11.2010 22:40

Цитата:

Сообщение от FieryWall (Сообщение 949708)
Если текст не динамичен то его можно зарекомендовать как Мувик и проделать с ним подобное :confused:

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

mikhailk 15.11.2010 13:41

чтобы динамическое текстовое поле можно было вращать, надо заэмбедить в него шрифт.

Цитата:

Потому что у вас объект сам крутиться вокруг точки, и ему нет дела до того в какой позиции он должен находиться, просто идет постоянное, динамическое, однотонное, добавление angle
Ну да.
Надо передавать в эту функцию изменение угла, а не сам угол.

Можно сделать проще. При размещении объекта на сцене ставить его в спрайте-оболочке. При необходимости повернуть фигуру относительно некоторой точки сдвигаем туда этот спрайт и параллельно фигуру внутри спрайта (чтобы фигура осталась на месте). После этого привязываем rotation этого спрайта к поступающему углу и все прекрасно крутится.

FieryWall 15.11.2010 20:18

Как раз поступающий угол и тяжело выяснить :wacko:

mikhailk 15.11.2010 21:18

а откуда он поступает?
рукоятку крутите?

FieryWall 15.11.2010 21:40

Именно, и градус объекта относительно точки должен быть равен градусу курсора относительно той же точки

i.o. 15.11.2010 21:46

что-то мне подсказывает, что все идет к Math.atan2()

mikhailk 15.11.2010 21:46

а саму рукоятку сделать-то удалось?
потому что если удалось, то снимать угол можно с нее
а если не удалось, то решите сначала эту задачу - когда сможете показать рукоятку, угол получите автоматически

FieryWall 15.11.2010 21:54

Собственно такой код (демо) с некоторыми результатами (отдельное спасибо другим as-программистам:drinks:). Все что осталось - корректный поворот вокруг точки на заданном радиусе и указать точку поворота самого object в его центре:
Код AS3:

package {
        import flash.display.Sprite;
        import flash.display.DisplayObject;
        import flash.events.MouseEvent;
        import flash.geom.Point;
        public class Main extends Sprite {
                var pot:Sprite;
                var rect:Sprite;
                var rec:Sprite;
                var point:Point;
                var save1:Point=new Point(0,0);
                var save2:Point=new Point(0,0);;
                var angle:Number;
                public function Main() {
                        rect=new Sprite();
                        rect.graphics.lineStyle(1);
                        rect.graphics.drawRect(0,0,100,100);
                        rec=new Sprite();
                        rec.graphics.beginFill(0x000000);
                        rec.graphics.drawRect(-5,-5,10,10);
                        addChild(rect);
                        rect.addChild(rec);
                        rect.x=300;
                        rect.y=170;
 
                        point=new Point(100,100);
                        pot=new Sprite;
                        pot.graphics.beginFill(0xFF0000);
                        pot.graphics.drawRect(-5,-5,10,10);
                        addChild(pot);
                        pot.x=point.x;
                        pot.y=point.y;
 
                        pot.addEventListener(MouseEvent.MOUSE_DOWN, potDownListener);
                        pot.addEventListener(MouseEvent.MOUSE_UP, potUpListener);
 
                        rec.addEventListener(MouseEvent.MOUSE_DOWN, onRecDown);
                        stage.addEventListener(MouseEvent.MOUSE_UP, onRecUp);
                }
                private function potDownListener(event:MouseEvent):void{
                        pot.startDrag(false);
                }
                private function potUpListener(event:MouseEvent):void{
                        point.x=pot.x;
                        point.y=pot.y;
                        pot.stopDrag();
                }
 
                private function onRecDown(event:MouseEvent):void{
                        rect.startDrag(false);
                        save1.x=mouseX;
                        save1.y=mouseY;
                        addEventListener(MouseEvent.MOUSE_MOVE, onRecMove);
                }
                private function onRecMove(event:MouseEvent):void{
                        save2.x = mouseX;
                        save2.y = mouseY;
                        var p01:Point = save1.clone().subtract(point);//01 - значит вектор от точки 0 к точке 1
                        var p02:Point = save2.clone().subtract(point);
                        var modul01:Number = p01.length;
                        var modul02:Number = p02.length;
                        var a:Number = Math.atan2(
                                (p01.x * p02.y - p02.x * p01.y) / (modul01 * modul02),
                                (p01.x * p02.x + p01.y * p02.y) / (modul01 * modul02)
                        );
                        angle=a * 180 / Math.PI;
                        rect.rotation=angle;
                }
 
                private function onRecUp(event:MouseEvent):void{
                        rect.stopDrag();
                        removeEventListener(MouseEvent.MOUSE_MOVE, onRecMove);
                }
        }
}

Добавлено через 13 минут
Цитата:

Сообщение от OFFmind (Сообщение 949730)
Может оффтопик:

Почему бы не использовать класс TransformTool от senocular. Это если важен только результат, а не сам принцип... просто сам недавно сталкивался с подобной проблемой, используя этот можно в Runtime изменять объект как в стандартом Flash редакторе.

А для поворота при нажатии кнопки идеально подходит TweenLite.

Еще раз извините, если это офф-топ, и тут главное - реализовать своими руками)))

И как эти классы включить в RunTime ?

-De- 15.11.2010 22:56

"/ (modul01 * modul02)" - не надо, если длины катетов вырастут в одинаковое число раз, то углы в тр-ке не изменятся.
И я таки считаю, что нефик студенту помогать, если что из математики и пригодится после армии, то это вот эта геометрия.
И почему тупо от прошлого угла новый угол не отнимать? Вродь попроще.
Код AS3:

package {
        import flash.display.Sprite;
        import flash.display.DisplayObject;
        import flash.events.MouseEvent;
        import flash.geom.Point;
        public class Main extends Sprite {
                public var pot:Sprite;
                public var rect:Sprite;
                public var rec:Sprite;
                public var point:Point;
                public var saveRot1:Number = 0;//rotation
                public var saveRot2:Number = 0;//baseAngle
                public var saveRot3:Number = 0;//newAngle
 
                public function Main() {
                        rect=new Sprite();
                        rect.graphics.lineStyle(1);
                        rect.graphics.drawRect(0,0,100,100);
                        rec=new Sprite();
                        rec.graphics.beginFill(0x000000);
                        rec.graphics.drawRect(-5,-5,10,10);
                        addChild(rect);
                        rect.addChild(rec);
                        rect.x=300;
                        rect.y=170;
 
                        point=new Point(100,100);
                        pot=new Sprite;
                        pot.graphics.beginFill(0xFF0000);
                        pot.graphics.drawRect(-5,-5,10,10);
                        addChild(pot);
                        pot.x=point.x;
                        pot.y=point.y;
 
                        pot.addEventListener(MouseEvent.MOUSE_DOWN, potDownListener);
                        pot.addEventListener(MouseEvent.MOUSE_UP, potUpListener);
 
                        rec.addEventListener(MouseEvent.MOUSE_DOWN, onRecDown);
                        stage.addEventListener(MouseEvent.MOUSE_UP, onRecUp);
                        saveRot2 = Math.atan2(rect.y - pot.y, rect.x - pot.x);
                }
                private function potDownListener(event:MouseEvent):void {
                        pot.startDrag(false);
                        saveRot1 = saveRot1 + saveRot3;
                }
                private function potUpListener(event:MouseEvent):void{
                        saveRot2 = Math.atan2(rect.y - pot.y, rect.x - pot.x);
                        pot.stopDrag();
                }
 
                private function onRecDown(event:MouseEvent):void{
                        rect.startDrag(false);
                        addEventListener(MouseEvent.MOUSE_MOVE, onRecMove);
                }
                private function onRecMove(event:MouseEvent):void{
                        saveRot3 = Math.atan2(mouseY - pot.y, mouseX - pot.x) - saveRot2;
                        rect.rotation = (saveRot1 + saveRot3) * 180 / Math.PI;
                }
 
                private function onRecUp(event:MouseEvent):void{
                        rect.stopDrag();
                        removeEventListener(MouseEvent.MOUSE_MOVE, onRecMove);
                }
        }
}


FieryWall 19.11.2010 00:59

Всем опять привет!!
Решил я єту задачу, вот такая значит там основная система:
Объект является чилдом спрайта который в свою очередь является чилдом еще одного спрайта, точка поворота - центр основного спрайта, и вложенный спрайт с объектом вращается только относительно ее. Объект в дополнительном спрайте, на случай если с ним нужно что нибудь сделать, типа Трансформации.
Может возникнуть проблема относительно переноса точки поворота, в этом случаи нужно на момент перетаскивания точки сохранить размещение вложенного спрайта в глобальном контейнере (относительно основной оси координат) с помощью localToGlobal, и возвращать его значение уже в главном контейнере с помощью globalToLocal соответственно.
Простите что нету кода, с классами я еще работать не научился и весь код у меня в одном классе, а там очень много не по теме.
Всем спасибо за помощ :drinks:

makanmel 19.11.2010 21:47

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

Использую TransformTool для поворота объектов в редакторе на любой угол.
Также мне нужно вращать отдельной кнопкой по 90 градусов (относительно центра). Пробую задавать напрямую объекту rotation но тогда сетка TransformTool "съезжает".

Код AS3:

selectedElement.transformX = selectedElement.width / 2;
selectedElement.transformY = selectedElement.height / 2;
selectedElement.rotation += 90;
SelectElement(selectedElement);

http://i52.tinypic.com/5v8xty.jpg

Как лучше сделать? Может вызывать TransformTool.toolMatrix.rotate()?


Часовой пояс GMT +4, время: 01:05.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.