/*
 * Copyright (c) 2009, 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 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.Shape;
import com.sun.javafx.geom.Vec3d;

/**
 *
 */
public abstract class BaseTransform implements CanTransformVec3d{
    public static final BaseTransform IDENTITY_TRANSFORM = new Identity();

    public static enum Degree {
        IDENTITY,
        TRANSLATE_2D,
        AFFINE_2D,
        TRANSLATE_3D,
        AFFINE_3D,
    }

    /*
     * This constant is only useful for a cached type field.
     * It indicates that the type has been decached and must be recalculated.
     */
    protected static final int TYPE_UNKNOWN = -1;

    
This constant indicates that the transform defined by this object is an identity transform. An identity transform is one in which the output coordinates are always the same as the input coordinates. If this transform is anything other than the identity transform, the type will either be the constant GENERAL_TRANSFORM or a combination of the appropriate flag bits for the various coordinate conversions that this transform performs.
See Also:
/** * This constant indicates that the transform defined by this object * is an identity transform. * An identity transform is one in which the output coordinates are * always the same as the input coordinates. * If this transform is anything other than the identity transform, * the type will either be the constant GENERAL_TRANSFORM or a * combination of the appropriate flag bits for the various coordinate * conversions that this transform performs. * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_IDENTITY = 0;
This flag bit indicates that the transform defined by this object performs a translation in addition to the conversions indicated by other flag bits. A translation moves the coordinates by a constant amount in x and y without changing the length or angle of vectors.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a translation in addition to the conversions indicated * by other flag bits. * A translation moves the coordinates by a constant amount in x * and y without changing the length or angle of vectors. * @see #TYPE_IDENTITY * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_TRANSLATION = 1;
This flag bit indicates that the transform defined by this object performs a uniform scale in addition to the conversions indicated by other flag bits. A uniform scale multiplies the length of vectors by the same amount in both the x and y directions without changing the angle between vectors. This flag bit is mutually exclusive with the TYPE_GENERAL_SCALE flag.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a uniform scale in addition to the conversions indicated * by other flag bits. * A uniform scale multiplies the length of vectors by the same amount * in both the x and y directions without changing the angle between * vectors. * This flag bit is mutually exclusive with the TYPE_GENERAL_SCALE flag. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_UNIFORM_SCALE = 2;
This flag bit indicates that the transform defined by this object performs a general scale in addition to the conversions indicated by other flag bits. A general scale multiplies the length of vectors by different amounts in the x and y directions without changing the angle between perpendicular vectors. This flag bit is mutually exclusive with the TYPE_UNIFORM_SCALE flag.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a general scale in addition to the conversions indicated * by other flag bits. * A general scale multiplies the length of vectors by different * amounts in the x and y directions without changing the angle * between perpendicular vectors. * This flag bit is mutually exclusive with the TYPE_UNIFORM_SCALE flag. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_GENERAL_SCALE = 4;
This constant is a bit mask for any of the scale flag bits.
See Also:
/** * This constant is a bit mask for any of the scale flag bits. * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE */
public static final int TYPE_MASK_SCALE = (TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE);
This flag bit indicates that the transform defined by this object performs a mirror image flip about some axis which changes the normally right handed coordinate system into a left handed system in addition to the conversions indicated by other flag bits. A right handed coordinate system is one where the positive X axis rotates counterclockwise to overlay the positive Y axis similar to the direction that the fingers on your right hand curl when you stare end on at your thumb. A left handed coordinate system is one where the positive X axis rotates clockwise to overlay the positive Y axis similar to the direction that the fingers on your left hand curl. There is no mathematical way to determine the angle of the original flipping or mirroring transformation since all angles of flip are identical given an appropriate adjusting rotation.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a mirror image flip about some axis which changes the * normally right handed coordinate system into a left handed * system in addition to the conversions indicated by other flag bits. * A right handed coordinate system is one where the positive X * axis rotates counterclockwise to overlay the positive Y axis * similar to the direction that the fingers on your right hand * curl when you stare end on at your thumb. * A left handed coordinate system is one where the positive X * axis rotates clockwise to overlay the positive Y axis similar * to the direction that the fingers on your left hand curl. * There is no mathematical way to determine the angle of the * original flipping or mirroring transformation since all angles * of flip are identical given an appropriate adjusting rotation. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_FLIP = 64; /* NOTE: TYPE_FLIP was added after GENERAL_TRANSFORM was in public * circulation and the flag bits could no longer be conveniently * renumbered without introducing binary incompatibility in outside * code. */
This flag bit indicates that the transform defined by this object performs a quadrant rotation by some multiple of 90 degrees in addition to the conversions indicated by other flag bits. A rotation changes the angles of vectors by the same amount regardless of the original direction of the vector and without changing the length of the vector. This flag bit is mutually exclusive with the TYPE_GENERAL_ROTATION flag.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a quadrant rotation by some multiple of 90 degrees in * addition to the conversions indicated by other flag bits. * A rotation changes the angles of vectors by the same amount * regardless of the original direction of the vector and without * changing the length of the vector. * This flag bit is mutually exclusive with the TYPE_GENERAL_ROTATION flag. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_QUADRANT_ROTATION = 8;
This flag bit indicates that the transform defined by this object performs a rotation by an arbitrary angle in addition to the conversions indicated by other flag bits. A rotation changes the angles of vectors by the same amount regardless of the original direction of the vector and without changing the length of the vector. This flag bit is mutually exclusive with the TYPE_QUADRANT_ROTATION flag.
See Also:
/** * This flag bit indicates that the transform defined by this object * performs a rotation by an arbitrary angle in addition to the * conversions indicated by other flag bits. * A rotation changes the angles of vectors by the same amount * regardless of the original direction of the vector and without * changing the length of the vector. * This flag bit is mutually exclusive with the * TYPE_QUADRANT_ROTATION flag. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_TRANSFORM * @see #getType */
public static final int TYPE_GENERAL_ROTATION = 16;
This constant is a bit mask for any of the rotation flag bits.
See Also:
/** * This constant is a bit mask for any of the rotation flag bits. * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION */
public static final int TYPE_MASK_ROTATION = (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION);
This constant indicates that the transform defined by this object performs an arbitrary conversion of the input coordinates. If this transform can be classified by any of the above constants, the type will either be the constant TYPE_IDENTITY or a combination of the appropriate flag bits for the various coordinate conversions that this transform performs.
See Also:
/** * This constant indicates that the transform defined by this object * performs an arbitrary conversion of the input coordinates. * If this transform can be classified by any of the above constants, * the type will either be the constant TYPE_IDENTITY or a * combination of the appropriate flag bits for the various coordinate * conversions that this transform performs. * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_FLIP * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #getType */
public static final int TYPE_GENERAL_TRANSFORM = 32; public static final int TYPE_AFFINE2D_MASK = (TYPE_TRANSLATION | TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE | TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION | TYPE_GENERAL_TRANSFORM | TYPE_FLIP); public static final int TYPE_AFFINE_3D = 128; /* * Convenience method used internally to throw exceptions when * an operation of degree higher than AFFINE_2D is attempted. */ static void degreeError(Degree maxSupported) { throw new InternalError("does not support higher than "+ maxSupported+" operations"); } public static BaseTransform getInstance(BaseTransform tx) { if (tx.isIdentity()) { return IDENTITY_TRANSFORM; } else if (tx.isTranslateOrIdentity()) { return new Translate2D(tx); } else if (tx.is2D()) { return new Affine2D(tx); } return new Affine3D(tx); } public static BaseTransform getInstance(double mxx, double mxy, double mxz, double mxt, double myx, double myy, double myz, double myt, double mzx, double mzy, double mzz, double mzt) { if (mxz == 0.0 && myz == 0.0 && mzx == 0.0 && mzy == 0.0 && mzz == 1.0 && mzt == 0.0) { return getInstance(mxx, myx, mxy, myy, mxt, myt); } else { return new Affine3D(mxx, mxy, mxz, mxt, myx, myy, myz, myt, mzx, mzy, mzz, mzt); } } public static BaseTransform getInstance(double mxx, double myx, double mxy, double myy, double mxt, double myt) { if (mxx == 1.0 && myx == 0.0 && mxy == 0.0 && myy == 1.0) { return getTranslateInstance(mxt, myt); } else { return new Affine2D(mxx, myx, mxy, myy, mxt, myt); } } public static BaseTransform getTranslateInstance(double mxt, double myt) { if (mxt == 0.0 && myt == 0.0) { return IDENTITY_TRANSFORM; } else { return new Translate2D(mxt, myt); } } public static BaseTransform getScaleInstance(double mxx, double myy) { return getInstance(mxx, 0, 0, myy, 0, 0); } public static BaseTransform getRotateInstance(double theta, double x, double y) { Affine2D a = new Affine2D(); a.setToRotation(theta, x, y); return a; } public abstract Degree getDegree();
Retrieves the flag bits describing the conversion properties of this transform. The return value is either one of the constants TYPE_IDENTITY or TYPE_GENERAL_TRANSFORM, or a combination of the appriopriate flag bits. A valid combination of flag bits is an exclusive OR operation that can combine the TYPE_TRANSLATION flag bit in addition to either of the TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits as well as either of the TYPE_QUADRANT_ROTATION or TYPE_GENERAL_ROTATION flag bits.
See Also:
Returns:the OR combination of any of the indicated flags that apply to this transform
/** * Retrieves the flag bits describing the conversion properties of * this transform. * The return value is either one of the constants TYPE_IDENTITY * or TYPE_GENERAL_TRANSFORM, or a combination of the * appriopriate flag bits. * A valid combination of flag bits is an exclusive OR operation * that can combine * the TYPE_TRANSLATION flag bit * in addition to either of the * TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits * as well as either of the * TYPE_QUADRANT_ROTATION or TYPE_GENERAL_ROTATION flag bits. * @return the OR combination of any of the indicated flags that * apply to this transform * @see #TYPE_IDENTITY * @see #TYPE_TRANSLATION * @see #TYPE_UNIFORM_SCALE * @see #TYPE_GENERAL_SCALE * @see #TYPE_QUADRANT_ROTATION * @see #TYPE_GENERAL_ROTATION * @see #TYPE_GENERAL_TRANSFORM */
public abstract int getType(); public abstract boolean isIdentity(); public abstract boolean isTranslateOrIdentity(); public abstract boolean is2D(); public abstract double getDeterminant(); public double getMxx() { return 1.0; } public double getMxy() { return 0.0; } public double getMxz() { return 0.0; } public double getMxt() { return 0.0; } public double getMyx() { return 0.0; } public double getMyy() { return 1.0; } public double getMyz() { return 0.0; } public double getMyt() { return 0.0; } public double getMzx() { return 0.0; } public double getMzy() { return 0.0; } public double getMzz() { return 1.0; } public double getMzt() { return 0.0; } public abstract Point2D transform(Point2D src, Point2D dst); public abstract Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException; public abstract Vec3d transform(Vec3d src, Vec3d dst); public abstract Vec3d deltaTransform(Vec3d src, Vec3d dst); public abstract Vec3d inverseTransform(Vec3d src, Vec3d dst) throws NoninvertibleTransformException; public abstract Vec3d inverseDeltaTransform(Vec3d src, Vec3d dst) throws NoninvertibleTransformException; public abstract void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts); public abstract void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts); public abstract void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts); public abstract void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts); public abstract void deltaTransform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts); public abstract void deltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts); public abstract void inverseTransform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException; public abstract void inverseDeltaTransform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException; public abstract void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws NoninvertibleTransformException; public abstract BaseBounds transform(BaseBounds bounds, BaseBounds result); public abstract void transform(Rectangle rect, Rectangle result); public abstract BaseBounds inverseTransform(BaseBounds bounds, BaseBounds result) throws NoninvertibleTransformException; public abstract void inverseTransform(Rectangle rect, Rectangle result) throws NoninvertibleTransformException; public abstract Shape createTransformedShape(Shape s); public abstract void setToIdentity(); public abstract void setTransform(BaseTransform xform);
This function inverts the BaseTransform in place. All current implementations can support their own inverted form, and that should likely remain true in the future as well.
/** * This function inverts the {@code BaseTransform} in place. All * current implementations can support their own inverted form, and * that should likely remain true in the future as well. */
public abstract void invert() throws NoninvertibleTransformException;
This function is only guaranteed to succeed if the transform is of degree AFFINE2D or less and the matrix parameters specified came from this same instance. In practice, they will also tend to succeed if they specify a transform of Degree less than or equal to the Degree of this instance as well, but the intent of this method is to restore the transform that had been read out of this transform into local variables.
/** * This function is only guaranteed to succeed if the transform is * of degree AFFINE2D or less and the matrix * parameters specified came from this same instance. In practice, * they will also tend to succeed if they specify a transform of * Degree less than or equal to the Degree of this instance as well, * but the intent of this method is to restore the transform that * had been read out of this transform into local variables. */
public abstract void restoreTransform(double mxx, double myx, double mxy, double myy, double mxt, double myt);
This function is only guaranteed to succeed if the matrix parameters specified came from this same instance. In practice, they will also tend to succeed if they specify a transform of Degree less than or equal to the Degree of this instance as well, but the intent of this method is to restore the transform that had been read out of this transform into local variables.
/** * This function is only guaranteed to succeed if the matrix * parameters specified came from this same instance. In practice, * they will also tend to succeed if they specify a transform of * Degree less than or equal to the Degree of this instance as well, * but the intent of this method is to restore the transform that * had been read out of this transform into local variables. */
public abstract 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); public abstract BaseTransform deriveWithTranslation(double mxt, double myt); public abstract BaseTransform deriveWithTranslation(double mxt, double myt, double mzt); public abstract BaseTransform deriveWithScale(double mxx, double myy, double mzz); public abstract BaseTransform deriveWithRotation(double theta, double axisX, double axisY, double axisZ); public abstract BaseTransform deriveWithPreTranslation(double mxt, double myt); public abstract BaseTransform deriveWithConcatenation(double mxx, double myx, double mxy, double myy, double mxt, double myt); public abstract 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); public abstract BaseTransform deriveWithPreConcatenation(BaseTransform transform); public abstract BaseTransform deriveWithConcatenation(BaseTransform tx); public abstract BaseTransform deriveWithNewTransform(BaseTransform tx);
This function always returns a new object, unless the transform is an identity transform in which case it might return the Identity singleton.
Returns:a new transform representing the inverse of this transform.
/** * This function always returns a new object, unless the transform * is an identity transform in which case it might return the * {@code Identity} singleton. * @return a new transform representing the inverse of this transform. */
public abstract BaseTransform createInverse() throws NoninvertibleTransformException; public abstract BaseTransform copy();
Returns the hashcode for this transform.
Returns: a hash code for this transform.
/** * Returns the hashcode for this transform. * @return a hash code for this transform. */
@Override public int hashCode() { if (isIdentity()) return 0; long bits = 0; bits = bits * 31 + Double.doubleToLongBits(getMzz()); bits = bits * 31 + Double.doubleToLongBits(getMzy()); bits = bits * 31 + Double.doubleToLongBits(getMzx()); bits = bits * 31 + Double.doubleToLongBits(getMyz()); bits = bits * 31 + Double.doubleToLongBits(getMxz()); bits = bits * 31 + Double.doubleToLongBits(getMyy()); bits = bits * 31 + Double.doubleToLongBits(getMyx()); bits = bits * 31 + Double.doubleToLongBits(getMxy()); bits = bits * 31 + Double.doubleToLongBits(getMxx()); bits = bits * 31 + Double.doubleToLongBits(getMzt()); bits = bits * 31 + Double.doubleToLongBits(getMyt()); bits = bits * 31 + Double.doubleToLongBits(getMxt()); return (((int) bits) ^ ((int) (bits >> 32))); }
Returns true if this BaseTransform represents the same coordinate transform as the specified argument.
Params:
  • obj – the Object to test for equality with this BaseTransform
Returns:true if obj equals this BaseTransform object; false otherwise.
/** * Returns <code>true</code> if this <code>BaseTransform</code> * represents the same coordinate transform as the specified * argument. * @param obj the <code>Object</code> to test for equality with this * <code>BaseTransform</code> * @return <code>true</code> if <code>obj</code> equals this * <code>BaseTransform</code> object; <code>false</code> otherwise. */
@Override public boolean equals(Object obj) { if (!(obj instanceof BaseTransform)) { return false; } BaseTransform a = (BaseTransform) obj; return (getMxx() == a.getMxx() && getMxy() == a.getMxy() && getMxz() == a.getMxz() && getMxt() == a.getMxt() && getMyx() == a.getMyx() && getMyy() == a.getMyy() && getMyz() == a.getMyz() && getMyt() == a.getMyt() && getMzx() == a.getMzx() && getMzy() == a.getMzy() && getMzz() == a.getMzz() && getMzt() == a.getMzt()); } static Point2D makePoint(Point2D src, Point2D dst) { if (dst == null) { dst = new Point2D(); } return dst; } static final double EPSILON_ABSOLUTE = 1.0e-5; public static boolean almostZero(double a) { return ((a < EPSILON_ABSOLUTE) && (a > -EPSILON_ABSOLUTE)); }
Returns the matrix elements and degree of this transform as a string.
Returns: the matrix elements and degree of this transform
/** * Returns the matrix elements and degree of this transform as a string. * @return the matrix elements and degree of this transform */
@Override public String toString() { return "Matrix: degree " + getDegree() + "\n" + getMxx() + ", " + getMxy() + ", " + getMxz() + ", " + getMxt() + "\n" + getMyx() + ", " + getMyy() + ", " + getMyz() + ", " + getMyt() + "\n" + getMzx() + ", " + getMzy() + ", " + getMzz() + ", " + getMzt() + "\n"; } }