/* * Copyright (c) 2003, the JUNG Project and the Regents of the University of * California All rights reserved. * * This software is open-source under the BSD license; see either "license.txt" * or http://jung.sourceforge.net/license.txt for a description. * */ package edu.uci.ics.jung.visualization.jai; import java.awt.Shape; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import javax.media.jai.PerspectiveTransform; import edu.uci.ics.jung.visualization.transform.MutableTransformer; import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; /** * PerspectiveShapeTransformer extends PerspectiveTransformer and * adds implementations for methods in ShapeTransformer. * It modifies the shapes (Vertex, Edge, and Arrowheads) so that * they are distorted by the perspective transformation * * @author Tom Nelson * * */ public class PerspectiveShapeTransformer extends PerspectiveTransformer implements ShapeTransformer { /** * Create an instance, setting values from the passed component * and registering to listen for size changes on the component. */ public PerspectiveShapeTransformer(PerspectiveTransform perspectiveTransform) { this(perspectiveTransform, null); } /** * Create an instance */ public PerspectiveShapeTransformer(PerspectiveTransform perspectiveTransform, MutableTransformer delegate) { super(perspectiveTransform, delegate); } /** * Transform the supplied shape with the overridden transform * method so that the shape is distorted by the perspective * transform. * @param shape a shape to transform * @return a GeneralPath for the transformed shape */ @Override public Shape transform(Shape shape) { return transform(shape, 0); } public Shape transform(Shape shape, float flatness) { GeneralPath newPath = new GeneralPath(); float[] coords = new float[6]; PathIterator iterator = null; if(flatness == 0) { iterator = shape.getPathIterator(null); } else { iterator = shape.getPathIterator(null, flatness); } for( ; iterator.isDone() == false; iterator.next()) { int type = iterator.currentSegment(coords); switch(type) { case PathIterator.SEG_MOVETO: Point2D p = transform(new Point2D.Float(coords[0], coords[1])); newPath.moveTo((float)p.getX(), (float)p.getY()); break; case PathIterator.SEG_LINETO: p = transform(new Point2D.Float(coords[0], coords[1])); newPath.lineTo((float)p.getX(), (float) p.getY()); break; case PathIterator.SEG_QUADTO: p = transform(new Point2D.Float(coords[0], coords[1])); Point2D q = transform(new Point2D.Float(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(new Point2D.Float(coords[0], coords[1])); q = transform(new Point2D.Float(coords[2], coords[3])); Point2D r = transform(new Point2D.Float(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; } @Override 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(new Point2D.Float(coords[0], coords[1])); newPath.moveTo((float)p.getX(), (float)p.getY()); break; case PathIterator.SEG_LINETO: p = inverseTransform(new Point2D.Float(coords[0], coords[1])); newPath.lineTo((float)p.getX(), (float) p.getY()); break; case PathIterator.SEG_QUADTO: p = inverseTransform(new Point2D.Float(coords[0], coords[1])); Point2D q = inverseTransform(new Point2D.Float(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(new Point2D.Float(coords[0], coords[1])); q = inverseTransform(new Point2D.Float(coords[2], coords[3])); Point2D r = inverseTransform(new Point2D.Float(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 Shape perspectiveTransform(Shape shape) { return perspectiveTransform(shape, 0); } public Shape perspectiveTransform(Shape shape, float flatness) { GeneralPath newPath = new GeneralPath(); float[] coords = new float[6]; PathIterator iterator = null; if(flatness == 0) { iterator = shape.getPathIterator(null); } else { iterator = shape.getPathIterator(null, flatness); } for( ; iterator.isDone() == false; iterator.next()) { int type = iterator.currentSegment(coords); switch(type) { case PathIterator.SEG_MOVETO: Point2D p = perspectiveTransform(new Point2D.Float(coords[0], coords[1])); newPath.moveTo((float)p.getX(), (float)p.getY()); break; case PathIterator.SEG_LINETO: p = perspectiveTransform(new Point2D.Float(coords[0], coords[1])); newPath.lineTo((float)p.getX(), (float) p.getY()); break; case PathIterator.SEG_QUADTO: p = perspectiveTransform(new Point2D.Float(coords[0], coords[1])); Point2D q = perspectiveTransform(new Point2D.Float(coords[2], coords[3])); newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); break; case PathIterator.SEG_CUBICTO: p = perspectiveTransform(new Point2D.Float(coords[0], coords[1])); q = perspectiveTransform(new Point2D.Float(coords[2], coords[3])); Point2D r = perspectiveTransform(new Point2D.Float(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 Shape inversePerspectiveTransform(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 = inversePerspectiveTransform(new Point2D.Float(coords[0], coords[1])); newPath.moveTo((float)p.getX(), (float)p.getY()); break; case PathIterator.SEG_LINETO: p = inversePerspectiveTransform(new Point2D.Float(coords[0], coords[1])); newPath.lineTo((float)p.getX(), (float) p.getY()); break; case PathIterator.SEG_QUADTO: p = inversePerspectiveTransform(new Point2D.Float(coords[0], coords[1])); Point2D q = inversePerspectiveTransform(new Point2D.Float(coords[2], coords[3])); newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); break; case PathIterator.SEG_CUBICTO: p = inversePerspectiveTransform(new Point2D.Float(coords[0], coords[1])); q = inversePerspectiveTransform(new Point2D.Float(coords[2], coords[3])); Point2D r = inversePerspectiveTransform(new Point2D.Float(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; } }