Java/2D Graphics GUI/Transform

Материал из Java эксперт
Перейти к: навигация, поиск

AffineTransform demo

   
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AffineTransformApp extends JFrame {
  DisplayPanel displayPanel;
  JComboBox scaleXval, scaleYval, shearXval, shearYval;
  String[] scaleValues = { "0.10", "0.25", "0.50", "0.75", "1.00", "1.25",
      "1.50", "1.75", "2.00" };
  String[] shearValues = { "0.00", "0.25", "0.50", "0.75", "1.00" };
  public AffineTransformApp() {
    super();
    Container container = getContentPane();
    displayPanel = new DisplayPanel();
    container.add(displayPanel);
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(2, 4, 5, 5));
    scaleXval = new JComboBox(scaleValues);
    scaleXval.setSelectedItem("1.00");
    scaleXval.addActionListener(new ComboBoxListener());
    scaleYval = new JComboBox(scaleValues);
    scaleYval.setSelectedItem("1.00");
    scaleYval.addActionListener(new ComboBoxListener());
    shearXval = new JComboBox(shearValues);
    shearXval.setSelectedItem("0.00");
    shearXval.addActionListener(new ComboBoxListener());
    shearYval = new JComboBox(shearValues);
    shearYval.setSelectedItem("0.00");
    shearYval.addActionListener(new ComboBoxListener());
    panel.add(new JLabel("Scale X value:"));
    panel.add(scaleXval);
    panel.add(new JLabel("Scale Y value:"));
    panel.add(scaleYval);
    panel.add(new JLabel("Shear X value:"));
    panel.add(shearXval);
    panel.add(new JLabel("Shear Y value:"));
    panel.add(shearYval);
    container.add(BorderLayout.SOUTH, panel);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
    setVisible(true);
  }
  public static void main(String arg[]) {
    new AffineTransformApp();
  }
  class ComboBoxListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      JComboBox temp = (JComboBox) e.getSource();
      if (temp == scaleXval) {
        displayPanel.scalex = Double.parseDouble((String) temp
            .getSelectedItem());
        displayPanel.applyValue(true, false);
        displayPanel.applyFilter();
        displayPanel.repaint();
      } else if (temp == scaleYval) {
        displayPanel.scaley = Double.parseDouble((String) temp
            .getSelectedItem());
        displayPanel.applyValue(true, false);
        displayPanel.applyFilter();
        displayPanel.repaint();
      } else if (temp == shearXval) {
        displayPanel.shearx = Double.parseDouble((String) temp
            .getSelectedItem());
        displayPanel.applyValue(false, true);
        displayPanel.applyFilter();
        displayPanel.repaint();
      } else if (temp == shearYval) {
        displayPanel.sheary = Double.parseDouble((String) temp
            .getSelectedItem());
        displayPanel.applyValue(false, true);
        displayPanel.applyFilter();
        displayPanel.repaint();
      }
    }
  }
}
class DisplayPanel extends JLabel {
  Image displayImage;
  BufferedImage biSrc, biDest;
  BufferedImage bi;
  Graphics2D big;
  AffineTransform transform;
  double scalex = 1.0;
  double scaley = 1.0;
  double shearx = 1.0;
  double sheary = 1.0;
  DisplayPanel() {
    setBackground(Color.black);
    loadImage();
    setSize(displayImage.getWidth(this), displayImage.getWidth(this)); // panel
    createBufferedImages();
    transform = new AffineTransform();
  }
  public void loadImage() {
    displayImage = Toolkit.getDefaultToolkit().getImage(
        "largejexpLogo.jpg");
    MediaTracker mt = new MediaTracker(this);
    mt.addImage(displayImage, 1);
    try {
      mt.waitForAll();
    } catch (Exception e) {
      System.out.println("Exception while loading.");
    }
    if (displayImage.getWidth(this) == -1) {
      System.out.println(" Missing .jpg file");
      System.exit(0);
    }
  }
  public void createBufferedImages() {
    biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
        .getHeight(this), BufferedImage.TYPE_INT_RGB);
    big = biSrc.createGraphics();
    big.drawImage(displayImage, 0, 0, this);
    bi = biSrc;
    biDest = new BufferedImage(displayImage.getWidth(this), displayImage
        .getHeight(this), BufferedImage.TYPE_INT_RGB);
  }
  public void applyValue(boolean scale, boolean shear) {
    if (scale) {
      transform.setToScale(scalex, scaley);
      scale = false;
    } else if (shear) {
      transform.setToShear(shearx, sheary);
      shear = false;
    }
  }
  public void applyFilter() {
    AffineTransformOp op = new AffineTransformOp(transform, null);
    Graphics2D biDestG2D = biDest.createGraphics();
    biDestG2D
        .clearRect(0, 0, biDest.getWidth(this), biDest.getHeight(this));
    op.filter(biSrc, biDest);
    bi = biDest;
  }
  public void reset() {
    big.setColor(Color.black);
    big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
    big.drawImage(displayImage, 0, 0, this);
  }
  public void update(Graphics g) {
    g.clearRect(0, 0, getWidth(), getHeight());
    paintComponent(g);
  }
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2D = (Graphics2D) g;
    g2D.drawImage(bi, 0, 0, this);
  }
}



Coordinate Demo

   
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/* CoordinatesDemo.java is a 1.4 application that requires no other files. */
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.event.MouseInputListener;
/*
 * This displays a framed area. As the user moves the cursor over the area, a
 * label displays the cursor"s location. When the user clicks, the area displays
 * a 7x7 dot at the click location.
 */
public class CoordinatesDemo {
  private JLabel label;
  private Point clickPoint, cursorPoint;
  private void buildUI(Container container) {
    container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
    CoordinateArea coordinateArea = new CoordinateArea(this);
    container.add(coordinateArea);
    label = new JLabel();
    resetLabel();
    container.add(label);
    //Align the left edges of the components.
    coordinateArea.setAlignmentX(Component.LEFT_ALIGNMENT);
    label.setAlignmentX(Component.LEFT_ALIGNMENT); //redundant
  }
  public void updateCursorLocation(int x, int y) {
    if (x < 0 || y < 0) {
      cursorPoint = null;
      updateLabel();
      return;
    }
    if (cursorPoint == null) {
      cursorPoint = new Point();
    }
    cursorPoint.x = x;
    cursorPoint.y = y;
    updateLabel();
  }
  public void updateClickPoint(Point p) {
    clickPoint = p;
    updateLabel();
  }
  public void resetLabel() {
    cursorPoint = null;
    updateLabel();
  }
  protected void updateLabel() {
    String text = "";
    if ((clickPoint == null) && (cursorPoint == null)) {
      text = "Click or move the cursor within the framed area.";
    } else {
      if (clickPoint != null) {
        text += "The last click was at (" + clickPoint.x + ", "
            + clickPoint.y + "). ";
      }
      if (cursorPoint != null) {
        text += "The cursor is at (" + cursorPoint.x + ", "
            + cursorPoint.y + "). ";
      }
    }
    label.setText(text);
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("CoordinatesDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Set up the content pane.
    CoordinatesDemo controller = new CoordinatesDemo();
    controller.buildUI(frame.getContentPane());
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
  public static class CoordinateArea extends JComponent implements
      MouseInputListener {
    Point point = null;
    CoordinatesDemo controller;
    Dimension preferredSize = new Dimension(400, 75);
    Color gridColor;
    public CoordinateArea(CoordinatesDemo controller) {
      this.controller = controller;
      //Add a border of 5 pixels at the left and bottom,
      //and 1 pixel at the top and right.
      setBorder(BorderFactory.createMatteBorder(1, 5, 5, 1, Color.RED));
      addMouseListener(this);
      addMouseMotionListener(this);
      setBackground(Color.WHITE);
      setOpaque(true);
    }
    public Dimension getPreferredSize() {
      return preferredSize;
    }
    protected void paintComponent(Graphics g) {
      //Paint background if we"re opaque.
      if (isOpaque()) {
        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());
      }
      //Paint 20x20 grid.
      g.setColor(Color.GRAY);
      drawGrid(g, 20);
      //If user has chosen a point, paint a small dot on top.
      if (point != null) {
        g.setColor(getForeground());
        g.fillRect(point.x - 3, point.y - 3, 7, 7);
      }
    }
    //Draws a 20x20 grid using the current color.
    private void drawGrid(Graphics g, int gridSpace) {
      Insets insets = getInsets();
      int firstX = insets.left;
      int firstY = insets.top;
      int lastX = getWidth() - insets.right;
      int lastY = getHeight() - insets.bottom;
      //Draw vertical lines.
      int x = firstX;
      while (x < lastX) {
        g.drawLine(x, firstY, x, lastY);
        x += gridSpace;
      }
      //Draw horizontal lines.
      int y = firstY;
      while (y < lastY) {
        g.drawLine(firstX, y, lastX, y);
        y += gridSpace;
      }
    }
    //Methods required by the MouseInputListener interface.
    public void mouseClicked(MouseEvent e) {
      int x = e.getX();
      int y = e.getY();
      if (point == null) {
        point = new Point(x, y);
      } else {
        point.x = x;
        point.y = y;
      }
      controller.updateClickPoint(point);
      repaint();
    }
    public void mouseMoved(MouseEvent e) {
      controller.updateCursorLocation(e.getX(), e.getY());
    }
    public void mouseExited(MouseEvent e) {
      controller.resetLabel();
    }
    public void mouseReleased(MouseEvent e) {
    }
    public void mouseEntered(MouseEvent e) {
    }
    public void mousePressed(MouseEvent e) {
    }
    public void mouseDragged(MouseEvent e) {
    }
  }
}



Create an complex shape by rotating an ellipse.

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class RotateTransformed extends JPanel {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);
    for (double i = 0; i < 360; i += 5) {
      AffineTransform at = AffineTransform.getTranslateInstance(400 / 2, 400 / 2);
      at.rotate(Math.toRadians(i));
      g2.draw(at.createTransformedShape(e));
    }
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new RotateTransformed());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setVisible(true);
  }
}



Creates and returns a translated shape.

 
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
 *
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * -------------------
 * ShapeUtilities.java
 * -------------------
 * (C)opyright 2003-2008, by Object Refinery Limited and Contributors.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: ShapeUtilities.java,v 1.18 2008/06/02 06:58:28 mungady Exp $
 *
 * Changes
 * -------
 * 13-Aug-2003 : Version 1 (DG);
 * 16-Mar-2004 : Moved rotateShape() from RefineryUtilities.java to here (DG);
 * 13-May-2004 : Added new shape creation methods (DG);
 * 30-Sep-2004 : Added createLineRegion() method (DG);
 *               Moved drawRotatedShape() method from RefineryUtilities class
 *               to this class (DG);
 * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
 * 26-Oct-2004 : Added a method to test the equality of two Line2D
 *               instances (DG);
 * 10-Nov-2004 : Added new translateShape() and equal(Ellipse2D, Ellipse2D)
 *               methods (DG);
 * 11-Nov-2004 : Renamed translateShape() --> createTranslatedShape() (DG);
 * 07-Jan-2005 : Minor Javadoc fix (DG);
 * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG);
 * 21-Jan-2005 : Modified return type of RectangleAnchor.coordinates()
 *               method (DG);
 * 22-Feb-2005 : Added equality tests for Arc2D and GeneralPath (DG);
 * 16-Mar-2005 : Fixed bug where equal(Shape, Shape) fails for two Polygon
 *               instances (DG);
 * 01-Jun-2008 : Fixed bug in equal(GeneralPath, GeneralPath) method (DG);
 *
 */
import java.awt.Shape;
import java.awt.geom.AffineTransform;
/**
 * Utility methods for {@link Shape} objects.
 *
 * @author David Gilbert
 */
public class Main {
  /**
   * Creates and returns a translated shape.
   *
   * @param shape  the shape (<code>null</code> not permitted).
   * @param transX  the x translation (in Java2D space).
   * @param transY  the y translation (in Java2D space).
   *
   * @return The translated shape.
   */
  public static Shape createTranslatedShape(final Shape shape,
                                            final double transX,
                                            final double transY) {
      if (shape == null) {
          throw new IllegalArgumentException("Null "shape" argument.");
      }
      final AffineTransform transform = AffineTransform.getTranslateInstance(
              transX, transY);
      return transform.createTransformedShape(shape);
  }
}



Line transformation, rotation, shear,scale

   
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class House extends JPanel {
  MyCanvas canvas;
  JSlider sliderTransX, sliderTransY, sliderRotateTheta, sliderRotateX,
      sliderRotateY, sliderScaleX, sliderScaleY, sliderWidth;
  double transX = 0.0;
  double transY = 0.0;
  double rotateTheta = 0.0;
  double rotateX = 150.0;
  double rotateY = 150.0;
  double scaleX = 1.0;
  double scaleY = 1.0;
  float width = 1.0f;
  public House() {
    super(new BorderLayout());
    JPanel controlPanel = new JPanel(new GridLayout(3, 3));
    add(controlPanel, BorderLayout.NORTH);
    controlPanel.add(new JLabel("Translate(dx,dy): "));
    sliderTransX = setSlider(controlPanel, JSlider.HORIZONTAL, 0, 300, 150,
        100, 50);
    sliderTransY = setSlider(controlPanel, JSlider.HORIZONTAL, 0, 300, 150,
        100, 50);
    // To control rotation
    controlPanel.add(new JLabel("Rotate(Theta,ox,oy): "));
    sliderRotateTheta = setSlider(controlPanel, JSlider.HORIZONTAL, 0, 360,
        0, 90, 45);
    JPanel subPanel = new JPanel();
    subPanel.setLayout(new GridLayout(1, 2));
    sliderRotateX = setSlider(subPanel, JSlider.HORIZONTAL, 0, 300, 150,
        150, 50);
    sliderRotateY = setSlider(subPanel, JSlider.HORIZONTAL, 0, 300, 150,
        150, 50);
    controlPanel.add(subPanel);
    // To control scaling
    controlPanel.add(new JLabel("Scale(sx,sy)x10E-2:"));
    sliderScaleX = setSlider(controlPanel, JSlider.HORIZONTAL, 0, 200, 100,
        100, 10);
    sliderScaleY = setSlider(controlPanel, JSlider.HORIZONTAL, 0, 200, 100,
        100, 10);
    // To control width of line segments
    JLabel label4 = new JLabel("Width Control:", JLabel.RIGHT);
    sliderWidth = new JSlider(JSlider.HORIZONTAL, 0, 20, 1);
    sliderWidth.setPaintTicks(true);
    sliderWidth.setMajorTickSpacing(5);
    sliderWidth.setMinorTickSpacing(1);
    sliderWidth.setPaintLabels(true);
    sliderWidth.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        width = sliderWidth.getValue();
        canvas.repaint();
      }
    });
    JPanel widthPanel = new JPanel();
    widthPanel.setLayout(new GridLayout(1, 2));
    widthPanel.add(label4);
    widthPanel.add(sliderWidth);
    add(widthPanel, BorderLayout.SOUTH);
    canvas = new MyCanvas();
    add(canvas, "Center");
  }
  public JSlider setSlider(JPanel panel, int orientation, int minimumValue,
      int maximumValue, int initValue, int majorTickSpacing,
      int minorTickSpacing) {
    JSlider slider = new JSlider(orientation, minimumValue, maximumValue,
        initValue);
    slider.setPaintTicks(true);
    slider.setMajorTickSpacing(majorTickSpacing);
    slider.setMinorTickSpacing(minorTickSpacing);
    slider.setPaintLabels(true);
    slider.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        JSlider tempSlider = (JSlider) e.getSource();
        if (tempSlider.equals(sliderTransX)) {
          transX = sliderTransX.getValue() - 150.0;
          canvas.repaint();
        } else if (tempSlider.equals(sliderTransY)) {
          transY = sliderTransY.getValue() - 150.0;
          canvas.repaint();
        } else if (tempSlider.equals(sliderRotateTheta)) {
          rotateTheta = sliderRotateTheta.getValue() * Math.PI / 180;
          canvas.repaint();
        } else if (tempSlider.equals(sliderRotateX)) {
          rotateX = sliderRotateX.getValue();
          canvas.repaint();
        } else if (tempSlider.equals(sliderRotateY)) {
          rotateY = sliderRotateY.getValue();
          canvas.repaint();
        } else if (tempSlider.equals(sliderScaleX)) {
          if (sliderScaleX.getValue() != 0.0) {
            scaleX = sliderScaleX.getValue() / 100.0;
            canvas.repaint();
          }
        } else if (tempSlider.equals(sliderScaleY)) {
          if (sliderScaleY.getValue() != 0.0) {
            scaleY = sliderScaleY.getValue() / 100.0;
            canvas.repaint();
          }
        }
      }
    });
    panel.add(slider);
    return slider;
  }
  class MyCanvas extends Canvas {
    public void paint(Graphics g) {
      Graphics2D g2D = (Graphics2D) g;
      g2D.translate(transX, transY);
      g2D.rotate(rotateTheta, rotateX, rotateY);
      g2D.scale(scaleX, scaleY);
      BasicStroke stroke = new BasicStroke(width);
      g2D.setStroke(stroke);
      drawHome(g2D);
    }
    public void drawHome(Graphics2D g2D) {
      Line2D line1 = new Line2D.Float(100f, 200f, 200f, 200f);
      Line2D line2 = new Line2D.Float(100f, 200f, 100f, 100f);
      Line2D line3 = new Line2D.Float(100f, 100f, 150f, 50f);
      Line2D line4 = new Line2D.Float(150f, 50f, 200f, 100f);
      Line2D line5 = new Line2D.Float(200f, 100f, 200f, 200f);
      Line2D line6 = new Line2D.Float(140f, 200f, 140f, 150f);
      Line2D line7 = new Line2D.Float(140f, 150f, 160f, 150f);
      Line2D line8 = new Line2D.Float(160f, 150f, 160f, 200f);
      g2D.draw(line1);
      g2D.draw(line2);
      g2D.draw(line3);
      g2D.draw(line4);
      g2D.draw(line5);
      g2D.draw(line6);
      g2D.draw(line7);
      g2D.draw(line8);
    }
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new House());
    f.setDefaultCloseOperation(1);
    f.setSize(700, 550);
    f.setVisible(true);
  }
}



Perform shearing: use share() method.

   
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Shear extends JPanel {
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform tx1 = new AffineTransform();
    tx1.translate(50, 90);
    g2d.setTransform(tx1);
    g2d.setColor(Color.green);
    g2d.drawRect(0, 0, 80, 50);
    AffineTransform tx2 = new AffineTransform();
    tx2.translate(50, 90);
    tx2.shear(0, 1);
    g2d.setTransform(tx2);
    g2d.setColor(Color.blue);
    g2d.draw(new Rectangle(0, 0, 80, 50));
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("Shearing");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new Shear());
    frame.setSize(330, 270);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}



Resizes or translates a Shape

 
/**
 * 
 * JFreeReport : a free Java reporting library
 * 
 *
 * Project Info:  http://reporting.pentaho.org/
 *
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * ------------
 * ShapeTransform.java
 * ------------
 * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
 */
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Dimension2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
/**
 * Utility class, which resizes or translates a Shape. The class contains
 * special handlers for Rectangles and Lines.
 * 
 * @author Thomas Morgner
 */
public final strictfp class ShapeTransform {
  // some constants for the cohenen-algorithmus
  /**
   * Flag for point lying left of clipping area.
   */
  public static final int LEFT = 0x01;
  /**
   * Flag for point lying between horizontal bounds of area.
   */
  public static final int H_CENTER = 0x02;
  /**
   * Flag for point lying right of clipping area.
   */
  public static final int RIGHT = 0x04;
  /**
   * Flag for point lying &quot;below&quot; clipping area.
   */
  public static final int BELOW = 0x10;
  /**
   * Flag for point lying between vertical bounds of clipping area.
   */
  public static final int V_CENTER = 0x20;
  /**
   * Flag for point lying &quot;above&quot; clipping area.
   */
  public static final int ABOVE = 0x40;
  /** A simple way to handle rounding errors. */
  private static final double DELTA = 0.000001;
  /**
   * Mask for points which are inside.
   */
  public static final int INSIDE = H_CENTER | V_CENTER;
  /**
   * Mask for points which are outside.
   */
  public static final int OUTSIDE = LEFT | RIGHT | BELOW | ABOVE;
  /**
   * Default constructor.
   */
  private ShapeTransform() {
  }
  /**
   * Resizes a line. Instead of creating a GeneralPath (as AffineTransform"s
   * scale would do) we modify the line itself.
   * 
   * @param line
   *          the line that should be scaled
   * @param width
   *          the new width of the line bounds
   * @param height
   *          the new height of the line bounds
   * @return the scale Line2D object.
   */
  private static Line2D resizeLine(final Line2D line, final double width, final double height) {
    final Line2D newLine = getNormalizedLine(line);
    final Point2D p1 = newLine.getP1();
    final Point2D p2 = newLine.getP2();
    final double normPointX = (p1.getX() - p2.getX());
    final double normPointY = (p1.getY() - p2.getY());
    final double scaleX = (normPointX == 0) ? 1 : width / Math.abs(normPointX);
    final double scaleY = (normPointY == 0) ? 1 : height / Math.abs(normPointY);
    p2.setLocation((p2.getX() - p1.getX()) * scaleX + p1.getX(), (p2.getY() - p1.getY()) * scaleY
        + p1.getY());
    newLine.setLine(p1, p2);
    return newLine;
  }
  /**
   * Normalize the line; the point with the lowest X is the primary point, if
   * both points have the same X, that point with the lowest Y value wins.
   * 
   * @param line
   *          the original line
   * @return the normalized line
   */
  private static Line2D getNormalizedLine(final Line2D line) {
    final Line2D lineClone = (Line2D) line.clone();
    final Point2D p1 = line.getP1();
    final Point2D p2 = line.getP2();
    if (p1.getX() < p2.getX()) {
      return lineClone;
    }
    if (p1.getX() > p2.getX()) {
      lineClone.setLine(p2, p1);
      return lineClone;
    }
    if (p1.getY() < p2.getY()) {
      return lineClone;
    }
    lineClone.setLine(p2, p1);
    return lineClone;
  }
  /**
   * Resizes a shape, so that the shape has the given width and height, but the
   * origin of the shape does not change. <p/> Unlike the AffineTransform, this
   * method tries to preserve the Shape"s Type.
   * 
   * @param s
   *          the shape
   * @param width
   *          the new width
   * @param height
   *          the new height
   * @return the resized shape.
   */
  public static Shape resizeShape(final Shape s, final float width, final float height) {
    if (s instanceof Line2D) {
      return resizeLine((Line2D) s, width, height);
    }
    if (s instanceof RectangularShape) {
      return resizeRect((RectangularShape) s, width, height);
    }
    return transformShape(s, true, false, new Dimension((int) width, (int) height));
  }
  /**
   * Resizes a rectangle. This works for real rectangles and produces funny
   * results for RoundRects etc ..
   * 
   * @param rectangularShape
   *          the rectangle
   * @param width
   *          the new width of the rectangle
   * @param height
   *          the new height of the rectangle.
   * @return the resized rectangle.
   */
  public static Shape resizeRect(final RectangularShape rectangularShape, final double width,
      final double height) {
    final RectangularShape retval = (RectangularShape) rectangularShape.clone();
    retval.setFrame(retval.getX(), retval.getY(), width, height);
    return retval;
  }
  /**
   * Translates the given shape. The shape is translated to the origin supplied
   * in <code>point</code>. If scaling is requested, the shape will also be
   * scaled using an AffineTransform.
   * 
   * @param s
   *          the shape that should be transformed
   * @param scale
   *          true, if the shape should be scaled, false otherwise
   * @param keepAR
   *          true, if the scaled shape should keep the aspect ratio
   * @param width
   *          the target width.
   * @param height
   *          the target height.
   * @return the transformed shape
   */
  public static Shape transformShape(final Shape s, final boolean scale, final boolean keepAR,
      final double width, final double height) {
    /**
     * Always scale to the maximum bounds ...
     */
    if (scale) {
      final Rectangle2D boundsShape = s.getBounds2D();
      final double w = boundsShape.getWidth();
      final double h = boundsShape.getHeight();
      double scaleX = 1;
      if (w != 0) {
        scaleX = width / w;
      }
      double scaleY = 1;
      if (h != 0) {
        scaleY = height / h;
      }
      if (scaleX != 1 || scaleY != 1) {
        if (s instanceof RectangularShape) {
          return ShapeTransform.resizeRect((RectangularShape) s, w * scaleX, h * scaleY);
        }
        if (s instanceof Line2D) {
          return ShapeTransform.resizeLine((Line2D) s, w * scaleX, h * scaleY);
        }
        if (keepAR) {
          final double scaleFact = Math.min(scaleX, scaleY);
          return performDefaultTransformation(s, scaleFact, scaleFact);
        } else {
          return performDefaultTransformation(s, scaleX, scaleY);
        }
      }
    }
    return s;
  }
  /**
   * Translates the given shape. The shape is translated to the origin supplied
   * in <code>point</code>. If scaling is requested, the shape will also be
   * scaled using an AffineTransform.
   * 
   * @param s
   *          the shape that should be transformed
   * @param scale
   *          true, if the shape should be scaled, false otherwise
   * @param keepAR
   *          true, if the scaled shape should keep the aspect ratio
   * @param dim
   *          the target dimension.
   * @return the transformed shape
   */
  public static Shape transformShape(final Shape s, final boolean scale, final boolean keepAR,
      final Dimension2D dim) {
    return transformShape(s, scale, keepAR, dim.getWidth(), dim.getHeight());
  }
  /**
   * Clips the given shape to the given bounds. If the shape is a Line2D, manual
   * clipping is performed, as the built in Area does not handle lines.
   * 
   * @param s
   *          the shape to be clipped
   * @param bounds
   *          the bounds to which the shape should be clipped
   * @return the clipped shape.
   */
  public static Shape performCliping(final Shape s, final Rectangle2D bounds) {
    if (s instanceof Line2D) {
      final Line2D line = (Line2D) s;
      final Point2D[] clipped = getClipped(line.getX1(), line.getY1(), line.getX2(), line.getY2(),
          -DELTA, DELTA + bounds.getWidth(), -DELTA, DELTA + bounds.getHeight());
      if (clipped == null) {
        return new GeneralPath();
      }
      return new Line2D.Float(clipped[0], clipped[1]);
    }
    final Rectangle2D boundsCorrected = bounds.getBounds2D();
    boundsCorrected.setRect(-DELTA, -DELTA, DELTA + boundsCorrected.getWidth(), DELTA
        + boundsCorrected.getHeight());
    final Area a = new Area(boundsCorrected);
    if (a.isEmpty()) {
      // don"t clip ... Area does not like lines
      // operations with lines always result in an empty Bounds:(0,0,0,0) area
      return new GeneralPath();
    }
    final Area clipArea = new Area(s);
    a.intersect(clipArea);
    return a;
  }
  /**
   * Scales a given shape. The shape is first normalized, then scaled and
   * finally brought back into its original position.
   * 
   * @param shape
   *          the shape to be scaled
   * @param scaleX
   *          the horizontal scaling factor
   * @param scaleY
   *          the vertical scaling factor
   * @return the scaled shape
   */
  private static Shape performDefaultTransformation(final Shape shape, final double scaleX,
      final double scaleY) {
    /**
     * Apply the normalisation shape transform ... bring the shape to pos (0,0)
     */
    final Rectangle2D bounds = shape.getBounds2D();
    AffineTransform af = AffineTransform.getTranslateInstance(0 - bounds.getX(), 0 - bounds.getY());
    // apply normalisation translation ...
    Shape s = af.createTransformedShape(shape);
    af = AffineTransform.getScaleInstance(scaleX, scaleY);
    // apply scaling ...
    s = af.createTransformedShape(s);
    // now retranslate the shape to its original position ...
    af = AffineTransform.getTranslateInstance(bounds.getX(), bounds.getY());
    return af.createTransformedShape(s);
  }
  /**
   * Translates a given shape. Special care is taken to preserve the shape"s
   * original class, if the shape is a rectangle or a line.
   * 
   * @param s
   *          the shape
   * @param x
   *          the x coordinate where the shape is translated to
   * @param y
   *          the y coordinate where the shape is translated to
   * @return the translated shape
   */
  public static Shape translateShape(final Shape s, final double x, final double y) {
    if (s instanceof RectangularShape) {
      final RectangularShape rect = (RectangularShape) s;
      final RectangularShape retval = (RectangularShape) rect.clone();
      retval.setFrame(retval.getX() + x, retval.getY() + y, retval.getWidth(), retval.getHeight());
      return retval;
    }
    if (s instanceof Line2D) {
      final Line2D line = (Line2D) s;
      final Line2D retval = (Line2D) line.clone();
      retval
          .setLine(retval.getX1() + x, retval.getY1() + y, retval.getX2() + x, retval.getY2() + y);
      return retval;
    }
    final AffineTransform af = AffineTransform.getTranslateInstance(x, y);
    return af.createTransformedShape(s);
  }
  /**
   * Calculate the clipping points of a line with a rectangle.
   * 
   * @param x1
   *          starting x of line
   * @param y1
   *          starting y of line
   * @param x2
   *          ending x of line
   * @param y2
   *          ending y of line
   * @param xmin
   *          lower left x of rectangle
   * @param xmax
   *          upper right x of rectangle
   * @param ymin
   *          lower left y of rectangle
   * @param ymax
   *          upper right y of rectangle
   * @return <code>null</code> (does not clip) or array of two points
   */
  public static Point2D[] getClipped(final double x1, final double y1, final double x2,
      final double y2, final double xmin, final double xmax, final double ymin, final double ymax) {
    int mask1 = 0; // position mask for first point
    if (x1 < xmin) {
      mask1 |= LEFT;
    } else if (x1 > xmax) {
      mask1 |= RIGHT;
    } else {
      mask1 |= H_CENTER;
    }
    if (y1 < ymin) {
      // btw: I know that in AWT y runs from down but I more used to
      // y pointing up and it makes no difference for the algorithms
      mask1 |= BELOW;
    } else if (y1 > ymax) {
      mask1 |= ABOVE;
    } else {
      mask1 |= V_CENTER;
    }
    int mask2 = 0; // position mask for second point
    if (x2 < xmin) {
      mask2 |= LEFT;
    } else if (x2 > xmax) {
      mask2 |= RIGHT;
    } else {
      mask2 |= H_CENTER;
    }
    if (y2 < ymin) {
      mask2 |= BELOW;
    } else if (y2 > ymax) {
      mask2 |= ABOVE;
    } else {
      mask2 |= V_CENTER;
    }
    final int mask = mask1 | mask2;
    if ((mask & OUTSIDE) == 0) {
      // fine. everything"s internal
      final Point2D[] ret = new Point2D[2];
      ret[0] = new Point2D.Double(x1, y1);
      ret[1] = new Point2D.Double(x2, y2);
      return ret;
    } else if ((mask & (H_CENTER | LEFT)) == 0 || // everything"s right
        (mask & (H_CENTER | RIGHT)) == 0 || // everything"s left
        (mask & (V_CENTER | BELOW)) == 0 || // everything"s above
        (mask & (V_CENTER | ABOVE)) == 0) { // everything"s below
      // nothing to do
      return null;
    } else {
      // need clipping
      return getClipped(x1, y1, mask1, x2, y2, mask2, xmin, xmax, ymin, ymax);
    }
  }
  /**
   * Calculate the clipping points of a line with a rectangle.
   * 
   * @param x1
   *          starting x of line
   * @param y1
   *          starting y of line
   * @param mask1
   *          clipping info mask for starting point
   * @param x2
   *          ending x of line
   * @param y2
   *          ending y of line
   * @param mask2
   *          clipping info mask for ending point
   * @param xmin
   *          lower left x of rectangle
   * @param ymin
   *          lower left y of rectangle
   * @param xmax
   *          upper right x of rectangle
   * @param ymax
   *          upper right y of rectangle
   * @return <code>null</code> (does not clip) or array of two points
   */
  private static Point2D[] getClipped(final double x1, final double y1, final int mask1,
      final double x2, final double y2, final int mask2, final double xmin, final double xmax,
      final double ymin, final double ymax) {
    final int mask = mask1 ^ mask2;
    Point2D p1 = null;
    if (mask1 == INSIDE) {
      // point 1 is internal
      p1 = new Point2D.Double(x1, y1);
      if (mask == 0) {
        // both masks are the same, so the second point is inside, too
        final Point2D[] ret = new Point2D[2];
        ret[0] = p1;
        ret[1] = new Point2D.Double(x2, y2);
        return ret;
      }
    } else if (mask2 == INSIDE) {
      // point 2 is internal
      p1 = new Point2D.Double(x2, y2);
    }
    if ((mask & LEFT) != 0) {
      // System.out.println("Trying left");
      // try to calculate intersection with left line
      final Point2D p = intersect(x1, y1, x2, y2, xmin, ymin, xmin, ymax);
      if (p != null) {
        if (p1 == null) {
          p1 = p;
        } else {
          final Point2D[] ret = new Point2D[2];
          ret[0] = p1;
          ret[1] = p;
          return ret;
        }
      }
    }
    if ((mask & RIGHT) != 0) {
      // System.out.println("Trying right");
      // try to calculate intersection with left line
      final Point2D p = intersect(x1, y1, x2, y2, xmax, ymin, xmax, ymax);
      if (p != null) {
        if (p1 == null) {
          p1 = p;
        } else {
          final Point2D[] ret = new Point2D[2];
          ret[0] = p1;
          ret[1] = p;
          return ret;
        }
      }
    }
    if (mask1 == (LEFT | BELOW) || mask1 == (RIGHT | BELOW)) {
      // for exactly these two special cases use different sequence!
      if ((mask & ABOVE) != 0) {
        // System.out.println("Trying top");
        // try to calculate intersection with lower line
        final Point2D p = intersect(x1, y1, x2, y2, xmin, ymax, xmax, ymax);
        if (p != null) {
          if (p1 == null) {
            p1 = p;
          } else {
            final Point2D[] ret = new Point2D[2];
            ret[0] = p1;
            ret[1] = p;
            return ret;
          }
        }
      }
      if ((mask & BELOW) != 0) {
        // System.out.println("Trying bottom");
        // try to calculate intersection with lower line
        final Point2D p = intersect(x1, y1, x2, y2, xmin, ymin, xmax, ymin);
        if (p != null && p1 != null) {
          final Point2D[] ret = new Point2D[2];
          ret[0] = p1;
          ret[1] = p;
          return ret;
        }
      }
    } else {
      if ((mask & BELOW) != 0) {
        // System.out.println("Trying bottom");
        // try to calculate intersection with lower line
        final Point2D p = intersect(x1, y1, x2, y2, xmin, ymin, xmax, ymin);
        if (p != null) {
          if (p1 == null) {
            p1 = p;
          } else {
            final Point2D[] ret = new Point2D[2];
            ret[0] = p1;
            ret[1] = p;
            return ret;
          }
        }
      }
      if ((mask & ABOVE) != 0) {
        // System.out.println("Trying top");
        // try to calculate intersection with lower line
        final Point2D p = intersect(x1, y1, x2, y2, xmin, ymax, xmax, ymax);
        if (p != null && p1 != null) {
          final Point2D[] ret = new Point2D[2];
          ret[0] = p1;
          ret[1] = p;
          return ret;
        }
      }
    }
    // no (or not enough) intersections found
    return null;
  }
  /**
   * Intersect two lines.
   * 
   * @param x11
   *          starting x of 1st line
   * @param y11
   *          starting y of 1st line
   * @param x12
   *          ending x of 1st line
   * @param y12
   *          ending y of 1st line
   * @param x21
   *          starting x of 2nd line
   * @param y21
   *          starting y of 2nd line
   * @param x22
   *          ending x of 2nd line
   * @param y22
   *          ending y of 2nd line
   * @return intersection point or <code>null</code>
   */
  private static Point2D intersect(final double x11, final double y11, final double x12,
      final double y12, final double x21, final double y21, final double x22, final double y22) {
    final double dx1 = x12 - x11;
    final double dy1 = y12 - y11;
    final double dx2 = x22 - x21;
    final double dy2 = y22 - y21;
    final double det = (dx2 * dy1 - dy2 * dx1);
    if (det != 0.0) {
      final double mu = ((x11 - x21) * dy1 - (y11 - y21) * dx1) / det;
      if (mu >= 0.0 && mu <= 1.0) {
        return new Point2D.Double(x21 + mu * dx2, y21 + mu * dy2);
      }
    }
    return null;
  }
}



Rotates a shape about the specified coordinates.

 
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
 *
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * -------------------
 * ShapeUtilities.java
 * -------------------
 * (C)opyright 2003-2008, by Object Refinery Limited and Contributors.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: ShapeUtilities.java,v 1.18 2008/06/02 06:58:28 mungady Exp $
 *
 * Changes
 * -------
 * 13-Aug-2003 : Version 1 (DG);
 * 16-Mar-2004 : Moved rotateShape() from RefineryUtilities.java to here (DG);
 * 13-May-2004 : Added new shape creation methods (DG);
 * 30-Sep-2004 : Added createLineRegion() method (DG);
 *               Moved drawRotatedShape() method from RefineryUtilities class
 *               to this class (DG);
 * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
 * 26-Oct-2004 : Added a method to test the equality of two Line2D
 *               instances (DG);
 * 10-Nov-2004 : Added new translateShape() and equal(Ellipse2D, Ellipse2D)
 *               methods (DG);
 * 11-Nov-2004 : Renamed translateShape() --> createTranslatedShape() (DG);
 * 07-Jan-2005 : Minor Javadoc fix (DG);
 * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG);
 * 21-Jan-2005 : Modified return type of RectangleAnchor.coordinates()
 *               method (DG);
 * 22-Feb-2005 : Added equality tests for Arc2D and GeneralPath (DG);
 * 16-Mar-2005 : Fixed bug where equal(Shape, Shape) fails for two Polygon
 *               instances (DG);
 * 01-Jun-2008 : Fixed bug in equal(GeneralPath, GeneralPath) method (DG);
 *
 */
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
/**
 * Utility methods for {@link Shape} objects.
 *
 * @author David Gilbert
 */
public class Main {
  /**
   * Rotates a shape about the specified coordinates.
   *
   * @param base  the shape (<code>null</code> permitted, returns
   *              <code>null</code>).
   * @param angle  the angle (in radians).
   * @param x  the x coordinate for the rotation point (in Java2D space).
   * @param y  the y coordinate for the rotation point (in Java2D space).
   *
   * @return the rotated shape.
   */
  public static Shape rotateShape(final Shape base, final double angle,
                                  final float x, final float y) {
      if (base == null) {
          return null;
      }
      final AffineTransform rotate = AffineTransform.getRotateInstance(
              angle, x, y);
      final Shape result = rotate.createTransformedShape(base);
      return result;
  }
}



Rotating a Drawn Image

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BasicDraw {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new MyComponent());
    frame.setSize(300, 300);
    frame.setVisible(true);
  }
}
class MyComponent extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform tx = new AffineTransform();
    double radians = -Math.PI / 4;
    tx.rotate(radians);
    g2d.setTransform(tx);
    g2d.drawImage(new ImageIcon("a.png").getImage(), tx, this);
  }
}



Rotating a Shape with AffineTransform

   

import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
public class BasicShapes {
  public static void main(String[] args) {
    AffineTransform tx = new AffineTransform();
    tx.rotate(0.5);
    Rectangle shape = new Rectangle(1, 1, 1, 1);
    Shape newShape = tx.createTransformedShape(shape);
  }
}



Rotating image using Java 2D AffineTransform class

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
class ImagePanel extends JPanel {
  int offset = 5;
  private Image image;
  private int angle;
  private int w, h;
  private AffineTransform transform;
  public ImagePanel(Image i) {
    image = i;
    w = image.getWidth(this);
    h = image.getHeight(this);
    transform = new AffineTransform();
  }
  public void paintComponent(Graphics grp) {
    Rectangle rect = this.getBounds();
    Graphics2D g2d = (Graphics2D) grp;
    transform.setToTranslation((rect.width - w) / 2,
        (rect.height - h) / 2);
    transform.rotate(Math.toRadians(angle), w / 2,
        h / 2);
    g2d.drawImage(image, transform, this);
  }
  public void rotate() {
    angle -= offset;
    if (angle <= 0) {
      angle = 360;
    }
    repaint();
  }
}



Rotation and coordinate translation

   
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Rotate extends JPanel {
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(new Color(150, 150, 150));
    g2d.fillRect(20, 20, 80, 50);
    g2d.translate(180, -150);
    g2d.rotate(Math.PI / 4);
    g2d.fillRect(20, 20, 80, 50);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("Rotation");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new Rotate());
    frame.setSize(300, 200);
    frame.setVisible(true);
  }
}



Scaling a Drawn Image

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BasicDraw {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new MyComponent());
    frame.setSize(300, 300);
    frame.setVisible(true);
  }
}
class MyComponent extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform tx = new AffineTransform();
    double scalex = .5;
    double scaley = 1;
    tx.scale(scalex, scaley);
    g2d.setTransform(tx);
    g2d.drawImage(new ImageIcon("a.png").getImage(), tx, this);
  }
}



Scaling an object

   
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Scale extends JPanel {
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(new Color(150, 150, 150));
    g2d.fillRect(0, 0, 80, 50);
    AffineTransform tx1 = new AffineTransform();
    tx1.translate(110, 20);
    tx1.scale(0.5, 0.5);
    g2d.setTransform(tx1);
    g2d.fillRect(0, 0, 80, 50);
    AffineTransform tx2 = new AffineTransform();
    tx2.translate(200, 20);
    tx2.scale(1.5, 1.5);
    g2d.setTransform(tx2);
    g2d.fillRect(0, 0, 80, 50);
  }
  public static void main(String[] args) {
    JFrame frame = new JFrame("Scaling");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new Scale());
    frame.setSize(330, 160);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}



Scaling a Shape with AffineTransform

   
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
public class BasicShapes {
  public static void main(String[] args) {
    AffineTransform tx = new AffineTransform();
    tx.scale(1, 1);
    Rectangle shape = new Rectangle(1, 1, 1, 1);
    Shape newShape = tx.createTransformedShape(shape);
  }
}



Shearing a Drawn Image

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BasicDraw {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new MyComponent());
    frame.setSize(300, 300);
    frame.setVisible(true);
  }
}
class MyComponent extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform tx = new AffineTransform();
    double shiftx = .1;
    double shifty = .3;
    tx.shear(shiftx, shifty);
    g2d.setTransform(tx);
    g2d.drawImage(new ImageIcon("a.png").getImage(), tx, this);
  }
}



Shearing a Shape with AffineTransform

   
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
public class BasicShapes {
  public static void main(String[] args) {
    AffineTransform tx = new AffineTransform();
    tx.shear(1, 1);
    Rectangle shape = new Rectangle(1, 1, 1, 1);
    Shape newShape = tx.createTransformedShape(shape);
  }
}



Transform Demo

   
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TransformDemo extends JPanel {
  public void init() {
    setBackground(Color.white);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    Rectangle rect = new Rectangle(5,5,200,200);
    
    int w = getSize().width;
    int h = getSize().height;
    
    AffineTransform saveXform = g2.getTransform();
    AffineTransform toCenterAt = new AffineTransform();
    toCenterAt.translate(w / 2 - (rect.width / 2), h / 2 - (rect.height / 2));
    g2.transform(toCenterAt);
  
    g2.fill(rect);
    
    g2.transform(saveXform);
  }
  public static void main(String s[]) {
    JFrame f = new JFrame();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    TransformDemo p = new TransformDemo();
    f.getContentPane().add("Center", p);
    p.init();
    f.pack();
    f.setSize(new Dimension(300, 300));
    f.show();
  }
}



Transforme Rotation demo

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformersRotation extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformersRotation() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
    g2.transform(AffineTransform.getRotateInstance(-Math.PI / 6));
    // Draw the "new" shapes in dashed.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformersRotation());
    f.setSize(350, 200);
    f.show();
  }
}



Transform Rotation Translation

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformersRotationTranslation extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformersRotationTranslation() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      AffineTransform rat = new AffineTransform();
      rat.setToRotation(Math.PI / 6);
      rat.translate(100, 100);
    
    g2.transform(rat);
    // Draw the "new" shapes in dashed.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformersRotationTranslation());
    f.setSize(350, 450);
    f.show();
  }
}



Transform Scale

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformScale extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformScale() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      g2.transform(AffineTransform.getScaleInstance(3, 3));
    // Draw the "new" shapes in dashed.
      g2.transform(AffineTransform.getTranslateInstance(75, 75));
      
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformScale());
    f.setSize(650, 550);
    f.show();
  }
}



Transform Shear

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformShear extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformShear() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      AffineTransform sat = AffineTransform.getTranslateInstance(150, 0);
      sat.shear(-.5, 0);
      g2.transform(sat);
    // Draw the "new" shapes in dashed.
      g2.transform(AffineTransform.getTranslateInstance(75, 75));
      
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformShear());
    f.setSize(450, 350);
    f.show();
  }
}



Transform Translated Rotation

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformTranslatedRotation extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformTranslatedRotation() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      float cm = 72 / 2.54f;
      g2.transform(AffineTransform.getRotateInstance(-Math.PI / 6, 3 * cm, 2 * cm));
    // Draw the "new" shapes in dashed.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformTranslatedRotation());
    f.setSize(450, 350);
    f.show();
  }
}



Transform Translation

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformTranslation extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformTranslation() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      g2.transform(AffineTransform.getTranslateInstance(150, 0));
    // Draw the "new" shapes in dashed.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformTranslation());
    f.setSize(450, 350);
    f.show();
  }
}



Transform Translation and Rotation

   
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class TransformTransRotation extends JComponent {
  Shape axes, shape;
  int length = 54, arrowLength = 4, tickSize = 4;
  public TransformTransRotation() {
    axes = createAxes();
    shape = createShape();
  }
  protected Shape createAxes() {
    GeneralPath path = new GeneralPath();
    // Axes.
    path.moveTo(-length, 0);
    path.lineTo(length, 0);
    path.moveTo(0, -length);
    path.lineTo(0, length);
    // Arrows.
    path.moveTo(length - arrowLength, -arrowLength);
    path.lineTo(length, 0);
    path.lineTo(length - arrowLength, arrowLength);
    path.moveTo(-arrowLength, length - arrowLength);
    path.lineTo(0, length);
    path.lineTo(arrowLength, length - arrowLength);
    // Half-centimeter tick marks
    float cm = 72 / 2.54f;
    float lengthCentimeter = length / cm;
    for (float i = 0.5f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize / 2);
      path.lineTo(tick, tickSize / 2);
      path.moveTo(-tick, -tickSize / 2);
      path.lineTo(-tick, tickSize / 2);
      path.moveTo(-tickSize / 2, tick);
      path.lineTo(tickSize / 2, tick);
      path.moveTo(-tickSize / 2, -tick);
      path.lineTo(tickSize / 2, -tick);
    }
    // Full-centimeter tick marks
    for (float i = 1.0f; i < lengthCentimeter; i += 1.0f) {
      float tick = i * cm;
      path.moveTo(tick, -tickSize);
      path.lineTo(tick, tickSize);
      path.moveTo(-tick, -tickSize);
      path.lineTo(-tick, tickSize);
      path.moveTo(-tickSize, tick);
      path.lineTo(tickSize, tick);
      path.moveTo(-tickSize, -tick);
      path.lineTo(tickSize, -tick);
    }
    return path;
  }
  protected Shape createShape() {
    float cm = 72 / 2.54f;
    return new Rectangle2D.Float(cm, cm, 2 * cm, cm);
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    // Use antialiasing.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    // Move the origin to 75, 75.
    AffineTransform at = AffineTransform.getTranslateInstance(75, 75);
    g2.transform(at);
    // Draw the shapes in their original locations.
    g2.setPaint(Color.black);
    g2.draw(axes);
    g2.draw(shape);
    // Transform the Graphics2D.
      AffineTransform rat = new AffineTransform();
      rat.setToTranslation(100, 0);
      rat.rotate(Math.PI / 6);
      g2.transform(rat);
    // Draw the "new" shapes in dashed.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_BEVEL, 0, new float[] { 3, 1 }, 0);
    g2.setStroke(stroke);
    g2.draw(axes);
    g2.draw(shape);
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.getContentPane().add(new TransformTransRotation());
    f.setSize(450, 350);
    f.show();
  }
}



Translating a Drawn Image

   
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BasicDraw {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new MyComponent());
    frame.setSize(300, 300);
    frame.setVisible(true);
  }
}
class MyComponent extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform tx = new AffineTransform();
    double x = 50;
    double y = 50;
    tx.translate(x, y);
    g2d.setTransform(tx);
    g2d.drawImage(new ImageIcon("a.png").getImage(), tx, this);
  }
}



Translating a Shape with AffineTransform

   
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
public class BasicShapes {
  public static void main(String[] args) {
    AffineTransform tx = new AffineTransform();
    tx.translate(1, 10);
    Rectangle shape = new Rectangle(1, 1, 1, 1);
    Shape newShape = tx.createTransformedShape(shape);
  }
}