![JAR search and dependency download from the Maven repository](/logo.png)
eu.hansolo.fx.geometry.transform.AffineBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of charts Show documentation
Show all versions of charts Show documentation
Charts is a JavaFX 8 library containing different kind of charts
The newest version!
/*
* Copyright (c) 2017 by Gerrit Grunwald
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.hansolo.fx.geometry.transform;
import eu.hansolo.fx.geometry.BaseBounds;
import eu.hansolo.fx.geometry.Path;
import eu.hansolo.fx.geometry.RectBounds;
import eu.hansolo.fx.geometry.Rectangle;
import eu.hansolo.fx.geometry.Shape;
import eu.hansolo.fx.geometry.tools.NonInvertibleTransformException;
import eu.hansolo.fx.geometry.tools.Point;
public abstract class AffineBase extends BaseTransform {
protected static final int APPLY_IDENTITY = 0;
protected static final int APPLY_TRANSLATE = 1;
protected static final int APPLY_SCALE = 2;
protected static final int APPLY_SHEAR = 4;
protected static final int APPLY_2D_MASK = (APPLY_TRANSLATE | APPLY_SCALE | APPLY_SHEAR);
protected static final int APPLY_2D_DELTA_MASK = (APPLY_SCALE | APPLY_SHEAR);
protected static final int HI_SHIFT = 4;
protected static final int HI_IDENTITY = APPLY_IDENTITY << HI_SHIFT;
protected static final int HI_TRANSLATE = APPLY_TRANSLATE << HI_SHIFT;
protected static final int HI_SCALE = APPLY_SCALE << HI_SHIFT;
protected static final int HI_SHEAR = APPLY_SHEAR << HI_SHIFT;
protected double mxx;
protected double myx;
protected double mxy;
protected double myy;
protected double mxt;
protected double myt;
protected transient int state;
protected transient int type;
private static final int rot90conversion[] = {
/* IDENTITY => */ APPLY_SHEAR,
/* TRANSLATE (TR) => */ APPLY_SHEAR | APPLY_TRANSLATE,
/* SCALE (SC) => */ APPLY_SHEAR,
/* SC | TR => */ APPLY_SHEAR | APPLY_TRANSLATE,
/* SHEAR (SH) => */ APPLY_SCALE,
/* SH | TR => */ APPLY_SCALE | APPLY_TRANSLATE,
/* SH | SC => */ APPLY_SHEAR | APPLY_SCALE,
/* SH | SC | TR => */ APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE,
};
protected static void stateError() { throw new InternalError("missing case in transform state switch"); }
protected void updateState() {
if (mxy == 0.0 && myx == 0.0) {
if (mxx == 1.0 && myy == 1.0) {
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_IDENTITY;
type = TYPE_IDENTITY;
} else {
state = APPLY_TRANSLATE;
type = TYPE_TRANSLATION;
}
} else {
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_SCALE;
} else {
state = (APPLY_SCALE | APPLY_TRANSLATE);
}
type = TYPE_UNKNOWN;
}
} else {
if (mxx == 0.0 && myy == 0.0) {
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_SHEAR;
} else {
state = (APPLY_SHEAR | APPLY_TRANSLATE);
}
} else {
if (mxt == 0.0 && myt == 0.0) {
state = (APPLY_SHEAR | APPLY_SCALE);
} else {
state = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE);
}
}
type = TYPE_UNKNOWN;
}
}
public int getType() {
if (type == TYPE_UNKNOWN) {
updateState();
if (type == TYPE_UNKNOWN) { type = calculateType(); }
}
return type;
}
protected int calculateType() {
int ret = TYPE_IDENTITY;
boolean sgn0, sgn1;
switch (state & APPLY_2D_MASK) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
ret |= TYPE_TRANSLATION;
case (APPLY_SHEAR | APPLY_SCALE):
if (mxx * mxy + myx * myy != 0) {
ret |= TYPE_GENERAL_TRANSFORM;
break;
}
sgn0 = (mxx >= 0.0);
sgn1 = (myy >= 0.0);
if (sgn0 == sgn1) {
if (mxx != myy || mxy != -myx) {
ret |= (TYPE_GENERAL_ROTATION | TYPE_GENERAL_SCALE);
} else if (mxx * myy - mxy * myx != 1.0) {
ret |= (TYPE_GENERAL_ROTATION | TYPE_UNIFORM_SCALE);
} else {
ret |= TYPE_GENERAL_ROTATION;
}
} else {
if (mxx != -myy || mxy != myx) {
ret |= (TYPE_GENERAL_ROTATION |
TYPE_FLIP |
TYPE_GENERAL_SCALE);
} else if (mxx * myy - mxy * myx != 1.0) {
ret |= (TYPE_GENERAL_ROTATION |
TYPE_FLIP |
TYPE_UNIFORM_SCALE);
} else {
ret |= (TYPE_GENERAL_ROTATION | TYPE_FLIP);
}
}
break;
case (APPLY_SHEAR | APPLY_TRANSLATE):
ret |= TYPE_TRANSLATION;
case (APPLY_SHEAR):
sgn0 = (mxy >= 0.0);
sgn1 = (myx >= 0.0);
if (sgn0 != sgn1) {
if (mxy != -myx) {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
} else if (mxy != 1.0 && mxy != -1.0) {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
} else {
ret |= TYPE_QUADRANT_ROTATION;
}
} else {
if (mxy == myx) {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_FLIP | TYPE_UNIFORM_SCALE);
} else {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_FLIP | TYPE_GENERAL_SCALE);
}
}
break;
case (APPLY_SCALE | APPLY_TRANSLATE):
ret |= TYPE_TRANSLATION;
case (APPLY_SCALE):
sgn0 = (mxx >= 0.0);
sgn1 = (myy >= 0.0);
if (sgn0 == sgn1) {
if (sgn0) {
if (mxx == myy) {
ret |= TYPE_UNIFORM_SCALE;
} else {
ret |= TYPE_GENERAL_SCALE;
}
} else {
if (mxx != myy) {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
} else if (mxx != -1.0) {
ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
} else {
ret |= TYPE_QUADRANT_ROTATION;
}
}
} else {
if (mxx == -myy) {
if (mxx == 1.0 || mxx == -1.0) {
ret |= TYPE_FLIP;
} else {
ret |= (TYPE_FLIP | TYPE_UNIFORM_SCALE);
}
} else {
ret |= (TYPE_FLIP | TYPE_GENERAL_SCALE);
}
}
break;
case (APPLY_TRANSLATE):
ret |= TYPE_TRANSLATION;
break;
case (APPLY_IDENTITY):
break;
}
return ret;
}
@Override public double getMxx() { return mxx; }
@Override public double getMyy() { return myy; }
@Override public double getMxy() { return mxy; }
@Override public double getMyx() { return myx; }
@Override public double getMxt() { return mxt; }
@Override public double getMyt() { return myt; }
public boolean isIdentity() {
return (state == APPLY_IDENTITY || (getType() == TYPE_IDENTITY));
}
@Override public boolean isTranslateOrIdentity() {
return (state <= APPLY_TRANSLATE || (getType() <= TYPE_TRANSLATION));
}
public double getDeterminant() {
switch (state) {
default : stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE) : return mxx * myy - mxy * myx;
case (APPLY_SHEAR | APPLY_TRANSLATE) :
case (APPLY_SHEAR) : return -(mxy * myx);
case (APPLY_SCALE | APPLY_TRANSLATE) :
case (APPLY_SCALE) : return mxx * myy;
case (APPLY_TRANSLATE) :
case (APPLY_IDENTITY) : return 1.0;
}
}
public void setToIdentity() {
mxx = myy = 1.0;
myx = mxy = mxt = myt = 0.0;
state = APPLY_IDENTITY;
type = TYPE_IDENTITY;
}
public void setTransform(double mxx, double myx, double mxy, double myy, double mxt, double myt) {
this.mxx = mxx;
this.myx = myx;
this.mxy = mxy;
this.myy = myy;
this.mxt = mxt;
this.myt = myt;
updateState();
}
public void setToShear(double shx, double shy) {
mxx = 1.0;
mxy = shx;
myx = shy;
myy = 1.0;
mxt = 0.0;
myt = 0.0;
if (shx != 0.0 || shy != 0.0) {
state = (APPLY_SHEAR | APPLY_SCALE);
type = TYPE_UNKNOWN;
} else {
state = APPLY_IDENTITY;
type = TYPE_IDENTITY;
}
}
public Point transform(Point pt) { return transform(pt, pt); }
public Point transform(Point ptSrc, Point ptDst) {
if (ptDst == null) { ptDst = new Point(); }
double x = ptSrc.x;
double y = ptSrc.y;
switch (state & APPLY_2D_MASK) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
ptDst.set((x * mxx + y * mxy + mxt), (x * myx + y * myy + myt));
return ptDst;
case (APPLY_SHEAR | APPLY_SCALE):
ptDst.set((x * mxx + y * mxy), (x * myx + y * myy));
return ptDst;
case (APPLY_SHEAR | APPLY_TRANSLATE):
ptDst.set((y * mxy + mxt), (x * myx + myt));
return ptDst;
case (APPLY_SHEAR):
ptDst.set((y * mxy), (x * myx));
return ptDst;
case (APPLY_SCALE | APPLY_TRANSLATE):
ptDst.set((x * mxx + mxt), (y * myy + myt));
return ptDst;
case (APPLY_SCALE):
ptDst.set((x * mxx), (y * myy));
return ptDst;
case (APPLY_TRANSLATE):
ptDst.set((x + mxt), (y + myt));
return ptDst;
case (APPLY_IDENTITY):
ptDst.set(x, y);
return ptDst;
}
}
public BaseBounds transform(BaseBounds src, BaseBounds dst) {
return transform2DBounds((RectBounds)src, (RectBounds)dst);
}
public void transform(Rectangle src, Rectangle dst) {
switch (state & APPLY_2D_MASK) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
case (APPLY_SHEAR | APPLY_TRANSLATE):
case (APPLY_SHEAR):
case (APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SCALE):
RectBounds b = new RectBounds(src);
b = (RectBounds) transform(b, b);
dst.setBounds(b);
return;
case (APPLY_TRANSLATE):
Translate.transform(src, dst, mxt, myt);
return;
case (APPLY_IDENTITY):
if (dst != src) { dst.setBounds(src); }
return;
}
}
public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
double Mxx, Mxy, Mxt, Myx, Myy, Myt; // For caching
switch (state & APPLY_2D_MASK) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxy = mxy; Mxt = mxt;
Myx = myx; Myy = myy; Myt = myt;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (Mxx * x + Mxy * y + Mxt);
dstPts[dstOff++] = (Myx * x + Myy * y + Myt);
}
return;
case (APPLY_SHEAR | APPLY_SCALE):
Mxx = mxx; Mxy = mxy;
Myx = myx; Myy = myy;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (Mxx * x + Mxy * y);
dstPts[dstOff++] = (Myx * x + Myy * y);
}
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
Mxy = mxy; Mxt = mxt;
Myx = myx; Myt = myt;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = (Mxy * srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (Myx * x + Myt);
}
return;
case (APPLY_SHEAR):
Mxy = mxy; Myx = myx;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = (Mxy * srcPts[srcOff++]);
dstPts[dstOff++] = (Myx * x);
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxt = mxt;
Myy = myy; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = (Mxx * srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (Myy * srcPts[srcOff++] + Myt);
}
return;
case (APPLY_SCALE):
Mxx = mxx; Myy = myy;
while (--numPts >= 0) {
dstPts[dstOff++] = (Mxx * srcPts[srcOff++]);
dstPts[dstOff++] = (Myy * srcPts[srcOff++]);
}
return;
case (APPLY_TRANSLATE):
Mxt = mxt; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (srcPts[srcOff++] + Myt);
}
return;
case (APPLY_IDENTITY):
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++]);
dstPts[dstOff++] = (srcPts[srcOff++]);
}
return;
}
}
private BaseBounds transform2DBounds(RectBounds src, RectBounds dst) {
switch (state & APPLY_2D_MASK) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
double x1 = src.getMinX();
double y1 = src.getMinY();
double x2 = src.getMaxX();
double y2 = src.getMaxY();
dst.setBoundsAndSort((x1 * mxx + y1 * mxy), (x1 * myx + y1 * myy), (x2 * mxx + y2 * mxy), (x2 * myx + y2 * myy));
dst.add((x1 * mxx + y2 * mxy), (x1 * myx + y2 * myy));
dst.add((x2 * mxx + y1 * mxy), (x2 * myx + y1 * myy));
dst.setBounds((dst.getMinX() + mxt), (dst.getMinY() + myt), (dst.getMaxX() + mxt), (dst.getMaxY() + myt));
break;
case (APPLY_SHEAR | APPLY_TRANSLATE):
dst.setBoundsAndSort((src.getMinY() * mxy + mxt), (src.getMinX() * myx + myt), (src.getMaxY() * mxy + mxt), (src.getMaxX() * myx + myt));
break;
case (APPLY_SHEAR):
dst.setBoundsAndSort((src.getMinY() * mxy), (src.getMinX() * myx), (src.getMaxY() * mxy), (src.getMaxX() * myx));
break;
case (APPLY_SCALE | APPLY_TRANSLATE):
dst.setBoundsAndSort((src.getMinX() * mxx + mxt), (src.getMinY() * myy + myt), (src.getMaxX() * mxx + mxt), (src.getMaxY() * myy + myt));
break;
case (APPLY_SCALE):
dst.setBoundsAndSort((src.getMinX() * mxx), (src.getMinY() * myy), (src.getMaxX() * mxx), (src.getMaxY() * myy));
break;
case (APPLY_TRANSLATE):
dst.setBounds((src.getMinX() + mxt), (src.getMinY() + myt), (src.getMaxX() + mxt), (src.getMaxY() + myt));
break;
case (APPLY_IDENTITY):
if (src != dst) { dst.setBounds(src); }
break;
}
return dst;
}
public void deltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
doTransform(srcPts, srcOff, dstPts, dstOff, numPts, (this.state & APPLY_2D_DELTA_MASK));
}
private void doTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts, int thestate) {
double Mxx, Mxy, Mxt, Myx, Myy, Myt; // For caching
if (dstPts == srcPts && dstOff > srcOff && dstOff < srcOff + numPts * 2) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
srcOff = dstOff;
}
switch (thestate) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxy = mxy; Mxt = mxt;
Myx = myx; Myy = myy; Myt = myt;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (Mxx * x + Mxy * y + Mxt);
dstPts[dstOff++] = (Myx * x + Myy * y + Myt);
}
return;
case (APPLY_SHEAR | APPLY_SCALE):
Mxx = mxx; Mxy = mxy;
Myx = myx; Myy = myy;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (Mxx * x + Mxy * y);
dstPts[dstOff++] = (Myx * x + Myy * y);
}
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
Mxy = mxy; Mxt = mxt;
Myx = myx; Myt = myt;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = (Mxy * srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (Myx * x + Myt);
}
return;
case (APPLY_SHEAR):
Mxy = mxy; Myx = myx;
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = (Mxy * srcPts[srcOff++]);
dstPts[dstOff++] = (Myx * x);
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxt = mxt;
Myy = myy; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = (Mxx * srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (Myy * srcPts[srcOff++] + Myt);
}
return;
case (APPLY_SCALE):
Mxx = mxx; Myy = myy;
while (--numPts >= 0) {
dstPts[dstOff++] = (Mxx * srcPts[srcOff++]);
dstPts[dstOff++] = (Myy * srcPts[srcOff++]);
}
return;
case (APPLY_TRANSLATE):
Mxt = mxt; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++] + Mxt);
dstPts[dstOff++] = (srcPts[srcOff++] + Myt);
}
return;
case (APPLY_IDENTITY):
if (srcPts != dstPts || srcOff != dstOff) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
}
return;
}
}
public Point inverseTransform(Point ptSrc, Point ptDst) throws NonInvertibleTransformException {
if (ptDst == null) { ptDst = new Point(); }
double x = ptSrc.x;
double y = ptSrc.y;
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
x -= mxt;
y -= myt;
case (APPLY_SHEAR | APPLY_SCALE):
double det = mxx * myy - mxy * myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
ptDst.set(((x * myy - y * mxy) / det), ((y * mxx - x * myx) / det));
return ptDst;
case (APPLY_SHEAR | APPLY_TRANSLATE):
x -= mxt;
y -= myt;
case (APPLY_SHEAR):
if (mxy == 0.0 || myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
ptDst.set((y / myx), (x / mxy));
return ptDst;
case (APPLY_SCALE | APPLY_TRANSLATE):
x -= mxt;
y -= myt;
case (APPLY_SCALE):
if (mxx == 0.0 || myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
ptDst.set((x / mxx), (y / myy));
return ptDst;
case (APPLY_TRANSLATE):
ptDst.set((x - mxt), (y - myt));
return ptDst;
case (APPLY_IDENTITY):
ptDst.set(x, y);
return ptDst;
}
}
private BaseBounds inversTransform2DBounds(RectBounds src, RectBounds dst) throws NonInvertibleTransformException {
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
double det = mxx * myy - mxy * myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
double x1 = src.getMinX() - mxt;
double y1 = src.getMinY() - myt;
double x2 = src.getMaxX() - mxt;
double y2 = src.getMaxY() - myt;
dst.setBoundsAndSort(((x1 * myy - y1 * mxy) / det),
((y1 * mxx - x1 * myx) / det),
((x2 * myy - y2 * mxy) / det),
((y2 * mxx - x2 * myx) / det));
dst.add(((x2 * myy - y1 * mxy) / det),
((y1 * mxx - x2 * myx) / det));
dst.add(((x1 * myy - y2 * mxy) / det),
((y2 * mxx - x1 * myx) / det));
return dst;
case (APPLY_SHEAR | APPLY_TRANSLATE):
if (mxy == 0.0 || myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
dst.setBoundsAndSort(((src.getMinY() - myt) / myx),
((src.getMinX() - mxt) / mxy),
((src.getMaxY() - myt) / myx),
((src.getMaxX() - mxt) / mxy));
break;
case (APPLY_SHEAR):
if (mxy == 0.0 || myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
dst.setBoundsAndSort((src.getMinY() / myx),
(src.getMinX() / mxy),
(src.getMaxY() / myx),
(src.getMaxX() / mxy));
break;
case (APPLY_SCALE | APPLY_TRANSLATE):
if (mxx == 0.0 || myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
dst.setBoundsAndSort(((src.getMinX() - mxt) / mxx),
((src.getMinY() - myt) / myy),
((src.getMaxX() - mxt) / mxx),
((src.getMaxY() - myt) / myy));
break;
case (APPLY_SCALE):
if (mxx == 0.0 || myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
dst.setBoundsAndSort((src.getMinX() / mxx),
(src.getMinY() / myy),
(src.getMaxX() / mxx),
(src.getMaxY() / myy));
break;
case (APPLY_TRANSLATE):
dst.setBounds((src.getMinX() - mxt),
(src.getMinY() - myt),
(src.getMaxX() - mxt),
(src.getMaxY() - myt));
break;
case (APPLY_IDENTITY):
if (dst != src) { dst.setBounds((RectBounds) src); }
break;
}
return dst;
}
public BaseBounds inverseTransform(BaseBounds src, BaseBounds dst) throws NonInvertibleTransformException {
return inversTransform2DBounds((RectBounds)src, (RectBounds)dst);
}
public void inverseTransform(Rectangle src, Rectangle dst) throws NonInvertibleTransformException {
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
case (APPLY_SHEAR | APPLY_TRANSLATE):
case (APPLY_SHEAR):
case (APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SCALE):
RectBounds b = new RectBounds(src);
b = (RectBounds) inverseTransform(b, b);
dst.setBounds(b);
return;
case (APPLY_TRANSLATE):
Translate.transform(src, dst, -mxt, -myt);
return;
case (APPLY_IDENTITY):
if (dst != src) { dst.setBounds(src); }
return;
}
}
public void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws NonInvertibleTransformException {
double Mxx, Mxy, Mxt, Myx, Myy, Myt; // For caching
double det;
if (dstPts == srcPts && dstOff > srcOff && dstOff < srcOff + numPts * 2) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
srcOff = dstOff;
}
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxy = mxy; Mxt = mxt;
Myx = myx; Myy = myy; Myt = myt;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
while (--numPts >= 0) {
double x = srcPts[srcOff++] - Mxt;
double y = srcPts[srcOff++] - Myt;
dstPts[dstOff++] = (x * Myy - y * Mxy) / det;
dstPts[dstOff++] = (y * Mxx - x * Myx) / det;
}
return;
case (APPLY_SHEAR | APPLY_SCALE):
Mxx = mxx; Mxy = mxy;
Myx = myx; Myy = myy;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (x * Myy - y * Mxy) / det;
dstPts[dstOff++] = (y * Mxx - x * Myx) / det;
}
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
Mxy = mxy; Mxt = mxt;
Myx = myx; Myt = myt;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
double x = srcPts[srcOff++] - Mxt;
dstPts[dstOff++] = (srcPts[srcOff++] - Myt) / Myx;
dstPts[dstOff++] = x / Mxy;
}
return;
case (APPLY_SHEAR):
Mxy = mxy; Myx = myx;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = srcPts[srcOff++] / Myx;
dstPts[dstOff++] = x / Mxy;
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxt = mxt;
Myy = myy; Myt = myt;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++] - Mxt) / Mxx;
dstPts[dstOff++] = (srcPts[srcOff++] - Myt) / Myy;
}
return;
case (APPLY_SCALE):
Mxx = mxx; Myy = myy;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
dstPts[dstOff++] = srcPts[srcOff++] / Mxx;
dstPts[dstOff++] = srcPts[srcOff++] / Myy;
}
return;
case (APPLY_TRANSLATE):
Mxt = mxt; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = srcPts[srcOff++] - Mxt;
dstPts[dstOff++] = srcPts[srcOff++] - Myt;
}
return;
case (APPLY_IDENTITY):
if (srcPts != dstPts || srcOff != dstOff) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff,numPts * 2);
}
return;
}
}
public void inverseDeltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws NonInvertibleTransformException {
doInverseTransform(srcPts, srcOff, dstPts, dstOff, numPts, state & ~APPLY_TRANSLATE);
}
private void doInverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts, int thestate) throws NonInvertibleTransformException {
double Mxx, Mxy, Mxt, Myx, Myy, Myt; // For caching
double det;
if (dstPts == srcPts && dstOff > srcOff && dstOff < srcOff + numPts * 2) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
srcOff = dstOff;
}
switch (thestate) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxy = mxy; Mxt = mxt;
Myx = myx; Myy = myy; Myt = myt;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
while (--numPts >= 0) {
double x = srcPts[srcOff++] - Mxt;
double y = srcPts[srcOff++] - Myt;
dstPts[dstOff++] = ((x * Myy - y * Mxy) / det);
dstPts[dstOff++] = ((y * Mxx - x * Myx) / det);
}
return;
case (APPLY_SHEAR | APPLY_SCALE):
Mxx = mxx; Mxy = mxy;
Myx = myx; Myy = myy;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
while (--numPts >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = ((x * Myy - y * Mxy) / det);
dstPts[dstOff++] = ((y * Mxx - x * Myx) / det);
}
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
Mxy = mxy; Mxt = mxt;
Myx = myx; Myt = myt;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
double x = srcPts[srcOff++] - Mxt;
dstPts[dstOff++] = ((srcPts[srcOff++] - Myt) / Myx);
dstPts[dstOff++] = (x / Mxy);
}
return;
case (APPLY_SHEAR):
Mxy = mxy; Myx = myx;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
double x = srcPts[srcOff++];
dstPts[dstOff++] = (srcPts[srcOff++] / Myx);
dstPts[dstOff++] = (x / Mxy);
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxt = mxt;
Myy = myy; Myt = myt;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
dstPts[dstOff++] = ((srcPts[srcOff++] - Mxt) / Mxx);
dstPts[dstOff++] = ((srcPts[srcOff++] - Myt) / Myy);
}
return;
case (APPLY_SCALE):
Mxx = mxx; Myy = myy;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++] / Mxx);
dstPts[dstOff++] = (srcPts[srcOff++] / Myy);
}
return;
case (APPLY_TRANSLATE):
Mxt = mxt; Myt = myt;
while (--numPts >= 0) {
dstPts[dstOff++] = (srcPts[srcOff++] - Mxt);
dstPts[dstOff++] = (srcPts[srcOff++] - Myt);
}
return;
case (APPLY_IDENTITY):
if (srcPts != dstPts || srcOff != dstOff) {
System.arraycopy(srcPts, srcOff, dstPts, dstOff,numPts * 2);
}
return;
}
}
public Shape createTransformedShape(Shape s) {
if (s == null) { return null; }
return new Path(s, this);
}
public void translate(double tx, double ty) {
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
mxt = tx * mxx + ty * mxy + mxt;
myt = tx * myx + ty * myy + myt;
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_SHEAR | APPLY_SCALE;
if (type != TYPE_UNKNOWN) { type &= ~TYPE_TRANSLATION; }
}
return;
case (APPLY_SHEAR | APPLY_SCALE):
mxt = tx * mxx + ty * mxy;
myt = tx * myx + ty * myy;
if (mxt != 0.0 || myt != 0.0) {
state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
type |= TYPE_TRANSLATION;
}
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
mxt = ty * mxy + mxt;
myt = tx * myx + myt;
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_SHEAR;
if (type != TYPE_UNKNOWN) { type &= ~TYPE_TRANSLATION;} }
return;
case (APPLY_SHEAR):
mxt = ty * mxy;
myt = tx * myx;
if (mxt != 0.0 || myt != 0.0) {
state = APPLY_SHEAR | APPLY_TRANSLATE;
type |= TYPE_TRANSLATION;
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
mxt = tx * mxx + mxt;
myt = ty * myy + myt;
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_SCALE;
if (type != TYPE_UNKNOWN) { type &= ~TYPE_TRANSLATION; }
}
return;
case (APPLY_SCALE):
mxt = tx * mxx;
myt = ty * myy;
if (mxt != 0.0 || myt != 0.0) {
state = APPLY_SCALE | APPLY_TRANSLATE;
type |= TYPE_TRANSLATION;
}
return;
case (APPLY_TRANSLATE):
mxt = tx + mxt;
myt = ty + myt;
if (mxt == 0.0 && myt == 0.0) {
state = APPLY_IDENTITY;
type = TYPE_IDENTITY;
}
return;
case (APPLY_IDENTITY):
mxt = tx;
myt = ty;
if (tx != 0.0 || ty != 0.0) {
state = APPLY_TRANSLATE;
type = TYPE_TRANSLATION;
}
return;
}
}
protected final void rotate90() {
double M0 = mxx;
mxx = mxy;
mxy = -M0;
M0 = myx;
myx = myy;
myy = -M0;
int newstate = rot90conversion[this.state];
if ((newstate & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
mxx == 1.0 && myy == 1.0)
{
newstate -= APPLY_SCALE;
}
this.state = newstate;
type = TYPE_UNKNOWN;
}
protected final void rotate180() {
mxx = -mxx;
myy = -myy;
int oldstate = this.state;
if ((oldstate & (APPLY_SHEAR)) != 0) {
// If there was a shear, then this rotation has no
// effect on the state.
mxy = -mxy;
myx = -myx;
} else {
// No shear means the SCALE state may toggle when
// m00 and m11 are negated.
if (mxx == 1.0 && myy == 1.0) {
this.state = oldstate & ~APPLY_SCALE;
} else {
this.state = oldstate | APPLY_SCALE;
}
}
type = TYPE_UNKNOWN;
}
protected final void rotate270() {
double M0 = mxx;
mxx = -mxy;
mxy = M0;
M0 = myx;
myx = -myy;
myy = M0;
int newstate = rot90conversion[this.state];
if ((newstate & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
mxx == 1.0 && myy == 1.0)
{
newstate -= APPLY_SCALE;
}
this.state = newstate;
type = TYPE_UNKNOWN;
}
public void rotate(double theta) {
// assert(APPLY_3D was dealt with at a higher level)
double sin = Math.sin(theta);
if (sin == 1.0) {
rotate90();
} else if (sin == -1.0) {
rotate270();
} else {
double cos = Math.cos(theta);
if (cos == -1.0) {
rotate180();
} else if (cos != 1.0) {
double M0, M1;
M0 = mxx;
M1 = mxy;
mxx = cos * M0 + sin * M1;
mxy = -sin * M0 + cos * M1;
M0 = myx;
M1 = myy;
myx = cos * M0 + sin * M1;
myy = -sin * M0 + cos * M1;
updateState();
}
}
}
public void scale(double sx, double sy) {
int mystate = this.state;
// assert(APPLY_3D was dealt with at a higher level)
switch (mystate) {
default:
stateError();
/* NOTREACHED */
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
mxx *= sx;
myy *= sy;
/* NOBREAK */
case (APPLY_SHEAR | APPLY_TRANSLATE):
case (APPLY_SHEAR):
mxy *= sy;
myx *= sx;
if (mxy == 0 && myx == 0) {
mystate &= APPLY_TRANSLATE;
if (mxx == 1.0 && myy == 1.0) {
this.type = (mystate == APPLY_IDENTITY
? TYPE_IDENTITY
: TYPE_TRANSLATION);
} else {
mystate |= APPLY_SCALE;
this.type = TYPE_UNKNOWN;
}
this.state = mystate;
}
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SCALE):
mxx *= sx;
myy *= sy;
if (mxx == 1.0 && myy == 1.0) {
this.state = (mystate &= APPLY_TRANSLATE);
this.type = (mystate == APPLY_IDENTITY
? TYPE_IDENTITY
: TYPE_TRANSLATION);
} else {
this.type = TYPE_UNKNOWN;
}
return;
case (APPLY_TRANSLATE):
case (APPLY_IDENTITY):
mxx = sx;
myy = sy;
if (sx != 1.0 || sy != 1.0) {
this.state = mystate | APPLY_SCALE;
this.type = TYPE_UNKNOWN;
}
return;
}
}
public void shear(double shx, double shy) {
int mystate = this.state;
// assert(APPLY_3D was dealt with at a higher level)
switch (mystate) {
default:
stateError();
/* NOTREACHED */
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SHEAR | APPLY_SCALE):
double M0, M1;
M0 = mxx;
M1 = mxy;
mxx = M0 + M1 * shy;
mxy = M0 * shx + M1;
M0 = myx;
M1 = myy;
myx = M0 + M1 * shy;
myy = M0 * shx + M1;
updateState();
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
case (APPLY_SHEAR):
mxx = mxy * shy;
myy = myx * shx;
if (mxx != 0.0 || myy != 0.0) {
this.state = mystate | APPLY_SCALE;
}
this.type = TYPE_UNKNOWN;
return;
case (APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SCALE):
mxy = mxx * shx;
myx = myy * shy;
if (mxy != 0.0 || myx != 0.0) {
this.state = mystate | APPLY_SHEAR;
}
this.type = TYPE_UNKNOWN;
return;
case (APPLY_TRANSLATE):
case (APPLY_IDENTITY):
mxy = shx;
myx = shy;
if (mxy != 0.0 || myx != 0.0) {
this.state = mystate | APPLY_SCALE | APPLY_SHEAR;
this.type = TYPE_UNKNOWN;
}
return;
}
}
public void concatenate(BaseTransform Tx) {
switch (Tx.getDegree()) {
case IDENTITY:
return;
case TRANSLATE:
translate(Tx.getMxt(), Tx.getMyt());
return;
case AFFINE:
break;
default:
degreeError(Degree.AFFINE);
if (!(Tx instanceof AffineBase)) { Tx = new Affine(Tx); }
break;
}
double M0, M1;
double Txx, Txy, Tyx, Tyy;
double Txt, Tyt;
int mystate = state;
AffineBase at = (AffineBase) Tx;
int txstate = at.state;
switch ((txstate << HI_SHIFT) | mystate) {
/* ---------- Tx == IDENTITY cases ---------- */
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):
return;
/* ---------- this == IDENTITY cases ---------- */
case (HI_SHEAR | HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
mxy = at.mxy;
myx = at.myx;
/* NOBREAK */
case (HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
mxx = at.mxx;
myy = at.myy;
/* NOBREAK */
case (HI_TRANSLATE | APPLY_IDENTITY):
mxt = at.mxt;
myt = at.myt;
state = txstate;
type = at.type;
return;
case (HI_SHEAR | HI_SCALE | APPLY_IDENTITY):
mxy = at.mxy;
myx = at.myx;
/* NOBREAK */
case (HI_SCALE | APPLY_IDENTITY):
mxx = at.mxx;
myy = at.myy;
state = txstate;
type = at.type;
return;
case (HI_SHEAR | HI_TRANSLATE | APPLY_IDENTITY):
mxt = at.mxt;
myt = at.myt;
/* NOBREAK */
case (HI_SHEAR | APPLY_IDENTITY):
mxy = at.mxy;
myx = at.myx;
mxx = myy = 0.0;
state = txstate;
type = at.type;
return;
/* ---------- Tx == TRANSLATE cases ---------- */
case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
case (HI_TRANSLATE | APPLY_SHEAR):
case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
case (HI_TRANSLATE | APPLY_SCALE):
case (HI_TRANSLATE | APPLY_TRANSLATE):
translate(at.mxt, at.myt);
return;
/* ---------- Tx == SCALE cases ---------- */
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):
case (HI_SCALE | APPLY_TRANSLATE):
scale(at.mxx, at.myy);
return;
/* ---------- Tx == SHEAR cases ---------- */
case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
Txy = at.mxy; Tyx = at.myx;
M0 = mxx;
mxx = mxy * Tyx;
mxy = M0 * Txy;
M0 = myx;
myx = myy * Tyx;
myy = M0 * Txy;
type = TYPE_UNKNOWN;
return;
case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
case (HI_SHEAR | APPLY_SHEAR):
mxx = mxy * at.myx;
mxy = 0.0;
myy = myx * at.mxy;
myx = 0.0;
state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
type = TYPE_UNKNOWN;
return;
case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
case (HI_SHEAR | APPLY_SCALE):
mxy = mxx * at.mxy;
mxx = 0.0;
myx = myy * at.myx;
myy = 0.0;
state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
type = TYPE_UNKNOWN;
return;
case (HI_SHEAR | APPLY_TRANSLATE):
mxx = 0.0;
mxy = at.mxy;
myx = at.myx;
myy = 0.0;
state = APPLY_TRANSLATE | APPLY_SHEAR;
type = TYPE_UNKNOWN;
return;
}
// If Tx has more than one attribute, pathIterator is not worth optimizing
// all of those cases...
Txx = at.mxx; Txy = at.mxy; Txt = at.mxt;
Tyx = at.myx; Tyy = at.myy; Tyt = at.myt;
switch (mystate) {
default:
stateError();
/* NOTREACHED */
case (APPLY_SHEAR | APPLY_SCALE):
state = mystate | txstate;
/* NOBREAK */
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
M0 = mxx;
M1 = mxy;
mxx = Txx * M0 + Tyx * M1;
mxy = Txy * M0 + Tyy * M1;
mxt += Txt * M0 + Tyt * M1;
M0 = myx;
M1 = myy;
myx = Txx * M0 + Tyx * M1;
myy = Txy * M0 + Tyy * M1;
myt += Txt * M0 + Tyt * M1;
type = TYPE_UNKNOWN;
return;
case (APPLY_SHEAR | APPLY_TRANSLATE):
case (APPLY_SHEAR):
M0 = mxy;
mxx = Tyx * M0;
mxy = Tyy * M0;
mxt += Tyt * M0;
M0 = myx;
myx = Txx * M0;
myy = Txy * M0;
myt += Txt * M0;
break;
case (APPLY_SCALE | APPLY_TRANSLATE):
case (APPLY_SCALE):
M0 = mxx;
mxx = Txx * M0;
mxy = Txy * M0;
mxt += Txt * M0;
M0 = myy;
myx = Tyx * M0;
myy = Tyy * M0;
myt += Tyt * M0;
break;
case (APPLY_TRANSLATE):
mxx = Txx;
mxy = Txy;
mxt += Txt;
myx = Tyx;
myy = Tyy;
myt += Tyt;
state = txstate | APPLY_TRANSLATE;
type = TYPE_UNKNOWN;
return;
}
updateState();
}
public void invert() throws NonInvertibleTransformException {
double Mxx, Mxy, Mxt;
double Myx, Myy, Myt;
double det;
switch (state) {
default:
stateError();
case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxy = mxy; Mxt = mxt;
Myx = myx; Myy = myy; Myt = myt;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
mxx = Myy / det;
myx = -Myx / det;
mxy = -Mxy / det;
myy = Mxx / det;
mxt = (Mxy * Myt - Myy * Mxt) / det;
myt = (Myx * Mxt - Mxx * Myt) / det;
break;
case (APPLY_SHEAR | APPLY_SCALE):
Mxx = mxx; Mxy = mxy;
Myx = myx; Myy = myy;
det = Mxx * Myy - Mxy * Myx;
if (det == 0 || Math.abs(det) <= Double.MIN_VALUE) { throw new NonInvertibleTransformException("Determinant is " + det); }
mxx = Myy / det;
myx = -Myx / det;
mxy = -Mxy / det;
myy = Mxx / det;
break;
case (APPLY_SHEAR | APPLY_TRANSLATE):
Mxy = mxy; Mxt = mxt;
Myx = myx; Myt = myt;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
myx = 1.0 / Mxy;
mxy = 1.0 / Myx;
mxt = -Myt / Myx;
myt = -Mxt / Mxy;
break;
case (APPLY_SHEAR):
Mxy = mxy;
Myx = myx;
if (Mxy == 0.0 || Myx == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
myx = 1.0 / Mxy;
mxy = 1.0 / Myx;
break;
case (APPLY_SCALE | APPLY_TRANSLATE):
Mxx = mxx; Mxt = mxt;
Myy = myy; Myt = myt;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
mxx = 1.0 / Mxx;
myy = 1.0 / Myy;
mxt = -Mxt / Mxx;
myt = -Myt / Myy;
break;
case (APPLY_SCALE):
Mxx = mxx;
Myy = myy;
if (Mxx == 0.0 || Myy == 0.0) { throw new NonInvertibleTransformException("Determinant is 0"); }
mxx = 1.0 / Mxx;
myy = 1.0 / Myy;
break;
case (APPLY_TRANSLATE):
mxt = -mxt;
myt = -myt;
break;
case (APPLY_IDENTITY):
break;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy