package net.gnehzr.tnoodle.svglite;
public class Transform {
// TODO - I don't know how to pick a good value here, should it be zero?
private static final double NEAR_THRESHOLD = 0.000001;
// a-f comprise the transformation matrix:
// [ a c e ]
// [ b d f ]
// [ 0 0 1 ]
private double a, b, c, d, e, f;
public Transform(double a, double b, double c, double d, double e, double f) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}
public Transform() {
setToIdentity();
}
public Transform(Transform t) {
setTransform(t);
}
public void concatenate(Transform that) {
Transform left = that;
Transform right = this;
double a = left.a*right.a + left.c*right.b;
double c = left.a*right.c + left.c*right.d;
double e = left.a*right.e + left.c*right.f + left.e;
double b = left.b*right.a + left.d*right.b;
double d = left.b*right.c + left.d*right.d;
double f = left.b*right.e + left.d*right.f + left.f;
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}
public void setTransform(Transform t) {
this.a = t.a;
this.b = t.b;
this.c = t.c;
this.d = t.d;
this.e = t.e;
this.f = t.f;
}
public void setToIdentity() {
a = d = 1;
c = e = b = f = 0;
}
private static boolean isNear(double a, double b) {
return -NEAR_THRESHOLD <= a - b && a - b <= NEAR_THRESHOLD;
}
public boolean isIdentity() {
return isNear(a, 1) && isNear(d, 1) &&
isNear(c, 0) && isNear(e, 0) && isNear(b, 0) && isNear(f, 0);
}
public static Transform getTranslateInstance(double tx, double ty) {
return new Transform(1, 0, 0, 1, tx, ty);
}
public static Transform getRotateInstance(double radians, double anchorx, double anchory) {
Transform trans = new Transform();
trans.translate(-anchorx, -anchory);
trans.rotate(radians);
trans.translate(anchorx, anchory);
return trans;
}
public static Transform getRotateInstance(double radians) {
double sin = Math.sin(radians);
double cos = Math.cos(radians);
return new Transform(cos, sin, -sin, cos, 0, 0);
}
public void rotate(double radians, double anchorx, double anchory) {
concatenate(Transform.getRotateInstance(radians, anchorx, anchory));
}
public void rotate(double radians) {
concatenate(Transform.getRotateInstance(radians));
}
public void translate(double x, double y) {
concatenate(Transform.getTranslateInstance(x, y));
}
public String toSvgTransform() {
return "matrix(" + a + "," + b + "," + c + "," + d + "," + e + "," + f+ ")";
}
}