/* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package test.com.sun.javafx.test; import javafx.scene.transform.Transform; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.sun.javafx.geom.transform.Affine3D; import com.sun.javafx.geom.transform.BaseTransform; import com.sun.javafx.geom.transform.GeneralTransform3D; import com.sun.javafx.scene.transform.TransformUtils; import javafx.geometry.Point3D; import javafx.scene.transform.Affine; import javafx.scene.transform.NonInvertibleTransformException; import javafx.scene.transform.Rotate; import javafx.scene.transform.Scale; import javafx.scene.transform.Shear; import javafx.scene.transform.Translate; /** * Helper class for transform tests. */ public final class TransformHelper { /** * Asserts the {@code matrix} equals to the specified expected values */ public static void assertMatrix(Transform matrix, double mxx, double mxy, double mxz, double tx, double myx, double myy, double myz, double ty, double mzx, double mzy, double mzz, double tz) { assertEquals(mxx, matrix.getMxx(), 0.00001); assertEquals(mxy, matrix.getMxy(), 0.00001); assertEquals(mxz, matrix.getMxz(), 0.00001); assertEquals(tx, matrix.getTx(), 0.00001); assertEquals(myx, matrix.getMyx(), 0.00001); assertEquals(myy, matrix.getMyy(), 0.00001); assertEquals(myz, matrix.getMyz(), 0.00001); assertEquals(ty, matrix.getTy(), 0.00001); assertEquals(mzx, matrix.getMzx(), 0.00001); assertEquals(mzy, matrix.getMzy(), 0.00001); assertEquals(mzz, matrix.getMzz(), 0.00001); assertEquals(tz, matrix.getTz(), 0.00001); } /** * Asserts the {@code matrix} equals to the specified expected values */ public static void assertMatrix(BaseTransform matrix, double mxx, double mxy, double mxz, double tx, double myx, double myy, double myz, double ty, double mzx, double mzy, double mzz, double tz) { assertEquals(mxx, matrix.getMxx(), 0.00001); assertEquals(mxy, matrix.getMxy(), 0.00001); assertEquals(mxz, matrix.getMxz(), 0.00001); assertEquals(tx, matrix.getMxt(), 0.00001); assertEquals(myx, matrix.getMyx(), 0.00001); assertEquals(myy, matrix.getMyy(), 0.00001); assertEquals(myz, matrix.getMyz(), 0.00001); assertEquals(ty, matrix.getMyt(), 0.00001); assertEquals(mzx, matrix.getMzx(), 0.00001); assertEquals(mzy, matrix.getMzy(), 0.00001); assertEquals(mzz, matrix.getMzz(), 0.00001); assertEquals(tz, matrix.getMzt(), 0.00001); } /** * Asserts the {@code matrix} elements equal to the expected values * specified by {@code reference} */ public static void assertMatrix(Transform matrix, Transform reference) { assertEquals(reference.getMxx(), matrix.getMxx(), 0.00001); assertEquals(reference.getMxy(), matrix.getMxy(), 0.00001); assertEquals(reference.getMxz(), matrix.getMxz(), 0.00001); assertEquals(reference.getTx(), matrix.getTx(), 0.00001); assertEquals(reference.getMyx(), matrix.getMyx(), 0.00001); assertEquals(reference.getMyy(), matrix.getMyy(), 0.00001); assertEquals(reference.getMyz(), matrix.getMyz(), 0.00001); assertEquals(reference.getTy(), matrix.getTy(), 0.00001); assertEquals(reference.getMzx(), matrix.getMzx(), 0.00001); assertEquals(reference.getMzy(), matrix.getMzy(), 0.00001); assertEquals(reference.getMzz(), matrix.getMzz(), 0.00001); assertEquals(reference.getTz(), matrix.getTz(), 0.00001); } /** * Asserts the {@code matrix} elements equal to the expected values * specified by {@code reference} */ public static void assertMatrix(Affine3D matrix, BaseTransform reference) { assertEquals(reference.getMxx(), matrix.getMxx(), 0.00001); assertEquals(reference.getMxy(), matrix.getMxy(), 0.00001); assertEquals(reference.getMxz(), matrix.getMxz(), 0.00001); assertEquals(reference.getMxt(), matrix.getMxt(), 0.00001); assertEquals(reference.getMyx(), matrix.getMyx(), 0.00001); assertEquals(reference.getMyy(), matrix.getMyy(), 0.00001); assertEquals(reference.getMyz(), matrix.getMyz(), 0.00001); assertEquals(reference.getMyt(), matrix.getMyt(), 0.00001); assertEquals(reference.getMzx(), matrix.getMzx(), 0.00001); assertEquals(reference.getMzy(), matrix.getMzy(), 0.00001); assertEquals(reference.getMzz(), matrix.getMzz(), 0.00001); assertEquals(reference.getMzt(), matrix.getMzt(), 0.00001); } /** * Asserts the {@code matrix} elements equal to the expected values * specified by {@code reference} */ public static void assertMatrix(String message, Transform matrix, Transform reference) { assertEquals(message, reference.getMxx(), matrix.getMxx(), 0.00001); assertEquals(message, reference.getMxy(), matrix.getMxy(), 0.00001); assertEquals(message, reference.getMxz(), matrix.getMxz(), 0.00001); assertEquals(message, reference.getTx(), matrix.getTx(), 0.00001); assertEquals(message, reference.getMyx(), matrix.getMyx(), 0.00001); assertEquals(message, reference.getMyy(), matrix.getMyy(), 0.00001); assertEquals(message, reference.getMyz(), matrix.getMyz(), 0.00001); assertEquals(message, reference.getTy(), matrix.getTy(), 0.00001); assertEquals(message, reference.getMzx(), matrix.getMzx(), 0.00001); assertEquals(message, reference.getMzy(), matrix.getMzy(), 0.00001); assertEquals(message, reference.getMzz(), matrix.getMzz(), 0.00001); assertEquals(message, reference.getTz(), matrix.getTz(), 0.00001); } /** * Asserts the {@code matrix} elements equal to the expected values * specified by {@code reference} */ public static void assertMatrix(GeneralTransform3D matrix, GeneralTransform3D reference) { for (int i = 0; i < 16; i++) { assertEquals(reference.get(i), matrix.get(i), 0.00001); } } /** * Asserts the {@code matrix} is NOT equal to the specified values */ public static void assertMatrixDiffers(Transform matrix, double mxx, double mxy, double mxz, double tx, double myx, double myy, double myz, double ty, double mzx, double mzy, double mzz, double tz) { assertTrue( mxx != matrix.getMxx() || mxy != matrix.getMxy() || mxz != matrix.getMxz() || tx != matrix.getTx() || myx != matrix.getMyx() || myy != matrix.getMyy() || myz != matrix.getMyz() || ty != matrix.getTy() || mzx != matrix.getMzx() || mzy != matrix.getMzy() || mzz != matrix.getMzz() || tz != matrix.getTz()); } /** * Inverts the given transform. * @throws NonInvertibleTransformException */ public static Transform invert(Transform t) throws NonInvertibleTransformException { final double det = determinant(t); if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Det is 0"); } final double cxx = minor(t, 0, 0); final double cyx = - minor(t, 0, 1); final double czx = minor(t, 0, 2); final double cxy = - minor(t, 1, 0); final double cyy = minor(t, 1, 1); final double czy = - minor(t, 1, 2); final double cxz = minor(t, 2, 0); final double cyz = - minor(t, 2, 1); final double czz = minor(t, 2, 2); final double cxt = - minor(t, 3, 0); final double cyt = minor(t, 3, 1); final double czt = - minor(t, 3, 2); return TransformUtils.immutableTransform( cxx / det, cxy / det, cxz / det, cxt / det, cyx / det, cyy / det, cyz / det, cyt / det, czx / det, czy / det, czz / det, czt / det); } /** * Concatenates the two transforms. */ public static Transform concatenate(Transform t1, Transform t2) { final double txx = t2.getMxx(); final double txy = t2.getMxy(); final double txz = t2.getMxz(); final double ttx = t2.getTx(); final double tyx = t2.getMyx(); final double tyy = t2.getMyy(); final double tyz = t2.getMyz(); final double tty = t2.getTy(); final double tzx = t2.getMzx(); final double tzy = t2.getMzy(); final double tzz = t2.getMzz(); final double ttz = t2.getTz(); final double rxx = (t1.getMxx() * txx + t1.getMxy() * tyx + t1.getMxz() * tzx /* + getMxt * 0.0 */); final double rxy = (t1.getMxx() * txy + t1.getMxy() * tyy + t1.getMxz() * tzy /* + getMxt * 0.0 */); final double rxz = (t1.getMxx() * txz + t1.getMxy() * tyz + t1.getMxz() * tzz /* + getMxt * 0.0 */); final double rxt = (t1.getMxx() * ttx + t1.getMxy() * tty + t1.getMxz() * ttz + t1.getTx() /* * 1.0 */); final double ryx = (t1.getMyx() * txx + t1.getMyy() * tyx + t1.getMyz() * tzx /* + getMyt * 0.0 */); final double ryy = (t1.getMyx() * txy + t1.getMyy() * tyy + t1.getMyz() * tzy /* + getMyt * 0.0 */); final double ryz = (t1.getMyx() * txz + t1.getMyy() * tyz + t1.getMyz() * tzz /* + getMyt * 0.0 */); final double ryt = (t1.getMyx() * ttx + t1.getMyy() * tty + t1.getMyz() * ttz + t1.getTy() /* * 1.0 */); final double rzx = (t1.getMzx() * txx + t1.getMzy() * tyx + t1.getMzz() * tzx /* + getMzt * 0.0 */); final double rzy = (t1.getMzx() * txy + t1.getMzy() * tyy + t1.getMzz() * tzy /* + getMzt * 0.0 */); final double rzz = (t1.getMzx() * txz + t1.getMzy() * tyz + t1.getMzz() * tzz /* + getMzt * 0.0 */); final double rzt = (t1.getMzx() * ttx + t1.getMzy() * tty + t1.getMzz() * ttz + t1.getTz() /* * 1.0 */); return TransformUtils.immutableTransform( rxx, rxy, rxz, rxt, ryx, ryy, ryz, ryt, rzx, rzy, rzz, rzt); } /** * Concatenates the two transforms. */ public static Transform concatenate(BaseTransform t1, Transform t2) { final double txx = t2.getMxx(); final double txy = t2.getMxy(); final double txz = t2.getMxz(); final double ttx = t2.getTx(); final double tyx = t2.getMyx(); final double tyy = t2.getMyy(); final double tyz = t2.getMyz(); final double tty = t2.getTy(); final double tzx = t2.getMzx(); final double tzy = t2.getMzy(); final double tzz = t2.getMzz(); final double ttz = t2.getTz(); final double rxx = (t1.getMxx() * txx + t1.getMxy() * tyx + t1.getMxz() * tzx /* + getMxt * 0.0 */); final double rxy = (t1.getMxx() * txy + t1.getMxy() * tyy + t1.getMxz() * tzy /* + getMxt * 0.0 */); final double rxz = (t1.getMxx() * txz + t1.getMxy() * tyz + t1.getMxz() * tzz /* + getMxt * 0.0 */); final double rxt = (t1.getMxx() * ttx + t1.getMxy() * tty + t1.getMxz() * ttz + t1.getMxt() /* * 1.0 */); final double ryx = (t1.getMyx() * txx + t1.getMyy() * tyx + t1.getMyz() * tzx /* + getMyt * 0.0 */); final double ryy = (t1.getMyx() * txy + t1.getMyy() * tyy + t1.getMyz() * tzy /* + getMyt * 0.0 */); final double ryz = (t1.getMyx() * txz + t1.getMyy() * tyz + t1.getMyz() * tzz /* + getMyt * 0.0 */); final double ryt = (t1.getMyx() * ttx + t1.getMyy() * tty + t1.getMyz() * ttz + t1.getMyt() /* * 1.0 */); final double rzx = (t1.getMzx() * txx + t1.getMzy() * tyx + t1.getMzz() * tzx /* + getMzt * 0.0 */); final double rzy = (t1.getMzx() * txy + t1.getMzy() * tyy + t1.getMzz() * tzy /* + getMzt * 0.0 */); final double rzz = (t1.getMzx() * txz + t1.getMzy() * tyz + t1.getMzz() * tzz /* + getMzt * 0.0 */); final double rzt = (t1.getMzx() * ttx + t1.getMzy() * tty + t1.getMzz() * ttz + t1.getMzt() /* * 1.0 */); return TransformUtils.immutableTransform( rxx, rxy, rxz, rxt, ryx, ryy, ryz, ryt, rzx, rzy, rzz, rzt); } /** * Computes determinant of the specified transform. */ public static double determinant(Transform t) { return t.getMxx() * (t.getMyy() * t.getMzz() - t.getMzy() * t.getMyz()) + t.getMxy() * (t.getMyz() * t.getMzx() - t.getMzz() * t.getMyx()) + t.getMxz() * (t.getMyx() * t.getMzy() - t.getMzx() * t.getMyy()); } /** * Needed for inversion. */ private static double minor(Transform t, int row, int col) { double m00 = t.getMxx(), m01 = t.getMxy(), m02 = t.getMxz(); double m10 = t.getMyx(), m11 = t.getMyy(), m12 = t.getMyz(); double m20 = t.getMzx(), m21 = t.getMzy(), m22 = t.getMzz(); switch (col) { case 0: m00 = m01; m10 = m11; m20 = m21; case 1: m01 = m02; m11 = m12; m21 = m22; case 2: m02 = t.getTx(); m12 = t.getTy(); m22 = t.getTz(); } switch (row) { case 0: m00 = m10; m01 = m11; // m02 = m12; case 1: m10 = m20; m11 = m21; // m12 = m22; case 2: // m20 = 0.0; // m21 = 0.0; // m22 = 1.0; break; case 3: // This is the only row that requires a full 3x3 determinant return (m00 * (m11 * m22 - m21 * m12) + m01 * (m12 * m20 - m22 * m10) + m02 * (m10 * m21 - m20 * m11)); } // return (m00 * (m11 * 1.0 - 0.0 * m12) + // m01 * (m12 * 0.0 - 1.0 * m10) + // m02 * (m10 * 0.0 - 0.0 * m11)); return (m00 * m11 - m01 * m10); } /** * Modifies the given transform, if possible. * @param t Transform to modify * @param value Value to set to one of transform's properties * @return true if the transform was modified */ public static boolean modify(Transform t, double value) { if (t instanceof Translate) { ((Translate) t).setY(value); } else if (t instanceof Scale) { ((Scale) t).setY(value); } else if (t instanceof Shear) { ((Shear) t).setY(value); } else if (t instanceof Rotate) { Rotate r = (Rotate) t; if (r.getAxis().equals(new Point3D(0, 0, 0))) { r.setAxis(Rotate.Z_AXIS); } if ((r.getAxis().getX() != 0 || r.getAxis().getY() != 0) && r.getAngle() == 0) { r.setAxis(Rotate.Z_AXIS); } r.setAngle(value); } else if (t instanceof Affine) { ((Affine) t).setMyx(value); } else { return false; } return true; } /** * Makes a small modification to the transform, if possible. * @param t Transform to modify * @return true if the transform was modified */ public static boolean tinyModify(Transform t) { if (t instanceof Translate) { Translate tr = (Translate) t; tr.setY(tr.getY() + 1); if (tr.getZ() != 0) { tr.setZ(tr.getZ() + 3); } } else if (t instanceof Scale) { Scale sc = (Scale) t; sc.setY(sc.getY() + 0.01); if (sc.getZ() != 1) { sc.setZ(sc.getZ() + 0.01); } } else if (t instanceof Shear) { ((Shear) t).setY(((Shear) t).getY() + 0.01); } else if (t instanceof Rotate) { Rotate r = (Rotate) t; if (r.getAxis().getX() == 0 && r.getAxis().getY() == 0 && r.getAxis().getZ() == 0) { return false; } if ((r.getAxis().getX() != 0 || r.getAxis().getY() != 0) && r.getAngle() == 0) { return false; } r.setAngle(r.getAngle() + 0.2); } else if (t instanceof Affine) { Affine a = (Affine) t; a.setTy(a.getTy() + 1); if (!a.isType2D()) { a.setMzz(a.getMzz() + 2); } } else { return false; } return true; } /** * Makes a small modification to one of the 3D (Z-axis-effective) properties * of the transform, if possible. * @param t Transform to modify * @return true if the transform was modified */ public static boolean tinyModify3D(Transform t) { if (t instanceof Translate) { ((Translate) t).setZ(((Translate) t).getZ() + 1); } else if (t instanceof Scale) { ((Scale) t).setZ(((Scale) t).getZ() + 0.01); } else if (t instanceof Shear) { return false; } else if (t instanceof Rotate) { Rotate r = (Rotate) t; if (r.getAxis().getX() == 0 && r.getAxis().getY() == 0 && r.getAxis().getZ() == 0) { return false; } r.setAngle(r.getAngle() + 0.2); } else if (t instanceof Affine) { ((Affine) t).setTy(((Affine) t).getTy() + 1); } else { return false; } return true; } /** * Makes the transform 3D, if possible. * @param t Transform to modify * @return true if the transform was modified to a 3D state */ public static boolean make3D(Transform t) { if (t instanceof Translate) { ((Translate) t).setZ(42); } else if (t instanceof Scale) { ((Scale) t).setZ(42); } else if (t instanceof Shear) { return false; } else if (t instanceof Rotate) { Rotate r = (Rotate) t; if (r.getAxis().getX() == 0 && r.getAxis().getY() == 0) { r.setAxis(Rotate.Y_AXIS); } if (r.getAngle() == 0) { r.setAngle(23); } } else if (t instanceof Affine) { ((Affine) t).setMyz(42); } else { return false; } return true; } /** * Makes the transform 2D, if possible. * @param t Transform to modify * @return true if the transform was modified to a 2D state */ public static boolean make2D(Transform t) { if (t instanceof Translate) { ((Translate) t).setZ(0); } else if (t instanceof Scale) { ((Scale) t).setZ(1); } else if (t instanceof Shear) { return true; } else if (t instanceof Rotate) { ((Rotate) t).setAxis(Rotate.Z_AXIS); } else if (t instanceof Affine) { ((Affine) t).setToIdentity(); } else { return false; } return true; } /** * Makes the transform identity, if possible. * @param t Transform to modify * @return true if the transform was modified to an identity state */ public static boolean makeIdentity(Transform t) { if (t instanceof Translate) { ((Translate) t).setX(0); ((Translate) t).setY(0); ((Translate) t).setZ(0); } else if (t instanceof Scale) { ((Scale) t).setX(1); ((Scale) t).setY(1); ((Scale) t).setZ(1); } else if (t instanceof Shear) { ((Shear) t).setX(0); ((Shear) t).setY(0); } else if (t instanceof Rotate) { ((Rotate) t).setAngle(0); } else if (t instanceof Affine) { ((Affine) t).setToIdentity(); } else { return false; } return true; } private static enum State2D { IDENTITY(0), TRANSLATE(1), SCALE(2), SC_TR(3), SHEAR(4), SH_TR(5), SH_SC(6), SH_SC_TR(7); private int value; private State2D(int value) { this.value = value; } public int getValue() { return value; } } private static enum State3D { NON_3D(0), TRANSLATE(1), SCALE(2), SC_TR(3), COMPLEX(4); private int value; private State3D(int value) { this.value = value; } public int getValue() { return value; } } private static State2D getExpectedState2D(Transform t) { if (t.getMxy() == 0.0 && t.getMyx() == 0.0) { if (t.getMxx() == 1.0 && t.getMyy() == 1.0) { if (t.getTx() == 0.0 && t.getTy() == 0.0) { return State2D.IDENTITY; } else { return State2D.TRANSLATE; } } else { if (t.getTx() == 0.0 && t.getTy() == 0.0) { return State2D.SCALE; } else { return State2D.SC_TR; } } } else { if (t.getMxx() == 0.0 && t.getMyy() == 0.0) { if (t.getTx() == 0.0 && t.getTy() == 0.0) { return State2D.SHEAR; } else { return State2D.SH_TR; } } else { if (t.getTx() == 0.0 && t.getTy() == 0.0) { return State2D.SH_SC; } else { return State2D.SH_SC_TR; } } } } private static State3D getExpectedState3D(Transform t) { if (t.getMxz() == 0.0 && t.getMyz() == 0.0 && t.getMzx() == 0.0 && t.getMzy() == 0.0 && t.getMzz() == 1.0 && t.getTz() == 0.0) { return State3D.NON_3D; } if (t.getMxy() != 0.0 || t.getMxz() != 0.0 || t.getMyx() != 0.0 || t.getMyz() != 0.0 || t.getMzx() != 0.0 || t.getMzy() != 0.0) { return State3D.COMPLEX; } if ((t.getMxx() != 1.0 || t.getMyy() != 1.0 || t.getMzz() != 1.0) && (t.getTx() != 0.0 || t.getTy() != 0.0 || t.getTz() != 0.0)) { return State3D.SC_TR; } if (t.getMxx() != 1.0 || t.getMyy() != 1.0 || t.getMzz() != 1.0) { return State3D.SCALE; } if (t.getTx() != 0.0 || t.getTy() != 0.0 || t.getTz() != 0.0) { return State3D.TRANSLATE; } return null; } public static void assertStateOk(Transform t, int state3d, int state2d) { TransformHelper.State3D expectedState3D = TransformHelper.getExpectedState3D(t); assertEquals(expectedState3D.getValue(), state3d); if (expectedState3D == TransformHelper.State3D.NON_3D) { assertEquals(TransformHelper.getExpectedState2D(t).getValue(), state2d); } } public static void assertStateOk(String message, Transform t, int state3d, int state2d) { TransformHelper.State3D expectedState3D = TransformHelper.getExpectedState3D(t); assertEquals(message, expectedState3D.getValue(), state3d); if (expectedState3D == TransformHelper.State3D.NON_3D) { assertEquals(message, TransformHelper.getExpectedState2D(t).getValue(), state2d); } } /** * Convenient factory for 2D immutable transforms. */ public static Transform immutableTransform( double mxx, double mxy, double tx, double myx, double myy, double ty) { return TransformUtils.immutableTransform( mxx, mxy, 0.0, tx, myx, myy, 0.0, ty, 0.0, 0.0, 1.0, 0.0); } /** * Creates a raw transformation to test the Transform class. */ public static Transform rawTransform( double mxx, double mxy, double mxz, double tx, double myx, double myy, double myz, double ty, double mzx, double mzy, double mzz, double tz) { return new RawTransform( mxx, mxy, mxz, tx, myx, myy, myz, ty, mzx, mzy, mzz, tz); } private static class RawTransform extends Transform { private final double mxx, mxy, mxz, tx; private final double myx, myy, myz, ty; private final double mzx, mzy, mzz, tz; public RawTransform( double mxx, double mxy, double mxz, double tx, double myx, double myy, double myz, double ty, double mzx, double mzy, double mzz, double tz) { this.mxx = mxx; this.mxy = mxy; this.mxz = mxz; this.tx = tx; this.myx = myx; this.myy = myy; this.myz = myz; this.ty = ty; this.mzx = mzx; this.mzy = mzy; this.mzz = mzz; this.tz = tz; } @Override public double getMxx() { return mxx; } @Override public double getMxy() { return mxy; } @Override public double getMxz() { return mxz; } @Override public double getTx() { return tx; } @Override public double getMyx() { return myx; } @Override public double getMyy() { return myy; } @Override public double getMyz() { return myz; } @Override public double getTy() { return ty; } @Override public double getMzx() { return mzx; } @Override public double getMzy() { return mzy; } @Override public double getMzz() { return mzz; } @Override public double getTz() { return tz; } @Override public void impl_apply(Affine3D t) { t.concatenate( getMxx(), getMxy(), getMxz(), getTx(), getMyx(), getMyy(), getMyz(), getTy(), getMzx(), getMzy(), getMzz(), getTz()); } @Override public BaseTransform impl_derive(BaseTransform t) { return t.deriveWithConcatenation( getMxx(), getMxy(), getMxz(), getTx(), getMyx(), getMyy(), getMyz(), getTy(), getMzx(), getMzy(), getMzz(), getTz()); } } }