Nesting parabolic curves from straight lines - java

I am having trouble replicating the picture for my assignment. I would appreciate any tips or solutions. I believe I have the general idea down, but I am having a hard time figuring out the math to replicate the image and doing everything in a single loop.
My program needs to meet these criteria:
Match the Image
Generate a random color for each pair of parabolic curve
Work with any width or height
Use a single loop to draw the entire figure.
Here is the image:
This is what I have tried so far
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
public static final int LINE_INCREMENT = 5;
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(WIDTH, HEIGHT);
Graphics g = panel.getGraphics();
int d = 0;
int iterations = HEIGHT/LINE_INCREMENT;
Random rand = new Random();
int red = 0, green = 0, blue = 0;
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
for(int y = 0; y < iterations; y++) {
g.drawLine(0, d, d, HEIGHT);
g.drawLine(WIDTH, d, d, 0);
d += LINE_INCREMENT;
}
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
d = 0;
for (int x = 0; x < iterations/2; x++) {
g.drawLine(WIDTH/4, d + HEIGHT/4, d + WIDTH/4, HEIGHT - HEIGHT/4);
g.drawLine(d + WIDTH/4, WIDTH/4, WIDTH - WIDTH/4, d + WIDTH/4);
d += LINE_INCREMENT;
}
}
The output:

The way to implement it is by overriding paintComponent:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ParabolicCurves extends JFrame {
private static final int SIZE = 600;
private static final int LINE_INCREMENT = 5;
private static final int NUM_OF_PATTERNS = 4;
private Random rand = new Random();
ParabolicCurves() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel panel = new DrawingPanel(SIZE);
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
}
class DrawingPanel extends JPanel{
public DrawingPanel(int size) {
setPreferredSize(new Dimension(size, size));
setBackground(Color.WHITE);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int red, green, blue, delta , iterations;
int height, width ,startX, startY, endX, endY ;
Rectangle boundingRrectangle = getBounds();
for(int pattern = 0 ; pattern < NUM_OF_PATTERNS; pattern++) {
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
height = (int) boundingRrectangle.getHeight();
width = (int) boundingRrectangle.getWidth();
startX = (int) boundingRrectangle.getX();
startY = (int) boundingRrectangle.getY();
endX = startX+width;
endY = startY+ height;
iterations = Math.min(width, height)/LINE_INCREMENT;
delta = 0;
for (int x = 0; x < iterations ; x++) {
g.drawLine(startX, startY+delta, startX+delta, endY);
g.drawLine(endX, startY+delta, startX+delta, startY);
delta += LINE_INCREMENT;
}
//change bounding rectangle
boundingRrectangle = new Rectangle(startX+(width/4),
startY+(width/4), width/2, height/2);
}
}
}
public static void main(String[] args) {
new ParabolicCurves();
}
}
Output:

Related

Java - Hexagon location in grid

Im searching for an algorythem to get the location of a hexagon in a grid.
I found this one but it doesnt seam to work:
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
}
}
The output is kind of strange:
output
This is the window-creating class(just a test class):
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Grid extends JPanel {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
int width = 2;
int height = 4;
int x = 100;
int y = 100;
Hexagon[][] grid = new Hexagon[width][height];
JFrame f = new JFrame();
Container cp = f.getContentPane();
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
cp.add(grid[i][j]);
}
}
f.setLayout(null);
f.setBounds(100, 100, 300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
The Hexagon.java class:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.swing.JButton;
public class Hexagon extends JButton {
public static final int S = 50;
public static final int A = (int) (Math.sqrt(3)*(S/2));
private static final long serialVersionUID = 1L;
private final int x, y;
private final Polygon shape;
public Hexagon(int x, int y) {
this.x = x;
this.y = y;
this.shape = initHexagon();
setSize(2*S, 2*A);
setLocation(x-S, y-A);
setContentAreaFilled(false);
}
private Polygon initHexagon() {
Polygon p = new Polygon();
p.addPoint(x+(S/2), y-A);
p.addPoint(x+S, y);
p.addPoint(x+(S/2), y+A);
p.addPoint(x-(S/2), y+A);
p.addPoint(x-S, y);
p.addPoint(x-(S/2), y-A);
return p;
}
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.drawPolygon(this.shape);
}
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4));
g2.drawPolygon(this.shape);
}
public boolean contains(int x, int y) {
return this.shape.contains(x, y);
}
}
As i said, this class worked just fine using non-rectangular shapes.
There was no clipping or such.
You've posted your definition of Hexagon too late, so I copy-pasted a modified version of a similar class from my collection of code snippets.
Here is one way to generate a hexagonal grid:
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.function.*;
public class Hexagons extends JPanel {
private static final long serialVersionUID = 1L;
/** Height of an equilateral triangle with side length = 1 */
private static final double H = Math.sqrt(3) / 2;
static class Hexagon {
final int row;
final int col;
final double sideLength;
public Hexagon(int r, int c, double a) {
this.row = r;
this.col = c;
this.sideLength = a;
}
double getCenterX() {
return 2 * H * sideLength * (col + (row % 2) * 0.5);
}
double getCenterY() {
return 3 * sideLength / 2 * row;
}
void foreachVertex(BiConsumer<Double, Double> f) {
double cx = getCenterX();
double cy = getCenterY();
f.accept(cx + 0, cy + sideLength);
f.accept(cx - H * sideLength, cy + 0.5 * sideLength);
f.accept(cx - H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + 0, cy - sideLength);
f.accept(cx + H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + H * sideLength, cy + 0.5 * sideLength);
}
}
public static void main(String[] args) {
final int width = 50;
final int height = 50;
final Hexagon[][] grid = new Hexagon[height][width];
for(int row = 0; row < height; row++) {
for(int col = 0; col < width; col++) {
grid[row][col] = new Hexagon(row, col, 50);
}
}
JFrame f = new JFrame("Hexagons");
f.getContentPane().setLayout(new GridLayout());
f.getContentPane().add(new JComponent() {
#Override public void paint(Graphics g) {
g.setColor(new Color(0xFF, 0xFF, 0xFF));
g.fillRect(0,0,1000,1000);
g.setColor(new Color(0,0,0));
final int[] xs = new int[6];
final int[] ys = new int[6];
for (Hexagon[] row : grid) {
for (Hexagon h: row) {
final int[] i = {0};
h.foreachVertex((x, y) -> {
xs[i[0]] = (int)((double)x);
ys[i[0]] = (int)((double)y);
i[0]++;
});
g.drawPolygon(xs, ys, 6);
g.drawString(
"(" + h.row + "," + h.col + ")",
(int)(h.getCenterX() - 15),
(int)(h.getCenterY() + 12)
);
}
}
}
});
f.setBounds(0, 0, 500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
try {
Thread.sleep(100);
} catch (Throwable e) {
} finally {
f.repaint();
}
}
}
It produces the following output:
Sorry for the lack of anti-aliasing. A few hints:
Height H of an equilateral triangle with unit side length is sqrt(3) / 2
The six offsets from the center are (0, +1), (H, +1/2), (H, -1/2), (0, -1), (-H, -1/2), (-H, +1/2), everything times side length.
Distance between rows is 1.5, distance between columns is 2 * H (times scaling constant = side length).
Every odd row is shifted by (0, H) (times scaling constant).
The position of (row,col)-th hexagon is (1.5 * row, 2 * H * (col + 0.5 * (row % 2))) (times constant).
If you want to rotate the hexagons such that two of their sides are horizontal, you have to flip rows and columns.

How to create a colour gradient without Javafx/AWT?

so i have a little Problem and i try to solve it since hours.
I have a BufferedImage and i want to change the colour in a fluent way f.e. from red to white.
My main:
public static void main(String[] args) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x != width; x++) {
for (int y = 0; y != height; y++) {
image.setRGB(x, y, color12(x, y));
try {
,,,
My method to change the color:
static int color12(int x, int y) {
int size = 100;
if (Math.abs(width / 2 - x) < size / 2 && Math.abs(height / 2 - y) < size / 2)
return new Color(255, 0, 0).getRGB();
else
return new Color(200, 200, 255).getRGB();
}
}
So i played around with the method, but i cant get it done.
My best "solution" was this:
int r = 0 ;
int b = 0;
int g = 0;
for (int i = 1; i < 255; i++)
r++;
else return new Color(r,g,b).getRGB();
Can anyone help me?
I'm not sure how you want the gradient (e.g. horizontal, vertical or diagonal), but here's an example using linear interpolation for a horizontal or vertical gradient.
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class ExampleFrame extends JFrame {
private static enum GradientOrientation {
HORIZONTAL, VERTICAL
};
private static BufferedImage createGradientImg(int width, int height, Color startColor, Color endColor, GradientOrientation o) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int pos = o.equals(GradientOrientation.HORIZONTAL) ? x : y;
int size = o.equals(GradientOrientation.HORIZONTAL) ? width : height;
image.setRGB(x, y, getGradientRGB(startColor, endColor, pos, size));
}
}
return image;
}
private static int getGradientRGB(Color startColor, Color endColor, int pos, int size) {
double perc = (double) pos / size;
int newRed = (int) (endColor.getRed() * perc + startColor.getRed() * (1 - perc));
int newGreen = (int) (endColor.getGreen() * perc + startColor.getGreen() * (1 - perc));
int newBlue = (int) (endColor.getBlue() * perc + startColor.getBlue() * (1 - perc));
return new Color(newRed, newGreen, newBlue).getRGB();
}
public void createAndShow() {
BufferedImage img1 = createGradientImg(200, 100, Color.RED,
Color.WHITE, GradientOrientation.HORIZONTAL);
BufferedImage img2 = createGradientImg(200, 100, Color.BLUE,
Color.YELLOW, GradientOrientation.HORIZONTAL);
BufferedImage img3 = createGradientImg(200, 100, Color.WHITE,
Color.YELLOW, GradientOrientation.VERTICAL);
BufferedImage img4 = createGradientImg(200, 100, Color.BLACK,
Color.WHITE, GradientOrientation.VERTICAL);
BoxLayout layout = new BoxLayout(getContentPane(), BoxLayout.Y_AXIS);
getContentPane().setLayout(layout);
getContentPane().add(new JLabel(new ImageIcon(img1)));
getContentPane().add(new JLabel(new ImageIcon(img2)));
getContentPane().add(new JLabel(new ImageIcon(img3)));
getContentPane().add(new JLabel(new ImageIcon(img4)));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExampleFrame ef = new ExampleFrame();
ef.createAndShow();
}
});
}
}

Java: Draw a circular spiral using drawArc

I'm working on a java programming exercise where we have to draw a circular spiral using the drawArc method so that the result looks similar to this:
I've been working on this for a while and this is what I have so far:
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int x = 100;
int y = 120;
int width = 40;
int height = 60;
int startAngle = 20;
int arcAngle = 80;
for (int i = 0; i < 5; i++) {
g.drawArc(x, y, width, height, startAngle, arcAngle);
g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
x = x + 5;
y = y + 5;
startAngle = startAngle - 10;
arcAngle = arcAngle + 10;
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
My code gives me this result:
I know the problem lies in my arguments for the drawArc method because the numbers aren't right, but I don't know how to go about making the numbers go in a circular manner. Any help is appreciated. Thank you!
Your idea is almost right. I did some modifications. You need to inverse the angle to draw the other side of the spiral and use fixed point to startAngle.
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int x = getSize().width / 2 - 10;
int y = getSize().height/ 2 - 10;
int width = 20;
int height = 20;
int startAngle = 0;
int arcAngle = 180;
int depth = 10;
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
// g.drawArc(x + 10, y + 10, width, height, startAngle + 10, -arcAngle);
// x = x - 5;
y = y - depth;
width = width + 2 * depth;
height = height + 2 * depth;
g.drawArc(x, y, width, height, startAngle, -arcAngle);
} else {
// g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
x = x - 2 * depth;
y = y - depth;
width = width + 2 * depth;
height = height + 2 * depth;
g.drawArc(x, y, width, height, startAngle, arcAngle);
}
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
If this were my project, yes I'd draw my arcs in a loop, but within the loop, I'd try to make the arc's bounding box bigger but still centered over the same location. To do this I'd decrement x and y by some small constant, say DELTA (which I'd set to == 1), and I'd increment width and height by 2 * DELTA. I'd also leave my arcAngle unchanged but rather would change my startAngle in the loop like so: startAngle = startAngle - arcAngle;.
For example, this:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class CircSpiral extends JPanel {
private static final int DELTA = 1;
private static final int ARC_ANGLE = 20;
private static final int PREF_W = 300;
private static final int PREF_H = PREF_W;
private static final int LOOP_MAX = 400;
public void paintComponent(Graphics g) {
int x = PREF_W / 2;
int y = PREF_H / 2;
int width = 1;
int height = 1;
int startAngle = 0;
int arcAngle = ARC_ANGLE;
for (int i = 0; i < LOOP_MAX; i++) {
g.drawArc(x, y, width, height, startAngle, arcAngle);
x = x - DELTA;
y = y - DELTA;
width += 2 * DELTA;
height += 2 * DELTA;
startAngle = startAngle - arcAngle;
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.pack();
application.setLocationRelativeTo(null);
application.setVisible(true);
}
}
Would result in this:
The following code will output this image:
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int numIterations = 5;
int arcWidth = 10;
int arcGrowDelta = 30;
for (int i = 0; i < numIterations; i++) {
g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth, 2 * arcWidth, 0, 180);
arcWidth += arcGrowDelta;
g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth - arcGrowDelta, 2 * arcWidth, 180, 180);
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
The idea is very simple, just draw the upper half of a circle, like this:
Then increment the arc size by a constant factor and draw the bottom half of the circle but making the end point of this circle and the upper circle match, for it, just substrate the arcGrowDelta from the bottom circle width:
And repeat.
This is my solution:
package mainpack;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;
public class SpiralPanel extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
int width = 10;
int height = 10;
int startAngle = 0;
int arcAngle = 180;
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
int i = 0;
int t = 0;
while (i < 36) {
g2d.drawArc(x + t, y, width, height, startAngle, arcAngle);
if (i % 2 == 0) {
t -= 10;
}
y -= 5;
width += 10;
height += 10;
startAngle += 180;
i++;
}
}
}
I am a beginner to java and finally managed how to create the spiral.
Here is my code:
int lineLength = 20; //starting line length
int x = getWidth() / 2; //start drawing from center of JPanel
int y = getHeight() / 2; //start drawing from center of JPanel
for( int counter = 0; counter < 10; counter++ )
{
g.drawArc( x, y, lineLength, lineLength, 0, 180 ); //draws top semicircle of equal width and height
lineLength += 20; //increases arc diameter
x -= 20; //moves x coordinate left
g.drawArc( x, y - 10, lineLength, lineLength, 0, -180 ); //draws bottom semicircle; 'y - 10' joins the 2 semicircles
lineLength += 20; //increases arc diameter
y -= 20; //moves y coordinate up
}
If you're willing to let some good old trigonometry do the work, you could use this:
import java.awt. *;
import javax.swing. *;
import java.math.*;
public class Spiral extends JFrame {
public Spiral()
{
// Set Window
setTitle("Spirale");
setSize(1500, 1500);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g)
{
super.paint(g);
for(double i = 1; i < 50000; i++)
{
int locY = 600 - (int) (Math.cos((Math.PI*i)/1800)*i/50);
int locX = 600 - (int) (Math.sin((Math.PI*i)/1800)*i/50);
g.drawLine(locX, locY, locX, locY);
}
}
public static void main(String[] args) {
new Spiral();
}
}

Trying to draw lines with JPanel

I am trying to draw lines using JPanel and I have hit somewhat of a wall. I can get two sides down but once it comes to subtracting from the x cord it all goes wrong.
package GUIstuff;
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 drawCounter = 0; // counters for all the while statements
int drawCounter2 = 0;
int drawCounter3 = 0;
int drawCounter4 = 0;
int x1 = 0; // cords change with the while statemetns
int x2 = 0;
int y1 = 0;
int y2 = 0;
while (drawCounter <= 15){ // counter
y2 = 250;
g.drawLine(x1, y1, x2, y2);
x2 = x2 + 15;
y1 = y1 + 15;
drawCounter++; }
int u1 = 0;
int u2 = 0;
int v1 = 0;
int v2 = 0;
while (drawCounter2 <= 15){
u2 = 250;
g.drawLine(u1, v1, u2, v2);
u1 = u1 + 15;
v2 = v2 + 15;
drawCounter2++;
}
int a1 = 0;
int a2 = 0;
int b1 = 0;
int b2 = 0;
while (drawCounter3 <= 15){
a2 = 250;
g.drawLine(a1, b1, a2, b2);
b1 = b1 + 15;
a2 = a2 - 15;
drawCounter3++;
}
}
}
Here is my runner class
package GUIstuff;
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 (250, 250);
application.setVisible(true);
}
}
I have a the lines in the bottom left and the upper right but when I try to subtract from x I just get lines going a crossed the whole box.
When doing custom painting you should override the getPreferredSize() method so the panel can be displayed at its preferred size.
When you draw the lines two variable are the same and two variables differ. Use the width/height variable when appropriate instead of hardcoding a number. In the example below I did the left and bottom sides. The bottom side shows how to subtract. I'll let you figure out the pattern for the other two side.
Also, I made the panel a little more dynamic so it will be easy to configure the number of lines you want painted and the gap between the lines.
import java.awt.*;
import javax.swing.*;
public class DrawSSCCE extends JPanel
{
private int lines;
private int lineGap;
public DrawSSCCE(int lines, int lineGap)
{
this.lines = lines;
this.lineGap = lineGap;
}
#Override
public Dimension getPreferredSize()
{
int size = lines * lineGap;
return new Dimension(size, size);
}
#Override
public void paintComponent(Graphics g)
{
int width = getWidth();
int height = getHeight();
// Draw lines starting from left to bottom
int x = lineGap;
int y = 0;
for (int i = 0; i < lines; i++)
{
g.drawLine(0, y, x, height);
x += lineGap;
y += lineGap;
}
// Draw lines starting from bottom to right
x = 0;
y = height - lineGap;
for (int i = 0; i < lines; i++)
{
g.drawLine(x, height, width, y);
x += lineGap;
y -= lineGap;
}
// Draw lines starting from right to top
// Draw lines starting from top to left
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("DrawSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new DrawSSCCE(15, 15) );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
One way to draw this type of graphic would be to divide the drawing into quadrants. Here's a GUI I came up with.
This drawing is created by drawing lines all around the rectangle.
I created a JFrame and a drawing JPanel. I created the drawing JPanel by dividing the horizontal width and vertical height into the same number of increments. Since the width is greater than the height, the width increment is greater than the height increment.
I divided the drawing into quarters, and worked on the code for each quarter separately, using fewer and larger increments. Once I had all four quarters working, I quadrupled the number of increments and divided the width increment and the height increment by four.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawOvalRectangle implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawOvalRectangle());
}
#Override
public void run() {
JFrame frame = new JFrame("Curved Lines 2021");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawingPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private int width, height, margin, increments, xIncrement, yIncrement;
public DrawingPanel() {
this.margin = 10;
this.increments = 80;
this.xIncrement = 8;
this.yIncrement = 6;
this.width = increments * xIncrement;
this.height = increments * yIncrement;
this.setPreferredSize(new Dimension(
width + margin + margin, height + margin + margin));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
drawNorthwestQuadrant(g);
drawNortheastQuadrant(g);
drawSouthwestQuadrant(g);
drawSoutheastQuadrant(g);
}
private void drawNorthwestQuadrant(Graphics g) {
int x1 = margin;
int y1 = height + margin;
int x2 = margin;
int y2 = margin;
for (int index = 0; index < increments; index++) {
g.drawLine(x1, y1, x2, y2);
x2 += xIncrement;
y1 -= yIncrement;
}
}
private void drawNortheastQuadrant(Graphics g) {
int x1 = margin;
int y1 = margin;
int x2 = width + margin;
int y2 = margin;
for (int index = 0; index < increments; index++) {
g.drawLine(x1, y1, x2, y2);
x1 += xIncrement;
y2 += yIncrement;
}
}
private void drawSouthwestQuadrant(Graphics g) {
int x1 = margin;
int y1 = height + margin;
int x2 = margin;
int y2 = margin;
for (int index = 0; index < increments; index++) {
g.drawLine(x1, y1, x2, y2);
x1 += xIncrement;
y2 += yIncrement;
}
}
private void drawSoutheastQuadrant(Graphics g) {
int x1 = margin;
int y1 = height + margin;
int x2 = width + margin;
int y2 = height + margin;
for (int index = 0; index < increments; index++) {
g.drawLine(x1, y1, x2, y2);
x1 += xIncrement;
y2 -= yIncrement;
}
}
}
}

Random Color Change Each Iteration

While using an ArrayList, I can't seem to figure out how to reset and re-apply the random color for each iteration of the for loop. I am trying to reset and apply my random color every time my XLeft position is changed. This is only a section of one class I am using, and my getMax() was defined by a Scanner input. Any suggestions?
import java.util.ArrayList;
import java.util.Random;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class BarChart {
private int width, height;
private ArrayList<Double> values = new ArrayList<Double>();
private Random generator = new Random();
int red = generator.nextInt(255);
int green = generator.nextInt(255);
int blue = generator.nextInt(255);
private Color randomColor = new Color(red, green, blue);
public BarChart(int aWidth, int aHeight) {
width = aWidth;
height = aHeight;
}
public void add(double inputValues) {
values.add(inputValues);
}
public double getMax() {
double max = values.get(0);
for (int i = 1; i < values.size(); i++) {
if ((values.get(i)) > max)
max = values.get(i);
}
return max;
}
public void draw(Graphics2D g2) {
int xLeft = 0;
double barWidth = width / values.size();
for (int i = 0; i < values.size(); i++) {
double barHeight = (values.get(i) / getMax()) * height;
Rectangle bar = new Rectangle(xLeft, height - ((int) barHeight),
(int) barWidth, (int) barHeight);
g2.setColor(randomColor);
g2.fill(bar);
xLeft = (int) (xLeft + barWidth);
xLeft++;
}
}
}
It sounds like you're defining your random color once, before the loop. This means that when you run the loop, it uses the same "random color" each time through. You need to move the definition of the random color into the loop, so that it runs with each iteration.
EDIT (based on your comments):
public void draw(Graphics2D g2) {
int xLeft = 0;
double barWidth = width / values.size();
for (int i = 0; i < values.size(); i++) {
double barHeight = (values.get(i) / getMax()) * height;
Rectangle bar = new Rectangle(xLeft, height - ((int) barHeight),
(int) barWidth, (int) barHeight);
red = generator.nextInt(255);
green = generator.nextInt(255);
blue = generator.nextInt(255);
randomColor = new Color(red, green, blue);
g2.setColor(randomColor);
g2.fill(bar);
xLeft = (int) (xLeft + barWidth);
xLeft++;
}

Categories

Resources