edu.uci.ics.jung.visualization.transform.AffineTransformer Maven / Gradle / Ivy
/*
* Copyright (c) 2005, The JUNG Authors
* All rights reserved.
*
* This software is open-source under the BSD license; see either "license.txt"
* or https://github.com/jrtom/jung/blob/master/LICENSE for a description.
*
* Created on Apr 16, 2005
*/
package edu.uci.ics.jung.visualization.transform;
import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
/**
* Provides methods to map points from one coordinate system to another, by delegating to a wrapped
* AffineTransform (uniform) and its inverse.
*
* @author Tom Nelson
*/
public class AffineTransformer implements BidirectionalTransformer, ShapeTransformer {
protected AffineTransform inverse;
/** The AffineTransform to use; initialized to identity. */
protected AffineTransform transform = new AffineTransform();
/** Create an instance that does not transform points. */
public AffineTransformer() {
// nothing left to do
}
/**
* Create an instance with the supplied transform.
*
* @param transform the transform to use
*/
public AffineTransformer(AffineTransform transform) {
if (transform != null) {
this.transform = transform;
}
}
/** @return Returns the transform. */
public AffineTransform getTransform() {
return transform;
}
/** @param transform The transform to set. */
public void setTransform(AffineTransform transform) {
this.transform = transform;
}
/**
* applies the inverse transform to the supplied point
*
* @param p the point to transform
* @return the transformed point
*/
public Point2D inverseTransform(Point2D p) {
return getInverse().transform(p, null);
}
public Point2D inverseTransform(double x, double y) {
return inverseTransform(new Point2D.Double(x, y));
}
public AffineTransform getInverse() {
if (inverse == null) {
try {
inverse = transform.createInverse();
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
}
}
return inverse;
}
/** @return the transform's x scale value */
public double getScaleX() {
return transform.getScaleX();
}
/** @return the transform's y scale value */
public double getScaleY() {
return transform.getScaleY();
}
/** @return the transform's overall scale magnitude */
public double getScale() {
return Math.sqrt(transform.getDeterminant());
}
/** @return the transform's x shear value */
public double getShearX() {
return transform.getShearX();
}
/** @return the transform's y shear value */
public double getShearY() {
return transform.getShearY();
}
/** @return the transform's x translate value */
public double getTranslateX() {
return transform.getTranslateX();
}
/** @return the transform's y translate value */
public double getTranslateY() {
return transform.getTranslateY();
}
/**
* Applies the transform to the supplied point.
*
* @param p the point to be transformed
* @return the transformed point
*/
public Point2D transform(Point2D p) {
if (p == null) {
return null;
}
return transform.transform(p, null);
}
public Point2D transform(double x, double y) {
return transform(new Point2D.Double(x, y));
}
/**
* Transform the supplied shape from graph (layout) to screen (view) coordinates.
*
* @return the GeneralPath of the transformed shape
*/
public Shape transform(Shape shape) {
GeneralPath newPath = new GeneralPath();
float[] coords = new float[6];
for (PathIterator iterator = shape.getPathIterator(null);
iterator.isDone() == false;
iterator.next()) {
int type = iterator.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
Point2D p = transform(coords[0], coords[1]);
newPath.moveTo((float) p.getX(), (float) p.getY());
break;
case PathIterator.SEG_LINETO:
p = transform(coords[0], coords[1]);
newPath.lineTo((float) p.getX(), (float) p.getY());
break;
case PathIterator.SEG_QUADTO:
p = transform(coords[0], coords[1]);
Point2D q = transform(coords[2], coords[3]);
newPath.quadTo((float) p.getX(), (float) p.getY(), (float) q.getX(), (float) q.getY());
break;
case PathIterator.SEG_CUBICTO:
p = transform(coords[0], coords[1]);
q = transform(coords[2], coords[3]);
Point2D r = transform(coords[4], coords[5]);
newPath.curveTo(
(float) p.getX(),
(float) p.getY(),
(float) q.getX(),
(float) q.getY(),
(float) r.getX(),
(float) r.getY());
break;
case PathIterator.SEG_CLOSE:
newPath.closePath();
break;
}
}
return newPath;
}
/**
* Transform the supplied shape from screen (view) to graph (layout) coordinates.
*
* @return the GeneralPath of the transformed shape
*/
public Shape inverseTransform(Shape shape) {
GeneralPath newPath = new GeneralPath();
float[] coords = new float[6];
for (PathIterator iterator = shape.getPathIterator(null);
iterator.isDone() == false;
iterator.next()) {
int type = iterator.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
Point2D p = inverseTransform(coords[0], coords[1]);
newPath.moveTo((float) p.getX(), (float) p.getY());
break;
case PathIterator.SEG_LINETO:
p = inverseTransform(coords[0], coords[1]);
newPath.lineTo((float) p.getX(), (float) p.getY());
break;
case PathIterator.SEG_QUADTO:
p = inverseTransform(coords[0], coords[1]);
Point2D q = inverseTransform(coords[2], coords[3]);
newPath.quadTo((float) p.getX(), (float) p.getY(), (float) q.getX(), (float) q.getY());
break;
case PathIterator.SEG_CUBICTO:
p = inverseTransform(coords[0], coords[1]);
q = inverseTransform(coords[2], coords[3]);
Point2D r = inverseTransform(coords[4], coords[5]);
newPath.curveTo(
(float) p.getX(),
(float) p.getY(),
(float) q.getX(),
(float) q.getY(),
(float) r.getX(),
(float) r.getY());
break;
case PathIterator.SEG_CLOSE:
newPath.closePath();
break;
}
}
return newPath;
}
public double getRotation() {
double[] unitVector = new double[] {0, 0, 1, 0};
double[] result = new double[4];
transform.transform(unitVector, 0, result, 0, 2);
double dy = Math.abs(result[3] - result[1]);
double length = Point2D.distance(result[0], result[1], result[2], result[3]);
double rotation = Math.asin(dy / length);
if (result[3] - result[1] > 0) {
if (result[2] - result[0] < 0) {
rotation = Math.PI - rotation;
}
} else {
if (result[2] - result[0] > 0) {
rotation = 2 * Math.PI - rotation;
} else {
rotation = rotation + Math.PI;
}
}
return rotation;
}
@Override
public String toString() {
return "Transformer using " + transform;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy