Reputation: 33
I am trying to understand how to use the drawRect(int x, int y, int width, int height) method of Graphics 2D class and the rotate(double theta, double x, double y) method.
What I want to do is draw a square on a JPanel and rotate it (all of this using the mouse). So the procedure for this would be - Click 1 (which would give the coordinates of Point 1 (P1) - this is one corner of the square), Move mouse (Mouse location gives the coordinates of Point 2 (P2) - this is the opposite corner of the square), Rotate the square (Again, the mouse location would give the coordinates of Point 2). Click 2 (Point 2 is updated via this click and is the final resting place of the square)
My understanding, and questions are:
I understand that P1.x and P1.y are the values that are used in the rotate method. P1 is the point of roation. I also understand that theta in the rotate method is the angle of rotation.
I understand that the width and height of the drawRect method should be equal to be a square, but this is where I start to get confused.
My questions are:
1) What (and where in terms of JPanel location) are x and y in the drawRect method and How do I work them out for my situation? (I thought it to be the top left corner of the square but it is confusing if I were to drag P2 to the upper left)
2) How do I work out theta from P1 and P2?
(Note: It it is any benefit, I am using MouseAdapter methods to handle clicks and mouse motion)
Upvotes: 3
Views: 1614
Reputation: 3390
Just for curiosity, I made something like this.
import java.awt.Color;
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.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RectanglePanel extends JPanel{
private Point anchorPoint = null;
private Point intermediatePoint = null;
private Point finalPoint = null;
public RectanglePanel(){
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent me){
if(anchorPoint == null){
// first click, set anchor point
anchorPoint = me.getPoint();
}else if(finalPoint == null){
// second click, set final point
finalPoint = me.getPoint();
}else{
// third click, reset clicks, anchor point, intermediate point and final point
anchorPoint = null;
finalPoint = null;
intermediatePoint = null;
}
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent me){
if(anchorPoint != null && finalPoint == null){
// mouse moved
// set intermediate point if anchor point is set and final point is not set yet
intermediatePoint = me.getPoint();
repaint();
}
}
});
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
if(anchorPoint != null){
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
Point p = finalPoint != null ? finalPoint : intermediatePoint;
if(p != null && !p.equals(anchorPoint)){
// final point or intermediate point is set, and is not same as anchor point
// draw square
// calculate angle to rotate canvas
double angle = -Math.toRadians(45) + Math.atan2(p.y - anchorPoint.y, p.x - anchorPoint.x);
// width of square, calculated using distance formaula and pythagorus theorem
// distance formula: distance = sqrt((x1-x2)^2 + (y1-y2)^2)
// pythagorus for right angled triangle: c^2 = a^2 + b^2
double width = Math.sqrt(((p.x - anchorPoint.x) * (p.x - anchorPoint.x) + (p.y - anchorPoint.y) * (p.y - anchorPoint.y)) / 2.0);
// set origin to anchorpoint
g2d.translate(anchorPoint.x, anchorPoint.y);
// rotate canvas
g2d.rotate(angle);
Rectangle2D rectangle2D = new Rectangle2D.Double(0, 0, width, width);
// draw square
g2d.draw(rectangle2D);
// rotate back canvas
g2d.rotate(-angle);
// reset back origin
g2d.translate(-anchorPoint.x, -anchorPoint.y);
}else{
g2d.drawRect(anchorPoint.x, anchorPoint.y, 1, 1);
}
}
}
public static void main(String [] args){
final JFrame frame = new JFrame("Rectangle Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 400);
frame.getContentPane().add(new RectanglePanel());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}
You can implement like this, to solve your problem. Let me know if this is what you looking for?
Steps:
1) Calculate width of square. You have points, representing opposite corners of square. Distance between these two points is length of diagonal. So, considering two points (x1, y1)
and (x2, y2)
, using distance formula, length of diagonal is given by:
diagonal_length * diagonal_length = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
Two sides of square and diagonal will make right angled triangle. Sides of square will be of equal length, let side of square be side
, then using pythagorus theorem:
side * side + side * side = diagonal_length * diagonal_length
Solving above two equations,
side = Math.sqrt(((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) / 2.0);
2) Calculate angle to rotate canvas, so second point makes 45 degree angle with x axis, considering first point as origin.
3) Make first point origin.
4) Rotate canvas, so second point makes 45 degree angle with x axis, first point is origin. This will make two sides of square to fall on axes and other two sides to parallel of axes, so you can use draw method of graphics to draw rectangle / square.
5) Draw square from origin, of side length calculated above.
6) Rotate canvas back in opposite, to make as it was before rotate.
7) Reset origin to original point as it was before setting origin.
Done!
Upvotes: 4