Trouble java graphics program - java

I have this java program that is made up of different classes. But it basically displays a circle and rectangle moving in a frame a Brownian motion.
I am trying to make a triangle class to add an equilateral triangle to the mix and to this I have to modify my nervous shape class and create a equilateral triangle class. I made a triangle class but I am not sure how to modify my nervous shape program to make it work. The nervous shape program work fine on it own without the triage class
I created my triangle class a subclass of shape but I am not sure how to modify nervous shape to make it work. I need to create the triangle class with one instance variable.
Any help will be appreciated.
// Program name: NervousShapes
//
// Displays a frame containing a random mixture of circles
// and rectangles with random colors, sizes, and positions.
// The shapes periodically change position, with the
// direction of motion chosen randomly for each shape. The
// new x coordinate for each shape will either be the same
// as the old x coordinate, one pixel smaller, or one pixel
// larger; the new y coordinate will be computed in a
// similar manner. Shapes will be constrained so that they
// do not move outside the drawing area.
public static void main(String[] args) {
createWindow();
createShapes();
animateShapes();
}
///////////////////////////////////////////////////////////
// NAME: createWindow
// BEHAVIOR: Creates a frame labeled "Nervous Shapes",
// displays the frame, and sets the size of
// the frame (using the WINDOW_SIZE class
// variable). Assigns the frame to the df
// class variable, and assigns the frame's
// graphics context to the g class variable.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createWindow() {
// Create a frame labeled "Nervous Shapes" and set its
// size
df = new DrawableFrame("Nervous Shapes");
df.show();
df.setSize(WINDOW_SIZE, WINDOW_SIZE);
// Get the frame's graphics context
g = df.getGraphicsContext();
}
///////////////////////////////////////////////////////////
// NAME: createShapes
/ / BEHAVIOR: Creates enough Circle and Rectangle objects
// to fill the shapes array. Each shape has a
// random color, size, and position. The height
// and width of each shape must lie between
// MIN_SIZE and MAX_SIZE (inclusive). The
// position is chosen so that the shape is
// completely within the drawing area.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createShapes() {
for (int i = 0; i < shapes.length; i++) {
// Select a random color
int red = generateRandomInt(0, 255);
int green = generateRandomInt(0, 255);
int blue = generateRandomInt(0, 255);
Color color = new Color(red, green, blue);
// Decide whether to create a circle or a rectangle
if (Math.random() < 0.5) {
// Generate a circle with a random size and position
int diameter = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - diameter);
int y = generateRandomInt(0, WINDOW_SIZE - diameter);
shapes[i] = new Circle(x, y, color, diameter);
} else {
// Generate a rectangle with a random size and
// position
int width = generateRandomInt(MIN_SIZE, MAX_SIZE);
int height = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - width);
int y = generateRandomInt(0, WINDOW_SIZE - height);
shapes[i] = new Rectangle(x, y, color, width, height);
}
}
}
///////////////////////////////////////////////////////////
// NAME: animateShapes
// BEHAVIOR: Establishes an infinite loop in which the
// shapes are animated. During each loop
// iteration, the drawing area is cleared and
// the shapes are then drawn at new positions.
// The new x and y coordinates for each shape
// will either be the same as the old ones,
// one pixel smaller, or one pixel larger. A
// shape is not moved if doing so would cause
// any portion of the shape to go outside the
// drawing area. At the end of each animation
// cycle, there is a brief pause, which is
// controlled by the delay constant.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void animateShapes() {
while (true) {
// Clear drawing area
g.setColor(Color.white);
g.fillRect(0, 0, WINDOW_SIZE - 1, WINDOW_SIZE - 1);
for (int i = 0; i < shapes.length; i++) {
// Change the x coordinate for shape i
int dx = generateRandomInt(-1, +1);
int newX = shapes[i].getX() + dx;
if (newX >= 0 &&
newX + shapes[i].getWidth() < WINDOW_SIZE)
shapes[i].move(dx, 0);
// Change the y coordinate for shape i
int dy = generateRandomInt(-1, +1);
int newY = shapes[i].getY() + dy;
if (newY >= 0 &&
newY + shapes[i].getHeight() < WINDOW_SIZE)
shapes[i].move(0, dy);
// Draw shape i at its new position
shapes[i].draw(g);
}
// Call repaint to update the screen
df.repaint();
// Pause briefly
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {}
}
}
///////////////////////////////////////////////////////////
// NAME: generateRandomInt
// BEHAVIOR: Generates a random integer within a
// specified range.
// PARAMETERS: min - the lower bound of the range
// max - the upper bound of the range
// RETURNS: A random integer that is greater than or
// equal to min and less than or equal to max
///////////////////////////////////////////////////////////
private static int generateRandomInt(int min, int max) {
return (int) ((max - min + 1) * Math.random()) + min;
}
}
Here is my shape superclass that I use to make my triangle.
// Represents a geometric shape that can be displayed in a
// graphics context
import java.awt.*;
public abstract class Shape {
// Instance variables
private int x;
private int y;
private Color color;
// Constructor
protected Shape(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
// Abstract methods
public abstract void draw(Graphics g);
public abstract int getHeight();
public abstract int getWidth();
// Other instance methods
public Color getColor() {
return color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void move(int dx, int dy) {
x += dx;
y += dy;
}
public void setColor(Color color) {
this.color = color;
}
}
Here is the rectangle subclass needed to make program work
// Represents a rectangle that can be displayed in a graphics
/ / context
import java.awt.*;
public class Rectangle extends Shape {
// Instance variables
private int width;
private int height;
// Constructor
public Rectangle(int x, int y, Color color,
int width, int height) {
super(x, y, color);
this.width = width;
this.height = height;
}
// Instance methods
public void draw(Graphics g) {
g.setColor(getColor());
g.fillRect(getX(), getY(), width, height);
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}
Here is the circle graphic in the nervous shape.
// Represents a circle that can be displayed in a graphics
// context
import java.awt.*;
public class Circle extends Shape {
// Instance variables
private int diameter;
// Constructor
public Circle(int x, int y, Color color, int diameter) {
super(x, y, color);
this.diameter = diameter;
}
// Instance methods
public void draw(Graphics g) {
g.setColor(getColor());
g.fillOval(getX(), getY(), diameter, diameter);
}
public int getHeight() {
return diameter;
}
public int getWidth() {
return diameter;
}
}
And here is the new triangle class I created and I am trying to make nervous shape program run I have to modify create shape part of my nervous shape.
import java.awt.*;
public class Triangle extends Shape {
// Instance variables
private int leng;
// Constructor
public Triangle(int x, int y, Color color,
int leng) {
super(x, y, color);
this.leng=leng;
}
// Instance methods
public void draw(Graphics g) {
int[]Xcoord={getX(),getX()+leng,getX()+leng/2};
int[]Ycoord={getY(),getY(),getY()+math.sqrt(3)/2};
g.drawPolygon(Xcoord,Ycoord,3);
}
public int getleng() {
return leng;
}

Related

Creating a 2D Cylinder with Java Graphics

I'm trying to make a cylinder using Java Graphics and the paintComponent() method.
The user of the application can select which shape they want (in this case it's a cylinder) and input the dimensions they want for the shape.
After they input the dimensions and click the submit button, another window will open with the image drawn on it.
My current issue is getting the shape made correctly. I'm currently trying to make two ovals and connect them using two lines. The base will be a red oval and everything else will have no color.
When you submit the dimensions for the cylinder, the sides are never the correct length or in the correct position on the Y-Axis. An example can be view here:
The dimensions for this cylinder: 200 height, 50 radius.
What the cylinder should look like:
300 height, 300 radius
I'll be working on adding the minimal version of the program for testing. However, for right now I'll be providing what the code is for the cylinder itself and the paintComponent() method.
Cylinder:
import java.awt.Color;
public class Cylinder extends Circle {
private int length;
public Cylinder(int radius, int length, Color color) {
super(radius, length, color);
this.length = length;
this.radius = radius;
}
public Cylinder(int newX, int newY, int newRadius, int newLength) {
super(newX, newY, newRadius);
length = newLength;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int calcArea() {
return (int) Math.ceil( 2 * 3.14 * radius * radius + 2 * 3.14 * radius * length);
}
public int calcVolume() {
return (int) Math.ceil(3.14 * radius * radius * length);
}
public DrawFigure drawFigure() {
DrawFigure cylinder1 = new DrawFigure(4, getRadius(), length);
return cylinder1;
}
public String toString() {
return "Length = " + length + " " + super.toString();
}
}
DrawFigure (paintComponent is the last method):
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawFigure extends JPanel {
int type;
int length, width, height, radius;
public DrawFigure() {
super();
type = 5;
}
public DrawFigure(int myType, int myWidth, int myLength, int myHeight) { // Box and Rectangle
super();
type = myType;
length = myLength;
width = myWidth;
height = myHeight;
}
public DrawFigure(int x, int y, int myType, int myWidth, int myLength, int myHeight) {
super();
type = myType;
length = myLength;
width = myWidth;
height = myHeight;
}
public DrawFigure(int myType, int myRadius, int myHeight) {
super();
type = myType;
radius = myRadius;
height = myHeight;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (type == 1) { // Draw Rectangle
} else if (type == 2) { // Draw Box
} else if(type == 3) { // Draw Circle
} else if(type == 4) { // Draw Cylinder
g.setColor(Color.BLACK);
g.drawOval(135, 65, radius, radius - radius / 2);
// Base
g.setColor(Color.RED);
g.fillOval(135, 65 + height, radius, radius / 2);
g.setColor(Color.BLACK);
g.drawLine(135, 65 + height + (height /4), 135, 135);
g.setColor(Color.BLACK);
g.drawLine(135 + radius, 65 + height + (height /4), 135 + radius, 135);
return;
}
}
}
Full code for the program:
Point.java https://pastebin.com/iVgN47e3
Lab6GUI.java https://pastebin.com/bKM790iQ
Rectangle.java https://pastebin.com/MdCrJYeA
Box.java https://pastebin.com/iZCZpUi7
Circle.java https://pastebin.com/aui1NgJi
Cylinder.java https://pastebin.com/fHDNmBXT
DrawFigure.java https://pastebin.com/z8t31put
LessThanOrEqualToZeroException.java https://pastebin.com/4ELEmsNX
LessThanOrGreaterThanException.java https://pastebin.com/1avRUudN
Okay, so drawing an oval extends from the x/y position, with a positive width/height, that would make the oval draw right/down from the x/y position, for example...
So, assuming we start at 0x0, this would mean that the lines would need to start at a y position of radius / 4, given that you're using radius for the width and radius / 2 for the height (I'm not going to mention how that is confusing). This will allow the lines to "appear" that they join the outer edge of the oval (and draw down)
The lines would then be height long. This means the bottom oval would then need to start at height - (radius / 4) ... okay, I had to go and double check this, but remember, the line ends at (radius / 4) + height, this also means that the cylinder is the height + (radius / 2) high in total.
🤪🤯
height=200, radius=50
height=300, radius=300
This prevents scenario where radius / 4 is greater than height, because that would just be a mess
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new DrawPane(300, 300));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends JPanel {
int height, radius;
public DrawPane(int myRadius, int myHeight) {
super();
radius = myRadius;
height = myHeight;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - radius) / 2;
int y = (getHeight() - (height + (radius / 4))) / 2;
g2d.translate(x, y);
g2d.setColor(Color.LIGHT_GRAY);
g2d.drawRect(0, 0, radius, height + (radius / 4));
// Base
g2d.setColor(Color.RED);
g2d.fillOval(0, height - (radius / 4), radius, radius / 2);
g2d.setColor(Color.BLACK);
g2d.drawOval(0, 0, radius, radius / 2);
g2d.setColor(Color.BLACK);
g2d.drawLine(0, radius / 4, 0, height);
g2d.drawLine(radius, radius / 4, radius, height);
g2d.dispose();
}
}
}

Is there a way to make a constructor that draws a rectangle

My partner and I are trying to remake Tetris for our final project of the year in my Computer Science class we currently have a for loop that draws individual rectangles in an overwritten paint method.
private final int spacer = 30;
public int getSpacer()
{
return spacer;
}
public void paint(Graphics g) {
setBackground(Color.GRAY);
for(int i = getHeight()/2 - (spacer * 10); i < getHeight()/2 + (spacer * 10); i += spacer) {
for(int x = getWidth()/2 - (spacer * 5); x < getWidth()/2 + (spacer * 5); x += (spacer)) {
g.drawRect(x, i, (spacer), (spacer));
}
}
setForeground(Color.black);
}
The method basically takes the width and height of the window and makes a 10 x 20 grid of boxes that are 30 units, pixels I think, wide.
We'd like to make a Grid.java class that takes in color, the spacer int, and an x and y int. The constructor for Grid.java should draw the exact same thing as the code above using the for loop, but when we tried it gave us a white screen that would not resize with the window.
private final int spacer = 30;
private static Grid[][] arr = new Grid[10][20];
public int getSpacer()
{
return spacer;
}
public void paint(Graphics g) {
setBackground(Color.GRAY);
int countY = 0;
int countX = 0;
for(int y = getHeight()/2 - (spacer * 10); y < getHeight()/2 + (spacer * 10); y += spacer) {
for(int x = getWidth()/2 - (spacer * 5); x < getWidth()/2 + (spacer * 5); x += spacer) {
arr[countX][countY] = new Grid(x, y, spacer, g);
countX++;
}
countY++;
}
setForeground(Color.black);
}
*Grid.java Class*
package Tetris_Shapes;
import javax.swing.*;
import java.awt.*;
public class Grid {
private int x;
private int y;
private int side;
private Graphics g;
public Grid(int x, int y, int side, Graphics g) {
// g.drawRect(x, y, spacer, spacer);
this.x = x;
this.y = y;
this.side = side;
this.g = g;
paint(this.g);
}
private void paint(Graphics g) {
g.drawRect(x, y, side, side);
}
}
When we try and run this we get the white box that doesn't resize. My question is does anyone know of a way to get a constructor to draw shapes. Thank you in advance, this is pretty niche so I'm also going to apologize in advance.

Having trouble displaying balls in the right position using Java and vector objects

I'm having issues with the balls that I display in my JFrame window. Here's the main idea of my application:
Point object (with coordinates x and y) --> Vector object (a class I wrote that has the x and y components of a vector, as well as a few methods... gets its location and head/tail points from the Point object) --> Ball object (the position, velocity, and acceleration vectors are collected in an ArrayList, also has radius and color attributes) --> ContainerBox object (contains the balls, defines the min/max x and y for collision detection purposes).
I'm working toward having one ball centered in the window and the other orbiting the first, but right now I'm just trying to get my objects to play nicely. I'm very new to OOP principles and this is the first time I've written a program using classes in this way.
Everything works perfectly, the JFrame comes up and displays the balls... the problem is that the balls won't show up in the right places. No matter what I put in for the x and y coordinates of the balls (either explicitly or using the objects), they always show up in the upper left-hand corner of the screen. Here's a pic of what I get: Picture Here
I don't know whether it's the vectors or the collision detection or what... any ideas? Thanks a lot for reading and replying!
EDIT: Here's some of the code that I'm using (sorry to put so much, I have no idea where the problem is):
EDIT AGAIN: Added the ball class that I forgot.
package chaneyBouncingBall;
import java.util.*;
public class Point
{
float x;
float y;
public Point(float x, float y)
{
this.x = x;
this.y = y;
}
}
package chaneyBouncingBall;
import java.util.ArrayList;
public class Chaney2DVector
{
float x;
float y;
Point fromLocation;
public Chaney2DVector(float x,
float y)
{
this.x = x;
this.y = y;
}
public Chaney2DVector(Point point1,
Point point2)
{
fromLocation = new Point(point1.x, point1.y);
this.x = point2.x - point1.x;
this.y = point2.y - point1.y;
}
}
package chaneyBouncingBall;
import java.awt.*;
import java.util.*;
public class Ball
{
float x, y;
float velX, velY;
float accelX, accelY;
float radius;
private Color color;
public Ball(float x, float y, float velX,
float velY, float accelX,
float accelY, float radius,
Color color)
{
Chaney2DVector position = new Chaney2DVector(x, y);
Chaney2DVector velocity = new Chaney2DVector(velX, velY);
Chaney2DVector acceleration = new Chaney2DVector(accelX, accelY);
ArrayList posVelAcc = new ArrayList();
posVelAcc.add(position);
posVelAcc.add(velocity);
posVelAcc.add(acceleration);
this.radius = radius;
this.color = color;
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval((int)(x - radius), (int)(y - radius),
(int)(2 * radius), (int)(2 * radius));
}
public void moveOneStepWithCollisionDetection( ContainerBox box)
{
float ballMinX = box.minX + radius;
float ballMinY = box.minY + radius;
float ballMaxX = box.maxX - radius;
float ballMaxY = box.maxY - radius;
x = x + velX;
y = y + velY;
if (x < ballMinX)
{
velX = -velX;
x = ballMinX;
}
else if (x > ballMaxX)
{
velX = -velX;
x = ballMaxX;
}
if (y < ballMinY)
{
velY = -velY;
y = ballMinY;
}
else if (y > ballMaxY)
{
velY = -velY;
y = ballMaxY;
}
}
}
package chaneyBouncingBall;
import java.awt.*;
/**
* A rectangular container box, containing the bouncing ball.
*/
public class ContainerBox {
int minX, maxX, minY, maxY; // Box's bounds (package access)
private Color colorFilled; // Box's filled color (background)
private Color colorBorder; // Box's border color
private static final Color DEFAULT_COLOR_FILLED = Color.BLACK;
private static final Color DEFAULT_COLOR_BORDER = Color.YELLOW;
/** Constructors */
public ContainerBox(int x, int y, int width, int height, Color colorFilled, Color colorBorder) {
minX = x;
minY = y;
maxX = x + width - 1;
maxY = y + height - 1;
this.colorFilled = colorFilled;
this.colorBorder = colorBorder;
}
/** Constructor with the default color */
public ContainerBox(int x, int y, int width, int height) {
this(x, y, width, height, DEFAULT_COLOR_FILLED, DEFAULT_COLOR_BORDER);
}
/** Set or reset the boundaries of the box. */
public void set(int x, int y, int width, int height) {
minX = x;
minY = y;
maxX = x + width - 1;
maxY = y + height - 1;
}
/** Draw itself using the given graphic context. */
public void draw(Graphics g) {
g.setColor(colorFilled);
g.fillRect(minX, minY, maxX - minX - 1, maxY - minY - 1);
g.setColor(colorBorder);
g.drawRect(minX, minY, maxX - minX - 1, maxY - minY - 1);
}
}
package chaneyBouncingBall;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
/**
* The control logic and main display panel for game.
*/
public class BallWorld extends JPanel {
private static final int UPDATE_RATE = 50; // Frames per second (fps)
private Ball ball; // A single bouncing Ball's instance
private Ball ball2;
private ContainerBox box; // The container rectangular box
private DrawCanvas canvas; // Custom canvas for drawing the box/ball
private int canvasWidth;
private int canvasHeight;
/**
* Constructor to create the UI components and init the game objects.
* Set the drawing canvas to fill the screen (given its width and height).
*
* #param width : screen width
* #param height : screen height
*/
public BallWorld(int width, int height) {
canvasWidth = width;
canvasHeight = height;
boolean stationary = true;
Random rand = new Random();
int angleInDegree = rand.nextInt(360);
int radius = 50;
int radius2 = 25;
// double accelAngle;
float x1 = rand.nextInt(canvasWidth - radius * 2 - 20) + radius + 10;
float y1 = rand.nextInt(canvasHeight - radius * 2 - 20) + radius + 10;
float x2 = rand.nextInt(canvasWidth - radius * 2 - 20) + radius + 10;
float y2 = rand.nextInt(canvasHeight - radius * 2 - 20) + radius + 10;
// float x = 100;
// float y = 100;
float velX1 = 0;
float velY1 = 0;
float accelX1 = 0;
float accelY1 = 0;
float velX2 = 0;
float velY2 = 0;
float accelX2 = 0;
float accelY2 = 0;
ball = new Ball(canvasWidth / 2, canvasHeight / 2, velX1, velY1, accelX1, accelY1,
radius, Color.BLUE);
ball2 = new Ball(x2, y2, velX2, velY2, accelX2, accelY2, radius / 5, Color.YELLOW);
// Init the Container Box to fill the screen
box = new ContainerBox(0, 0, canvasWidth, canvasHeight, Color.BLACK, Color.WHITE);
// Init the custom drawing panel for drawing the game
canvas = new DrawCanvas();
this.setLayout(new BorderLayout());
this.add(canvas, BorderLayout.CENTER);
// Handling window resize.
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
Component c = (Component)e.getSource();
Dimension dim = c.getSize();
canvasWidth = dim.width;
canvasHeight = dim.height;
// Adjust the bounds of the container to fill the window
box.set(0, 0, canvasWidth, canvasHeight);
}
});
// Start the ball bouncing
gameStart();
}
/** Start the ball bouncing. */
public void gameStart() {
// Run the game logic in its own thread.
Thread gameThread = new Thread() {
public void run() {
while (true) {
// Execute one time-step for the game
gameUpdate();
// Refresh the display
repaint();
// Delay and give other thread a chance
try {
Thread.sleep(1000 / UPDATE_RATE);
} catch (InterruptedException ex) {}
}
}
};
gameThread.start(); // Invoke GaemThread.run()
}
/**
* One game time-step.
* Update the game objects, with proper collision detection and response.
*/
public void gameUpdate() {
ball.moveOneStepWithCollisionDetection(box);
ball2.moveOneStepWithCollisionDetection(box);
}
/** The custom drawing panel for the bouncing ball (inner class). */
class DrawCanvas extends JPanel {
/** Custom drawing codes */
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // Paint background
// Draw the box and the ball
box.draw(g);
ball.draw(g);
ball2.draw(g);
// Display ball's information
g.setColor(Color.WHITE);
g.setFont(new Font("Courier New", Font.PLAIN, 12));
// g.drawString("Ball " + ball.toString(), 20, 30);
}
/** Called back to get the preferred size of the component. */
#Override
public Dimension getPreferredSize() {
return (new Dimension(canvasWidth, canvasHeight));
}
}
}
package chaneyBouncingBall;
import javax.swing.JFrame;
public class Main
{
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame("Matt Chaney's Gravity App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new BallWorld(550, 450));
frame.pack();
frame.setVisible(true);
}
});
}
}
In the constructor of your Ball class, you don't assign all the instance variables to their parameters, these need to be added.
public Ball(float x, float y, float velX, float velY, float accelX, float accelY, float radius, Color color) {
...
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.accelX = accelX;
this.accelY = accelY;
}

Graphics2D circular table

I'm trying to build a User Interface for the RGBike POV:
http://www.instructables.com/id/RGBike-POV-Open-project/
The program will display a bike wheel in form of a grid. The user can click
onto the single squares and changes the colour of these.
I want to build this applet in java. I'm stuck at drawing the wheel in the right way.
I need to have a sort of array of every rectangle, to export the colour later.
The best thing would be to draw a sort of circular table. Drawing each shape
With graphics2D to have each as a single object would be an idea, too. But that would
be around 860 single shapes, little bit too much to update them every time by paint().
Spoke POV has done such a user Interface for their project already:
http://www.ladyada.net/make/spokepov/software.html
But only their old python script is open source.
Be VERY grateful that I have previously generate a "segment" shape in the past ;)
This basically generates each segment individually (does some funky translation into real space) and maintains a cache of shapes which can be checked to see if the mouse falls within there bounds.
This is rather inefficient, but I think you get the idea.
I should also be noted, that I didn't bother with a backing buffer. Not to say it could use one, I just got away without it...
public class TestSpoke {
public static void main(String[] args) {
new TestSpoke();
}
public TestSpoke() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public static final int CIRCLE_COUNT = 16;
public static final int SEGMENT_COUNT = 80;
private Map<Integer, List<Shape>> mapWheel;
private Map<Point, Color> mapColors;
public TestPane() {
mapColors = new HashMap<>(CIRCLE_COUNT * SEGMENT_COUNT);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Map<Integer, List<Shape>> mapWheel = getWheel();
for (Integer circle : mapWheel.keySet()) {
List<Shape> segments = mapWheel.get(circle);
for (int index = 0; index < segments.size(); index++) {
Shape segment = segments.get(index);
if (segment.contains(e.getPoint())) {
mapColors.put(new Point(circle, index), Color.RED);
repaint();
break;
}
}
}
}
});
}
#Override
public void invalidate() {
mapWheel = null;
super.invalidate();
}
protected float getRadius() {
return Math.min(getWidth(), getHeight());
}
/**
* This builds a wheel (if required) made of segments.
* #return
*/
protected Map<Integer, List<Shape>> getWheel() {
if (mapWheel == null) {
mapWheel = new HashMap<>(CIRCLE_COUNT);
// The current radius
float radius = getRadius();
// The radius of each individual circle...
float circleRadius = radius / CIRCLE_COUNT;
// The range of each segment
float extent = 360f / SEGMENT_COUNT;
for (int circle = 0; circle < CIRCLE_COUNT; circle++) {
float startAngle = 0;
List<Shape> segments = new ArrayList<>(SEGMENT_COUNT);
mapWheel.put(circle, segments);
// Calculate the "translation" to place each segement in the
// center of the screen
float innerRadius = circleRadius * circle;
float x = (getWidth() - innerRadius) / 2;
float y = (getHeight() - innerRadius) / 2;
for (int seg = 0; seg < SEGMENT_COUNT; seg++) {
// Generate a Segment shape
Segment segment = new Segment(circleRadius * circle, circleRadius, startAngle, extent);
startAngle += extent;
// We translate the segment to the screen space
// This will make it faster to paint and check for mouse clicks
PathIterator pi = segment.getPathIterator(AffineTransform.getTranslateInstance(x, y));
Path2D path = new Path2D.Float();
path.append(pi, true);
segments.add(path);
}
}
}
return mapWheel;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Map<Integer, List<Shape>> mapWheel = getWheel();
for (Integer circle : mapWheel.keySet()) {
List<Shape> segments = mapWheel.get(circle);
for (int index = 0; index < segments.size(); index++) {
Shape segment = segments.get(index);
Color color = mapColors.get(new Point(circle, index));
if (color != null) {
g2d.setColor(color);
g2d.fill(segment);
}
g2d.setColor(Color.BLACK);
g2d.draw(segment);
}
}
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class Segment extends Path2D.Float {
public Segment(float radius, float thickness, float extent) {
this(radius, thickness, 0f, extent);
}
public Segment(float radius, float thickness, float startAngle, float extent) {
// Basically, we want to draw the outter edge from a to b angle,
// draw the connecting line from the outter to the inner,
// draw the inner from b to a angel and
// draw the connecting line from the inner to out the outter
// We want to span about 30 degrees, with a small gap...
// I want the gap to be a factor of the radius
Arc2D.Float outter = new Arc2D.Float(0, 0, radius, radius, startAngle, extent, Arc2D.OPEN);
Arc2D.Float inner = new Arc2D.Float(thickness / 2f, thickness / 2f, radius - thickness, radius - thickness, startAngle + extent, -extent, Arc2D.OPEN);
append(outter, true);
float angel = startAngle + extent;
Point2D p1 = getPointOnEdge(angel, radius);
Point2D p2 = getPointOnEdge(angel, radius - thickness);
// We need to adjust in for the change in the radius
p2.setLocation(p2.getX() + (thickness / 2f), p2.getY() + (thickness / 2f));
lineTo(p2.getX(), p2.getY());
append(inner, true);
angel = startAngle;
p1 = getPointOnEdge(angel, radius);
p2 = getPointOnEdge(angel, radius - thickness);
p2.setLocation(p2.getX() + (thickness / 2f), p2.getY() + (thickness / 2f));
lineTo(p1.getX(), p1.getY());
closePath();
}
public Point2D getPointOnEdge(float angel, float radius) {
angel -= 90;
float x = radius / 2f;
float y = radius / 2f;
double rads = Math.toRadians((angel + 90));
// This determins the length of tick as calculate from the center of
// the circle. The original code from which this derived allowed
// for a varible length line from the center of the cirlce, we
// actually want the opposite, so we calculate the outter limit first
float fullLength = (radius / 2f);
// Calculate the outter point of the line
float xPosy = (float) (x + Math.cos(rads) * fullLength);
float yPosy = (float) (y - Math.sin(rads) * fullLength);
return new Point2D.Float(xPosy, yPosy);
}
}
}

Draw circle (using pixels applied in an image with for loop)

I want to draw a circle (with 1 or 2 for loops) using pixels position (starts from top left and ends at bottom right)
I successfully drew a rectangle with this method:
private void drawrect(int width,int height,int x,int y) {
int top=y;
int left=x;
if(top<0){
height+=top;
top=0;
}
if(left<0){
width+=left;
left=0;
}
for (int j = 0; j <width; j++) {
for (int i = 0; i <height; i++) {
pixels[((i+top)*w)+j+left] = 0xffffff;//white color
}
}
}
The pixels array contains the pixel index followed by it's color.
pixels[index]=color;
Before that I use this code for "image" and "pixels" array (if this helps you)
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
But how can I draw only the white pixels like in this image and ignore the other pixels?
Here is the code for drawing circle with pixels: It uses the formula xend = x + r cos(angle) and yend = y + r sin(angle).
#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <math.h>
void DrawCircle(int x, int y, int r, int color)
{
static const double PI = 3.1415926535;
double i, angle, x1, y1;
for(i = 0; i < 360; i += 0.1)
{
angle = i;
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
putpixel(x + x1, y + y1, color);
}
}
Reference: http://www.softwareandfinance.com/Turbo_C/DrawCircle.html
You can calculate the minimum angle between two pixels and improve the Kathir solution
...
void DrawCircle(int x, int y, int r, int color)
{
static const double PI = 3.1415926535;
double x1, y1;
// calculates the minimun angle between two pixels in a diagonal.
// you can multiply minAngle by a security factor like 0.9 just to be sure you wont have empty pixels in the circle
double minAngle = acos(1 - 1/r);
for(double angle = 0; angle <= 360; angle += minAngle)
{
x1 = r * cos(angle);
y1 = r * sin(angle);
putpixel(x + x1, y + y1, color);
}
}
Since you already have a BufferedImage, why not create a graphics object for it and use that to draw the circle? That way you don't have to reinvent the wheel:
BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.WHITE);
g.fillOval(x, y, width, height);
Update
Here is a SSCCE:
public class DrawCircleExample extends Canvas {
private static final int WIDTH = 32;
private static final int HEIGHT = 32;
public static void main(String[] args) {
JFrame f = new JFrame("Draw circle example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new DrawCircleExample());
f.pack();
f.setVisible(true);
}
private final BufferedImage img;
public DrawCircleExample() {
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.WHITE);
g.fillOval(8, 8, 14, 14);
}
#Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(),img.getHeight());
}
}
It should produce an image like this:
One way to do this would be to test, for each point in the rectangle, whether or not the distance from that pixel to the center of the square is less than the intended radius of the circle. You could then draw the pixels that pass the test and skip the pixels that don't. The ratio of the area of the circle to the area of the total square is π/4, which is about .77, so this actually isn't all that inefficient.
If you want to draw an arbitrary oval that fits in the rectangle, you can use this same idea, but would modify the computation that would determine the distance to the center such that you give proportionally less weight to the long axis of the ellipse.
Hope this helps!
Sorry for the delay
This code works perfectly
private void drawcircle(int x,int y,int radius){
for(int i=x;i<radius*2;i++)
for(int j=x;j<radius*2;j++){
int d= (int) Math.sqrt((i-radius)*(i-radius)+(j-radius)*(j-radius));
if(d<radius)
pixels[i+j*WIDTH]=346346;
}
}

Categories

Resources