BitNinja
BitNinja

Reputation: 1487

Finding AffineTransform origin on screen

Let's say I have an AffineTransform (transform) and call a bunch of it's methods. Lets say I rotate and translate it. Then I transform a graphics object (g2d) with it:

g2d.transform(transform);

I want to find the coordinate on my screen where my new (0, 0) is. So if I drew a rectangle at those coordinates with an untransformed g2d and one with my transformed g2d they would overlap. So how can I get this point, do I have to do some math, does AffineTransform or Graphics2D have a built in way (I couldn't find one)?

Upvotes: 0

Views: 778

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347334

You could...

Create a copy of the original Graphics context (Graphics#create) (which is always a good idea) then apply the transform to the copy (this will leave the original unaffected, just don't forget to dispose of the copy when you're done)

All hail to Hypno toad

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;

        public TestPane() {
            try {
                img = ImageIO.read(your source image here...);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - img.getWidth()) / 2;
            int y = (getHeight() - img.getHeight()) / 2;
            AffineTransform at = AffineTransform.getTranslateInstance(x, y);
            at.rotate(Math.toRadians(180), img.getWidth() / 2, img.getHeight() / 2);
            g2d.setTransform(at);
            g2d.drawImage(img, 0, 0, this);
            g2d.dispose();

            // I don't like touching the original ;)
            g2d = (Graphics2D) g.create();
            FontMetrics fm = g2d.getFontMetrics();
            g2d.drawString("Top Left", 0, 0 + fm.getAscent());

            String txt = "Bottom right";
            g2d.drawString(txt, getWidth() - fm.stringWidth(txt) - 1, ((getHeight() - fm.getHeight()) - 1) + fm.getAscent());
            g2d.dispose();
        }

    }

}

You could...

Reverse the transformation, always tricky if it's a complex transformation...

You could...

Get a reference to the original transformation first, apply the new transform, paint what ever you needed painted and then reapply the original transformation

You could...

Use AffineTransform#setToIdentity to "reset" the transform back to it's original state...

    AffineTransform at = g2d.getTransform();
    at.translate(x, y);
    at.rotate(Math.toRadians(180), img.getWidth() / 2, img.getHeight() / 2);
    // Some drawing...

    at.setToIdentity();
    g2d.setTransform(at);
    // Back to basics

Upvotes: 2

Related Questions