28 votos

extracción de los valores de rotación y escala a partir de una matriz de transformación 2D

¿Cómo puedo extraer los valores de rotación y escala de una matriz de transformación 2D?

matrix = [1, 0, 0, 1, 0, 0]

matrix.rotate(45 / 180 * PI)
matrix.scale(3, 4)
matrix.translate(50, 100)
matrix.rotate(30 / 180 * PI)
matrix.scale(-2, 4)

Ahora mi matriz tiene valores [a, b, c, d, tx, ty] . Olvidémonos de los procesos anteriores e imaginemos que sólo tenemos los valores a, b, c, d, tx y ty. ¿Cómo puedo encontrar los valores finales de rotación y escala?

49voto

Sergio del Amo Puntos 390

Básicamente, tiene que resolver lo siguiente

[abtxcdty]=[sxcosψsxsinψxcsysinψsycosψyc]

donde sx , sy son las escalas, xc , yc es la traslación y ψ es el ángulo de rotación. Los resultados que obtengo son:

xc=tx yc=ty sx=sign(a)a2+b2 sy=sign(d)c2+d2 tanψ=ba=cd

Así que el ángulo es ψ=atan2(b,a) o ψ=atan2(c,d)

5voto

Simon Epskamp Puntos 111

El término es descomposición matricial . He aquí una solución que incluye inclinación como describe Frédéric Wang .

Opera sobre una matriz 2d definida como tal:

[actxbdty]

function decompose_2d_matrix(mat) {
  var a = mat[0];
  var b = mat[1];
  var c = mat[2];
  var d = mat[3];
  var e = mat[4];
  var f = mat[5];

  var delta = a * d - b * c;

  let result = {
    translation: [e, f],
    rotation: 0,
    scale: [0, 0],
    skew: [0, 0],
  };

  // Apply the QR-like decomposition.
  if (a != 0 || b != 0) {
    var r = Math.sqrt(a * a + b * b);
    result.rotation = b > 0 ? Math.acos(a / r) : -Math.acos(a / r);
    result.scale = [r, delta / r];
    result.skew = [Math.atan((a * c + b * d) / (r * r)), 0];
  } else if (c != 0 || d != 0) {
    var s = Math.sqrt(c * c + d * d);
    result.rotation =
      Math.PI / 2 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s));
    result.scale = [delta / s, s];
    result.skew = [0, Math.atan((a * c + b * d) / (s * s))];
  } else {
    // a = b = c = d = 0
  }

  return result;
}

4voto

Grue Puntos 21

Extracción de escala y rotación para Action Script 3

package nid.utils 
{
    import flash.geom.Matrix;
    import flash.geom.Point;
    import nid.geom.DMatrix;
    /**
     * ...
     * @author Nidin P Vinayakan
     */
    public class MatrixConvertor 
    {
        public static const degree:Number = 180 / Math.PI;
        public static const radian:Number = Math.PI / 180;

        public function MatrixConvertor()
        {

        }
        public static function convert(mat:Matrix):DMatrix 
        {
            var dmat:DMatrix = new DMatrix(mat.a, mat.b, mat.c, mat.d, mat.tx, mat.ty);
            var rad:Number;
            var deg:Number;
            var sign:Number;
            /**
             * scaleX = √(a^2+c^2)
             * scaleY = √(b^2+d^2)
             * rotation = tan^-1(c/d) = tan^-1(-b/a) it will not work sometimes 
             * rotation = a / scaleX  = d / scaleY
             */
            with (dmat)
            {
                scaleX = Math.sqrt((a * a) + (c * c));
                scaleY = Math.sqrt((b * b) + (d * d));

                sign = Math.atan(-c / a);
                rad  = Math.acos(a / scaleX);
                deg  = rad * degree;

                if (deg > 90 && sign > 0)
                {
                    rotation = (360 - deg) * radian;
                }
                else if (deg < 90 && sign < 0)
                {
                    rotation = (360 - deg) * radian;
                }
                else
                {
                    rotation = rad;
                }
                rotationInDegree = rotation * degree;
            }
            return dmat;
        }
    }

}

/**
* DMatrix Class
*/
package nid.geom 
{
    import flash.geom.Matrix;
    /**
     * ...
     * @author Nidin P Vinayakan
     */
    public class DMatrix extends Matrix
    {
        public var rotation:Number=0;
        public var rotationInDegree:Number=0;
        public var scaleX:Number=1;
        public var scaleY:Number=1;

        public function DMatrix(a:Number=1, b:Number=0, c:Number=0, d:Number=1, tx:Number=0, ty:Number=0)
        {
            super(a, b, c, d, tx, ty);
        }

    }

}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X