📄 affinetransform.java
字号:
double n11 = tx.m10 * m01 + tx.m11 * m11; double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12; m00 = n00; m01 = n01; m02 = n02; m10 = n10; m11 = n11; m12 = n12; updateType(); } /** * Returns a transform, which if concatenated to this one, will result in * the identity transform. This is useful for undoing transformations, but * is only possible if the original transform has an inverse (ie. does not * map multiple points to the same line or point). A transform exists only * if getDeterminant() has a non-zero value. * * @return a new inverse transform * @throws NoninvertibleTransformException if inversion is not possible * @see #getDeterminant() */ public AffineTransform createInverse() throws NoninvertibleTransformException { double det = getDeterminant(); if (det == 0) throw new NoninvertibleTransformException("can't invert transform"); return new AffineTransform(m11 / det, -m10 / det, m01 / det, -m00 / det, -m02, -m12); } /** * Perform this transformation on the given source point, and store the * result in the destination (creating it if necessary). It is safe for * src and dst to be the same. * * @param src the source point * @param dst the destination, or null * @return the transformation of src, in dst if it was non-null * @throws NullPointerException if src is null */ public Point2D transform(Point2D src, Point2D dst) { if (dst == null) dst = new Point2D.Double(); double x = src.getX(); double y = src.getY(); double nx = m00 * x + m01 * y + m02; double ny = m10 * x + m11 * y + m12; dst.setLocation(nx, ny); return dst; } /** * Perform this transformation on an array of points, storing the results * in another (possibly same) array. This will not create a destination * array, but will create points for the null entries of the destination. * The transformation is done sequentially. While having a single source * and destination point be the same is safe, you should be aware that * duplicate references to the same point in the source, and having the * source overlap the destination, may result in your source points changing * from a previous transform before it is their turn to be evaluated. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points (may have null entries) * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null, or src has null * entries * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded * @throws ArrayStoreException if new points are incompatible with dst */ public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int num) { while (--num >= 0) dst[dstOff] = transform(src[srcOff++], dst[dstOff++]); } /** * Perform this transformation on an array of points, in (x,y) pairs, * storing the results in another (possibly same) array. This will not * create a destination array. All sources are copied before the * transformation, so that no result will overwrite a point that has not yet * been evaluated. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded */ public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int num) { if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) { float[] f = new float[2 * num]; System.arraycopy(srcPts, srcOff, f, 0, 2 * num); srcPts = f; } while (--num >= 0) { float x = srcPts[srcOff++]; float y = srcPts[srcOff++]; dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); dstPts[dstOff++] = (float) (m10 * x + m10 * y + m12); } } /** * Perform this transformation on an array of points, in (x,y) pairs, * storing the results in another (possibly same) array. This will not * create a destination array. All sources are copied before the * transformation, so that no result will overwrite a point that has not yet * been evaluated. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded */ public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) { if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) { double[] d = new double[2 * num]; System.arraycopy(srcPts, srcOff, d, 0, 2 * num); srcPts = d; } while (--num >= 0) { double x = srcPts[srcOff++]; double y = srcPts[srcOff++]; dstPts[dstOff++] = m00 * x + m01 * y + m02; dstPts[dstOff++] = m10 * x + m10 * y + m12; } } /** * Perform this transformation on an array of points, in (x,y) pairs, * storing the results in another array. This will not create a destination * array. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded */ public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) { while (--num >= 0) { float x = srcPts[srcOff++]; float y = srcPts[srcOff++]; dstPts[dstOff++] = m00 * x + m01 * y + m02; dstPts[dstOff++] = m10 * x + m10 * y + m12; } } /** * Perform this transformation on an array of points, in (x,y) pairs, * storing the results in another array. This will not create a destination * array. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded */ public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int num) { while (--num >= 0) { double x = srcPts[srcOff++]; double y = srcPts[srcOff++]; dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); dstPts[dstOff++] = (float) (m10 * x + m10 * y + m12); } } /** * Perform the inverse of this transformation on the given source point, * and store the result in the destination (creating it if necessary). It * is safe for src and dst to be the same. * * @param src the source point * @param dst the destination, or null * @return the inverse transformation of src, in dst if it was non-null * @throws NullPointerException if src is null * @throws NoninvertibleTransformException if the inverse does not exist * @see #getDeterminant() */ public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException { double det = getDeterminant(); if (det == 0) throw new NoninvertibleTransformException("couldn't invert transform"); if (dst == null) dst = new Point2D.Double(); double x = src.getX(); double y = src.getY(); double nx = (m11 * x + -m10 * y) / det - m02; double ny = (m01 * x + -m00 * y) / det - m12; dst.setLocation(nx, ny); return dst; } /** * Perform the inverse of this transformation on an array of points, in * (x,y) pairs, storing the results in another (possibly same) array. This * will not create a destination array. All sources are copied before the * transformation, so that no result will overwrite a point that has not yet * been evaluated. * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded * @throws NoninvertibleTransformException if the inverse does not exist * @see #getDeterminant() */ public void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) throws NoninvertibleTransformException { double det = getDeterminant(); if (det == 0) throw new NoninvertibleTransformException("couldn't invert transform"); if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) { double[] d = new double[2 * num]; System.arraycopy(srcPts, srcOff, d, 0, 2 * num); srcPts = d; } while (--num >= 0) { double x = srcPts[srcOff++]; double y = srcPts[srcOff++]; dstPts[dstOff++] = (m11 * x + -m10 * y) / det - m02; dstPts[dstOff++] = (m01 * x + -m00 * y) / det - m12; } } /** * Perform this transformation, less any translation, on the given source * point, and store the result in the destination (creating it if * necessary). It is safe for src and dst to be the same. The reduced * transform is equivalent to: * <pre> * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] * </pre> * * @param src the source point * @param dst the destination, or null * @return the delta transformation of src, in dst if it was non-null * @throws NullPointerException if src is null */ public Point2D deltaTransform(Point2D src, Point2D dst) { if (dst == null) dst = new Point2D.Double(); double x = src.getX(); double y = src.getY(); double nx = m00 * x + m01 * y; double ny = m10 * x + m11 * y; dst.setLocation(nx, ny); return dst; } /** * Perform this transformation, less any translation, on an array of points, * in (x,y) pairs, storing the results in another (possibly same) array. * This will not create a destination array. All sources are copied before * the transformation, so that no result will overwrite a point that has * not yet been evaluated. The reduced transform is equivalent to: * <pre> * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] * </pre> * * @param src the array of source points * @param srcOff the starting offset into src * @param dst the array of destination points * @param dstOff the starting offset into dst * @param num the number of points to transform * @throws NullPointerException if src or dst is null * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded */ public void deltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) { if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) { double[] d = new double[2 * num]; System.arraycopy(srcPts, srcOff, d, 0, 2 * num); srcPts = d; } while (--num >= 0) { double x = srcPts[srcOff++]; double y = srcPts[srcOff++]; dstPts[dstOff++] = m00 * x + m01 * y; dstPts[dstOff++] = m10 * x + m11 * y; } } /** * Return a new Shape, based on the given one, where the path of the shape * has been transformed by this transform. Notice that this uses GeneralPath, * which only stores points in float precision. * * @param src the shape source to transform * @return the shape, transformed by this * @throws NullPointerException if src is null * @see GeneralPath#transform(AffineTransform) */ public Shape createTransformedShape(Shape src) { GeneralPath p = new GeneralPath(src); p.transform(this); return p; } /** * Returns a string representation of the transform, in the format: * <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" * + m10 + ", " + m11 + ", " + m12 + "]]"</code>. * * @return the string representation */ public String toString() { return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" + m10 + ", " + m11 + ", " + m12 + "]]"; } /** * Tests if this transformation is the identity: * <pre> * [ 1 0 0 ] * [ 0 1 0 ] * [ 0 0 1 ] * </pre> * * @return true if this is the identity transform */ public boolean isIdentity() { // Rather than rely on type, check explicitly. return (m00 == 1 && m01 == 0 && m02 == 0 && m10 == 0 && m11 == 1 && m12 == 0); } /** * Create a new transform of the same run-time type, with the same * transforming properties as this one. * * @return the clone */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw (Error) new InternalError().initCause(e); // Impossible } } /** * Return the hashcode for this transformation. The formula is not * documented, but appears to be the same as: * <pre> * long l = Double.doubleToLongBits(getScaleX()); * l = l * 31 + Double.doubleToLongBits(getShearY()); * l = l * 31 + Double.doubleToLongBits(getShearX()); * l = l * 31 + Double.doubleToLongBits(getScaleY()); * l = l * 31 + Double.doubleToLongBits(getTranslateX()); * l = l * 31 + Double.doubleToLongBits(getTranslateY()); * return (int) ((l >> 32) ^ l); * </pre> * * @return the hashcode */ public int hashCode() { long l = Double.doubleToLongBits(m00); l = l * 31 + Double.doubleToLongBits(m10); l = l * 31 + Double.doubleToLongBits(m01); l = l * 31 + Double.doubleToLongBits(m11); l = l * 31 + Double.doubleToLongBits(m02); l = l * 31 + Double.doubleToLongBits(m12); return (int) ((l >> 32) ^ l); } /** * Compares two transforms for equality. This returns true if they have the * same matrix values. * * @param o the transform to compare * @return true if it is equal */ public boolean equals(Object obj) { if (! (obj instanceof AffineTransform)) return false; AffineTransform t = (AffineTransform) obj; return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02 && m10 == t.m10 && m11 == t.m11 && m12 == t.m12); } /** * Helper to decode the type from the matrix. This is not guaranteed * to find the optimal type, but at least it will be valid. */ private void updateType() { double det = getDeterminant(); if (det == 0) { type = TYPE_GENERAL_TRANSFORM; return; } // Scale (includes rotation by PI) or translation. if (m01 == 0 && m10 == 0) { if (m00 == m11) type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE; else type = TYPE_GENERAL_SCALE; if (m02 != 0 || m12 != 0) type |= TYPE_TRANSLATION; } // Rotation. else if (m00 == m11 && m01 == -m10) { type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION; if (det != 1) type |= TYPE_UNIFORM_SCALE; if (m02 != 0 || m12 != 0) type |= TYPE_TRANSLATION; } else type = TYPE_GENERAL_TRANSFORM; } /** * Reads a transform from an object stream. * * @param s the stream to read from * @throws ClassNotFoundException if there is a problem deserializing * @throws IOException if there is a problem deserializing */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); updateType(); }} // class AffineTransform
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -