import java.awt.*; import java.awt.geom.*; import java.util.Date; /** * An example for an animation based on convex combinations of two * geometric transformations. An ellipse in the upper left corner of * the window is transformed stepwise into another ellipse * in the lower right corner of the window. * * @author Frank Klawonn * Last change 21.01.2005 */ public class ConvexCombTransforms extends Frame { //Constructor public ConvexCombTransforms() { //Enables the closing of the window. addWindowListener(new MyFinishWindow()); } public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; //Use of antialiasing to have nicer lines. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); int xul, yul, xwidth, yheight; xul = 20; //x-coordinate for the definition of a bounding recatangle //for an ellipse yul = 40; //y-coordinate the definition of the rectangle xwidth = 50; //Width of the rectangle yheight = 20; //Height of the rectangle //Generating an ellipse from the rectangle. //This ellipse is used to construct the initial and the final ellipse. Ellipse2D.Double elli = new Ellipse2D.Double(xul,yul,xwidth,yheight); //Midpoint of the ellipse/rectangle double xmid = xul+xwidth/2.0; double ymid = yul+yheight/2.0; //Transformation for constructing the initial ellipse. AffineTransform initialTransform = new AffineTransform(); initialTransform.setToRotation(Math.PI/6,xmid,ymid); //The matrix for the transformation of the initial ellipse. //The matrix is needed for the computation of the convex combinations. double[] initialMatrix = new double[6]; initialTransform.getMatrix(initialMatrix); //Transformation for constructing the final ellipse. AffineTransform finalTransform = new AffineTransform(); finalTransform.setToTranslation(500,200); finalTransform.concatenate(scalingWRTXY(xmid,ymid,2,0.5)); finalTransform.rotate(3*Math.PI/4,xmid,ymid); //The matrix for the transformation of the final ellipse. //The matrix is needed for the computation of the convex combinations. double[] finalMatrix = new double[6]; finalTransform.getMatrix(finalMatrix); //Number of steps/images/frames for the transformation of the //initial into the final eellipse. int steps = 200; //The initial ellipse Shape initialElli = initialTransform.createTransformedShape(elli); //The final ellipse Shape finalElli = finalTransform.createTransformedShape(elli); //This shape is used for drawing the intermediate ellipses. Shape s; //This transformation is used for the convex combinations of the //initial and the final transformations. AffineTransform intermediateTransform; double stepsDouble = steps; //Number of steps as a Double-value in order //to avoid repeated casting in the loop. for (int i=0; i<=steps; i++) { //Computation of the i-th convex combination. intermediateTransform = new AffineTransform( convexCombination(initialMatrix,finalMatrix,i/stepsDouble)); //Generate the intermediate ellipse. s = intermediateTransform.createTransformedShape(elli); //Wait a little bit before the next image (frame) is drawn. sustain(50); //Clear the whole window. clearWindow(g2d); //Draw the intermediate ellipse. g2d.fill(s); //Draw the initial ellipse in green. g2d.setPaint(Color.green); g2d.fill(initialElli); //Draw the final ellipse in red. g2d.setPaint(Color.red); g2d.fill(finalElli); } } /** * Conmputes the convex combination of two vectors/points (given as Java-ArraysC). * * @param a initial point * @param b endpoint (must have the same length as the array a) * @param alpha Proportion that the initial point contributes to the convex combination. * soll. 0<=alpha<=1 must hold. * * @return The convex combination (1-alpha)*a + alpha*b of the two points. */ public static double[] convexCombination(double[] a, double[] b, double alpha) { double[] result = new double[a.length]; for (int i=0; i