1
votes

I'm trying to maintain and then use a transformation matrix for a computer graphics program. It's a 3x3 matrix that stores scale, rotate, and translate information for (x,y) points.

My program can handle any individual case... i.e. if I only scale or only rotate it works fine. However, it does not seem to work when combining scale and rotate, and I think that has to do with how I combine rotation and scale in the code. The matrix is called transformation and is of type float. The following methods clear, rotate, scale, and translate (in that order) the matrix.

public void clearTransform()
{
    transformation[0][0] = 1;transformation[0][1] = 0;transformation[0][2] = 0;
    transformation[1][0] = 0;transformation[1][1] = 1;transformation[1][2] = 0;
    transformation[2][0] = 0;transformation[2][1] = 0;transformation[2][2] = 1;
}

public void rotate (float degrees)
{
    double r = degrees * (Math.PI/180);
    float sin = (float)Math.sin(r);
    float cos = (float)Math.cos(r);
    transformation[0][0] *= cos;
    transformation[1][1] *= cos;
    if(transformation[0][1] == 0)
        transformation[0][1] = -sin;
    else 
        transformation[0][1] *= -sin;
    if(transformation[1][0] == 0) 
        transformation[1][0] = sin;
    else 
        transformation[1][0] *= sin;
}

public void scale (float x, float y)
{
    transformation[0][0] *= x;
    transformation[1][1] *= y;
}

public void translate (float x, float y)
{
    transformation[0][2] += x;
    transformation[1][2] += y;
}

For scale, the matrix hold info like this:

(Sx, 0, 0) (0, Sy, 0) (0, 0, 1)

for rotation, like this:

(cos(theta), -sin(theta), 0) (sin(theta), cos(theta), 0) (0, 0, 1)

for translation, this:

(1, 0, Tx) (0, 1, Ty) (0, 0, 1)

I don't think I'm correctly combining scale and rotate. Here is where I actually apply the transformation:

public float[] transformX(float[] x, float[] y, int n) {
    float[] newX = new float[n];
    for(int i = 0; i < n; i ++) {
        newX[i] = (x[i] * transformation[0][0]) + (y[i] * transformation[0][1]) + transformation[0][2];
    }
    return newX;
}

public float[] transformY(float[] x, float[] y, int n) {
    float[] newY = new float[n];
    for(int i = 0; i < n; i ++) {
        newY[i] = (x[i] * transformation[1][0]) + (y[i] * transformation[1][1]) + transformation[1][2];
    }
    return newY;
}

Where x and y are the pre-transformed point arrays, and n is the number of points

Thank you for any help!

1
Since it seems you are only transforming two dimensions, you can also use the Java2D AffineTransform class: docs.oracle.com/javase/tutorial/2d/advanced/transforming.html - The Nail
Nice, but rotate should be a matrix multiplication with the old values; the ifs on 0 have no right to be there. In general you would need a temporary matrix to write the new values into. Maybe you could borrow existing code from java. - Joop Eggen
I originally had those two as (*= -sin) and (*= sin), but in the event that they were 0, (which is always the case when applying the first rotation) then the values would remain 0. - user1028885

1 Answers

3
votes

I think the correct transformation should be:

enter image description here