I'm trying to rotate a Rectangle2D with some angles. I need draw a rectanglebox and in there a rotate rectangle from x,y to x + width , y+height. How can I do this. The rotate takes an angle and I don't know how to calculate the angle between my rectangles x,y and x + width , y + height
is there somewhere I can calculate this during mousedrag? Probably, depends on what you are trying to do. If you wanted to click on a rectangle with the mouse and drag so as to rotate the rectangle about a given point, eg, the center of the rectangle, then you could calculate the initial angle of the line between the mousePressed location and the rotation center, then calculate the angular change for each mouseDragged event, pass this to the graphic component and add it to the last/current rotation angle of the rectangle, compute an updated AffineTransform for the rotation and call repaint to show the new rotation.
I have a similar problem. For a school project I'm writing a 2D Rigid Body Physics Engine in Java.
In order to simulate torque, I'm using AffineTransform.setToRotation(). Torque spins around the center-point, so I have
pos being a Point2D object, and .x and .y being the x and y coordinates of the rectangles center-point (found using getCenterX() and getCenterY().
This all works fine right up to the point where I assign a velocity vector to the rectangle, i.e. change pos.x and pos.x each time-step. As soon as I do this the rotation goes loopy, it doesn't rotate around the center-point anymore, but only close to the center-point.
I can't test whats going wrong because I use a Shape object to allow for AffineTransform.createTransformedShape();, and there are no getCenter() methods for Shape objects.
I tried using getRotateInstance to hopefully keep my rectangles as Rectangle2D objects and so be able to see whats happening with the center-point, but when I use getRotateInstance, rotation gets even loopier.
Here's my code, just to get a better idea of what I'm talking about. I have two rectangles, RectA and RectB, and hence two of each variable. To witness the loopiness, simply change any of the velocityA/B values to anything other than 0, positive or negative. 3 shows it pretty well.
Thanks in advance for your support. Should I post what I tried to do with getRotateInstance?
[ October 21, 2008: Message edited by: J.J. Zing ] [ October 21, 2008: Message edited by: J.J. Zing ]
Originally posted by J.J. Zing: Here's my code, just to get a better idea of what I'm talking about. I have two rectangles, RectA and RectB, and hence two of each variable. To witness the loopiness, simply change any of the velocityA/B values to anything other than 0, positive or negative. 3 shows it pretty well.
(A) How exactly do I set one of the velocityA/B values to 3? I tried changing velocityA = new Point2D.Double() to velocityA = new Point2D.Double(3,0) but I didn't see anything obviously loopy, which brings me to
(B) Can you describe how the actual behaviour differs from the expected behaviour? I can see some rectangles flipping around. They look fine to my untrained eye. How exactly are they flipping incorrectly? Presume I have no idea what your goals are. (Because I don't.)
Also, while I'm here, I feel I really need to point out that this isn't the proper way to do animation in Java. You have a loop in paint() that essentially never terminates. This results in bad things. For example have you noticed that you can't really quit your app? What you should be doing is drawing one single frame in paint() that terminates quickly. Then elsewhere repeatedly call update() so that multiple calls to paint() will be scheduled.
Thanks for the quick response. Sorry, I realise my info is a bit sparse and my post a bit cluttered. If you change the values here:
the 'loopiness' should be visible. velocityA.y = 3; makes the rectangle move down 3 pixels each time-step, and you might be able to see that it doesn't rotate around its center anymore. When you changed velocityA = new Point2D.Double() to velocityA = new Point2D.Double(3,0) the change was undone later by velocityA.x = 0 etc.
The aim of this app is to realistically simulate physical interactions between rigid bodies. This means that when I'm done, the bodies will ideally be bouncing physically correctly off the walls and off each other. This 'physically correctly' is gonna be supplied by a few physics calculations, supplied to me by my friend doing physics and our school's physics text book. Each time a collision occurs, the velocity info is sent to the CollisionHandling (not yet written) class, which performs the necessary calculations to determine what changes need to be made to the velocities of the two bodies. For rectangles, this includes torque, or rotation around the center-point. Hence, its essential that the rectangles actually rotate around the center-point determined by me.
I realize I'm probably violating a whole slew of unwritten rules, and I would appreciate any guidance. This is the first time I'm writing Java outside of the classroom (I take Comp Sci in high-school) and there is a lot I have to learn. The while (!done) loop will be made to end when a Collision is detected, and I was planning on making done = true; when the close button is clicked, which should solve the unquittable problem.
Would you care to elaborate on this paint() and update() method? I saw examples of it while browsing through tutorials, but never really looked into it / understood it. I understand the logic behind it, but am unsure as how to go about implementing it.
As the deadline is getting closer, I have decided to move from simulating rectangles to simply simulating circles, as my planned collision detection would only be able to tell me whether a collision had occured, but not where specifically (coordinates) this collision occurred, essential info if taking torque into account. Torque isn't important when simulating circles however, cause the spinning isn't visible. This gets rid of the loopiness problem (I'll see if I can't figure it out myself once I know more, and know better how to approach something like this). The assignment assess the 'journey of learning' rather than the end-product alone, so this shouldn't cost me any marks.
While I've gotten rid of one problem, I would still be grateful for any pointers as to animation etc. You also may have noticed that each time-step I g2.fillRect(0,0,this.getWidth(),this.getHeight()); to erase the previously drawn rectangles, and I realize this is also a horrible method, which the method mentioned by you seems to be able to fix.
Thanks again for your time and the quick response. [ October 22, 2008: Message edited by: J.J. Zing ]
Joined: Jan 14, 2004
Here's a comparison of the accuracy of two ways of animating a geom primitive. Storing the location of the primitive in a Shape that is animating leads to errors that compound. Another way is to keep the original primitive and draw it as a transformedShape for animation. To detect collision with this you can use the transformedShape with the Shape intersects method. For circles you can use the Ellipse2D class and its intersects method. For more complex shapes you can try the Area, Path2D or Polygon classes. Overriding the (Container) paint method in a JFrame is AWT drawing as opposed to Swing drawing. Swing is double–buffered by default and makes animations easier than they are in AWT drawing. Using a separate JComponent extension, eg, JPanel, for drawing allows for Swing drawing and for encapsulating graphics code in its own class. There are different ways to do animation and everyone seems to have their favorite/preferred idiom. Here's one way to approach it in Swing.
Joined: Oct 21, 2008
Another quick reply! Thank you. Holidays have ended and its back to other school work so im kinda rushing right now. But, I'll respond to this in greater length eventually.
I'm impressed at your coding skills: what I posted is the fruits of about 5 solid days of labor, and you did what i did better than i did it, overnight. This explains a lot, like why assigning velocity vectors to circles works (no need for AffineTransform, just paint new). Thanks!