fixed a bug in matrix multiply

This commit is contained in:
hneemann 2018-12-03 21:39:25 +01:00
parent 1e3c6ee806
commit 402a38387f
6 changed files with 94 additions and 30 deletions

View File

@ -46,12 +46,12 @@ public interface Transform {
TransformMatrix m1 = t1.getMatrix(); TransformMatrix m1 = t1.getMatrix();
TransformMatrix m2 = t2.getMatrix(); TransformMatrix m2 = t2.getMatrix();
return new TransformMatrix( return new TransformMatrix(
m1.a * m2.a + m1.b * m2.c, m1.a * m2.a + m1.c * m2.b,
m1.c * m2.a + m1.d * m2.c, m1.b * m2.a + m1.d * m2.b,
m1.a * m2.b + m1.b * m2.d, m1.a * m2.c + m1.c * m2.d,
m1.c * m2.b + m1.d * m2.d, m1.b * m2.c + m1.d * m2.d,
m1.a * m2.x + m1.b * m2.y + m1.x, m2.a * m1.x + m2.b * m1.y + m2.x,
m1.c * m2.x + m1.d * m2.y + m1.y); m2.c * m1.x + m2.d * m1.y + m2.y);
} }

View File

@ -23,7 +23,7 @@ public class TransformMatrix implements Transform {
final double phi = w / 180 * Math.PI; final double phi = w / 180 * Math.PI;
float cos = (float) Math.cos(phi); float cos = (float) Math.cos(phi);
float sin = (float) Math.sin(phi); float sin = (float) Math.sin(phi);
return new TransformMatrix(cos, sin, -sin, cos, 0, 0); return new TransformMatrix(cos, -sin, sin, cos, 0, 0);
} }
/** /**

View File

@ -152,7 +152,7 @@ class Context {
private static void readTransform(Context c, String value) throws SvgException { private static void readTransform(Context c, String value) throws SvgException {
StringTokenizer st = new StringTokenizer(value, "(),"); StringTokenizer st = new StringTokenizer(value, "(),");
Transform t = null; Transform t;
final String trans = st.nextToken(); final String trans = st.nextToken();
switch (trans) { switch (trans) {
case "translate": case "translate":
@ -170,10 +170,13 @@ class Context {
t = new TransformMatrix(xs, 0, 0, ys, 0, 0); t = new TransformMatrix(xs, 0, 0, ys, 0, 0);
break; break;
case "matrix": case "matrix":
final float ma = Float.parseFloat(st.nextToken());
final float mb = Float.parseFloat(st.nextToken());
final float mc = Float.parseFloat(st.nextToken());
t = new TransformMatrix( t = new TransformMatrix(
Float.parseFloat(st.nextToken()), ma,
Float.parseFloat(st.nextToken()), mc,
Float.parseFloat(st.nextToken()), mb,
Float.parseFloat(st.nextToken()), Float.parseFloat(st.nextToken()),
Float.parseFloat(st.nextToken()), Float.parseFloat(st.nextToken()),
Float.parseFloat(st.nextToken())); Float.parseFloat(st.nextToken()));
@ -184,15 +187,15 @@ class Context {
t = TransformMatrix.rotate(w); t = TransformMatrix.rotate(w);
float xc = Float.parseFloat(st.nextToken()); float xc = Float.parseFloat(st.nextToken());
float yc = Float.parseFloat(st.nextToken()); float yc = Float.parseFloat(st.nextToken());
t = Transform.mul(new TransformTranslate(xc, yc), t); t = Transform.mul(new TransformTranslate(-xc, -yc), t);
t = Transform.mul(t, new TransformTranslate(-xc, -yc)); t = Transform.mul(t, new TransformTranslate(xc, yc));
} else } else
t = TransformMatrix.rotate(w); t = TransformMatrix.rotate(w);
break; break;
default: default:
throw new SvgException("unknown transform: " + value, null); throw new SvgException("unknown transform: " + value, null);
} }
c.tr = Transform.mul(c.tr, t); c.tr = Transform.mul(t, c.tr);
} }
private static Color getColorFromString(String v) { private static Color getColorFromString(String v) {

View File

@ -20,7 +20,7 @@ public class TransformMatrixTest extends TestCase {
TransformMatrix tr = TransformMatrix.rotate(45); TransformMatrix tr = TransformMatrix.rotate(45);
VectorInterface p = new VectorFloat(2, 0).transform(tr); VectorInterface p = new VectorFloat(2, 0).transform(tr);
assertEquals(Math.sqrt(2), p.getXFloat(), 1e-4); assertEquals(Math.sqrt(2), p.getXFloat(), 1e-4);
assertEquals(-Math.sqrt(2), p.getYFloat(), 1e-4); assertEquals(Math.sqrt(2), p.getYFloat(), 1e-4);
} }
public void testRotateInverse() { public void testRotateInverse() {
@ -65,4 +65,30 @@ public class TransformMatrixTest extends TestCase {
assertTrue(TransformMatrix.scale(2, 3).noRotation()); assertTrue(TransformMatrix.scale(2, 3).noRotation());
} }
public void testMul() {
final TransformMatrix t1 = new TransformTranslate(10, 10).getMatrix();
final TransformMatrix t2 = new TransformTranslate(10, 10).getMatrix();
final VectorFloat v = new VectorFloat(2, 3);
compare(v.transform(t1).transform(t2), v.transform(Transform.mul(t1, t2)));
}
public void testMul2() {
final TransformMatrix t1 = new TransformTranslate(10, 10).getMatrix();
final TransformMatrix t2 = new TransformRotate(new Vector(10, 10), 1).getMatrix();
final VectorFloat v = new VectorFloat(2, 3);
compare(v.transform(t1).transform(t2), v.transform(Transform.mul(t1, t2)));
}
public void testMul3() {
final TransformMatrix t1 = new TransformTranslate(10, 10).getMatrix();
final TransformMatrix t2 = TransformMatrix.rotate(45);
final VectorFloat v = new VectorFloat(2, 3);
compare(v.transform(t1).transform(t2), v.transform(Transform.mul(t1, t2)));
}
private void compare(VectorInterface v1, VectorInterface v2) {
assertEquals(v1.getXFloat(), v2.getXFloat(), 1e-4);
assertEquals(v1.getYFloat(), v2.getYFloat(), 1e-4);
}
} }

View File

@ -424,6 +424,34 @@ public class SvgImporterTest extends TestCase {
.check(); .check();
} }
public void testInkscape7() throws IOException, SvgException, PolygonParser.ParserException, PinException {
CustomShapeDescription custom = new SvgImporter(
in("<svg viewBox=\"0 0 200 200\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
"<g transform=\"rotate(45, 100, 100)\">\n" +
"<g transform=\"translate(10,10)\">\n" +
"<rect fill=\"none\" stroke=\"black\" stroke-width=\"3\"\n" +
" x=\"50\" y=\"50\" width=\"100\" height=\"100\" /> \n" +
"</g>\n" +
"</g>\n" +
"</svg>")).create();
new CSDChecker(custom)
.checkPolygon("M 100,43.431458 L 170.71068,114.142136 L 100,184.85281 L 29.289322,114.142136 Z")
.check();
}
public void testInkscape8() throws IOException, SvgException, PolygonParser.ParserException, PinException {
CustomShapeDescription custom = new SvgImporter(
in("<svg viewBox=\"0 0 200 200\" xmlns=\"http://www.w3.org/2000/svg\">\n" +
"<rect fill=\"none\" stroke=\"yellow\" stroke-width=\"5\" transform=\"rotate(45, 100, 100) translate(10,10)\"\n" +
" x=\"50\" y=\"50\" width=\"100\" height=\"100\" />\n" +
"</svg>")).create();
new CSDChecker(custom)
.checkPolygon("M 100,43.431458 L 170.71068,114.142136 L 100,184.85281 L 29.289322,114.142136 Z")
.check();
}
//***************************************************************************************************** //*****************************************************************************************************

View File

@ -13,4 +13,11 @@ public class ContextTest extends TestCase {
assertEquals(new Color(63, 127, 191), Context.readStyle(new Context(), "stroke:rgb(25%,50%,75%)").getStroke()); assertEquals(new Color(63, 127, 191), Context.readStyle(new Context(), "stroke:rgb(25%,50%,75%)").getStroke());
} }
public void testInkscape1() throws SvgException {
Context c = Context.readStyle(new Context(), "fill:#000000;fill-opacity:0.5;stroke:none");
assertNull(c.getStroke());
assertEquals(new Color(0, 0, 0, 127), c.getFilled());
}
} }