blob: a39b22631a777fb86b0edcc8aed7dca22a0ec29d [file] [log] [blame]
/*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 2001-3 Paul Murrell
* 2003 The R Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, a copy is available at
* https://www.R-project.org/Licenses/
*/
#include "grid.h"
#include <math.h>
/* Code for matrices, matrix multiplication, etc for performing
* 2D affine transformations: translations, scaling, and rotations.
*/
double locationX(LLocation l) {
return l[0];
}
double locationY(LLocation l) {
return l[1];
}
void copyTransform(LTransform t1, LTransform t2)
{
int i, j;
for (i=0; i<3; i++)
for (j=0; j<3; j++)
t2[i][j] = t1[i][j];
}
void invTransform(LTransform t, LTransform invt)
{
double det = t[0][0]*(t[2][2]*t[1][1] - t[2][1]*t[1][2]) -
t[1][0]*(t[2][2]*t[0][1] - t[2][1]*t[0][2]) +
t[2][0]*(t[1][2]*t[0][1] - t[1][1]*t[0][2]);
if (det == 0)
error(_("singular transformation matrix"));
invt[0][0] = 1/det*(t[2][2]*t[1][1] - t[2][1]*t[1][2]);
invt[0][1] = -1/det*(t[2][2]*t[0][1] - t[2][1]*t[0][2]);
invt[0][2] = 1/det*(t[1][2]*t[0][1] - t[1][1]*t[0][2]);
invt[1][0] = -1/det*(t[2][2]*t[1][0] - t[2][0]*t[1][2]);
invt[1][1] = 1/det*(t[2][2]*t[0][0] - t[2][0]*t[0][2]);
invt[1][2] = -1/det*(t[1][2]*t[0][0] - t[1][0]*t[0][2]);
invt[2][0] = 1/det*(t[2][1]*t[1][0] - t[2][0]*t[1][1]);
invt[2][1] = -1/det*(t[2][1]*t[0][0] - t[2][0]*t[0][1]);
invt[2][2] = 1/det*(t[1][1]*t[0][0] - t[1][0]*t[0][1]);
}
void identity(LTransform m)
{
int i, j;
for (i=0; i<3; i++)
for (j=0; j<3; j++)
if (i == j)
m[i][j] = 1;
else
m[i][j] = 0;
}
void translation(double tx, double ty, LTransform m)
{
identity(m);
m[2][0] = tx;
m[2][1] = ty;
}
void scaling(double sx, double sy, LTransform m)
{
identity(m);
m[0][0] = sx;
m[1][1] = sy;
}
void rotation(double theta, LTransform m)
{
double thetarad = theta/180*M_PI;
double costheta = cos(thetarad);
double sintheta = sin(thetarad);
identity(m);
m[0][0] = costheta;
m[0][1] = sintheta;
m[1][0] = -sintheta;
m[1][1] = costheta;
}
void multiply(LTransform m1, LTransform m2, LTransform m)
{
m[0][0] = m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0] + m1[0][2]*m2[2][0];
m[0][1] = m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1] + m1[0][2]*m2[2][1];
m[0][2] = m1[0][0]*m2[0][2] + m1[0][1]*m2[1][2] + m1[0][2]*m2[2][2];
m[1][0] = m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0] + m1[1][2]*m2[2][0];
m[1][1] = m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1] + m1[1][2]*m2[2][1];
m[1][2] = m1[1][0]*m2[0][2] + m1[1][1]*m2[1][2] + m1[1][2]*m2[2][2];
m[2][0] = m1[2][0]*m2[0][0] + m1[2][1]*m2[1][0] + m1[2][2]*m2[2][0];
m[2][1] = m1[2][0]*m2[0][1] + m1[2][1]*m2[1][1] + m1[2][2]*m2[2][1];
m[2][2] = m1[2][0]*m2[0][2] + m1[2][1]*m2[1][2] + m1[2][2]*m2[2][2];
}
void location(double x, double y, LLocation v)
{
v[0] = x;
v[1] = y;
v[2] = 1;
}
void trans(LLocation vin, LTransform m, LLocation vout)
{
vout[0] = vin[0]*m[0][0] + vin[1]*m[1][0] + vin[2]*m[2][0];
vout[1] = vin[0]*m[0][1] + vin[1]*m[1][1] + vin[2]*m[2][1];
vout[2] = vin[0]*m[0][2] + vin[1]*m[1][2] + vin[2]*m[2][2];
}
/* Testing code
* Need to undocument main() below and add #include <math.h> at top of file
* Correct answers are "2.67 2.00 1.00" for m4=identity
* and "0.00 2.00 1.00" for m4=rotation
*/
/*
main()
{
LLocation v1, v2;
LTransform m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11;
location(9, 10, v1);
translation(-5, -6, m1);
scaling(1/7.0, 1/8.0, m2);
scaling(7, 8, m3);
identity(m4);
rotation(3.141592 / 2, m4);
translation(4, 4, m5);
scaling(1/3.0, 1/4.0, m6);
multiply(m1, m2, m7);
multiply(m7, m3, m8);
multiply(m8, m4, m9);
multiply(m9, m5, m10);
multiply(m10, m6, m11);
transform(v1, m11, v2);
printf("%1.2f %1.2f %1.2f\n", v2[0], v2[1], v2[2]);
}
*/