X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FTransformUtil.java;h=6b14f9ed98434b9557088610e6ed9fa9e754c517;hb=56e6bade5f3a9cd2210184ffc13ffb29f007dccf;hp=e1c7719e0bbf488d5f4966e1b74379c021a7c6e5;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/TransformUtil.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/TransformUtil.java index e1c7719e0..6b14f9ed9 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/TransformUtil.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/TransformUtil.java @@ -1,456 +1,456 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.participant; - - -import static org.simantics.g2d.canvas.Hints.KEY_CANVAS_TRANSFORM; - -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; -import java.awt.geom.Path2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import org.simantics.g2d.canvas.Hints; -import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; -import org.simantics.g2d.canvas.impl.HintReflection.HintListener; -import org.simantics.g2d.scenegraph.SceneGraphConstants; -import org.simantics.g2d.utils.GeometryUtils; -import org.simantics.scenegraph.g2d.IG2DNode; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintObservable; -import org.simantics.utils.page.MarginUtils.Margins; - -/** - * This class contains utilities for coordinate conversions between control - * and canvas. - * - * @author Toni Kalajainen - * @author J-P Laine - * @author Tuukka Lehtonen - */ -public class TransformUtil extends AbstractCanvasParticipant { - - /** Set dirty if transform changes */ - @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") - public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { - if (oldValue != null && oldValue.equals(newValue)) return; - //System.out.println("TransformUtil: CANVAS TRANSFORM CHANGED TO " + newValue); - setDirty(); - } - - /** - * Get viewport rectangle. - * Transforms controlRect to area on canvas. - * - * @param controlRect rectangle on control - * @return area on canvas - */ - public Path2D toCanvasArea(Rectangle2D controlRect) - { - Point2D p[] = toCanvasCorners(controlRect); - - Path2D path = new Path2D.Double(); - path.moveTo(p[0].getX(), p[0].getY()); - path.lineTo(p[1].getX(), p[1].getY()); - path.lineTo(p[2].getX(), p[2].getY()); - path.lineTo(p[3].getX(), p[3].getY()); - path.closePath(); - - return path; - } - - /** - * Returns 4 canvas corders in order: top-left, top-right, bottom-right, bottom-left - * @param controlRect rectangle on control - * @return area on canvas - */ - public Point2D[] toCanvasCorners(Rectangle2D controlRect) - { - // at·control point = canvas point - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) at = new AffineTransform(); - - try { - at = at.createInverse(); - } catch (NoninvertibleTransformException e) { - } - - // Get corners - Point2D p1 = new Point2D.Double(controlRect.getMinX(), controlRect.getMinY()); - Point2D p2 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMinY()); - Point2D p3 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMaxY()); - Point2D p4 = new Point2D.Double(controlRect.getMinX(), controlRect.getMaxY()); - - - // Convert corners - at.transform(p1, p1); - at.transform(p2, p2); - at.transform(p3, p3); - at.transform(p4, p4); - - return new Point2D[] {p1, p2, p3, p4}; - } - - /** - * Converts control rectangle to a rectangle on canvas that contains control rect. - * @param controlRect rectangle on control - * @return rectangle on canvas that contains control rect - */ - public Rectangle2D toCanvasRect(Rectangle2D controlRect) - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) - return (Rectangle2D) controlRect.clone(); - - Path2D path = toCanvasArea(controlRect); - return path.getBounds2D(); - } - - /** - * Transforms from canvas coordinate system to canvas coordinate system (also diagram) - * @param g2d - */ - public void controlToCanvas(Graphics2D g2d) - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) return; - g2d.transform(at); - } - - /** - * Transforms coordinate system of g2d from canvas to control - * @param g2d - */ - public void canvasToControl(Graphics2D g2d) - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) return; - try { - g2d.transform(at.createInverse()); - } catch (NoninvertibleTransformException e) { - } - } - - /** - * Convert control point to canvas point - * @param g2d - */ - public Point2D controlToCanvas(Point2D control, Point2D canvas) - { - AffineTransform at = getInverseTransform(); - if (canvas==null) canvas = new Point2D.Double(); - if (at==null) { - canvas.setLocation(control); - return canvas; - } - at.transform(control, canvas); - return canvas; - } - - /** - * Convert canvas point to control - * @param g2d - */ - public Point2D canvasToControl(Point2D canvas, Point2D control) - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (control==null) control = new Point2D.Double(); - if (at==null) { - control.setLocation(canvas); - return canvas; - } - at.transform(canvas, control); - return control; - } - - /** - * Convert canvas vector to control vector - * @param g2d - */ - public Point2D canvasVectorToControlVector(Point2D canvas, Point2D control) - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (control==null) control = new Point2D.Double(); - if (at==null) { - control.setLocation(canvas); - return canvas; - } - double x = canvas.getX(); - double y = canvas.getY(); - - double m00 = at.getScaleX(); - double m11 = at.getScaleY(); - double m01 = at.getShearX(); - double m10 = at.getShearY(); - - control.setLocation( - x * m00 + y * m01, - x * m10 + y * m11 - ); - return control; - } - - /** - * Convert control vector to canvas vector - * @param g2d - */ - public Point2D controlVectorToCanvasVector(Point2D control, Point2D canvas) - { - AffineTransform at = getInverseTransform(); - if (canvas==null) canvas = new Point2D.Double(); - if (at==null) { - canvas.setLocation(control); - return canvas; - } - double x = control.getX(); - double y = control.getY(); - - double m00 = at.getScaleX(); - double m11 = at.getScaleY(); - double m01 = at.getShearX(); - double m10 = at.getShearY(); - - canvas.setLocation( - x * m00 + y * m01, - x * m10 + y * m11 - ); - return canvas; - } - /** - * Get a transform that converts - * diagram coordinates to control coordinates. - * - * @return transform a clone - */ - public AffineTransform getTransform() - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) return new AffineTransform(); - return (AffineTransform) at.clone(); - } - - /** - * Get a transform that converts - * diagram vector to control vector. - * - * @return transform a clone - */ - public AffineTransform getVectorTransform() - { - AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); - if (at==null) return new AffineTransform(); - double m00 = at.getScaleX(); - double m11 = at.getScaleY(); - double m01 = at.getShearX(); - double m10 = at.getShearY(); - return new AffineTransform(m00, m10, m01, m11, 0, 0); - } - - - /** - * Transforms control coordinates to diagram coordinates. - * - * @return inverted transform or null if inversion failed - */ - public AffineTransform getInverseTransform() - { - AffineTransform at = getTransform(); - if (at==null) return null; - try { - at = at.createInverse(); - return at; - } catch (NoninvertibleTransformException e) { - return null; - } - } - - /** - * Tries to invert the specified {@link AffineTransform}. - * - * @parameter at the transform to invert - * @return inverted transform or null if inversion failed - */ - public AffineTransform getInverseTransform(AffineTransform at) - { - if (at == null) - return null; - try { - return at.createInverse(); - } catch (NoninvertibleTransformException e) { - return null; - } - } - - /** - * Transforms control vector to diagram vector - * @return a clone - */ - public AffineTransform getInverseVectorTransform() - { - AffineTransform at = getTransform(); - if (at==null) return null; - try { - at = at.createInverse(); - double m00 = at.getScaleX(); - double m11 = at.getScaleY(); - double m01 = at.getShearX(); - double m10 = at.getShearY(); - return new AffineTransform(m00, m10, m01, m11, 0, 0); - } catch (NoninvertibleTransformException e) { - return null; - } - } - - - public void setTransform(AffineTransform at) - { - assert(at.getShearX()!=Double.POSITIVE_INFINITY && at.getShearX()!=Double.NEGATIVE_INFINITY); - assert(at.getShearY()!=Double.POSITIVE_INFINITY && at.getShearY()!=Double.NEGATIVE_INFINITY); - AffineTransform old = getHint(KEY_CANVAS_TRANSFORM); - if(at.equals(old) == false) { // Send event only if the transform has really changed - setHint(KEY_CANVAS_TRANSFORM, at); - - IG2DNode node = NodeUtil.findNodeById(getContext().getSceneGraph(), SceneGraphConstants.NAVIGATION_NODE_PATH); - if (node != null) - // This is not in hintListener, because we don't want to update - // transform if it already came for scenegraph. - node.setTransform(at); - } - } - - public void zoom(double scaleFactor) - { - if (scaleFactor==1.0) return; - AffineTransform diagramToControl = getTransform(); - diagramToControl.scale(scaleFactor, scaleFactor); - setTransform(diagramToControl); - } - - public void rotate(Point2D centerPointCanvas, double angle) - { - if (angle==0.0) return; // and modulos too - AffineTransform diagramToControl = getTransform(); - diagramToControl.rotate(-angle, centerPointCanvas.getX(), centerPointCanvas.getY()); - setTransform(diagramToControl); - } - - public void restoreOrientation(Point2D centerPointCanvas) - { - AffineTransform res = new AffineTransform(); - AffineTransform at = getTransform(); - double m01 = at.getShearX(); - double m11 = at.getScaleY(); - double theta = Math.atan2(m01, m11); - at.rotate(-theta, centerPointCanvas.getX(), centerPointCanvas.getY()); - res.translate(at.getTranslateX(), at.getTranslateY()); - res.scale(at.getScaleX(), at.getScaleY()); - setTransform(res); - } - - /** - * Get rotate in radians. - * @return - */ - public double getRotate() { - AffineTransform at = getTransform(); - double m01 = at.getShearX(); - double m11 = at.getScaleY(); - return Math.atan2(m01, m11); - } - - /** - * Zoom the view port - * @param scaleFactor amount to zoom - * @param aroundPoint The center point of zoom in diagram coordinates - */ - public void zoomAroundDiagramPoint(double scaleFactor, Point2D aroundPoint) - { - AffineTransform diagramToControl = getTransform(); - // convert to control point - aroundPoint = diagramToControl.transform(aroundPoint, new Point2D.Double()); - zoomAroundControlPoint(scaleFactor, aroundPoint); - } - - /** - * Zoom the view port - * @param scaleFactor amount to zoom - * @param centerPoint the control point to zoom around - */ - public void zoomAroundControlPoint(double scaleFactor, Point2D centerPoint) - { - if (scaleFactor==1.0) return; - AffineTransform diagramToControl = getTransform(); - try { - Point2D pointBeforeScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double()); - diagramToControl.scale(scaleFactor, scaleFactor); - Point2D pointAfterScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double()); - double _dx = pointAfterScale.getX() - pointBeforeScale.getX(); - double _dy = pointAfterScale.getY() - pointBeforeScale.getY(); - diagramToControl.translate(_dx, _dy); - } catch (NoninvertibleTransformException e1) { - } - setTransform(diagramToControl); - } - - /** - * Transform the viewport. The transform values are in diagram coordinates - * @param dx - * @param dy - */ - public void translateWithCanvasCoordinates(double dx, double dy) - { - AffineTransform controlToDiagram = getTransform(); - controlToDiagram.translate(dx, dy); - setTransform(controlToDiagram); - } - - /** - * Transform the viewport. The transform values are in control coordinates - * @param dx - * @param dy - */ - public void translateWithControlCoordinates(Point2D offset) - { - if (offset.getX()==0 && offset.getY()==0) return; - AffineTransform at = getInverseTransform(); - offset = at.transform(offset, new Point2D.Double()); - translateWithCanvasCoordinates(offset.getX()-at.getTranslateX(), offset.getY()-at.getTranslateY()); - } - - /** - * Get scale ratio between control and canvas - * @param pt - * @return - */ - public Point2D getScale(Point2D pt) - { - AffineTransform at = getTransform(); - return GeometryUtils.getScaleXY(at, pt); - } - - /** - * Modifies transform to make canvas area fully visible. - * @param controlArea - * @param diagramArea - * @param margins margins - */ - public void fitArea(Rectangle2D controlArea, Rectangle2D diagramArea, Margins margins) - { - AffineTransform fitTx = org.simantics.scenegraph.utils.GeometryUtils.fitArea(controlArea, diagramArea, margins); - //System.out.println("fitArea(" + controlArea + ", " + diagramArea + ", " + margins + "): " + fitTx); - setTransform(fitTx); - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.participant; + + +import static org.simantics.g2d.canvas.Hints.KEY_CANVAS_TRANSFORM; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.g2d.canvas.Hints; +import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; +import org.simantics.g2d.canvas.impl.HintReflection.HintListener; +import org.simantics.g2d.scenegraph.SceneGraphConstants; +import org.simantics.g2d.utils.GeometryUtils; +import org.simantics.scenegraph.g2d.IG2DNode; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.page.MarginUtils.Margins; + +/** + * This class contains utilities for coordinate conversions between control + * and canvas. + * + * @author Toni Kalajainen + * @author J-P Laine + * @author Tuukka Lehtonen + */ +public class TransformUtil extends AbstractCanvasParticipant { + + /** Set dirty if transform changes */ + @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") + public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + if (oldValue != null && oldValue.equals(newValue)) return; + //System.out.println("TransformUtil: CANVAS TRANSFORM CHANGED TO " + newValue); + setDirty(); + } + + /** + * Get viewport rectangle. + * Transforms controlRect to area on canvas. + * + * @param controlRect rectangle on control + * @return area on canvas + */ + public Path2D toCanvasArea(Rectangle2D controlRect) + { + Point2D p[] = toCanvasCorners(controlRect); + + Path2D path = new Path2D.Double(); + path.moveTo(p[0].getX(), p[0].getY()); + path.lineTo(p[1].getX(), p[1].getY()); + path.lineTo(p[2].getX(), p[2].getY()); + path.lineTo(p[3].getX(), p[3].getY()); + path.closePath(); + + return path; + } + + /** + * Returns 4 canvas corders in order: top-left, top-right, bottom-right, bottom-left + * @param controlRect rectangle on control + * @return area on canvas + */ + public Point2D[] toCanvasCorners(Rectangle2D controlRect) + { + // at·control point = canvas point + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) at = new AffineTransform(); + + try { + at = at.createInverse(); + } catch (NoninvertibleTransformException e) { + } + + // Get corners + Point2D p1 = new Point2D.Double(controlRect.getMinX(), controlRect.getMinY()); + Point2D p2 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMinY()); + Point2D p3 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMaxY()); + Point2D p4 = new Point2D.Double(controlRect.getMinX(), controlRect.getMaxY()); + + + // Convert corners + at.transform(p1, p1); + at.transform(p2, p2); + at.transform(p3, p3); + at.transform(p4, p4); + + return new Point2D[] {p1, p2, p3, p4}; + } + + /** + * Converts control rectangle to a rectangle on canvas that contains control rect. + * @param controlRect rectangle on control + * @return rectangle on canvas that contains control rect + */ + public Rectangle2D toCanvasRect(Rectangle2D controlRect) + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) + return (Rectangle2D) controlRect.clone(); + + Path2D path = toCanvasArea(controlRect); + return path.getBounds2D(); + } + + /** + * Transforms from canvas coordinate system to canvas coordinate system (also diagram) + * @param g2d + */ + public void controlToCanvas(Graphics2D g2d) + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) return; + g2d.transform(at); + } + + /** + * Transforms coordinate system of g2d from canvas to control + * @param g2d + */ + public void canvasToControl(Graphics2D g2d) + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) return; + try { + g2d.transform(at.createInverse()); + } catch (NoninvertibleTransformException e) { + } + } + + /** + * Convert control point to canvas point + * @param g2d + */ + public Point2D controlToCanvas(Point2D control, Point2D canvas) + { + AffineTransform at = getInverseTransform(); + if (canvas==null) canvas = new Point2D.Double(); + if (at==null) { + canvas.setLocation(control); + return canvas; + } + at.transform(control, canvas); + return canvas; + } + + /** + * Convert canvas point to control + * @param g2d + */ + public Point2D canvasToControl(Point2D canvas, Point2D control) + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (control==null) control = new Point2D.Double(); + if (at==null) { + control.setLocation(canvas); + return canvas; + } + at.transform(canvas, control); + return control; + } + + /** + * Convert canvas vector to control vector + * @param g2d + */ + public Point2D canvasVectorToControlVector(Point2D canvas, Point2D control) + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (control==null) control = new Point2D.Double(); + if (at==null) { + control.setLocation(canvas); + return canvas; + } + double x = canvas.getX(); + double y = canvas.getY(); + + double m00 = at.getScaleX(); + double m11 = at.getScaleY(); + double m01 = at.getShearX(); + double m10 = at.getShearY(); + + control.setLocation( + x * m00 + y * m01, + x * m10 + y * m11 + ); + return control; + } + + /** + * Convert control vector to canvas vector + * @param g2d + */ + public Point2D controlVectorToCanvasVector(Point2D control, Point2D canvas) + { + AffineTransform at = getInverseTransform(); + if (canvas==null) canvas = new Point2D.Double(); + if (at==null) { + canvas.setLocation(control); + return canvas; + } + double x = control.getX(); + double y = control.getY(); + + double m00 = at.getScaleX(); + double m11 = at.getScaleY(); + double m01 = at.getShearX(); + double m10 = at.getShearY(); + + canvas.setLocation( + x * m00 + y * m01, + x * m10 + y * m11 + ); + return canvas; + } + /** + * Get a transform that converts + * diagram coordinates to control coordinates. + * + * @return transform a clone + */ + public AffineTransform getTransform() + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) return new AffineTransform(); + return (AffineTransform) at.clone(); + } + + /** + * Get a transform that converts + * diagram vector to control vector. + * + * @return transform a clone + */ + public AffineTransform getVectorTransform() + { + AffineTransform at = getHint(KEY_CANVAS_TRANSFORM); + if (at==null) return new AffineTransform(); + double m00 = at.getScaleX(); + double m11 = at.getScaleY(); + double m01 = at.getShearX(); + double m10 = at.getShearY(); + return new AffineTransform(m00, m10, m01, m11, 0, 0); + } + + + /** + * Transforms control coordinates to diagram coordinates. + * + * @return inverted transform or null if inversion failed + */ + public AffineTransform getInverseTransform() + { + AffineTransform at = getTransform(); + if (at==null) return null; + try { + at = at.createInverse(); + return at; + } catch (NoninvertibleTransformException e) { + return null; + } + } + + /** + * Tries to invert the specified {@link AffineTransform}. + * + * @parameter at the transform to invert + * @return inverted transform or null if inversion failed + */ + public AffineTransform getInverseTransform(AffineTransform at) + { + if (at == null) + return null; + try { + return at.createInverse(); + } catch (NoninvertibleTransformException e) { + return null; + } + } + + /** + * Transforms control vector to diagram vector + * @return a clone + */ + public AffineTransform getInverseVectorTransform() + { + AffineTransform at = getTransform(); + if (at==null) return null; + try { + at = at.createInverse(); + double m00 = at.getScaleX(); + double m11 = at.getScaleY(); + double m01 = at.getShearX(); + double m10 = at.getShearY(); + return new AffineTransform(m00, m10, m01, m11, 0, 0); + } catch (NoninvertibleTransformException e) { + return null; + } + } + + + public void setTransform(AffineTransform at) + { + assert(at.getShearX()!=Double.POSITIVE_INFINITY && at.getShearX()!=Double.NEGATIVE_INFINITY); + assert(at.getShearY()!=Double.POSITIVE_INFINITY && at.getShearY()!=Double.NEGATIVE_INFINITY); + AffineTransform old = getHint(KEY_CANVAS_TRANSFORM); + if(at.equals(old) == false) { // Send event only if the transform has really changed + setHint(KEY_CANVAS_TRANSFORM, at); + + IG2DNode node = NodeUtil.findNodeById(getContext().getSceneGraph(), SceneGraphConstants.NAVIGATION_NODE_PATH); + if (node != null) + // This is not in hintListener, because we don't want to update + // transform if it already came for scenegraph. + node.setTransform(at); + } + } + + public void zoom(double scaleFactor) + { + if (scaleFactor==1.0) return; + AffineTransform diagramToControl = getTransform(); + diagramToControl.scale(scaleFactor, scaleFactor); + setTransform(diagramToControl); + } + + public void rotate(Point2D centerPointCanvas, double angle) + { + if (angle==0.0) return; // and modulos too + AffineTransform diagramToControl = getTransform(); + diagramToControl.rotate(-angle, centerPointCanvas.getX(), centerPointCanvas.getY()); + setTransform(diagramToControl); + } + + public void restoreOrientation(Point2D centerPointCanvas) + { + AffineTransform res = new AffineTransform(); + AffineTransform at = getTransform(); + double m01 = at.getShearX(); + double m11 = at.getScaleY(); + double theta = Math.atan2(m01, m11); + at.rotate(-theta, centerPointCanvas.getX(), centerPointCanvas.getY()); + res.translate(at.getTranslateX(), at.getTranslateY()); + res.scale(at.getScaleX(), at.getScaleY()); + setTransform(res); + } + + /** + * Get rotate in radians. + * @return + */ + public double getRotate() { + AffineTransform at = getTransform(); + double m01 = at.getShearX(); + double m11 = at.getScaleY(); + return Math.atan2(m01, m11); + } + + /** + * Zoom the view port + * @param scaleFactor amount to zoom + * @param aroundPoint The center point of zoom in diagram coordinates + */ + public void zoomAroundDiagramPoint(double scaleFactor, Point2D aroundPoint) + { + AffineTransform diagramToControl = getTransform(); + // convert to control point + aroundPoint = diagramToControl.transform(aroundPoint, new Point2D.Double()); + zoomAroundControlPoint(scaleFactor, aroundPoint); + } + + /** + * Zoom the view port + * @param scaleFactor amount to zoom + * @param centerPoint the control point to zoom around + */ + public void zoomAroundControlPoint(double scaleFactor, Point2D centerPoint) + { + if (scaleFactor==1.0) return; + AffineTransform diagramToControl = getTransform(); + try { + Point2D pointBeforeScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double()); + diagramToControl.scale(scaleFactor, scaleFactor); + Point2D pointAfterScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double()); + double _dx = pointAfterScale.getX() - pointBeforeScale.getX(); + double _dy = pointAfterScale.getY() - pointBeforeScale.getY(); + diagramToControl.translate(_dx, _dy); + } catch (NoninvertibleTransformException e1) { + } + setTransform(diagramToControl); + } + + /** + * Transform the viewport. The transform values are in diagram coordinates + * @param dx + * @param dy + */ + public void translateWithCanvasCoordinates(double dx, double dy) + { + AffineTransform controlToDiagram = getTransform(); + controlToDiagram.translate(dx, dy); + setTransform(controlToDiagram); + } + + /** + * Transform the viewport. The transform values are in control coordinates + * @param dx + * @param dy + */ + public void translateWithControlCoordinates(Point2D offset) + { + if (offset.getX()==0 && offset.getY()==0) return; + AffineTransform at = getInverseTransform(); + offset = at.transform(offset, new Point2D.Double()); + translateWithCanvasCoordinates(offset.getX()-at.getTranslateX(), offset.getY()-at.getTranslateY()); + } + + /** + * Get scale ratio between control and canvas + * @param pt + * @return + */ + public Point2D getScale(Point2D pt) + { + AffineTransform at = getTransform(); + return GeometryUtils.getScaleXY(at, pt); + } + + /** + * Modifies transform to make canvas area fully visible. + * @param controlArea + * @param diagramArea + * @param margins margins + */ + public void fitArea(Rectangle2D controlArea, Rectangle2D diagramArea, Margins margins) + { + AffineTransform fitTx = org.simantics.scenegraph.utils.GeometryUtils.fitArea(controlArea, diagramArea, margins); + //System.out.println("fitArea(" + controlArea + ", " + diagramArea + ", " + margins + "): " + fitTx); + setTransform(fitTx); + } + +}