2009-05-11 13 views
2

En Javascript, nous rendions souvent graphiques par rotation et translation du plan de coordonnées avant d'envoyer les chosesGet non traduit, non tourné (x, y) de coordonnées d'un point à partir d'une toile Javascript

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 Comment puis-je déterminer les valeurs réelles des extrémités de ce segment de ligne que j'ai dessiné? Parce que, après cette traduction et rotation, (x1, y1) et (x2, y2) sont quelque part loin d'où ils seraient sans la traduction et la rotation. Y a-t-il un moyen facile de savoir quelles sont leurs valeurs réelles?

Répondre

3

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/vous mettre à l'échelle.

Pour réellement effectuer la transformation, vous devez multiplier la matrice de transformation par le point (en tant que 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 Sylvester matrix library 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)]; 
} 
+0

Cela doit mettre en œuvre de sauvegarde() et de restauration() aussi bien, mais il semble juste et devrait obtenir le coche . –

+0

Bon point sur save() et restore(). Je vais ajouter ceux-ci. –

+0

Cela a fonctionné dès le départ ... parfait, merci !! Bien que la raison pour laquelle ils n'auraient pas pensé à cela dans l'original est au-delà de moi. : / – HostileFork

1

Je pense que la seule façon de trouver cela serait d'appliquer les mêmes transformations que vous avez faites sur le contexte de rendu aux points dont 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 cartesian coordinates