Java: Rotate Rectangle - java

I am trying to rotate a Rectangle from the vertices closest to the origin, but it is placing it way off the frame.
I have the following class:
class MyRectangle {
MyRectangle(int x, int y, int w, int h, int a){
xPos = x;
yPos = y;
width = w;
height = h;
angle = a;
}
public int xPos;
public int yPos;
public int width;
public int height;
public int angle;
public void paintComponent(Graphics g) {
g.drawRect(xPos, yPos, width, height);
Rectangle rect2 = new Rectangle(xPos, yPos, width, height);
Graphics2D gg = (Graphics2D) g.create();
AffineTransform transform = new AffineTransform();
transform.rotate(angle, rect2.getX() + rect2.width/2, rect2.getY() + rect2.height/2);
AffineTransform old = gg.getTransform();
gg.transform(transform);
gg.rotate(Math.toDegrees(-angle));
gg.draw(rect2);
}
}
I am caling the rectangle with:
MyRectangle rect = new MyRectangle(10, 200, 30, 50, 70);
It is showing up like this:
I included the original un-rotated rectangle. It should rotate from the bottom left vertex.

Related

Drawing lines in loop

How to draw horizontal lines between those four lines and have same space between them like on image.
DrawPanel.java:
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int pieces = 5;
g.drawLine(0, height/2, width/2, 0);
g.drawLine(width/2, 0, width, height/2);
g.drawLine(0, height, width/2, height/2);
g.drawLine(width/2, height/2, width, height);
for (int i = 0; i < pieces; i++) {
int y = height * i/pieces;
if (y > height / 2)
g.drawLine(0, y, width / 2, y);
}
}
}
DrawPanelTest.java:
import javax.swing.JFrame;
public class DrawPanelTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(1280,720);
application.setVisible(true);
}
}
What i've got so far:
how to make those lines in bottom left corner fit between lines not in the for loop (something like show above)?
You could draw the bottom triangle to overwrite the lines, or you can calculate the distance away from the center that you need to start/end drawing the lines.
Since we know the height and width of the triangle (half the pyramid) you can calculate the top angle. Once you know the top angle, you can use that to calculate the width of the bottom side at each iteration of the line.
public class PyramidLinesTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(1280,720);
application.setVisible(true);
}
static class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int pieces = 5;
drawPyramids(g, width, height);
drawLines(g, width, height, pieces);
}
private void drawPyramids(Graphics g, int width, int height) {
g.drawLine(0, height/2, width/2, 0);
g.drawLine(width/2, 0, width, height/2);
g.drawLine(0, height, width/2, height/2);
g.drawLine(width/2, height/2, width, height);
}
private void drawLines(Graphics g, int width, int height, int pieces) {
// Determine the size of the side and bottom (adjacent and opposite)
double halfY = height / 2;
double halfW = width / 2;
// Tan = O / A
// Tan = halfW / halfY
double tanTheta = halfW / halfY;
double theta = Math.atan(tanTheta); // Radians Math.toDegrees()
double dist = halfY / pieces;
for (int i = 0; i < pieces; i++) {
// Start at halfY and move down by I distance
int y = (int) (halfY + (i * dist));
// Calculate the distance away from halfX using theta
// tan(theta) = O / A
// O = tan(theta) * A
int fromHalfW = (int) (Math.tan(theta) * (i * dist));
// Draw the lines accordingly
g.drawLine(0, y, (int) (halfW - fromHalfW), y);
g.drawLine((int) (halfW + fromHalfW), y, width, y);
}
}
}
}

How to rotate shape from its center as well as from center of the screen

I have created Star shape using drawPolygon() but I want to rotate it from the center point of the star as well as from center of the screen.
Here is my code to rotate star from its center:
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform origX = g2d.getTransform();
AffineTransform newX = (AffineTransform) origX.clone();
newX.rotate(Math.toRadians(angle), x, y + 62); // Rotate about center of the star
g2d.setTransform(newX);
g2d.drawPolygon(starX, starY, 5);
g2d.dispose();
g.dispose();
}
If i replace:
newX.rotate(Math.toRadians(angle), x, y + 62);
to
newX.rotate(Math.toRadians(angle), this.getWidth() / 2, this.getHeight() / 2);
I can able to rotate it from center of the screen.
However, I want to achieve both the effects simultaneously.
i.e.: Like the earth which rotate around the sun as well as its own axis.
I have tried creating another AffineTransform object but it overwrite the previous one when I set it using g2d.setTransform(newObj);
Any suggestions will be extremely helpful.
Thank you.
Here is my complete code if you want to see
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
public class Star extends Applet implements Runnable{
private int[] starX;
private int[] starY;
private Thread mainThread;
private int x;
private int y;
private int angleFromCenterShape;
#Override
public void init() {
this.setSize(800, 480);
x = 250;
y = 150;
angleFromCenterShape = 0;
starX = new int[5];
starY = new int[5];
mainThread = new Thread(this);
mainThread.start();
this.setBackground(Color.BLACK);
}
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform origX = g2d.getTransform();
AffineTransform newX = (AffineTransform) origX.clone();
newX.rotate(Math.toRadians(angleFromCenterShape), x, y + 65); //Rotate about center of the star
g2d.setTransform(newX);
g2d.setColor(Color.red);
g2d.fillPolygon(starX, starY, 5);
g2d.dispose();
g.dispose();
}
#Override
public void run() {
while(true){
angleFromCenterScreen = (angleFromCenterScreen + 1) % 360; // angle loop from 0 to 36o
initStar();
try{
Thread.sleep(30);
}catch(Exception e){}
repaint();
}
}
private void initStar(){
starX[0] = x;
starX[1] = x - 50;
starX[2] = x + 75;
starX[3] = x - 75;
starX[4] = x + 50;
starY[0] = y;
starY[1] = y + 130;
starY[2] = y + 50;
starY[3] = y + 50;
starY[4] = y + 130;
}
}
I have found a workaround for my problem but it is not an exact solution.
However adding another rotate() on the same AffineTransform object mimic the 2 rotations
Here is the code
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform origX = g2d.getTransform();
AffineTransform newX = (AffineTransform) origX.clone();
newX.rotate(Math.toRadians(angle), this.getWidth() / 2, this.getHeight() / 2); // Rotate from the center of screen
newX.rotate(Math.toRadians(angle), x, y + 65); // Rotate from the center of the shape
g2d.setTransform(newX);
g2d.setColor(Color.red);
g2d.fillPolygon(starX, starY, 5);
g2d.dispose();
g.dispose();
}

Java - Change the color of some squares created with Graphics2D

I just want to create a simple game with 100 x 100 square, each square is 5 pixels.
I created a class:
public class Draw extends JComponent{
private List<Graphics2D> recList = new ArrayList<Graphics2D>();
public void paint(Graphics g) {
//THIS TO SET (0,0) PANEL START AT BOTTOM LEFT
Graphics2D g2 = (Graphics2D)g;
AffineTransform at = g2.getTransform();
at.translate(0, getHeight());
at.scale(1, -1);
g2.setTransform(at);
//THIS TO DRAW ALL THE SQUARES
for (int i = 0;i<100;i++){
for (int j=0;j<100;j++){
g2.setColor(Color.red);
g2.drawRect(5*i, 5*j, 5, 5);
recList.add(g2); //Store each square to the list to change the color
}
}
}
}
Then I just drag it to the design windows of netbeans and the squares are painted, looks good...
But it seems like I made a wrong move. At the first time I wanted to get a specific square from the list using their location, but the Graphic2d doesn't have any method to get the location (x and y) or to change the color.
I don't know if there is any other way I can make it come true?
PS: One more thing, can I set the location of each square to its center?
You could create your own Tile class, which stores info such as x, y, width, height, and color. Each Tile object could also be in charge of painting itself:
class Tile {
private int x, y, width, height;
private Color color;
public Tile(int x, int y, int width, int height, Color color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
public void paint(Graphics g) {
g.setColor(color);
g.fillRect(x, y, width, height);
}
}
Create the tiles before-hand:
List<Tile> tiles = ...;
void createTiles() {
for(int x = 0; x < 100; x++) {
for(int y = 0; y < 100; y++) {
Color color = ...; //choose color
int size = 5;
int tileX = x * size;
int tileY = y * size;
tiles.add(new Tile(tileX, tileY, size, size, color));
}
}
}
Then render by passing the graphics object to them in the paint method:
void paint(Graphics g) {
tiles.forEach(tile -> tile.paint(g));
}

Drawing graphics in Java

I am trying to draw a circle in side a square and having multiple square circles in java. I am almost done but my output isn't coming out as I wanted to. The picture is what I am trying to do but it's not working out.
Here is my code:
a.awt.*;
public class SquaredCircles {
public static final int WIDTH=400;
public static final int HEIGHT=400;
public static void main (String[] args) {
DrawingPanel panel = new DrawingPanel(WIDTH,HEIGHT);
Graphics g = panel.getGraphics ();
panel.setBackground(new Color(0, 255, 255 ) );
int x = 0;
int y = 0;
int size = 100;
int rows = 5;
int numSquares = 1;
drawManySquares ( g, numSquares, x, y, size, rows );
x = 10;
y = 120;
size = 24;
rows = 4;
numSquares = 4;
drawManySquares( g, numSquares, x, y, size, rows );
x = 150;
y = 20;
size = 40;
rows = 6;
numSquares = 5;
drawManySquares( g, numSquares, x, y, size, rows );
x = 130;
y = 275;
size = 36;
rows = 3;
numSquares = 3;
drawManySquares( g, numSquares, x, y, size, rows );
}
public static void drawManySquares( Graphics g, int numSquares, int x, int y, int size, int rows ) {
for ( int i = 0; i < numSquares; i++ ) {
for ( int j = 0; j < numSquares; j++ ) {
drawOneSquare( g, x + i size, y + j size, size, rows );
}
}
}
public static void drawOneSquare( Graphics g, int x, int y, int size, int rows ) {
g.setColor ( Color.GREEN);
g.fillRect(x , y, size, size);
g.setColor ( Color.YELLOW);
g.fillOval ( x, y, size, size);
g.setColor ( Color.BLACK);
g.drawLine(size / 2, x, size / 2, size);
g.setColor ( Color.BLACK);
g.drawLine(x, size / 2, size, size / 2);
for (int i = 0; i <= rows; i = i + 1) {
g.setColor ( Color.BLACK);
g.drawOval(x + (i* (size/rows)), y+ (i*(size/rows)), size - (i*(size/rows +10 )) , size - (i*(size/rows +10)));
}
}
}
Start by having a look at Painting in AWT and Swing and Performing Custom Painting to see how painting should be done in Swing
Break down your problem into manageable chunks. The first thing you need to be able to do is paint a circle of a given size at a specific location, something like
public void paintCircleAt(Graphics2D g2d, int radius, int centerX, int centerY, Color stroke, Color fill) {
Ellipse2D.Double circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2);
g2d.setColor(fill);
g2d.fill(circle);
g2d.setColor(stroke);
g2d.draw(circle);
}
So, this allows you to paint a circle of a given radius around the center points of x/y filled and outlined with the specified color, pretty simple.
Now, you need someway to paint a series of circles around the same center point, something like...
public void paintCirclesIn(Graphics2D g2d, int count, int radius, int centerX, int centerY, Color stroke, Color fill) {
System.out.println(radius + "; " + centerX + "; " + centerY);
int delta = radius / count;
int innerRadius = radius;
for (int index = 0; index < count; index++, innerRadius -= delta) {
paintCircleAt(g2d, innerRadius, centerX, centerY, stroke, fill);
}
}
Okay, this basically calculates the difference (delta) between each circle and the paints that many circles with that much difference in their radius from the previous one. Because of the way the painting is done, we start with the outer circle and paint in.
And finally, we need someway to paint a square and circles, something like...
public void paintCirclesInSquare(Graphics2D g2d, int count, int x, int y, int width, int height, Color squareStroke, Color squareFill, Color circleStroke, Color circleFill) {
int centerX = x + (width / 2);
int centerY = y + (height / 2);
int radius = Math.min(centerX, centerY);
Rectangle2D box = new Rectangle2D.Double(x, y, width, height);
g2d.setColor(squareFill);
g2d.fill(box);
g2d.setColor(squareStroke);
g2d.draw(box);
paintCirclesIn(g2d, count, radius, centerX, centerY, circleStroke, circleFill);
g2d.drawLine(centerX, y, centerX, y + height);
g2d.drawLine(x, centerY, x + width, centerY);
}
This, again, simply reuses the existing code we already have and adds to it, painting the square, the circles in the square and finally the lines.
Now, from here, you could write a method which took the number of columns/rows you wanted, the x/y position to start from, the size of each of square, the number of circles you need and the colors and reuse this functionality, but I'll leave that up to you ;)
Runnable example for you to play with...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CirclesAndSquares {
public static void main(String[] args) {
new CirclesAndSquares();
}
public CirclesAndSquares() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int x = getWidth() / 2;
int y = getHeight() / 2;
// paintCircleAt(g2d, Math.min(x, y), y, y, Color.BLACK, Color.YELLOW);
// paintCirclesIn(g2d, 5, Math.min(x, y), x, y, Color.BLACK, Color.YELLOW);
paintCirclesInSquare(g2d, 5, 0, 0, getWidth() - 1, getHeight() - 1, Color.BLACK, Color.GREEN, Color.BLACK, Color.YELLOW);
g2d.dispose();
}
public void paintCirclesInSquare(Graphics2D g2d, int count, int x, int y, int width, int height, Color squareStroke, Color squareFill, Color circleStroke, Color circleFill) {
int centerX = x + (width / 2);
int centerY = y + (height / 2);
int radius = Math.min(centerX, centerY);
Rectangle2D box = new Rectangle2D.Double(x, y, width, height);
g2d.setColor(squareFill);
g2d.fill(box);
g2d.setColor(squareStroke);
g2d.draw(box);
paintCirclesIn(g2d, count, radius, centerX, centerY, circleStroke, circleFill);
g2d.drawLine(centerX, y, centerX, y + height);
g2d.drawLine(x, centerY, x + width, centerY);
}
public void paintCirclesIn(Graphics2D g2d, int count, int radius, int centerX, int centerY, Color stroke, Color fill) {
System.out.println(radius + "; " + centerX + "; " + centerY);
int delta = radius / count;
int innerRadius = radius;
for (int index = 0; index < count; index++, innerRadius -= delta) {
paintCircleAt(g2d, innerRadius, centerX, centerY, stroke, fill);
}
}
public void paintCircleAt(Graphics2D g2d, int radius, int centerX, int centerY, Color stroke, Color fill) {
Ellipse2D.Double circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2);
g2d.setColor(fill);
g2d.fill(circle);
g2d.setColor(stroke);
g2d.draw(circle);
}
}
}

canvas.drawBitmap and canvas.drawRect, the draw up object is not the same size

I have a problem with canvas.drawBitmap and canvas.drawRect when i use canvas.drawRect everything works fine but when i use canvas.drawBitmap that when thing start to get strange. The size of the object drawn on the screen are not the same size for DrawRect as for DrawProcentObject. I haven't been able to find a problem with the math in my code so i guess the problem lies in how canvas.drawBitmap works.
I would be grateful if someone could tell me what the problem is and how to solve it.
The width, height is the size of the object here, bmp is a bitmap.
DrawRect(canvas, width, height, x, y, Color.BLACK);
DrawProcentObject(canvas, bmp, x, y, width, height);
the width, height in this method are the screen resolution.
public void DrawObject(Canvas canvas, Bitmap bmp, int X, int Y) {
canvas.save();
canvas.drawColor(Color.TRANSPARENT);
Paint paint = new Paint();
canvas.drawBitmap(bmp, X, Y, paint);
canvas.restore();
}
public void DrawProcentObject(Canvas canvas, Bitmap bmp, int X, int Y, int SizeWidth, int SizeHeight)
{
double x = width * ((double)X/1000);
double y = height * ((double)Y/1000);
double sizeWidth = width * ((double)SizeWidth/1000);
double sizeHeight = height * ((double)SizeHeight/1000);
bmp = Bitmap.createScaledBitmap(bmp, (int) sizeWidth, (int) sizeHeight, true);
DrawObject(canvas, bmp, (int) x, (int) y);
}
public void DrawRect(Canvas canvas, int SizeWidth, int SizeHeight, int X, int Y, int rectColer)
{
canvas.save();
canvas.drawColor(Color.TRANSPARENT);
Paint paint = new Paint();
paint.setColor(rectColer);
canvas.drawRect(ProcentRect(SizeWidth, SizeHeight, X, Y), paint);
canvas.restore();
}
public Rect ProcentRect(int SizeWidth, int SizeHeight, int X, int Y)
{
double x = width * ((double)X/1000);
double y = height * ((double)Y/1000);
double sizeWidth = width * ((double)SizeWidth/1000);
double sizeHeight = height * ((double)SizeHeight/1000);
Rect rect = new Rect((int)x, (int)y, (int)x + (int)sizeWidth, (int)y + (int)sizeHeight);
return rect;
}

Categories