Edit C:\Program Files\Java\jdk1.8.0_121\com\sun\javafx\geom\transform\Affine3D.java
/* * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.javafx.geom.transform; import com.sun.javafx.geom.BaseBounds; import com.sun.javafx.geom.Point2D; import com.sun.javafx.geom.Rectangle; import com.sun.javafx.geom.Vec3d; /** * */ public class Affine3D extends AffineBase { private double mxz; private double myz; private double mzx; private double mzy; private double mzz; private double mzt; public Affine3D() { mxx = myy = mzz = 1.0; // mxy = mxz = mxt = 0.0; /* Not needed. */ // myx = myz = myt = 0.0; /* Not needed. */ // mzx = mzy = mzt = 0.0; /* Not needed. */ // type = TYPE_IDENTITY; /* Not needed. */ } public Affine3D(BaseTransform transform) { setTransform(transform); } public Affine3D(double mxx, double mxy, double mxz, double mxt, double myx, double myy, double myz, double myt, double mzx, double mzy, double mzz, double mzt) { this.mxx = mxx; this.mxy = mxy; this.mxz = mxz; this.mxt = mxt; this.myx = myx; this.myy = myy; this.myz = myz; this.myt = myt; this.mzx = mzx; this.mzy = mzy; this.mzz = mzz; this.mzt = mzt; updateState(); } public Affine3D(Affine3D other) { this.mxx = other.mxx; this.mxy = other.mxy; this.mxz = other.mxz; this.mxt = other.mxt; this.myx = other.myx; this.myy = other.myy; this.myz = other.myz; this.myt = other.myt; this.mzx = other.mzx; this.mzy = other.mzy; this.mzz = other.mzz; this.mzt = other.mzt; this.state = other.state; this.type = other.type; } @Override public BaseTransform copy() { return new Affine3D(this); } @Override public Degree getDegree() { return Degree.AFFINE_3D; } @Override protected void reset3Delements() { this.mxz = 0.0; this.myz = 0.0; this.mzx = 0.0; this.mzy = 0.0; this.mzz = 1.0; this.mzt = 0.0; } @Override protected void updateState() { super.updateState(); if (!almostZero(mxz) || !almostZero(myz) || !almostZero(mzx) || !almostZero(mzy) || !almostOne(mzz) || !almostZero(mzt)) { state |= APPLY_3D; if (type != TYPE_UNKNOWN) { type |= TYPE_AFFINE_3D; } } } @Override public double getMxz() { return mxz; } @Override public double getMyz() { return myz; } @Override public double getMzx() { return mzx; } @Override public double getMzy() { return mzy; } @Override public double getMzz() { return mzz; } @Override public double getMzt() { return mzt; } @Override public double getDeterminant() { if ((state & APPLY_3D) == 0) { return super.getDeterminant(); } // D=a11{a22a33-a32a23} // +a12{a23a31-a33a21} // +a13{a21a32-a31a22} return (mxx * (myy * mzz - mzy * myz) + mxy * (myz * mzx - mzz * myx) + mxz * (myx * mzy - mzx * myy)); } public void setTransform(BaseTransform transform) { this.mxx = transform.getMxx(); this.mxy = transform.getMxy(); this.mxz = transform.getMxz(); this.mxt = transform.getMxt(); this.myx = transform.getMyx(); this.myy = transform.getMyy(); this.myz = transform.getMyz(); this.myt = transform.getMyt(); this.mzx = transform.getMzx(); this.mzy = transform.getMzy(); this.mzz = transform.getMzz(); this.mzt = transform.getMzt(); updateState(); } public void setTransform(double mxx, double mxy, double mxz, double mxt, double myx, double myy, double myz, double myt, double mzx, double mzy, double mzz, double mzt) { this.mxx = mxx; this.mxy = mxy; this.mxz = mxz; this.mxt = mxt; this.myx = myx; this.myy = myy; this.myz = myz; this.myt = myt; this.mzx = mzx; this.mzy = mzy; this.mzz = mzz; this.mzt = mzt; updateState(); } public void setToTranslation(double tx, double ty, double tz) { this.mxx = 1.0; this.mxy = 0.0; this.mxz = 0.0; this.mxt = tx; this.myx = 0.0; this.myy = 1.0; this.myz = 0.0; this.myt = ty; this.mzx = 0.0; this.mzy = 0.0; this.mzz = 1.0; this.mzt = tz; if (tz == 0.0) { if (tx == 0.0 && ty == 0.0) { state = APPLY_IDENTITY; type = TYPE_IDENTITY; } else { state = APPLY_TRANSLATE; type = TYPE_TRANSLATION; } } else { if (tx == 0.0 && ty == 0.0) { state = APPLY_3D; type = TYPE_AFFINE_3D; } else { state = APPLY_TRANSLATE | APPLY_3D; type = TYPE_TRANSLATION | TYPE_AFFINE_3D; } } } public void setToScale(double sx, double sy, double sz) { this.mxx = sx; this.mxy = 0.0; this.mxz = 0.0; this.mxt = 0.0; this.myx = 0.0; this.myy = sy; this.myz = 0.0; this.myt = 0.0; this.mzx = 0.0; this.mzy = 0.0; this.mzz = sz; this.mzt = 0.0; if (sz == 1.0) { if (sx == 1.0 && sy == 1.0) { state = APPLY_IDENTITY; type = TYPE_IDENTITY; } else { state = APPLY_SCALE; type = TYPE_UNKNOWN; } } else { if (sx == 1.0 && sy == 1.0) { state = APPLY_3D; type = TYPE_AFFINE_3D; } else { state = APPLY_SCALE | APPLY_3D; type = TYPE_UNKNOWN; } } } public void setToRotation(double theta, double axisX, double axisY, double axisZ, double pivotX, double pivotY, double pivotZ) { setToRotation(theta, axisX, axisY, axisZ); if (pivotX != 0.0 || pivotY != 0.0 || pivotZ != 0.0) { preTranslate(pivotX, pivotY, pivotZ); translate(-pivotX, -pivotY, -pivotZ); } } public void setToRotation(double theta, double axisX, double axisY, double axisZ) { double mag = Math.sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); if (almostZero(mag)) { setToIdentity(); return; } mag = 1.0 / mag; double ax = axisX * mag; double ay = axisY * mag; double az = axisZ * mag; double sinTheta = Math.sin(theta); double cosTheta = Math.cos(theta); double t = 1.0 - cosTheta; double xz = ax * az; double xy = ax * ay; double yz = ay * az; this.mxx = t * ax * ax + cosTheta; this.mxy = t * xy - sinTheta * az; this.mxz = t * xz + sinTheta * ay; this.mxt = 0.0; this.myx = t * xy + sinTheta * az; this.myy = t * ay * ay + cosTheta; this.myz = t * yz - sinTheta * ax; this.myt = 0.0; this.mzx = t * xz - sinTheta * ay; this.mzy = t * yz + sinTheta * ax; this.mzz = t * az * az + cosTheta; this.mzt = 0.0; updateState(); } @Override public BaseBounds transform(BaseBounds src, BaseBounds dst) { if ((state & APPLY_3D) == 0) { return dst = super.transform(src, dst); } switch (state) { default: /* NOBREAK */ // TODO: Optimize these cases ... (RT-26800) case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): /* NOBREAK */ case (APPLY_SHEAR | APPLY_SCALE): /* NOBREAK */ case (APPLY_SHEAR | APPLY_TRANSLATE): /* NOBREAK */ case (APPLY_SHEAR): Vec3d tempV3d = new Vec3d(); dst = TransformHelper.general3dBoundsTransform(this, src, dst, tempV3d); break; case (APPLY_SCALE | APPLY_TRANSLATE): dst = dst.deriveWithNewBoundsAndSort( (float) (src.getMinX() * mxx + mxt), (float) (src.getMinY() * myy + myt), (float) (src.getMinZ() * mzz + mzt), (float) (src.getMaxX() * mxx + mxt), (float) (src.getMaxY() * myy + myt), (float) (src.getMaxZ() * mzz + mzt)); break; case (APPLY_SCALE): dst = dst.deriveWithNewBoundsAndSort( (float) (src.getMinX() * mxx), (float) (src.getMinY() * myy), (float) (src.getMinZ() * mzz), (float) (src.getMaxX() * mxx), (float) (src.getMaxY() * myy), (float) (src.getMaxZ() * mzz)); break; case (APPLY_TRANSLATE): dst = dst.deriveWithNewBounds( (float) (src.getMinX() + mxt), (float) (src.getMinY() + myt), (float) (src.getMinZ() + mzt), (float) (src.getMaxX() + mxt), (float) (src.getMaxY() + myt), (float) (src.getMaxZ() + mzt)); break; case (APPLY_IDENTITY): if (src != dst) { dst = dst.deriveWithNewBounds(src); } break; } return dst; } @Override public Vec3d transform(Vec3d src, Vec3d dst) { if ((state & APPLY_3D) == 0) { return super.transform(src, dst); } if (dst == null) { dst = new Vec3d(); } double x = src.x; double y = src.y; double z = src.z; dst.x = mxx * x + mxy * y + mxz * z + mxt; dst.y = myx * x + myy * y + myz * z + myt; dst.z = mzx * x + mzy * y + mzz * z + mzt; return dst; } @Override public Vec3d deltaTransform(Vec3d src, Vec3d dst) { if ((state & APPLY_3D) == 0) { return super.deltaTransform(src, dst); } if (dst == null) { dst = new Vec3d(); } double x = src.x; double y = src.y; double z = src.z; dst.x = mxx * x + mxy * y + mxz * z; dst.y = myx * x + myy * y + myz * z; dst.z = mzx * x + mzy * y + mzz * z; return dst; } @Override public void inverseTransform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { super.inverseTransform(srcPts, srcOff, dstPts, dstOff, numPts); } else { // TODO: Optimize... (RT-26800) createInverse().transform(srcPts, srcOff, dstPts, dstOff, numPts); } } @Override public void inverseDeltaTransform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { super.inverseDeltaTransform(srcPts, srcOff, dstPts, dstOff, numPts); } else { // TODO: Optimize... (RT-26800) createInverse().deltaTransform(srcPts, srcOff, dstPts, dstOff, numPts); } } @Override public void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { super.inverseTransform(srcPts, srcOff, dstPts, dstOff, numPts); } else { // TODO: Optimize... (RT-26800) createInverse().transform(srcPts, srcOff, dstPts, dstOff, numPts); } } @Override public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { return super.inverseTransform(src, dst); } else { // TODO: Optimize... (RT-26800) return createInverse().transform(src, dst); } } @Override public Vec3d inverseTransform(Vec3d src, Vec3d dst) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { return super.inverseTransform(src, dst); } else { // TODO: Optimize... (RT-26800) return createInverse().transform(src, dst); } } @Override public Vec3d inverseDeltaTransform(Vec3d src, Vec3d dst) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { return super.inverseDeltaTransform(src, dst); } else { // TODO: Optimize... (RT-26800) return createInverse().deltaTransform(src, dst); } } @Override public BaseBounds inverseTransform(BaseBounds bounds, BaseBounds result) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { result = super.inverseTransform(bounds, result); } else { // TODO: Optimize... (RT-26800) result = createInverse().transform(bounds, result); } return result; } @Override public void inverseTransform(Rectangle bounds, Rectangle result) throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { super.inverseTransform(bounds, result); } else { // TODO: Optimize... (RT-26800) createInverse().transform(bounds, result); } } @Override public BaseTransform createInverse() throws NoninvertibleTransformException { BaseTransform t = copy(); t.invert(); return t; } @Override public void invert() throws NoninvertibleTransformException { if ((state & APPLY_3D) == 0) { super.invert(); return; } // InvM = Transpose(Cofactor(M)) / det(M) // Cofactor(M) = matrix of cofactors(0..3,0..3) // cofactor(r,c) = (-1 if r+c is odd) * minor(r,c) // minor(r,c) = det(M with row r and col c removed) // For an Affine3D matrix, minor(r, 3) is {0, 0, 0, det} // which generates {0, 0, 0, 1} and so can be ignored. // TODO: Inlining the minor calculations should allow them // to be simplified... (RT-26800) double cxx = minor(0, 0); double cyx = - minor(0, 1); double czx = minor(0, 2); double cxy = - minor(1, 0); double cyy = minor(1, 1); double czy = - minor(1, 2); double cxz = minor(2, 0); double cyz = - minor(2, 1); double czz = minor(2, 2); double cxt = - minor(3, 0); double cyt = minor(3, 1); double czt = - minor(3, 2); double det = getDeterminant(); mxx = cxx / det; mxy = cxy / det; mxz = cxz / det; mxt = cxt / det; myx = cyx / det; myy = cyy / det; myz = cyz / det; myt = cyt / det; mzx = czx / det; mzy = czy / det; mzz = czz / det; mzt = czt / det; updateState(); } private double minor(int row, int col) { double m00 = mxx, m01 = mxy, m02 = mxz; double m10 = myx, m11 = myy, m12 = myz; double m20 = mzx, m21 = mzy, m22 = mzz; switch (col) { case 0: m00 = m01; m10 = m11; m20 = m21; case 1: m01 = m02; m11 = m12; m21 = m22; case 2: m02 = mxt; m12 = myt; m22 = mzt; } 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); } @Override public Affine3D deriveWithNewTransform(BaseTransform tx) { setTransform(tx); return this; } @Override public Affine3D deriveWithTranslation(double tx, double ty) { translate(tx, ty, 0.0); return this; } @Override public void translate(double tx, double ty) { if ((state & APPLY_3D) == 0) { super.translate(tx, ty); } else { translate(tx, ty, 0.0); } } public void translate(double tx, double ty, double tz) { if ((state & APPLY_3D) == 0) { super.translate(tx, ty); if (tz != 0.0) { this.mzt = tz; state |= APPLY_3D; if (type != TYPE_UNKNOWN) { type |= TYPE_AFFINE_3D; } } return; } this.mxt = tx * mxx + ty * mxy + tz * mxz + mxt; this.myt = tx * myx + ty * myy + tz * myz + myt; this.mzt = tx * mzx + ty * mzy + tz * mzz + mzt; updateState(); } @Override public Affine3D deriveWithPreTranslation(double mxt, double myt) { preTranslate(mxt, myt, 0.0); return this; } @Override public BaseTransform deriveWithTranslation(double mxt, double myt, double mzt) { translate(mxt, myt, mzt); return this; } @Override public BaseTransform deriveWithScale(double mxx, double myy, double mzz) { scale(mxx, myy, mzz); return this; } @Override public BaseTransform deriveWithRotation(double theta, double axisX, double axisY, double axisZ) { rotate(theta, axisX, axisY, axisZ); return this; } public void preTranslate(double mxt, double myt, double mzt) { this.mxt += mxt; this.myt += myt; this.mzt += mzt; int clearflags = 0; int setflags = 0; if (this.mzt == 0.0) { if ((state & APPLY_3D) != 0) { // Might have become non-3D... updateState(); return; } } else { state |= APPLY_3D; setflags = TYPE_AFFINE_3D; } if (this.mxt == 0.0 && this.myt == 0.0) { state &= ~APPLY_TRANSLATE; clearflags = TYPE_TRANSLATION; } else { state |= APPLY_TRANSLATE; setflags |= TYPE_TRANSLATION; } if (type != TYPE_UNKNOWN) { type = ((type & ~clearflags) | setflags); } } @Override public void scale(double sx, double sy) { if ((state & APPLY_3D) == 0) { super.scale(sx, sy); } else { scale(sx, sy, 1.0); } } public void scale(double sx, double sy, double sz) { if ((state & APPLY_3D) == 0) { super.scale(sx, sy); if (sz != 1.0) { this.mzz = sz; state |= APPLY_3D; if (type != TYPE_UNKNOWN) { type |= TYPE_AFFINE_3D; } } return; } this.mxx *= sx; this.mxy *= sy; this.mxz *= sz; this.myx *= sx; this.myy *= sy; this.myz *= sz; this.mzx *= sx; this.mzy *= sy; this.mzz *= sz; // TODO: Optimize the state... (RT-26800) updateState(); } @Override public void rotate(double theta) { if ((state & APPLY_3D) == 0) { super.rotate(theta); } else { rotate(theta, 0, 0, 1); } } public void rotate(double theta, double axisX, double axisY, double axisZ) { if ((state & APPLY_3D) == 0 && almostZero(axisX) && almostZero(axisY)) { if (axisZ > 0) { super.rotate(theta); } else if (axisZ < 0) { super.rotate(-theta); } // else rotating about zero vector - NOP return; } double mag = Math.sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); if (almostZero(mag)) { return; } mag = 1.0 / mag; double ax = axisX * mag; double ay = axisY * mag; double az = axisZ * mag; double sinTheta = Math.sin(theta); double cosTheta = Math.cos(theta); double t = 1.0 - cosTheta; double xz = ax * az; double xy = ax * ay; double yz = ay * az; double Txx = t * ax * ax + cosTheta; double Txy = t * xy - sinTheta * az; double Txz = t * xz + sinTheta * ay; double Tyx = t * xy + sinTheta * az; double Tyy = t * ay * ay + cosTheta; double Tyz = t * yz - sinTheta * ax; double Tzx = t * xz - sinTheta * ay; double Tzy = t * yz + sinTheta * ax; double Tzz = t * az * az + cosTheta; double rxx = (mxx * Txx + mxy * Tyx + mxz * Tzx /* + mxt * 0.0 */); double rxy = (mxx * Txy + mxy * Tyy + mxz * Tzy /* + mxt * 0.0 */); double rxz = (mxx * Txz + mxy * Tyz + mxz * Tzz /* + mxt * 0.0 */); double ryx = (myx * Txx + myy * Tyx + myz * Tzx /* + myt * 0.0 */); double ryy = (myx * Txy + myy * Tyy + myz * Tzy /* + myt * 0.0 */); double ryz = (myx * Txz + myy * Tyz + myz * Tzz /* + myt * 0.0 */); double rzx = (mzx * Txx + mzy * Tyx + mzz * Tzx /* + mzt * 0.0 */); double rzy = (mzx * Txy + mzy * Tyy + mzz * Tzy /* + mzt * 0.0 */); double rzz = (mzx * Txz + mzy * Tyz + mzz * Tzz /* + mzt * 0.0 */); this.mxx = rxx; this.mxy = rxy; this.mxz = rxz; this.myx = ryx; this.myy = ryy; this.myz = ryz; this.mzx = rzx; this.mzy = rzy; this.mzz = rzz; updateState(); } @Override public void shear(double shx, double shy) { if ((state & APPLY_3D) == 0) { super.shear(shx, shy); return; } double rxx = (mxx + mxy * shy); double rxy = (mxy + mxx * shx); double ryx = (myx + myy * shy); double ryy = (myy + myx * shx); double rzx = (mzx + mzy * shy); double rzy = (mzy + mzx * shx); this.mxx = rxx; this.mxy = rxy; this.myx = ryx; this.myy = ryy; this.mzx = rzx; this.mzy = rzy; updateState(); } @Override public Affine3D deriveWithConcatenation(BaseTransform transform) { concatenate(transform); return this; } @Override public Affine3D deriveWithPreConcatenation(BaseTransform transform) { preConcatenate(transform); return this; } @Override public void concatenate(BaseTransform transform) { switch (transform.getDegree()) { case IDENTITY: return; case TRANSLATE_2D: translate(transform.getMxt(), transform.getMyt()); return; case TRANSLATE_3D: translate(transform.getMxt(), transform.getMyt(), transform.getMzt()); return; case AFFINE_3D: if (!transform.is2D()) { break; } /* No Break */ case AFFINE_2D: if ((state & APPLY_3D) == 0) { super.concatenate(transform); return; } break; } double Txx = transform.getMxx(); double Txy = transform.getMxy(); double Txz = transform.getMxz(); double Txt = transform.getMxt(); double Tyx = transform.getMyx(); double Tyy = transform.getMyy(); double Tyz = transform.getMyz(); double Tyt = transform.getMyt(); double Tzx = transform.getMzx(); double Tzy = transform.getMzy(); double Tzz = transform.getMzz(); double Tzt = transform.getMzt(); double rxx = (mxx * Txx + mxy * Tyx + mxz * Tzx /* + mxt * 0.0 */); double rxy = (mxx * Txy + mxy * Tyy + mxz * Tzy /* + mxt * 0.0 */); double rxz = (mxx * Txz + mxy * Tyz + mxz * Tzz /* + mxt * 0.0 */); double rxt = (mxx * Txt + mxy * Tyt + mxz * Tzt + mxt /* * 1.0 */); double ryx = (myx * Txx + myy * Tyx + myz * Tzx /* + myt * 0.0 */); double ryy = (myx * Txy + myy * Tyy + myz * Tzy /* + myt * 0.0 */); double ryz = (myx * Txz + myy * Tyz + myz * Tzz /* + myt * 0.0 */); double ryt = (myx * Txt + myy * Tyt + myz * Tzt + myt /* * 1.0 */); double rzx = (mzx * Txx + mzy * Tyx + mzz * Tzx /* + mzt * 0.0 */); double rzy = (mzx * Txy + mzy * Tyy + mzz * Tzy /* + mzt * 0.0 */); double rzz = (mzx * Txz + mzy * Tyz + mzz * Tzz /* + mzt * 0.0 */); double rzt = (mzx * Txt + mzy * Tyt + mzz * Tzt + mzt /* * 1.0 */); this.mxx = rxx; this.mxy = rxy; this.mxz = rxz; this.mxt = rxt; this.myx = ryx; this.myy = ryy; this.myz = ryz; this.myt = ryt; this.mzx = rzx; this.mzy = rzy; this.mzz = rzz; this.mzt = rzt; updateState(); } public void concatenate(double Txx, double Txy, double Txz, double Txt, double Tyx, double Tyy, double Tyz, double Tyt, double Tzx, double Tzy, double Tzz, double Tzt) { double rxx = (mxx * Txx + mxy * Tyx + mxz * Tzx /* + mxt * 0.0 */); double rxy = (mxx * Txy + mxy * Tyy + mxz * Tzy /* + mxt * 0.0 */); double rxz = (mxx * Txz + mxy * Tyz + mxz * Tzz /* + mxt * 0.0 */); double rxt = (mxx * Txt + mxy * Tyt + mxz * Tzt + mxt /* * 1.0 */); double ryx = (myx * Txx + myy * Tyx + myz * Tzx /* + myt * 0.0 */); double ryy = (myx * Txy + myy * Tyy + myz * Tzy /* + myt * 0.0 */); double ryz = (myx * Txz + myy * Tyz + myz * Tzz /* + myt * 0.0 */); double ryt = (myx * Txt + myy * Tyt + myz * Tzt + myt /* * 1.0 */); double rzx = (mzx * Txx + mzy * Tyx + mzz * Tzx /* + mzt * 0.0 */); double rzy = (mzx * Txy + mzy * Tyy + mzz * Tzy /* + mzt * 0.0 */); double rzz = (mzx * Txz + mzy * Tyz + mzz * Tzz /* + mzt * 0.0 */); double rzt = (mzx * Txt + mzy * Tyt + mzz * Tzt + mzt /* * 1.0 */); this.mxx = rxx; this.mxy = rxy; this.mxz = rxz; this.mxt = rxt; this.myx = ryx; this.myy = ryy; this.myz = ryz; this.myt = ryt; this.mzx = rzx; this.mzy = rzy; this.mzz = rzz; this.mzt = rzt; updateState(); } @Override public Affine3D deriveWithConcatenation(double Txx, double Tyx, double Txy, double Tyy, double Txt, double Tyt) { double rxx = (mxx * Txx + mxy * Tyx /* + mxz * 0.0 + mxt * 0.0 */); double rxy = (mxx * Txy + mxy * Tyy /* + mxz * 0.0 + mxt * 0.0 */); // double rxz = (mxz /* * 1.0 + mxx * 0.0 + mxy * 0.0 + mxt * 0.0 */); double rxt = (mxx * Txt + mxy * Tyt + mxt /* + mxz * 0.0 * 1.0 */); double ryx = (myx * Txx + myy * Tyx /* + myz * 0.0 + myt * 0.0 */); double ryy = (myx * Txy + myy * Tyy /* + myz * 0.0 + myt * 0.0 */); // double ryz = (myz /* * 1.0 + myx * 0.0 + myy * 0.0 + myt * 0.0 */); double ryt = (myx * Txt + myy * Tyt + myt /* * 1.0 + myz * 0.0 */); double rzx = (mzx * Txx + mzy * Tyx /* + mzz * 0.0 + mzt * 0.0 */); double rzy = (mzx * Txy + mzy * Tyy /* + mzz * 0.0 + mzt * 0.0 */); // double rzz = (mzz /* * 1.0 + mzx * 0.0 + mzy * 0.0 + mzt * 0.0 */); double rzt = (mzx * Txt + mzy * Tyt + mzt /* * 1.0 + mzz * 0.0 */); this.mxx = rxx; this.mxy = rxy; // this.mxz = rxz; // == mxz anyway this.mxt = rxt; this.myx = ryx; this.myy = ryy; // this.myz = ryz; // == myz anyway this.myt = ryt; this.mzx = rzx; this.mzy = rzy; // this.mzz = rzz; // == mzz anyway this.mzt = rzt; updateState(); return this; } @Override public BaseTransform deriveWithConcatenation( double mxx, double mxy, double mxz, double mxt, double myx, double myy, double myz, double myt, double mzx, double mzy, double mzz, double mzt) { concatenate(mxx, mxy, mxz, mxt, myx, myy, myz, myt, mzx, mzy, mzz, mzt); return this; } public void preConcatenate(BaseTransform transform) { switch (transform.getDegree()) { case IDENTITY: return; case TRANSLATE_2D: preTranslate(transform.getMxt(), transform.getMyt(), 0.0); return; case TRANSLATE_3D: preTranslate(transform.getMxt(), transform.getMyt(), transform.getMzt()); return; } double Txx = transform.getMxx(); double Txy = transform.getMxy(); double Txz = transform.getMxz(); double Txt = transform.getMxt(); double Tyx = transform.getMyx(); double Tyy = transform.getMyy(); double Tyz = transform.getMyz(); double Tyt = transform.getMyt(); double Tzx = transform.getMzx(); double Tzy = transform.getMzy(); double Tzz = transform.getMzz(); double Tzt = transform.getMzt(); double rxx = (Txx * mxx + Txy * myx + Txz * mzx /* + Txt * 0.0 */); double rxy = (Txx * mxy + Txy * myy + Txz * mzy /* + Txt * 0.0 */); double rxz = (Txx * mxz + Txy * myz + Txz * mzz /* + Txt * 0.0 */); double rxt = (Txx * mxt + Txy * myt + Txz * mzt + Txt /* * 1.0 */); double ryx = (Tyx * mxx + Tyy * myx + Tyz * mzx /* + Tyt * 0.0 */); double ryy = (Tyx * mxy + Tyy * myy + Tyz * mzy /* + Tyt * 0.0 */); double ryz = (Tyx * mxz + Tyy * myz + Tyz * mzz /* + Tyt * 0.0 */); double ryt = (Tyx * mxt + Tyy * myt + Tyz * mzt + Tyt /* * 1.0 */); double rzx = (Tzx * mxx + Tzy * myx + Tzz * mzx /* + Tzt * 0.0 */); double rzy = (Tzx * mxy + Tzy * myy + Tzz * mzy /* + Tzt * 0.0 */); double rzz = (Tzx * mxz + Tzy * myz + Tzz * mzz /* + Tzt * 0.0 */); double rzt = (Tzx * mxt + Tzy * myt + Tzz * mzt + Tzt /* * 1.0 */); this.mxx = rxx; this.mxy = rxy; this.mxz = rxz; this.mxt = rxt; this.myx = ryx; this.myy = ryy; this.myz = ryz; this.myt = ryt; this.mzx = rzx; this.mzy = rzy; this.mzz = rzz; this.mzt = rzt; updateState(); } @Override public void restoreTransform(double mxx, double myx, double mxy, double myy, double mxt, double myt) { throw new InternalError("must use Affine3D restore method "+ "to prevent loss of information"); } @Override public void restoreTransform(double mxx, double mxy, double mxz, double mxt, double myx, double myy, double myz, double myt, double mzx, double mzy, double mzz, double mzt) { this.mxx = mxx; this.mxy = mxy; this.mxz = mxz; this.mxt = mxt; this.myx = myx; this.myy = myy; this.myz = myz; this.myt = myt; this.mzx = mzx; this.mzy = mzy; this.mzz = mzz; this.mzt = mzt; updateState(); } /** * Sets this transform to a viewing transform computed from the specified * eye point, center point, and up vector. * The resulting transform can be used as the view transform * in a 3D camera. * * @param eye the eye point * * @param center the center point * * @param up the up vector * * @return this transform */ public Affine3D lookAt(Vec3d eye, Vec3d center, Vec3d up) { double forwardx, forwardy, forwardz, invMag; double upx, upy, upz; double sidex, sidey, sidez; forwardx = eye.x - center.x; forwardy = eye.y - center.y; forwardz = eye.z - center.z; invMag = 1.0 / Math.sqrt(forwardx * forwardx + forwardy * forwardy + forwardz * forwardz); forwardx = forwardx * invMag; forwardy = forwardy * invMag; forwardz = forwardz * invMag; invMag = 1.0 / Math.sqrt(up.x * up.x + up.y * up.y + up.z * up.z); upx = up.x * invMag; upy = up.y * invMag; upz = up.z * invMag; // side = Up cross forward sidex = upy * forwardz - forwardy * upz; sidey = upz * forwardx - upx * forwardz; sidez = upx * forwardy - upy * forwardx; invMag = 1.0 / Math.sqrt(sidex * sidex + sidey * sidey + sidez * sidez); sidex *= invMag; sidey *= invMag; sidez *= invMag; // recompute up = forward cross side upx = forwardy * sidez - sidey * forwardz; upy = forwardz * sidex - forwardx * sidez; upz = forwardx * sidey - forwardy * sidex; // transpose because we calculated the inverse of what we want mxx = sidex; mxy = sidey; mxz = sidez; myx = upx; myy = upy; myz = upz; mzx = forwardx; mzy = forwardy; mzz = forwardz; mxt = -eye.x * mxx + -eye.y * mxy + -eye.z * mxz; myt = -eye.x * myx + -eye.y * myy + -eye.z * myz; mzt = -eye.x * mzx + -eye.y * mzy + -eye.z * mzz; updateState(); return this; } static boolean almostOne(double a) { return ((a < 1+EPSILON_ABSOLUTE) && (a > 1-EPSILON_ABSOLUTE)); } // Round values to sane precision for printing // Note that Math.sin(Math.PI) has an error of about 10^-16 private static double _matround(double matval) { return Math.rint(matval * 1E15) / 1E15; } /** * Returns a <code>String</code> that represents the value of this * {@link Object}. * @return a <code>String</code> representing the value of this * <code>Object</code>. */ @Override public String toString() { return ("Affine3D[[" + _matround(mxx) + ", " + _matround(mxy) + ", " + _matround(mxz) + ", " + _matround(mxt) + "], [" + _matround(myx) + ", " + _matround(myy) + ", " + _matround(myz) + ", " + _matround(myt) + "], [" + _matround(mzx) + ", " + _matround(mzy) + ", " + _matround(mzz) + ", " + _matround(mzt) + "]]"); } }
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de