![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|
|
|||||
|
Регистрация: Jan 2010
Сообщений: 32
|
Доброго времечка!
Бьюсь с одной проблемой, которую визуально можно описать так: 1. картинка (см. вложение) 2. красный контур -- спрайт вокруг которого нужно описать сиреневый спрайт 3. большой серый прямоуг -- это то состояние до которого нужно довести сиреневый спрайт чтобы он описал спрайт отмеченный красным контуром 4. сиреневый спрайт может быть как угодно повернут и трансформирован Хороший человек подсказал такой способ: Если отрисовать этот рект в системе координат purpleSprite, то он опишет redSprite. Прим.: Ниже в лайф-демке этот прямоуг обозначен круглыми маркерами и синими соединительными линиями. Вот заготовочка, чтобы попробовать, а главное форкнуть(!) это в живую: http://wonderfl.net/c/r6kr Прим.: Все основные манипуляции происходят в методе test(). В итоге: нужно пропорцильно(!) увеличить/уменьшить габариты purpleSprite чтобы он описал redSprite. С уважением и надеждой на помощь. |
|
|||||
|
Регистрация: Feb 2010
Адрес: Город суеты
Сообщений: 191
|
Пример testRect.swf.
Алгоритм: Проходим циклом по всем вершинам(точнее по двум соседним) красного прямоугольника, и опускаем перпендикуляр до ближайшего ребра фиолетового прямоугольника. Длина этого перпендикуляра - это та разница на которую надо увеличить соседнее(!!!) ребро фиолетового прямоугольника, так, что бы фиолетовый прямоугольник прошел через проверяемую вершину красного. Далее находим максимальный scale и применяем его к фиолетовому прямоугольнику. Вот как выглядит код: package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.MouseEvent; import ru.flashpress.geom.line.FPGLine2d; import ru.flashpress.geom.line.math.FPGLineToPoint2dMath; import ru.flashpress.geom.point.FPGPoint2d; import ru.flashpress.geom.polygon.FPGEdge2d; import ru.flashpress.geom.polygon.FPGPolygon2d; import ru.flashpress.geom.polygon.FPGVertex2d; [SWF(width="600", height="600")] public class testRect extends Sprite { private var redRect:Sprite; private var purpleRect:Sprite; private var grayRect:Sprite; private var polygonRed:FPGPolygon2d; private var polygonPurp:FPGPolygon2d; public function testRect() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; // var cx:Number = 300; var cy:Number = 300; var wRed:Number = 100; var hRed:Number = 200; var wPur:Number = 100; var hPur:Number = 150; // redRect = new Sprite(); redRect.graphics.lineStyle(1, 0xff0000, 1); redRect.graphics.drawRect(-wRed/2, -hRed/2, wRed, hRed); redRect.graphics.endFill(); this.addChild(redRect); redRect.x = cx; redRect.y = cy; // purpleRect = new Sprite(); purpleRect.graphics.lineStyle(1, 0xff00ff, 1); purpleRect.graphics.drawRect(-wPur/2, -hPur/2, wPur, hPur); purpleRect.graphics.endFill(); this.addChild(purpleRect); purpleRect.x = cx; purpleRect.y = cy; // grayRect = new Sprite(); grayRect.graphics.lineStyle(1, 0x999999, 1); grayRect.graphics.drawRect(-wPur/2, -hPur/2, wPur, hPur); grayRect.graphics.endFill(); this.addChild(grayRect); grayRect.x = cx; grayRect.y = cy; // var redPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>(); redPoints.push(new FPGPoint2d(cx-wRed/2, cy-hRed/2)); redPoints.push(new FPGPoint2d(cx+wRed/2, cy-hRed/2)); redPoints.push(new FPGPoint2d(cx+wRed/2, cy+hRed/2)); redPoints.push(new FPGPoint2d(cx-wRed/2, cy+hRed/2)); polygonRed = new FPGPolygon2d(redPoints); // var purpPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>(); purpPoints.push(new FPGPoint2d(cx-wPur/2, cy-hPur/2)); purpPoints.push(new FPGPoint2d(cx+wPur/2, cy-hPur/2)); purpPoints.push(new FPGPoint2d(cx+wPur/2, cy+hPur/2)); purpPoints.push(new FPGPoint2d(cx-wPur/2, cy+hPur/2)); polygonPurp = new FPGPolygon2d(purpPoints); // this.stage.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler); rotate(0); calculate(); } private function moveHandler(event:MouseEvent):void { event.updateAfterEvent(); var dx:Number = this.mouseX-purpleRect.x; var dy:Number = this.mouseY-purpleRect.y; var radians:Number = Math.atan2(dy, dx); rotate(radians); calculate(); } private var oldRotate:Number = 0; private function rotate(radians:Number):void { grayRect.rotation = purpleRect.rotation = radians*180/Math.PI; polygonPurp.rotation(radians-oldRotate, new FPGPoint2d(purpleRect.x, purpleRect.y)); oldRotate = radians; } private function calculate():void { var i:int; var j:int; var vertex:FPGVertex2d; var edge:FPGEdge2d; var heightLine:FPGLine2d; // var leftPoint:FPGVertex2d; var leftEdge:FPGEdge2d; var maxScale:Number = 1; for (i=0; i<polygonRed.vertexes.length; i++) { vertex = polygonRed.vertexes[i]; for (j=0; j<polygonPurp.edges.length; j++) { edge = polygonPurp.edges[j]; if (edge.valueFromPoint(vertex) <= 0) continue; heightLine = FPGLineToPoint2dMath.lineHeight(edge, vertex); // leftPoint = edge.p1 as FPGVertex2d; leftEdge = leftPoint.leftEdge; maxScale = Math.max(maxScale, (leftEdge.length+heightLine.length*2)/leftEdge.length); } } grayRect.scaleX = grayRect.scaleY = maxScale; } } }
__________________
FlashPress.ru | Blog Последний раз редактировалось maincode; 25.06.2013 в 16:42. |
|
|||||
|
Регистрация: Jan 2010
Сообщений: 32
|
В версии swc которая доступна для скачивания (http://flashpress.ru/projects/geom/2d/FPGeometry2d.swc), нет например класса FPGPolygon2d используемого в коде примера.
И повлияет ли на результат если "точка регистрации" спрайта будет не в центре, как в Вашем коде, а в левом верхнем углу? |
|
|||||
|
Регистрация: Feb 2010
Адрес: Город суеты
Сообщений: 191
|
Последняя версия (ru.flashpress.geom.FPAbout.VERSION = 0.1) лежит здесь http://flashpress.ru/blog/libs/ .
Если точка регистрации будет лежать не в центре, то мой пример работать не будет, надо поэкспериментировать, как будет время - допишу Добавлено через 21 час 53 минуты Дописал код так, что бы можно было вертеть объекты с точкой регистрации в левом верхнем углу: package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.MouseEvent; import ru.flashpress.geom.line.FPGLine2d; import ru.flashpress.geom.line.math.FPGLineToPoint2dMath; import ru.flashpress.geom.point.FPGPoint2d; import ru.flashpress.geom.polygon.FPGEdge2d; import ru.flashpress.geom.polygon.FPGPolygon2d; import ru.flashpress.geom.polygon.FPGVertex2d; [SWF(width="600", height="600")] public class testRect2 extends Sprite { private static const CENTER_X:Number = 300; private static const CENTER_Y:Number = 300; // private var redRect:Sprite; private var purpleRect:Sprite; private var grayRect:Sprite; private var polygonRed:FPGPolygon2d; private var polygonPurp:FPGPolygon2d; public function testRect2() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; // var wRed:Number = 100; var hRed:Number = 200; var wPur:Number = 100; var hPur:Number = 150; // redRect = new Sprite(); redRect.graphics.lineStyle(1, 0xff0000, 1); redRect.graphics.drawRect(0, 0, wRed, hRed); redRect.graphics.endFill(); this.addChild(redRect); redRect.x = CENTER_X-wRed/2; redRect.y = CENTER_Y-hRed/2; // purpleRect = new Sprite(); purpleRect.graphics.lineStyle(1, 0xff00ff, 1); purpleRect.graphics.drawRect(0, 0, wPur, hPur); purpleRect.graphics.endFill(); this.addChild(purpleRect); purpleRect.x = redRect.x + (redRect.width-purpleRect.width)/2; purpleRect.y = redRect.y + (redRect.height-purpleRect.height)/2; // grayRect = new Sprite(); grayRect.graphics.lineStyle(1, 0x999999, 1); grayRect.graphics.drawRect(0, 0, wPur, hPur); grayRect.graphics.endFill(); this.addChild(grayRect); // // создаем полигон красного прямоугольника var redPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>(); redPoints.push(new FPGPoint2d(CENTER_X-wRed/2, CENTER_Y-hRed/2)); redPoints.push(new FPGPoint2d(CENTER_X+wRed/2, CENTER_Y-hRed/2)); redPoints.push(new FPGPoint2d(CENTER_X+wRed/2, CENTER_Y+hRed/2)); redPoints.push(new FPGPoint2d(CENTER_X-wRed/2, CENTER_Y+hRed/2)); polygonRed = new FPGPolygon2d(redPoints); // // создаем полигон фиолетового прямоугольника var purpPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>(); purpPoints.push(new FPGPoint2d(CENTER_X-wPur/2, CENTER_Y-hPur/2)); purpPoints.push(new FPGPoint2d(CENTER_X+wPur/2, CENTER_Y-hPur/2)); purpPoints.push(new FPGPoint2d(CENTER_X+wPur/2, CENTER_Y+hPur/2)); purpPoints.push(new FPGPoint2d(CENTER_X-wPur/2, CENTER_Y+hPur/2)); polygonPurp = new FPGPolygon2d(purpPoints); // this.stage.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler); rotate(0); calculate(); } private function moveHandler(event:MouseEvent):void { event.updateAfterEvent(); var dx:Number = this.mouseX-purpleRect.x; var dy:Number = this.mouseY-purpleRect.y; var radians:Number = Math.atan2(dy, dx); rotate(radians); calculate(); } private var oldRotate:Number = 0; private function rotate(radians:Number):void { // поворачиваем филотетовый полигон относительно центральной точки CENTER_X-CENTER_Y // на угол равный разнице между текущим значением и предыдущим polygonPurp.rotation(radians-oldRotate, new FPGPoint2d(CENTER_X, CENTER_Y)); oldRotate = radians; // // // поворачиваем Displayobject-ы grayRect.rotation = purpleRect.rotation = radians*180/Math.PI; // задаем фиолетовому спрайту координаты смещения purpleRect.x = polygonPurp.vertexes[0].x; purpleRect.y = polygonPurp.vertexes[0].y; } private function calculate():void { var i:int; var j:int; var vertex:FPGVertex2d; var edge:FPGEdge2d; var heightLine:FPGLine2d; // var leftPoint:FPGVertex2d; var leftEdge:FPGEdge2d; var maxScale:Number = 1; for (i=0; i<polygonRed.vertexes.length; i++) { // текущая вершина красного полигона vertex = polygonRed.vertexes[i]; for (j=0; j<polygonPurp.edges.length; j++) { // текущее ребро фиолетового полигона edge = polygonPurp.edges[j]; // если вершина лежит "слева" от ребра, то пропускаем проверку // в случае прямоугольников если вершина лежит "слева" - // это значит что данное ребро не является наиближайщим к данной вершине if (edge.valueFromPoint(vertex) <= 0) continue; // получаем отрезок прямой опущенной из вершины на ребро heightLine = FPGLineToPoint2dMath.lineHeight(edge, vertex); // // определяем левую вершину ребра leftPoint = edge.p1 as FPGVertex2d; // определяем левое ребро // в итоге leftEdge будет ссылаться на ребро соседнее с edge leftEdge = leftPoint.leftEdge; // определяем максимальный scale // длина перпендикуляра heightLine умноженная на 2 - это то значение, // на которое надо увеличить соседнее ребро, // что бы фиолетовый прямоугольник прошел через текущую вершину maxScale = Math.max(maxScale, (leftEdge.length+heightLine.length*2)/leftEdge.length); } } // grayRect.scaleX = grayRect.scaleY = maxScale; // создаем копию фиолетового полигона var polygonClone:FPGPolygon2d = polygonPurp.clone(); // применяем к этому полигону scale относительно центральной точки polygonClone.scale(maxScale, maxScale, new FPGPoint2d(CENTER_X, CENTER_Y)); // и задаем увеличенному спрайту координаты смещения grayRect.x = polygonClone.vertexes[0].x; grayRect.y = polygonClone.vertexes[0].y; } } }
__________________
FlashPress.ru | Blog |
|
|||||
|
Регистрация: Jan 2010
Сообщений: 32
|
to maincode: Спасибо за наводку, которая помогла форкнуть мой же пример и получить требуемый результат http://wonderfl.net/c/37hj
Проблема решена, спасибо! |
![]() |
![]() |
Часовой пояс GMT +4, время: 20:15. |
|
|
« Предыдущая тема | Следующая тема » |
|
|