package org.openstreetmap.josm.plugins.piclayer.transform;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.List;
class Matrix3D {
double[][] a;
Matrix3D() {
a = new double[3][]; a[0] = new double[3]; a[1] = new double[3]; a[2] = new double[3];
}
Matrix3D(PictureTransform pictureTransform, double b11, double b12, double b13, double b21, double b22, double b23, double b31, double b32, double b33) {
this();
a[0][0] = b11; a[0][1] = b12; a[0][2] = b13;
a[1][0] = b21; a[1][1] = b22; a[1][2] = b23;
a[2][0] = b31; a[2][1] = b32; a[2][2] = b33;
}
Matrix3D(List<? extends Point2D> list) {
this();
for (int i = 0; i < 3; i++) {
Point2D p = list.get(i);
a[0][i] = p.getX();
a[1][i] = p.getY();
a[2][i] = 1;
}
}
public Matrix3D multiply(Matrix3D m) {
Matrix3D result = new Matrix3D();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
double sum = 0;
for (int k = 0; k < 3; k++) {
sum += a[i][k]*m.a[k][j];
}
result.a[i][j] = sum;
}
}
return result;
}
private double determinant() {
return a[0][0]*(a[1][1]*a[2][2]-a[1][2]*a[2][1])-a[0][1]*(a[1][0]*a[2][2]-a[1][2]*a[2][0])
+a[0][2]*(a[1][0]*a[2][1]-a[1][1]*a[2][0]);
}
public Matrix3D inverse() throws NoSolutionException {
Matrix3D invert = new Matrix3D();
double det = determinant();
if (Math.abs(det) <= Double.MIN_VALUE)
throw new NoSolutionException("Determinant = 0");
double s = 1/det;
invert.a[0][0] = (s) * (a[1][1] * a[2][2] - a[1][2] * a[2][1]);
invert.a[1][0] = (s) * (a[1][2] * a[2][0] - a[1][0] * a[2][2]);
invert.a[2][0] = (s) * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
invert.a[0][1] = (s) * (a[0][2] * a[2][1] - a[0][1] * a[2][2]);
invert.a[1][1] = (s) * (a[0][0] * a[2][2] - a[0][2] * a[2][0]);
invert.a[2][1] = (s) * (a[0][1] * a[2][0] - a[0][0] * a[2][1]);
invert.a[0][2] = (s) * (a[0][1] * a[1][2] - a[0][2] * a[1][1]);
invert.a[1][2] = (s) * (a[0][2] * a[1][0] - a[0][0] * a[1][2]);
invert.a[2][2] = (s) * (a[0][0] * a[1][1] - a[0][1] * a[1][0]);
return invert;
}
public AffineTransform toAffineTransform() throws NoSolutionException {
if (!(Math.abs(a[2][0]) <= 1e-2 && Math.abs(a[2][1]) <= 1e-2 && Math.abs(a[2][2]-1) <= 1e-2))
throw new NoSolutionException("Resulted matrix is not AF");
return new AffineTransform(a[0][0], a[1][0], a[0][1], a[1][1], a[0][2], a[1][2]);
}
}