Rotate shape around two points, calculate translation

876 Views Asked by At

I'm learning to script Photoshop and I have encountered a math problem. Basically I want to rotate a shape around an arbitrary point (the baseline of some text), but Photoshop only allows me to rotate around corner or center points. I think I need to rotate the shape around one of the constrained points (the center point in my illustration) and then translate the result to align with the arbitrarily rotated shape. How could I calculate the translation mathematically?

Example

3

There are 3 best solutions below

0
On BEST ANSWER

I got it working. It turned out to be simpler than I thought. Just had to rotate the preset anchor point around the arbitrary point and translate by the difference. In Adobe Photoshop Javascript, it looks like this:

rotateAroundPoint(doc.layers[0], 90, 100, 100);

function rotateAroundPoint(layer, angle, ax, ay) {
    /*
    * Photoshop scripting constrains rotation to corner or center points
    * To rotate around an arbitrary point, we must rotate the shape around a
    * corner point and then translate the shape to align it with our target location.
    * Note that Photoshop uses a pixel-coordinate system and rotates clockwise.
    */
    var bx = layer.bounds[0].value,
        by = layer.bounds[1].value,
        c = rotate(ax, ay, bx, by, -angle);

    layer.rotate(angle, AnchorPosition.TOPLEFT);
    layer.translate(c.x-bx, c.y-by);
}

function rotate(ax, ay, bx, by, angle) {
    /*
    * http://stackoverflow.com/a/17411276/1017480
    * Rotate Point B around Point A by angle in degrees.
    * Assumes cartesian coordinates (y decreases as you go "down").
    * A positive angle rotates in a clockwide direction.
    * A negative angle rotates in a counterclockwise direction.
    * For pixel coordinates, rotation reverses direction.
    * (y increases as you go "down")
    */
    var rad = (Math.PI / 180) * angle,
        cos = Math.cos(rad),
        sin = Math.sin(rad),
        run = bx - ax,
        rise = by - ay,
        cx = (cos * run) + (sin * rise) + ax,
        cy = (cos * rise) - (sin * run) + ay;
    return {x: cx, y: cy};
}
0
On

Let $p_1$ and $p_2$ be the two points. Let $r_{\theta}$ represent rotating the points around the origin for an angle of $\theta$.

The rotations are given by $$f_1(p) = r_{\theta}(p - p_1) + p_1$$ $$f_2(p) = r_{-\theta}(p - p_2) + p_2$$ $$f_2(f_1(p)) = r_{-\theta}(r_{\theta}(p - p_1) + p_1 - p_2) + p_2$$

Rotation is a linear operation ($r_{\theta}(sp + p') = sr_{\theta}(p) + r_{\theta}(p')$, so it distributes over the difference

$$f_2(f_1(p)) = r_{-\theta}(r_{\theta}(p - p_1) + p_1 - p_2) + p_2$$ $$ = (p - p_1) + r_{-\theta}(p_1 - p_2) + p_2$$ $$ = p + r_{-\theta}(p_1 - p_2) - (p_1 - p_2)$$

0
On

As you can see in the picture below, the translation vector $\vec{A'A}$ has a length $AA'=2AO\sin(\theta/2)$, where $\theta$ is the rotation angle, and forms with the horizontal an angle $90°+\theta/2+\alpha$, where $\sin\alpha=2AO/AB$.

enter image description here