Question

En Javascript nous rendons souvent graphiques par rotation et translation du plan de coordonnées avant d'envoyer les choses

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();

Donc, après avoir fait cela, comment puis-je déterminer les valeurs réelles des extrémités de ce segment de ligne, je suis sortie? Parce qu'après que la traduction et la rotation, (x1, y1) et (x2, y2) sont quelque part loin de l'endroit où ils seraient sans traduction et la rotation. Est-il un moyen facile de savoir ce que leurs valeurs réelles sont?

Était-ce utile?

La solution

Il n'y a aucun moyen dès maintenant pour obtenir la matrice de transformation, de sorte que vous auriez besoin de garder une trace de toutes les rotations / traductions / mise à l'échelle vous.

Pour effectuer réellement la transformation, il faut multiplier la matrice de transformation par le point (comme vecteur de colonne).

Vous pouvez remplacer les méthodes qui affectent la transformation pour stocker votre propre copie de la matrice. Je ne l'ai pas testé ce code, mais quelque chose comme cela devrait fonctionner:

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);
}

J'ai utilisé le bibliothèque de la matrice de Sylvester pour plus de commodité, mais vous pouvez faire votre propre multiplication.

Pour obtenir le point transformé, il suffit de multiplier la matrice de transformation par le 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)];
}

Autres conseils

Je pense que la seule façon de trouver ce serait d'appliquer les mêmes transformations que vous avez fait sur le contexte de rendu aux points que vous voulez connaître les coordonnées réelles. Quelques bibliothèques fournissent des opérations de matrice, comme: http://sylvester.jcoglan.com/ Vous pouvez essayer d'effectuer des opérations de rotation à la coordonnées cartésiennes

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top