📄 affinetransform.java
字号:
* different depending on whether the SHEAR flag is also set. * <pre> * SCALE SHEAR TRANSLATE * m00/m11 m01/m10 m02/m12 * * IDENTITY 1.0 0.0 0.0 * TRANSLATE (TR) 1.0 0.0 not both 0.0 * SCALE (SC) not both 1.0 0.0 0.0 * TR | SC not both 1.0 0.0 not both 0.0 * SHEAR (SH) 0.0 not both 0.0 0.0 * TR | SH 0.0 not both 0.0 not both 0.0 * SC | SH not both 0.0 not both 0.0 0.0 * TR | SC | SH not both 0.0 not both 0.0 not both 0.0 * </pre> */ void updateState() { if (m01 == 0.0 && m10 == 0.0) { if (m00 == 1.0 && m11 == 1.0) { if (m02 == 0.0 && m12 == 0.0) { state = APPLY_IDENTITY; type = TYPE_IDENTITY; } else { state = APPLY_TRANSLATE; type = TYPE_TRANSLATION; } } else { if (m02 == 0.0 && m12 == 0.0) { state = APPLY_SCALE; type = TYPE_UNKNOWN; } else { state = (APPLY_SCALE | APPLY_TRANSLATE); type = TYPE_UNKNOWN; } } } else { if (m00 == 0.0 && m11 == 0.0) { if (m02 == 0.0 && m12 == 0.0) { state = APPLY_SHEAR; type = TYPE_UNKNOWN; } else { state = (APPLY_SHEAR | APPLY_TRANSLATE); type = TYPE_UNKNOWN; } } else { if (m02 == 0.0 && m12 == 0.0) { state = (APPLY_SHEAR | APPLY_SCALE); type = TYPE_UNKNOWN; } else { state = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE); type = TYPE_UNKNOWN; } } } } /* * Convenience method used internally to throw exceptions when * a case was forgotten in a switch statement. */ private void stateError() {//#ifdef notdef throw new InternalError("missing case in transform state switch");//#else System.out.println("missing case in transform state switch");//#endif } /** * Retrieves the 6 specifiable values in the 3x3 affine transformation * matrix and places them into an array of double precisions values. * The values are stored in the array as * { m00 m10 m01 m11 m02 m12 }. * An array of 4 doubles can also be specified, in which case only the * first four elements representing the non-transform * parts of the array are retrieved and the values are stored into * the array as { m00 m10 m01 m11 } * @param flatmatrix the double array used to store the returned * values. * @see #getScaleX * @see #getScaleY * @see #getShearX * @see #getShearY * @see #getTranslateX * @see #getTranslateY */ public void getMatrix(double[] flatmatrix) { flatmatrix[0] = m00; flatmatrix[1] = m10; flatmatrix[2] = m01; flatmatrix[3] = m11; if (flatmatrix.length > 5) { flatmatrix[4] = m02; flatmatrix[5] = m12; } } /** * Returns the X coordinate scaling element (m00) of the 3x3 * affine transformation matrix. * @return a double value that is the X coordinate of the scaling * element of the affine transformation matrix. * @see #getMatrix */ public double getScaleX() { return m00; } /** * Returns the Y coordinate scaling element (m11) of the 3x3 * affine transformation matrix. * @return a double value that is the Y coordinate of the scaling * element of the affine transformation matrix. * @see #getMatrix */ public double getScaleY() { return m11; } /** * Returns the X coordinate shearing element (m01) of the 3x3 * affine transformation matrix. * @return a double value that is the X coordinate of the shearing * element of the affine transformation matrix. * @see #getMatrix */ public double getShearX() { return m01; } /** * Returns the Y coordinate shearing element (m10) of the 3x3 * affine transformation matrix. * @return a double value that is the Y coordinate of the shearing * element of the affine transformation matrix. * @see #getMatrix */ public double getShearY() { return m10; } /** * Returns the X coordinate of the translation element (m02) of the * 3x3 affine transformation matrix. * @return a double value that is the X coordinate of the translation * element of the affine transformation matrix. * @see #getMatrix */ public double getTranslateX() { return m02; } /** * Returns the Y coordinate of the translation element (m12) of the * 3x3 affine transformation matrix. * @return a double value that is the Y coordinate of the translation * element of the affine transformation matrix. * @see #getMatrix */ public double getTranslateY() { return m12; } /** * Concatenates this transform with a translation transformation. * This is equivalent to calling concatenate(T), where T is an * <code>AffineTransform</code> represented by the following matrix: * <pre> * [ 1 0 tx ] * [ 0 1 ty ] * [ 0 0 1 ] * </pre> * @param tx the distance by which coordinates are translated in the * X axis direction * @param ty the distance by which coordinates are translated in the * Y axis direction */ public void translate(double tx, double ty) { switch (state) { default: stateError(); break; /* NOTREACHED */ case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): m02 = tx * m00 + ty * m01 + m02; m12 = tx * m10 + ty * m11 + m12; if (m02 == 0.0 && m12 == 0.0) { state = APPLY_SHEAR | APPLY_SCALE; if (type != TYPE_UNKNOWN) { type -= TYPE_TRANSLATION; } } return; case (APPLY_SHEAR | APPLY_SCALE): m02 = tx * m00 + ty * m01; m12 = tx * m10 + ty * m11; if (m02 != 0.0 || m12 != 0.0) { state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE; type |= TYPE_TRANSLATION; } return; case (APPLY_SHEAR | APPLY_TRANSLATE): m02 = ty * m01 + m02; m12 = tx * m10 + m12; if (m02 == 0.0 && m12 == 0.0) { state = APPLY_SHEAR; if (type != TYPE_UNKNOWN) { type -= TYPE_TRANSLATION; } } return; case (APPLY_SHEAR): m02 = ty * m01; m12 = tx * m10; if (m02 != 0.0 || m12 != 0.0) { state = APPLY_SHEAR | APPLY_TRANSLATE; type |= TYPE_TRANSLATION; } return; case (APPLY_SCALE | APPLY_TRANSLATE): m02 = tx * m00 + m02; m12 = ty * m11 + m12; if (m02 == 0.0 && m12 == 0.0) { state = APPLY_SCALE; if (type != TYPE_UNKNOWN) { type -= TYPE_TRANSLATION; } } return; case (APPLY_SCALE): m02 = tx * m00; m12 = ty * m11; if (m02 != 0.0 || m12 != 0.0) { state = APPLY_SCALE | APPLY_TRANSLATE; type |= TYPE_TRANSLATION; } return; case (APPLY_TRANSLATE): m02 = tx + m02; m12 = ty + m12; if (m02 == 0.0 && m12 == 0.0) { state = APPLY_IDENTITY; type = TYPE_IDENTITY; } return; case (APPLY_IDENTITY): m02 = tx; m12 = ty; if (tx != 0.0 || ty != 0.0) { state = APPLY_TRANSLATE; type = TYPE_TRANSLATION; } return; } } /** * Concatenates this transform with a rotation transformation. * This is equivalent to calling concatenate(R), where R is an * <code>AffineTransform</code> represented by the following matrix: * <pre> * [ cos(theta) -sin(theta) 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 0 1 ] * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta the angle of rotation in radians */ public void rotate(double theta) { double sin = Math.sin(theta); double cos = Math.cos(theta); if (Math.abs(sin) < 1E-15) { if (cos < 0.0) { m00 = -m00; m11 = -m11; int state = this.state; if ((state & (APPLY_SHEAR)) != 0) { // If there was a shear, then this rotation has no // effect on the state. m01 = -m01; m10 = -m10; } else { // No shear means the SCALE state may toggle when // m00 and m11 are negated. if (m00 == 1.0 && m11 == 1.0) { this.state = state & ~APPLY_SCALE; } else { this.state = state | APPLY_SCALE; } } type = TYPE_UNKNOWN; } return; } if (Math.abs(cos) < 1E-15) { if (sin < 0.0) { double M0 = m00; m00 = -m01; m01 = M0; M0 = m10; m10 = -m11; m11 = M0; } else { double M0 = m00; m00 = m01; m01 = -M0; M0 = m10; m10 = m11; m11 = -M0; } int state = rot90conversion[this.state]; if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE && m00 == 1.0 && m11 == 1.0) { state -= APPLY_SCALE; } this.state = state; type = TYPE_UNKNOWN; return; } double M0, M1; M0 = m00; M1 = m01; m00 = cos * M0 + sin * M1; m01 = -sin * M0 + cos * M1; M0 = m10; M1 = m11; m10 = cos * M0 + sin * M1; m11 = -sin * M0 + cos * M1; updateState(); } private static int rot90conversion[] = { APPLY_SHEAR, APPLY_SHEAR | APPLY_TRANSLATE, APPLY_SHEAR, APPLY_SHEAR | APPLY_TRANSLATE, APPLY_SCALE, APPLY_SCALE | APPLY_TRANSLATE, APPLY_SHEAR | APPLY_SCALE, APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE, }; /** * Concatenates this transform with a transform that rotates * coordinates around an anchor point. * This operation is equivalent to translating the coordinates so * that the anchor point is at the origin (S1), then rotating them * about the new origin (S2), and finally translating so that the * intermediate origin is restored to the coordinates of the original * anchor point (S3). * <p> * This operation is equivalent to the following sequence of calls: * <pre> * translate(x, y); // S3: final translation * rotate(theta); // S2: rotate around anchor * translate(-x, -y); // S1: translate anchor to origin * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta the angle of rotation in radians * @param x, y the coordinates of the anchor point of the * rotation */ public void rotate(double theta, double x, double y) { // REMIND: Simple for now - optimize later translate(x, y); rotate(theta); translate(-x, -y); } /** * Concatenates this transform with a scaling transformation. * This is equivalent to calling concatenate(S), where S is an * <code>AffineTransform</code> represented by the following matrix: * <pre> * [ sx 0 0 ] * [ 0 sy 0 ] * [ 0 0 1 ] * </pre> * @param sx the factor by which coordinates are scaled along the * X axis direction * @param sy the factor by which coordinates are scaled along the * Y axis direction */ public void scale(double sx, double sy) { int state = this.state; switch (state) { default: stateError(); break; /* NOTREACHED */ case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): m00 *= sx; m11 *= sy; /* NOBREAK */ case (APPLY_SHEAR | APPLY_TRANSLATE): case (APPLY_SHEAR): m01 *= sy; m10 *= sx; if (m01 == 0 && m10 == 0) { this.state = state - APPLY_SHEAR; // REMIND: Is it possible for m00 and m11 to be both 1.0? } this.type = TYPE_UNKNOWN; return; case (APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SCALE): m00 *= sx; m11 *= sy; if (m00 == 1.0 && m11 == 1.0) { this.state = (state &= APPLY_TRANSLATE); this.type = (state == APPLY_IDENTITY ? TYPE_IDENTITY : TYPE_TRANSLATION); } else { this.type = TYPE_UNKNOWN; } return; case (APPLY_TRANSLATE): case (APPLY_IDENTITY):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -