Reputation: 193311
In Javascript we often render graphics by rotating and translating the coordinate plane before sending things
ctx.save();
ctx.translate(someX, someY);
ctx.rotate(someAngle * Math.PI / 180);
ctx.beginPath();
ctx.moveTo(x1, y1); // What's the actual (x1,y1)?
ctx.lineTo(x2, y2); // What's the actual (x2,y2)?
ctx.stroke();
ctx.restore();
So having done this, how do I figure out the actual values of the endpoints of that line segment I've drawn? Because after that translating and rotating, (x1,y1) and (x2,y2) are somewhere far away from where they'd be without the translating and rotating. Is there an easy way to find out what their actual values are?
Upvotes: 2
Views: 1568
Reputation: 102765
There's no way right now to get the current transformation matrix, so you would need to keep track of any rotations/translations/scaling yourself.
To actually perform the transformation, you need to multiply the transformation matrix by the point (as a column vector).
You could override the methods that affect the transformation to store your own copy of the matrix. I haven't tested this code, but something like this should work:
var contextPrototype = CanvasRenderingContext2D.prototype;
contextPrototype.xform = Matrix.I(3);
contextPrototype.realSave = contextPrototype.save;
contextPrototype.save = function() {
if (!this.xformStack) {
this.xformStack = [];
}
this.xformStack.push(this.xform.dup());
this.realSave();
}
contextPrototype.realRestore = contextPrototype.restore;
contextPrototype.restore = function() {
if (this.xformStack && this.xformStack.length > 0) {
this.xform = this.xformStack.pop();
}
this.realRestore();
}
contextPrototype.realScale = contextPrototype.scale;
contextPrototype.scale = function(x, y) {
this.xform = this.xform.multiply($M([
[x, 0, 0],
[0, y, 0],
[0, 0, 1]
]));
this.realScale(x, y);
}
contextPrototype.realRotate = contextPrototype.rotate;
contextPrototype.rotate = function(angle) {
var sin = Math.sin(angle);
var cos = Math.cos(angle);
this.xform = this.xform.multiply($M([
[cos, -sin, 0],
[sin, cos, 0],
[ 0, 0, 1]
]));
this.realRotate(angle);
}
contextPrototype.realTranslate = contextPrototype.translate;
contextPrototype.translate = function(x, y) {
this.xform = this.xform.multiply($M([
[1, 0, x],
[0, 1, y],
[0, 0, 1]
]));
this.realTranslate(x, y);
}
contextPrototype.realTransform = contextPrototype.transform;
contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
this.xform = this.xform.multiply($M([
[m11, m21, dx],
[m12, m22, dy],
[ 0, 0, 1]
]));
this.realTransform(m11, m12, m21, m22, dx, dy);
}
contextPrototype.realSetTransform = contextPrototype.setTransform;
contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
this.xform = $M([
[m11, m21, dx],
[m12, m22, dy],
[ 0, 0, 1]
]);
this.realSetTransform(m11, m12, m21, m22, dx, dy);
}
I used the Sylvester matrix library for convenience, but you could do your own multiplication.
To get the transformed point, just multiply the transformation matrix by the point:
// Get the transformed point as [x, y]
contextPrototype.getTransformedPoint = function(x, y) {
var point = this.xform.multiply($V([x, y, 1]));
return [point.e(1), point.e(2)];
}
Upvotes: 3
Reputation: 140185
I think the only way to find that would be to apply the same transformations as you did on the rendering context to the points you want to know the actual coordinates. A few libraries provide matrix operations, like : http://sylvester.jcoglan.com/ You can try to perform rotation operations to the cartesian coordinates
Upvotes: 1