Mapping the mouse to an affinetransformed shape.
Greetings,
I am writing a drawing tool and using affine transform to place my shapes. The problem is, I do not know how to map the cursor such that it's coordinate space is the same as my shapes once I have transformed them. Can anyone help me?
Below is a simplified example. If you compile and run, you will notice that the mouse thinks it's on the graphics when its in the upper left corner of the Panel. That is because the default graphics context is in the upper left corner of the screen, while the shape's bounds provide a the coordinates relative to their universal center, which is the affine transformed location.
Method mousemoved has the handler code, and you can see what I am doing to test location match.
In the actual application, I have levels of transformations, because shapes are children/dependent on other shapes, and must move relative to other shapes. etc.
Thanks in Advance for even looking at this problem.
Any questions, please feel free to contact me at richard.cromer@itt.com. No spam please!
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
public class RolloverTest
{
public static void main(String[] args){
new RolloverTest();
}
public RolloverTest(){
shapes = new ArrayList();
//
// Notice this ellipse is at 0, 0. The top left hand corner of default graphics context.
// The shape size is completely arbitrary.
Ellipse2D oval1 = new Ellipse2D.Double(0, 0, 90, 40);
shapes.add(new HotShape(oval1, mouseOff));
//
// Notice this rectangle object is at 20, 0. Twenty pixels right of the top left hand corner of default graphics context.
// The shape size is completely arbitrary.
Rectangle rect1 = new Rectangle(20, 0, 50, 50);
shapes.add(new HotShape(rect1, mouseOff));
hotPiece = (HotShape)shapes.get(0);
drawingBoard = new DrawingBoard(this);
frame = new JFrame("Rollover Test");
frame.setContentPane(drawingBoard);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class DrawingBoard extends JPanel implements MouseMotionListener{
public DrawingBoard(RolloverTest rt){
this.rt = rt;
this.setBackground(Color.WHITE);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D gfx = (Graphics2D)g;
gfx.setStroke(new BasicStroke(3));
HotShape shape;
AffineTransform at;
// First transform moves the origin down and right.
at = AffineTransform.getTranslateInstance(80,80);
gfx.transform(at);
shape = (HotShape)rt.shapes.get(0);
gfx.setColor(shape.color);
gfx.setClip(null);
gfx.draw(shape.shape);
//
// second transform moves the origin down and right some more.
at = AffineTransform.getTranslateInstance(100,100);
gfx.transform(at);
shape = (HotShape)rt.shapes.get(1);
gfx.setColor(shape.color);
gfx.setClip(null);
gfx.draw(shape.shape);
}
public void mouseMoved(MouseEvent evt)
{
Rectangle rect = new Rectangle(evt.getX(), evt.getY(), 1, 1);
for(int i = 0; i < rt.shapes.size(); i++)
{
HotShape shape = (HotShape)rt.shapes.get(i);
if (shape.shape.intersects(rect)){
rt.hotPiece.color = rt.mouseOff;
rt.hotPiece = shape;
shape.color = rt.mouseOn;
this.repaint();
}
else
{
if (shape.color == rt.mouseOn)
{
rt.hotPiece.color = rt.mouseOff;
shape.color = rt.mouseOff;
this.repaint();
}
}
}
}
public void mouseDragged(MouseEvent e) {
}
RolloverTest rt;
}
public class HotShape{
public HotShape(Shape shape, Color color){
this.shape = shape;
this.color = color;
}
Shape shape;
Color color;
}
JFrame frame;
DrawingBoard drawingBoard;
ArrayList shapes;
HotShape hotPiece;
Color mouseOff = Color.BLUE;
Color mouseOn = Color.RED;
}

