How to have rotated Ellipse shape in Java? - java

How to have rotated ellipse Shape in java? I.e. so that its semi-axes are not parallel to coordinate axes?
P.S. I need not just draw this ellipse but have it in memory as a shape object.

Just take an Ellipse2D object and apply an AffineTransform rotation to it, no?
AffineTransform.getRotateInstance(Math.PI / 4)
.createTransformedShape(new Ellipse2D.Double(0, 0, 2, 1));

Related

Why Do Graphics Get Smaller Using Affine Transform in Java

I'm pretty new to Affine Transformations and am finding a few things quite frustrating..
I've been working on a personal project that draws a laser (think Star Wars) on the screen. I use the RadialGradientPaint class to draw the glow for the laser, and then use scale and rotate Affine Transformations to change the oval's shape and turn the laser in a specific direction.
When I try to rotate the graphic (without the scale), it appears to shrink it, and I'm not sure why this is. I've tried looking this up to no avail. Perhaps I misinterpreted the Java Doc on this class. Why is this?
I'm also curious as to how I can get the transformed object to move to the same location as an un-transformed graphic. Both graphics move to different places even with the same coordinates. I know this might be due to an Affine Transformation shifting the whole graph, and that I might have to translate the transformed graphic to get it to the same exact place as the un-transformed graphic, but I'm not sure how to approach this.
Here is the portion of my code that draws the laser:
public void render(Graphics g) {
// If the graphic is visible on the frame, draw it
if(onScreen()) {
Graphics2D g2d = (Graphics2D) g;
// Preserves the original presets of the program's graphics
AffineTransform ogTransform = g2d.getTransform();
Shape ogClip = g2d.getClip();
Point2D center = new Point2D.Float(x, y);
float[] dist = {0.3f, 0.9f};
Color[] colors = {new Color(1.0f, 1.0f, 1.0f, 0.9f), new Color(0.0f, 1.0f, 0.0f, 0.1f)};
g2d.setPaint(new RadialGradientPaint(center, radius, dist, colors));
AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY);
AffineTransform rotationTransform = AffineTransform.getRotateInstance(angle, x + width/2f, y + height/2f);
// Transforms the shape to look more like a laser
rotationTransform.concatenate(scaleTransform);
g2d.setTransform(rotationTransform);
// Draws a "cut-out" of the rectangle
g2d.setClip(new Ellipse2D.Double(x - radius, y - radius, radius * 2, radius * 2));
g2d.fillRect(x - radius, y - radius, radius * 2, radius * 2);
// Default transformation and clip are set
g2d.setTransform(ogTransform);
g2d.setClip(ogClip);
// Outlines where the transformed graphic should be
g.setColor(Color.orange);
g.drawRect(x - 10, y - 10, 20, 20);
}
}
Any help is appreciated!

Drawing a square in canvas

I have a canvas that is drawing a circle with predefined bounds.
canvas.drawCircle((float) (getBounds().right / 2), (float) (getBounds().bottom / 2), (float) (getBounds().right / 2), paint);
and now I need to make it draw a square instead of a circle. so this is what I modified
(getBounds().right / 2) instead of it dividing by 2 I didn't divide it by anything for the radius
how ever it just overflows.
So this is how it looks like when its a normal circle.
and this is how it looks when I attempted to make it a square
can someone please suggest me how I can draw a successful square with the bounds I have been given?
Look's like the answer was fairly simple.
all I had to do is pass my rect and paint to Canvas::drawRect
here is the code
Rect rect = drawable.getBounds();
canvas.drawRect(rect, paint);
and image of the result

Move a Rectangle from point to point in a ramp with changing angle

So I have this program to test the possibility of an object to slide down in a ramp given its friction, object mass and ramp angle. However I need to animate the box if the force is positive. Just a simple animation moving the box from that point to the end of the ramp. But I can't. Please help
private void drawTransform(Graphics g, double modifier) {
// redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE);
Rectangle rect = new Rectangle(130,350, 350, 15);
Rectangle box = new Rectangle((int) (rect.getX()+300), 300, 50, 50);
AffineTransform at = new AffineTransform();
at.rotate(-Math.toRadians(modifier), rect.getX(), rect.getY() + rect.height);
// Transform the shape and draw it to screen
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.DARK_GRAY);
// g2d.fillRect(0, 0, 350, 600);
g2d.fill(at.createTransformedShape(rect));
g2d.draw(at.createTransformedShape(box));
}
Screenshot:
If all you want to do is move the box, this can be done by simply updating it's X position. You should be able to manipulate the rectangle's X position directly using something like "box.x++". Alternatively you could create a variable and reference that to provide the initial X co-ordinate, then updating that variable will "move" the box. One issue is this will only move the box along the X axis, hence you will also need some kind of constant downward force acting as gravity. This is easy to achieve, just minus the box's Y position value when it is not colliding with the ground, or your ramp.
Another approach is velocity based movement using vectors, however you mentioned that the animation should be simple. If you do want a smoother animation velocity based movement will provide this but you will need to perform a little research first.

Rotating the Rectangle object in java

Is it possible to rotate the Rectangle object to a certain degree around it's axis? Is it as easy as Rectangle rect = new Rectangle(x,y,w,h,r)?
If it is not possible to rotate the object, what would be a way I could get similar results?
Edit: for clarity here is my dilemma, I have images that rotate but when they colide with other images the collisions only work at 90 and 180 degree rotations because their hit box Rectangle objects don't rotate.
Edit: for clarity here is my dilemma, I have images that rotate but when they colide with other images the collisions only work at 90 and 180 degree rotations because their hit box Rectangle objects don't rotate.
You can rotate a Shape-derived object, such as a Rectangle2D by using the AffineTransform method, createTransformedShape(...).
Rectangle2D myRect = new Rectangle2D.Double(100, 100, 200, 200);
AffineTransform at = AffineTransform.getRotateInstance(Math.PI / 4, 150, 150);
Shape rotatedRect = at.createTransformedShape(myRect);
Note: code not compiled nor tested.
To rotate the rectangle, you give the graphics context an AffineTransform for rotation. Here's an example:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
AffineTransform oldTransform = g2d.getTransform();
g2d.setTransform(AffineTransform.getRotateInstance(radians);
g2d.draw(rectangle);
g2d.setTransform(oldTransform);
}
You can also use g2d.rotate(radians) for rotation.
Note that the angle must be in radians. To convert degrees into radians, use degrees * (Math.PI/180) for the angle.
There's also another way to do this (besides createTransformedShape) which creates fewer temporary objects, if that's desirable.
Instead of keeping a Rectangle2D for the bounding box, you can keep a Path2D and then do the transform in place, using Path2D.transform(AffineTransform):
import java.awt.geom.*;
public class Example {
private final Path2D hitBox;
public Example(Rectangle2D initialHitBox) {
this.hitBox = new Path2D.Double(initialHitBox);
}
public void transform(AffineTransform tx) {
path.transform(tx); // In-place transformation.
}
// ...
}
This is very similar to what AffineTransform actually does under the hood.

How can I draw on JPanel using another quadrant for the coordinates?

I would like to draw some shapes on a JPanel by overriding paintComponent. I would like to be able to pan and zoom. Panning and zooming is easy to do with AffineTransform and the setTransform method on the Graphics2D object. After doing that I can easyli draw the shapes with g2.draw(myShape) The shapes are defined with the "world coordinates" so it works fine when panning and I have to translate them to the canvas/JPanel coordinates before drawing.
Now I would like to change the quadrant of the coordinates. From the 4th quadrant that JPanel and computer often uses to the 1st quadrant that the users are most familiar with. The X is the same but the Y-axe should increase upwards instead of downwards. It is easy to redefine origo by new Point(origo.x, -origo.y);
But How can I draw the shapes in this quadrant? I would like to keep the coordinates of the shapes (defined in the world coordinates) rather than have them in the canvas coordinates. So I need to transform them in some way, or transform the Graphics2D object, and I would like to do it efficiently. Can I do this with AffineTransform too?
My code for drawing:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.blue);
AffineTransform at = g2.getTransform();
at.translate(-origo.x, -origo.y);
at.translate(0, getHeight());
at.scale(1, -1);
g2.setTransform(at);
g2.drawLine(30, 30, 140, 20);
g2.draw(new CubicCurve2D.Double(30, 65, 23, 45, 23, 34, 67, 58));
}
This is an off the cuff answer, so it's untested, but I think it will work.
Translate by (0, height). That should reposition the origin to the lower left.
Scale by (1, -1). That should flip it about the x axis.
I don't think the order of operations matters in this case.

Categories

Resources