2
votes

Stuck again... I am trying to adapt the rotate()code at bottom so that the rotation is absolute i.e. rotate(33) rotates to that angle not by that number of degrees.

And I am failing. My attempt is below. I thought I would be able to just set the rotation once the matrix had been translated but that does nothing. Trying to read up on Matrices is making my head explode. Is there a simple thing I am missing here?

        public function myRotate(angle:Number):void
        {
            trace("angle", angle);

            var m:Matrix = this.transform.matrix;
            var aroundPoint:Point = resetCenterPoint(this, this.width/2, this.height/2);
            var cm:Matrix = new Matrix(1, 0, 0, 1, -aroundPoint.x, -aroundPoint.y);
            m.concat(cm);

            // I thought I could apply the matrix to shift the reg point, 
            // set the absolute rotation
            // then use that matrix for when it gets shifted back
            // but it doesn't work.

            this.transform.matrix = m;
            this.rotation = angle;
            m = this.transform.matrix;

            //m.rotate(Math.PI * angle / 180);

            var rcm:Matrix = new Matrix(1, 0, 0, 1, aroundPoint.x, aroundPoint.y);
            m.concat(rcm);
            this.transform.matrix = m;
        }

This code works great but the rotations are relative (i.e. cumulative).

        public function rotate(angle:Number):void
        {
            var m:Matrix = this.transform.matrix;
            var aroundPoint:Point = resetCenterPoint(this, this.width/2, this.height/2);
            var cm:Matrix = new Matrix(1, 0, 0, 1, -aroundPoint.x, -aroundPoint.y);
            m.concat(cm);

            m.rotate(Math.PI * angle / 180);

            var rcm:Matrix = new Matrix(1, 0, 0, 1, aroundPoint.x, aroundPoint.y);
            m.concat(rcm);
            this.transform.matrix = m;
        }

        private function resetCenterPoint(obj:DisplayObject, orgX:Number, orgY:Number):Point
        {
            var m:Matrix = obj.transform.matrix;
            var orgXY:Point = m.deltaTransformPoint(new Point(orgX, orgY));
            orgXY.x += m.tx;
            orgXY.y += m.ty;
            return orgXY;
        }
1
What if you turn the relative function into an absolute one by passing "target angle value" - "current angle value" to it? So the absolute rotation function is just a wrapper to the relative one. I'm not sure if this should be a comment or an answer.null
@null ... Yes, I am an idiot (or allegedly math-phobic or just tired). var newAngle:Number = angle - this.rotation; seems to calculate the proper relative angle based on the angle specified. Post as an answer if you want the points.spring

1 Answers

0
votes

It's possible to turn the relative function into an absolute one, by modifying the argument.

instead of rotate(relativeAngle), one can call rotate(absoluteAngle - currentAngle)

However, there are problems in your code. I tried it and it does not work "great" for me. I have no compiler installed and had to use wonderfl. When I run the code, I can see the shape "drifting" out of position. Additionally it's rotating around some point but not the middle/registration point of the shape.

package {
    import flash.display.Sprite;
    import flash.events.Event;
    public class FlashTest extends Sprite {
        public function FlashTest() {
            // write as3 code here..

            var r:Rotator = new Rotator();
            addChild(r);

            r.x = r.y = 200;

            addEventListener(Event.ENTER_FRAME, function(e:Event):void{r.rotate(1)});
        }
    }
}
import flash.display.Shape;
import flash.display.DisplayObject;

import flash.geom.Matrix;
import flash.geom.Point;

internal class Rotator extends Shape
{
    public function Rotator()
    {
        graphics.beginFill(0xff00);
        graphics.drawRect(-50, -100, 100, 200);
        graphics.endFill();
    }

    public function rotate(angle:Number):void
        {
            var m:Matrix = this.transform.matrix;
            var aroundPoint:Point = resetCenterPoint(this, this.width/2, this.height/2);
            var cm:Matrix = new Matrix(1, 0, 0, 1, -aroundPoint.x, -aroundPoint.y);
            m.concat(cm);

            m.rotate(Math.PI * angle / 180);

            var rcm:Matrix = new Matrix(1, 0, 0, 1, aroundPoint.x, aroundPoint.y);
            m.concat(rcm);
            this.transform.matrix = m;
        }

        private function resetCenterPoint(obj:DisplayObject, orgX:Number, orgY:Number):Point
        {
            var m:Matrix = obj.transform.matrix;
            var orgXY:Point = m.deltaTransformPoint(new Point(orgX, orgY));
            orgXY.x += m.tx;
            orgXY.y += m.ty;
            return orgXY;
        }
}

So there's something wrong with the whole repositioning part of the code. It doesn't matter for the issue at hand as the rotation is still correct and the idea of using relative/absolute positioning as substitutes of each other should also hold true.

But I would investigate further into the code and see what's going on. While typing my answer here, the example code was running and the shape is almost off the screen now. It drifted to 0/0.

If I had to guess, I'd say this is a rounding/precision problem.

Sorry for the proliferating problems.