diff --git a/core/src/main/java/edu/umd/cs/piccolo/PCamera.java b/core/src/main/java/edu/umd/cs/piccolo/PCamera.java index ccbfe60..f98ccf4 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/PCamera.java +++ b/core/src/main/java/edu/umd/cs/piccolo/PCamera.java @@ -45,6 +45,7 @@ import edu.umd.cs.piccolo.activities.PTransformActivity; import edu.umd.cs.piccolo.util.PAffineTransform; +import edu.umd.cs.piccolo.util.PAffineTransformException; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PDebug; import edu.umd.cs.piccolo.util.PDimension; @@ -209,9 +210,9 @@ * * @param layer the layer to be removed */ - public PLayer removeLayer(PLayer layer) { + public PLayer removeLayer(PLayer layer) { layer.removeCamera(this); - if (layers.remove(layer)) { + if (layers.remove(layer)) { invalidatePaint(); firePropertyChange(PROPERTY_CODE_LAYERS, PROPERTY_LAYERS, null, layers); } @@ -675,14 +676,8 @@ * camera's view coordinate system. The given point is modified by this * method. */ - public Point2D localToView(Point2D localPoint) { - try { - return viewTransform.inverseTransform(localPoint, localPoint); - } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); - } - return null; + public Point2D localToView(Point2D localPoint) { + return viewTransform.inverseTransform(localPoint, localPoint); } /** @@ -690,8 +685,8 @@ * camera's view coordinate system. The given dimension is modified by this * method. */ - public Dimension2D localToView(Dimension2D localDimension) { - return viewTransform.inverseTransform(localDimension, localDimension); + public Dimension2D localToView(Dimension2D localDimension) { + return viewTransform.inverseTransform(localDimension, localDimension); } /** diff --git a/core/src/main/java/edu/umd/cs/piccolo/PNode.java b/core/src/main/java/edu/umd/cs/piccolo/PNode.java index a78eff0..ad86a58 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/PNode.java +++ b/core/src/main/java/edu/umd/cs/piccolo/PNode.java @@ -747,13 +747,8 @@ public Point2D parentToLocal(Point2D parentPoint) { if (transform == null) return parentPoint; - try { - return transform.inverseTransform(parentPoint, parentPoint); - } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); - } - return null; + + return transform.inverseTransform(parentPoint, parentPoint); } /** diff --git a/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java index 3489320..69eabb6 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java +++ b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransform.java @@ -87,8 +87,10 @@ } public void setScale(double scale) { - if (scale == 0) - throw new RuntimeException("Can't set scale to 0"); + if (scale == 0) { + throw new PAffineTransformException("Can't set scale to 0", this); + } + scaleAboutPoint(scale / getScale(), 0, 0); } @@ -151,6 +153,15 @@ return dimDst; } + public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst) { + try { + return super.inverseTransform(ptSrc, ptDst); + } + catch (NoninvertibleTransformException e) { + throw new PAffineTransformException("Could not invert Transform", e, this); + } + } + public Dimension2D inverseTransform(Dimension2D dimSrc, Dimension2D dimDst) { if (dimDst == null) { dimDst = (Dimension2D) dimSrc.clone(); @@ -164,14 +175,11 @@ double m10 = getShearY(); double det = m00 * m11 - m01 * m10; - try { - if (Math.abs(det) <= Double.MIN_VALUE) { - throw new NoninvertibleTransformException("Determinant is " + det); - } + if (Math.abs(det) > Double.MIN_VALUE) { dimDst.setSize((width * m11 - height * m01) / det, (height * m00 - width * m10) / det); } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); + else { + throw new PAffineTransformException("Could not invert transform", this); } return dimDst; @@ -253,16 +261,22 @@ break; case AffineTransform.TYPE_UNIFORM_SCALE: - scale = 1 / getScaleX(); - rectDst.setRect(rectSrc.getX() * scale, rectSrc.getY() * scale, rectSrc.getWidth() * scale, rectSrc - .getHeight() - * scale); + scale = getScaleX(); + if (scale == 0) { + throw new PAffineTransformException("Could not invertTransform rectangle", this); + } + + rectDst.setRect(rectSrc.getX() / scale, rectSrc.getY() / scale, rectSrc.getWidth() / scale, rectSrc + .getHeight() / scale); break; case AffineTransform.TYPE_TRANSLATION | AffineTransform.TYPE_UNIFORM_SCALE: - scale = 1 / getScaleX(); - rectDst.setRect((rectSrc.getX() - getTranslateX()) * scale, (rectSrc.getY() - getTranslateY()) * scale, - rectSrc.getWidth() * scale, rectSrc.getHeight() * scale); + scale = getScaleX(); + if (scale == 0) { + throw new PAffineTransformException("Could not invertTransform rectangle", this); + } + rectDst.setRect((rectSrc.getX() - getTranslateX()) / scale, (rectSrc.getY() - getTranslateY()) / scale, + rectSrc.getWidth() / scale, rectSrc.getHeight() / scale); break; default: @@ -271,7 +285,7 @@ inverseTransform(pts, 0, pts, 0, 4); } catch (NoninvertibleTransformException e) { - e.printStackTrace(); + throw new PAffineTransformException("Could not invert transform", e, this); } rectFromArray(rectDst, pts); break; diff --git a/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransformException.java b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransformException.java new file mode 100644 index 0000000..c2b539e --- /dev/null +++ b/core/src/main/java/edu/umd/cs/piccolo/util/PAffineTransformException.java @@ -0,0 +1,30 @@ +package edu.umd.cs.piccolo.util; + +public class PAffineTransformException extends RuntimeException { + + private final PAffineTransform errantTransform; + + public PAffineTransformException(PAffineTransform errantTransform) { + this.errantTransform = errantTransform; + } + + public PAffineTransformException(String message, PAffineTransform errantTransform) { + super(message); + this.errantTransform = errantTransform; + } + + public PAffineTransformException(Throwable throwable, PAffineTransform errantTransform) { + super(throwable); + this.errantTransform = errantTransform; + } + + public PAffineTransformException(String message, Throwable throwable, PAffineTransform errantTransform) { + super(message, throwable); + this.errantTransform = errantTransform; + } + + public PAffineTransform getErrantTransform() { + return errantTransform; + } + +} diff --git a/core/src/main/java/edu/umd/cs/piccolo/util/PPickPath.java b/core/src/main/java/edu/umd/cs/piccolo/util/PPickPath.java index 1b8922b..6246bd4 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/util/PPickPath.java +++ b/core/src/main/java/edu/umd/cs/piccolo/util/PPickPath.java @@ -287,14 +287,8 @@ * pick path (and through any camera view transforms applied to the path) to * the local coordinates of the given node. */ - public Point2D canvasToLocal(Point2D canvasPoint, PNode nodeOnPath) { - try { - return getPathTransformTo(nodeOnPath).inverseTransform(canvasPoint, canvasPoint); - } - catch (NoninvertibleTransformException e) { - e.printStackTrace(); - } - return null; + public Point2D canvasToLocal(Point2D canvasPoint, PNode nodeOnPath) { + return getPathTransformTo(nodeOnPath).inverseTransform(canvasPoint, canvasPoint); } /** diff --git a/core/src/test/java/edu/umd/cs/piccolo/PCameraTest.java b/core/src/test/java/edu/umd/cs/piccolo/PCameraTest.java index 2c4508f..d73f075 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/PCameraTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/PCameraTest.java @@ -32,6 +32,7 @@ import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; +import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.IOException; @@ -39,8 +40,10 @@ import edu.umd.cs.piccolo.activities.PActivity; import edu.umd.cs.piccolo.activities.PTransformActivity; import edu.umd.cs.piccolo.util.PAffineTransform; +import edu.umd.cs.piccolo.util.PAffineTransformException; import edu.umd.cs.piccolo.util.PBounds; import edu.umd.cs.piccolo.util.PDebug; +import edu.umd.cs.piccolo.util.PDimension; import edu.umd.cs.piccolo.util.PPaintContext; import edu.umd.cs.piccolo.util.PPickPath; @@ -347,7 +350,7 @@ camera.setViewConstraint(PCamera.VIEW_CONSTRAINT_ALL); assertEquals(PCamera.VIEW_CONSTRAINT_ALL, camera.getViewConstraint()); } - + class MockPComponent implements PComponent { public void paintImmediately() { diff --git a/core/src/test/java/edu/umd/cs/piccolo/util/PAffineTransformTest.java b/core/src/test/java/edu/umd/cs/piccolo/util/PAffineTransformTest.java index 672b83b..ff2c17c 100644 --- a/core/src/test/java/edu/umd/cs/piccolo/util/PAffineTransformTest.java +++ b/core/src/test/java/edu/umd/cs/piccolo/util/PAffineTransformTest.java @@ -30,6 +30,8 @@ import java.awt.Dimension; import java.awt.geom.Dimension2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import junit.framework.TestCase; import edu.umd.cs.piccolo.PiccoloAsserts; @@ -118,5 +120,35 @@ at.setScale(2); Dimension2D d2 = at.transform(d1, null); assertEquals(new Dimension(200, 100), d2); - } + } + + public void testLocalToViewDimensionThrowsExceptionWhenTransformIsNonInvertible() { + at.setTransform(new PAffineTransform(new double[] {0,0,0,0,0,0})); + try { + at.inverseTransform(new PDimension(1,2), null); + fail("Exception not thrown when inverting non-invertible transform"); + } catch (PAffineTransformException e) { + // expected + } + } + + public void testLocalToViewPoint2DThrowsExceptionWhenTransformIsNonInvertible() { + at.setTransform(new PAffineTransform(new double[] {0,0,0,0,0,0})); + try { + at.inverseTransform(new Point2D.Double(1,2), null); + fail("Exception not thrown when inverting non-invertible transform"); + } catch (PAffineTransformException e) { + // expected + } + } + + public void testLocalToViewRectangle2DThrowsExceptionWhenTransformIsNonInvertible() { + at.setTransform(new PAffineTransform(new double[] {0,0,0,0,0,0})); + try { + at.inverseTransform(new Rectangle2D.Double(1,2,3,4), null); + fail("Exception not thrown when inverting non-invertible transform"); + } catch (PAffineTransformException e) { + // expected + } + } }