📄 affinetransform.java
字号:
m01 = Tx.m01; m10 = Tx.m10; m11 = 0.0; state = APPLY_TRANSLATE | APPLY_SHEAR; type = TYPE_UNKNOWN; return; } // If Tx has more than one attribute, it is not worth optimizing // all of those cases... T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02; T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12; switch (mystate) { default: stateError(); return; /* NOTREACHED */ case (APPLY_SHEAR | APPLY_SCALE): state = mystate | txstate; /* NOBREAK */ case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M0 = m00; M1 = m01; m00 = T00 * M0 + T10 * M1; m01 = T01 * M0 + T11 * M1; m02 += T02 * M0 + T12 * M1; M0 = m10; M1 = m11; m10 = T00 * M0 + T10 * M1; m11 = T01 * M0 + T11 * M1; m12 += T02 * M0 + T12 * M1; type = TYPE_UNKNOWN; return; case (APPLY_SHEAR | APPLY_TRANSLATE): case (APPLY_SHEAR): M0 = m01; m00 = T10 * M0; m01 = T11 * M0; m02 += T12 * M0; M0 = m10; m10 = T00 * M0; m11 = T01 * M0; m12 += T02 * M0; break; case (APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SCALE): M0 = m00; m00 = T00 * M0; m01 = T01 * M0; m02 += T02 * M0; M0 = m11; m10 = T10 * M0; m11 = T11 * M0; m12 += T12 * M0; break; case (APPLY_TRANSLATE): m00 = T00; m01 = T01; m02 += T02; m10 = T10; m11 = T11; m12 += T12; state = txstate | APPLY_TRANSLATE; type = TYPE_UNKNOWN; return; } updateState(); } /** * Concatenates an <code>AffineTransform</code> <code>Tx</code> to * this <code>AffineTransform</code> Cx * in a less commonly used way such that <code>Tx</code> modifies the * coordinate transformation relative to the absolute pixel * space rather than relative to the existing user space. * Cx is updated to perform the combined transformation. * Transforming a point p by the updated transform Cx' is * equivalent to first transforming p by the original transform * Cx and then transforming the result by * <code>Tx</code> like this: * Cx'(p) = Tx(Cx(p)) * In matrix notation, if this transform Cx * is represented by the matrix [this] and <code>Tx</code> is * represented by the matrix [Tx] then this method does the * following: * <pre> * [this] = [Tx] x [this] * </pre> * @param Tx the <code>AffineTransform</code> object to be * concatenated with this <code>AffineTransform</code> object. * @see #concatenate */ public void preConcatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; double T02, T12; int mystate = state; int txstate = Tx.state; switch ((txstate << HI_SHIFT) | mystate) { case (HI_IDENTITY | APPLY_IDENTITY): case (HI_IDENTITY | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SCALE): case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR): case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): // Tx is IDENTITY... return; case (HI_TRANSLATE | APPLY_IDENTITY): case (HI_TRANSLATE | APPLY_SCALE): case (HI_TRANSLATE | APPLY_SHEAR): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE): // Tx is TRANSLATE, this has no TRANSLATE m02 = Tx.m02; m12 = Tx.m12; state = mystate | APPLY_TRANSLATE; type |= TYPE_TRANSLATION; return; case (HI_TRANSLATE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): // Tx is TRANSLATE, this has one too m02 = m02 + Tx.m02; m12 = m12 + Tx.m12; return; case (HI_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_IDENTITY): // Only these two existing states need a new state state = mystate | APPLY_SCALE; /* NOBREAK */ case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE): case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR): case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SCALE): // Tx is SCALE, this is anything T00 = Tx.m00; T11 = Tx.m11; if ((mystate & APPLY_SHEAR) != 0) { m01 = m01 * T00; m10 = m10 * T11; if ((mystate & APPLY_SCALE) != 0) { m00 = m00 * T00; m11 = m11 * T11; } } else { m00 = m00 * T00; m11 = m11 * T11; } if ((mystate & APPLY_TRANSLATE) != 0) { m02 = m02 * T00; m12 = m12 * T11; } type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR): mystate = mystate | APPLY_SCALE; /* NOBREAK */ case (HI_SHEAR | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_IDENTITY): case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SCALE): state = mystate ^ APPLY_SHEAR; /* NOBREAK */ case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE): // Tx is SHEAR, this is anything T01 = Tx.m01; T10 = Tx.m10; M0 = m00; m00 = m10 * T01; m10 = M0 * T10; M0 = m01; m01 = m11 * T01; m11 = M0 * T10; M0 = m02; m02 = m12 * T01; m12 = M0 * T10; type = TYPE_UNKNOWN; return; } // If Tx has more than one attribute, it is not worth optimizing // all of those cases... T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02; T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12; switch (mystate) { default: stateError(); return; /* NOTREACHED */ case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M0 = m02; M1 = m12; T02 += M0 * T00 + M1 * T01; T12 += M0 * T10 + M1 * T11; /* NOBREAK */ case (APPLY_SHEAR | APPLY_SCALE): m02 = T02; m12 = T12; M0 = m00; M1 = m10; m00 = M0 * T00 + M1 * T01; m10 = M0 * T10 + M1 * T11; M0 = m01; M1 = m11; m01 = M0 * T00 + M1 * T01; m11 = M0 * T10 + M1 * T11; break; case (APPLY_SHEAR | APPLY_TRANSLATE): M0 = m02; M1 = m12; T02 += M0 * T00 + M1 * T01; T12 += M0 * T10 + M1 * T11; /* NOBREAK */ case (APPLY_SHEAR): m02 = T02; m12 = T12; M0 = m10; m00 = M0 * T01; m10 = M0 * T11; M0 = m01; m01 = M0 * T00; m11 = M0 * T10; break; case (APPLY_SCALE | APPLY_TRANSLATE): M0 = m02; M1 = m12; T02 += M0 * T00 + M1 * T01; T12 += M0 * T10 + M1 * T11; /* NOBREAK */ case (APPLY_SCALE): m02 = T02; m12 = T12; M0 = m00; m00 = M0 * T00; m10 = M0 * T10; M0 = m11; m01 = M0 * T01; m11 = M0 * T11; break; case (APPLY_TRANSLATE): M0 = m02; M1 = m12; T02 += M0 * T00 + M1 * T01; T12 += M0 * T10 + M1 * T11; /* NOBREAK */ case (APPLY_IDENTITY): m02 = T02; m12 = T12; m00 = T00; m10 = T10; m01 = T01; m11 = T11; state = mystate | txstate; type = TYPE_UNKNOWN; return; } updateState(); } /** * Returns an <code>AffineTransform</code> object representing the * inverse transformation. * The inverse transform Tx' of this transform Tx * maps coordinates transformed by Tx back * to their original coordinates. * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)). * <p> * If this transform maps all coordinates onto a point or a line * then it will not have an inverse, since coordinates that do * not lie on the destination point or line will not have an inverse * mapping. * The <code>getDeterminant</code> method can be used to determine if this * transform has no inverse, in which case an exception will be * thrown if the <code>createInverse</code> method is called. * @return a new <code>AffineTransform</code> object representing the * inverse transformation. * @see #getDeterminant * @exception NoninvertibleTransformException * if the matrix cannot be inverted. */ public AffineTransform createInverse() throws NoninvertibleTransformException { double det; switch (state) { default: stateError(); return null; /* NOTREACHED */ case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): det = m00 * m11 - m01 * m10; if (Math.abs(det) <= Double.MIN_VALUE) { throw new NoninvertibleTransformException("Determinant is "+ det); } return new AffineTransform( m11 / det, -m10 / det, -m01 / det, m00 / det, (m01 * m12 - m11 * m02) / det, (m10 * m02 - m00 * m12) / det, (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE)); case (APPLY_SHEAR | APPLY_SCALE): det = m00 * m11 - m01 * m10; if (Math.abs(det) <= Double.MIN_VALUE) { throw new NoninvertibleTransformException("Determinant is "+ det); } return new AffineTransform( m11 / det, -m10 / det, -m01 / det, m00 / det, 0.0, 0.0, (APPLY_SHEAR | APPLY_SCALE)); case (APPLY_SHEAR | APPLY_TRANSLATE): if (m01 == 0.0 || m10 == 0.0) { throw new NoninvertibleTransformException("Determinant is 0"); } return new AffineTransform( 0.0, 1.0 / m01, 1.0 / m10, 0.0, -m12 / m10, -m02 / m01, (APPLY_SHEAR | APPLY_TRANSLATE)); case (APPLY_SHEAR): if (m01 == 0.0 || m10 == 0.0) { throw new NoninvertibleTransformException("Determinant is 0"); } return new AffineTransform(0.0, 1.0 / m01, 1.0 / m10, 0.0, 0.0, 0.0, (APPLY_SHEAR)); case (APPLY_SCALE | APPLY_TRANSLATE): if (m00 == 0.0 || m11 == 0.0) { throw new NoninvertibleTransformException("Determinant is 0"); } return new AffineTransform( 1.0 / m00, 0.0, 0.0, 1.0 / m11, -m02 / m00, -m12 / m11, (APPLY_SCALE | APPLY_TRANSLATE)); case (APPLY_SCALE): if (m00 == 0.0 || m11 == 0.0) { throw new NoninvertibleTransformException("Determinant is 0"); } return new AffineTransform(1.0 / m00, 0.0, 0.0, 1.0 / m11, 0.0, 0.0, (APPLY_SCALE)); case (APPLY_TRANSLATE): return new AffineTransform( 1.0, 0.0, 0.0, 1.0, -m02, -m12, (APPLY_TRANSLATE)); case (APPLY_IDENTITY): return new AffineTransform(); } /* NOTREACHED */ } /** * Transforms the specified <code>ptSrc</code> and stores the result * in <code>ptDst</code>. * If <code>ptDst</code> is <code>null</code>, a new {@link Point2D} * object is allocated and then the result of the transformation is * stored in this object. * In either case, <code>ptDst</code>, which contains the * transformed point, is returned for convenience. * If <code>ptSrc</code> and <code>ptDst</code> are the same * object, the input point is correctly overwritten with * the transformed point. * @param ptSrc the specified <code>Point2D</code> to be transformed * @param ptDst the specified <code>Point2D</code> that stores the * result of transforming <code>ptSrc</code> * @return the <code>ptDst</code> after transforming * <code>ptSrc</code> and stroring the result in <code>ptDst</code>. */ public Point2D transform(Point2D ptSrc, Point2D ptDst) { if (ptDst == null) { if (ptSrc instanceof Point2D.Double) { ptDst = new Point2D.Double(); } else { ptDst = new Point2D.Float(); } } // Copy source coords into local variables in case src == dst double x = ptSrc.getX(); double y = ptS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -