Coordenadas escalonadas e rotacionadas do Java Graphics2D reverso

Eu uso o Graphics2D em Java para dimensionar e girar a imagem que desenho. Agora quero poder dizer quais foram as coordenadas originais quando clico em um determinado ponto da imagem. Então, dadas as coordenadas rotacionadas e escalonadas, quero calcular as originais. Existe uma maneira simples de fazer isso?

Se você mantiver uma cópia do AffineTransform você usa ao pintar a imagem, você pode usar AffineTransform.inverseTransform (Point2D ptSrc, Point2D ptDst) para transformar uma coordenada de espaço de dispositivo de volta para o espaço do usuário

Edit : Se você capturar a transformação atual do Graphics2D durante a pintura, cuidado com o Graphics2D sendo reutilizado para vários filhos leves da mesma janela / painel, porque então a transformação será relativa ao componente pai, mas as coordenadas do mouse serão em relação à criança. Você precisa capturar as alterações feitas na transformação e não seu valor final. Exemplo:

 import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JComponent; import javax.swing.JFrame; public class Main { public static void main(String[] args) throws MalformedURLException, IOException { JFrame frame = new JFrame(); Box box = new Box(BoxLayout.Y_AXIS); BufferedImage image = ImageIO.read(new URL("http://sstatic.net/so/img/logo.png")); AffineTransform xfrm1 = AffineTransform.getScaleInstance(0.95, 1.25); xfrm1.rotate(-0.3); box.add(new ImageView(image, xfrm1)); AffineTransform xfrm2 = AffineTransform.getShearInstance(0.1, 0.2); xfrm2.scale(1.3, 0.9); box.add(new ImageView(image, xfrm2)); frame.add(box); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } @SuppressWarnings("serial") class ImageView extends JComponent { @Override public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; try { paintXfrm = g2d.getTransform(); paintXfrm.invert(); g2d.translate(getWidth() / 2, getHeight() / 2); g2d.transform(xfrm); g2d.translate(image.getWidth() * -0.5, image.getHeight() * -0.5); paintXfrm.concatenate(g2d.getTransform()); g2d.drawImage(image, 0, 0, this); } catch (NoninvertibleTransformException ex) { ex.printStackTrace(); } } @Override public Dimension getPreferredSize() { return new Dimension(image.getWidth() * 2, image.getHeight() * 2); } ImageView(final BufferedImage image, final AffineTransform xfrm) { this.canvas = image.createGraphics(); canvas.setColor(Color.BLACK); canvas.setStroke(new BasicStroke(3.0f)); this.image = image; this.xfrm = xfrm; addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { try { mouseDownCoord = e.getPoint(); paintXfrm.inverseTransform(mouseDownCoord, mouseDownCoord); } catch (NoninvertibleTransformException ex) { } } @Override public void mouseExited(MouseEvent e) { mouseDownCoord = null; } }); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseDragged(MouseEvent e) { Point p = e.getPoint(); try { paintXfrm.inverseTransform(p, p); if (mouseDownCoord != null) { canvas.drawLine(mouseDownCoord.x, mouseDownCoord.y, px, py); for (Component sibling: getParent().getComponents()) { sibling.repaint(); } } mouseDownCoord = p; } catch (NoninvertibleTransformException ex) { ex.printStackTrace(); } } }); } private Graphics2D canvas; private BufferedImage image; private AffineTransform xfrm; private AffineTransform paintXfrm; private Point mouseDownCoord; } 

Não está claro exatamente como você está girando e dimensionando. Mas provavelmente você está usando um AffineTransform . Felizmente, existe um método createInverse () e um método inverseTransform () .

Então, seu código pode ser

 AffineTransform transform = AffineTransform.rotate(theta); transform.scale(sx, sy); 

Então, para inverter, você pode dizer

 Point2D pointInOrigCoords = transform.inverseTransform(clickPoint,null); 

Não é tão difícil 😉

  1. Quando você repinta o componente, salve o AffineTransform após a transformação com g2.getTransform()

  2. Então chame a function invert() nela

  3. No mouseClicked() evento nos o seguinte código:

     Point2D p= trans.transform(new Point2D.Double(evt.getX(), evt.getY()), null); System.out.println("click x="+p.getX()+" y="+p.getY()); 

É isso aí!

Intereting Posts