My Mandelbrot set doesn't generate. What's wrong with my equation? - java

//Generator class
public class Generator {
double jump;
double sizeModifier;
int iterationRate,range;
ComplexNumber c;
public Generator(double jump) {
this.jump=jump;
this.sizeModifier=40;
this.iterationRate=10;
this.range=100;
c=new ComplexNumber();
}
public void generateSet(){
DrawSet ds = new DrawSet();
int ticker=0;
for(double i=-2*range;i<=range;i+=jump){
for(double j=-2*range;j<=range;j+=jump){
c= new ComplexNumber((i/range),(j/range));
double fz=c.square().mod()+c.mod();
//System.out.println("c mod is: "+c.mod());
//System.out.println("fz is: "+fz);
if (fz < 2) {
for(int k=0;k<=iterationRate;k++) {
//System.out.println("nc:"+nc);
ticker++;
//System.out.println("ticker:"+ticker);
if(ticker==iterationRate) {
ds.addPoint(i + 450, j + 450);
}
if(fz>=2){
break;
}
else {
fz = Math.pow(fz, 2) + 1;
}
}
}
ticker=0;
}
}
}
//Drawset class
public class DrawSet extends JPanel {
private ArrayList<Point> Points;
private ArrayList<Point> nPoints;
GraphicWindow gw;
public DrawSet(){
this.Points=new ArrayList<>();
this.nPoints=new ArrayList<>();
gw = new GraphicWindow(1000,1000);
gw.add(this);
}
public void addPoint(double x,double y){
int ix=(int)x;
int iy=(int)y;
//int iwidth=(int)width*sizeModifier;
//int iheight=(int)height*sizeModifier;
Point a=new Point(ix,iy);
Points.add(a);
//System.out.println(Points.size());
}
public void paintComponent(Graphics g) {
int pointSize = 1;
super.paintComponents(g);
System.out.println(Points.size());
for (int i = 0; i < Points.size(); i++) {
g.setColor(Color.BLACK);
g.drawOval((int) Points.get(i).getX(), (int) Points.get(i).getY(), pointSize, pointSize);
}
}
The basic problem is that fz is never <2 after just 10 iterations, so no points are drawn. Why is this? What equation should I be implementing?
I am using a complex number to generate the value. The class which I use can be seen here:
https://github.com/abdulfatir/jcomplexnumber/
(or on the stack overflow forum Does Java have a class for complex numbers? by Mr Abdul Fatir)

Okay, observationally
Generator should not be creating a new instance of DrawSet
DrawSet should not be creating a new instance of GraphicWindow
These are the responsibilities of these classes or methods. This is highly coupling your code and generating side effects.
Instead, generate should pass back the points it creates and these should then be applied in what ever way you want, Generator shouldn't care.
Because I don't have access to your full code, I've just hacked together a random series of points instead to illustrate the point.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DrawSet drawSet = new DrawSet();
Generator generator = new Generator(100);
drawSet.setPoints(generator.generateSet());
JFrame frame = new JFrame();
frame.add(drawSet);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawSet extends JPanel {
private ArrayList<Point> points;
private ArrayList<Point> nPoints;
public DrawSet() {
this.points = new ArrayList<>();
this.nPoints = new ArrayList<>();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public void setPoints(ArrayList<Point> points) {
this.points = points;
repaint();
}
// public void addPoint(double x, double y) {
// int ix = (int) x;
// int iy = (int) y;
// //int iwidth=(int)width*sizeModifier;
// //int iheight=(int)height*sizeModifier;
// Point a = new Point(ix, iy);
// Points.add(a);
// //System.out.println(Points.size());
// }
#Override
protected void paintComponent(Graphics g) {
int pointSize = 5;
super.paintComponents(g);
for (int i = 0; i < points.size(); i++) {
g.setColor(Color.BLACK);
g.drawOval((int) points.get(i).getX(), (int) points.get(i).getY(), pointSize, pointSize);
}
}
}
public class Generator {
double jump;
double sizeModifier;
int iterationRate, range;
//ComplexNumber c;
public Generator(double jump) {
this.jump = jump;
this.sizeModifier = 40;
this.iterationRate = 10;
this.range = 100;
//c = new ComplexNumber();
}
public ArrayList<Point> generateSet() {
Random rnd = new Random();
ArrayList<Point> points = new ArrayList<>(range);
for (int index = 0; index < range; index++) {
int x = (int)(490 * rnd.nextDouble());
int y = (int)(490 * rnd.nextDouble());
points.add(new Point(x, y));
}
return points;
// DrawSet ds = new DrawSet();
// int ticker = 0;
// for (double i = -2 * range; i <= range; i += jump) {
// for (double j = -2 * range; j <= range; j += jump) {
// c = new ComplexNumber((i / range), (j / range));
// double fz = c.square().mod() + c.mod();
// //System.out.println("c mod is: "+c.mod());
// //System.out.println("fz is: "+fz);
// if (fz < 2) {
// for (int k = 0; k <= iterationRate; k++) {
// //System.out.println("nc:"+nc);
// ticker++;
// //System.out.println("ticker:"+ticker);
// if (ticker == iterationRate) {
// ds.addPoint(i + 450, j + 450);
//
// }
// if (fz >= 2) {
// break;
// } else {
// fz = Math.pow(fz, 2) + 1;
// }
// }
// }
// ticker = 0;
// }
// }
}
}
}
I've also made the pointSize bigger, so you can actually see the results, although I'd consider filling the points.
If the Generator is takes a long time to perform its calculations, you might consider using a SwingWorker to perform the operation. This will allow to offload the operation to seperate thread and not block the main UI thread. You can then use the SwingWorker to either feed back each individual point as it's calculated or all the points when the whole generation is done, back to the main UI thread in a safe manner.
See Worker Threads and SwingWorker for more details
Why is this?
Swing is lazy. It won't make repaints or updates to the UI unless it thinks it needs to. So, if you change some state the UI is depending on, you need to nudge Swing to encourage it to make a new paint pass. In the simplest terms, this means calling repaint on the component which is has changed

Related

How to update the position of snakes and ladders in an 2D array code?

public class ChutesAndLadders2d {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] numbersOnBoard = new int [6][6];
boardSetUpA (numbersOnBoard);
printTwoD(numbersOnBoard);
}
public static void boardSetUpA (int[][]twoD) {
//Square with even size
//even rows
for (int row = 0;row<twoD.length; row ++) {
if (row %2 ==0) {
int num = twoD.length*(twoD.length-row);
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num--;
}
}//
else {
int num = twoD.length*(twoD.length-(row + 1))+ 1;
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num++;
}
}
}//for row
}//
public static void printTwoD(int [][] array){
for (int row = 0; row < array.length; row++){
for (int column = 0; column < array[row].length; column++){
System.out.print(array[row][column] + "\t");
}
System.out.println();
}
}
public static void boardDetails(String[][]board) {
for (int row = 0;row<board.length; row++){
for (int col = 0;col<board[row].length; col++){
if( col+2 == row||col+1 == row*2 ){
board[row][col] = "Lad"; // Append value
}
else if (col*2 == row|| row*2 == col){
board[row][col] = "Cht";// Append value
}
else {
board[row][col] = " ";
}
}
board[board.length-1][0] = "Start";
if (board.length%2 ==0) {
board[0][0] = "End";}
else {
board[0][board.length-1]="End";
}
}
}
public static void printBoard (int[][]twoD, String[][]strTwoD) {
//Printing
for (int row = 0;row<twoD.length;row++) {
for (int col = 0;col<twoD[row].length;col++) {
System.out.print(twoD[row][col] + " "+strTwoD[row][col]+"\t\t");
}
System.out.println("\n");
}
}
}
This is the starter code I have for setting up the snakes and ladders game. I also tried to set the chutes/snakes and ladders on the board but it is not printing. How should I fix it and how do I develop this code to have three methods: update the moves of a player once he reaches a snake, a ladder, and once he rolls his die, from one place to another?
Is it possible to implement a Shutes & Ladders game using a 2D Array? For sure! Does that make sense in an object-oriented language such as Java? I dont know ....
What do you need for that?
A square board with e.g. 36 playing fields.
Connections between two playing fields. (shutes and ladders)
Pawns and a dice.
A renderer that outputs the playing field (as text or graphics).
A program that allows input and connects everything to a functioning game.
Here is an example that works with a List instead of an Array. That can certainly be changed if it is necessary for your purposes.
I hope this is of some help to you.
P.S .: After the start, the board is displayed with field numbers. Shutes are shown as red lines. Ladders as green lines. Keys 1-6 on the keyboard simulate rolling the dice..
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
public class ChutesAndLadders2d {
public static void main(String[] args) {
JFrame frame = new JFrame("Chutes and Ladders 2D");
Game game = new ChutesAndLadders2d().new Game();
game.setPreferredSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class Game extends JPanel{
private final Font defaultFont = new Font("Arial", Font.PLAIN, 16);
private final BasicStroke stroke = new BasicStroke(4f);
private static final int SCALE = 64;
// board and pawns
private final Board board = new Board(6);
private final List<Pawn> pawns = new ArrayList<>();
public Game(){
setFocusable(true); // receive Keyboard-Events
addKeyListener(new KeyAdapter(){
#Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if(c >= '1' && c <= '6'){
int steps = Integer.parseInt(Character.toString(c));
Pawn pawn = pawns.get(0);
pawn.move(steps);
Field field = board.get(pawn.fieldIndex);
if(field.targetKind() != Kind.NONE){
pawn.move(field.getTarget().index - field.index);
}
repaint();
}
}
});
board.connect(5, 12); // Ladder 5 -> 12
board.connect(8, 4); // Shute 8 -> 4
board.connect(15, 32); // Ladder 15 -> 32
board.connect(35, 17); // Shute 35 -> 17
board.connect(23, 30); // Ladder 23 -> 30
pawns.add(new Pawn(Color.BLUE, board.size() - 1));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
setFont(defaultFont);
for(Field field : board){
Point p = field.getLocation();
g2d.drawRect(p.x * SCALE, p.y * SCALE, SCALE, SCALE);
g2d.drawString(field.text, p.x * SCALE + 24, p.y * SCALE + 40);
}
for(Field field : board){
if(field.targetKind() != Kind.NONE){
g2d.setColor(field.targetKind() == Kind.LADDER ? Color.GREEN : Color.RED);
g2d.setStroke(stroke);
Point source = field.getLocation();
Point target = field.getTarget().getLocation();
g2d.drawLine(source.x * SCALE + 40, source.y * SCALE + 24, target.x * SCALE + 40, target.y * SCALE + 24);
}
}
for(Pawn pawn : pawns){
Point loc = board.get(pawn.fieldIndex).getLocation();
g2d.setColor(pawn.color);
g2d.fillOval(loc.x * SCALE + 32, loc.y * SCALE + 32, 16, 16);
}
}
}
class Board implements Iterable<Field>{
private final List<Field> fields = new ArrayList<>();
public Board(int size){
for(int index = 0; index < size * size; index++)
fields.add(new Field(index, size));
}
public Field get(int index){
return fields.get(index);
}
public void connect(int startFieldnumber, int targetFieldnumber){
get(startFieldnumber - 1).setTarget(get(targetFieldnumber - 1));
}
#Override
public Iterator<Field> iterator() {
return fields.iterator();
}
public int size(){
return fields.size();
}
}
class Field{
final int index;
final String text;
final int size;
private Field target;
public Field(int index, int size){
this.index = index;
this.size = size;
text = "" + (index + 1);
}
public void setTarget(Field target){
if(target == this) return;
this.target = target;
}
public Field getTarget(){
return target;
}
public Kind targetKind(){
if(target == null) return Kind.NONE;
return index < target.index ? Kind.LADDER : Kind.SHUTE;
}
public Point getLocation(){
int x = index % size;
int y = index / size;
if(y % 2 != 0) x = size - x - 1;
return new Point(x, size - y - 1);
}
}
class Pawn{
int fieldIndex = 0;
int maxIndex;
Color color;
public Pawn(Color color, int maxIndex){
this.color = color;
this.maxIndex = maxIndex;
}
public void move(int steps){
fieldIndex += steps;
if(fieldIndex < 0) fieldIndex = 0;
if(fieldIndex > maxIndex) fieldIndex = maxIndex;
}
}
enum Kind{
NONE, SHUTE, LADDER
}
}

Simple FPS counter

I'm making a CUI game in java and want to make an FPS counter in the game. Can anyone give me the code for a simple FPS counter which updates constantly?
I have tried
package Main;
public class Main {
public static void main(String[] args) {
double old_time = System.nanoTime();
System.out.println("FPS: " + get_fps(old_time));
}
private double get_fps(double old_time) {
double new_time = System.nanoTime();
double delta = - old_time;
double fps = 1 / (delta * 1000);
old_time = new_time;
return fps;
}
}
NOTE: The output should be like
FPS: FPS
Just in case you really are starting out, I thought I'd share a really basic example of an FPS counter in a loop. I'm not sure what a 'CUI' game is, but this illustrates a basic render/update loop. Why a snow-storm? It's cold here today.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class FpsDemo extends JFrame implements Runnable {
// statics
private final static int SCREENHEIGHT = 800;
private final static int SCREENWIDTH = 1200;
private final static int NOF_SNOWFLAKES = 1000;
private final static int NOF_SPEEDS = 5;
private final static int BACKGROUND = colour(0xB, 0x16, 0x2C);
private final static int WHITE = colour(0xFF, 0xFF, 0xFF);
// for each snowflake [i], [i][0] = x coord, [i][1] = y coord and [i][2] = speed
private final static int snow[][] = new int[NOF_SNOWFLAKES][3];
// for each column, a height
private final static int pile[] = new int[SCREENWIDTH];
/* Code entry point */
public static void main(String[] args) {
new FpsDemo().run();
}
/* Instantiates an instance of this class */
public FpsDemo() {
super("My FPS Demo");
setSize(SCREENWIDTH, SCREENHEIGHT);
setVisible(true);
}
/* Contains the main loop */
#Override
public void run() {
// setup an off-screen buffer to draw to
BufferedImage screen = new BufferedImage(SCREENWIDTH, SCREENHEIGHT, BufferedImage.TYPE_INT_RGB);
int[] screenData = ((DataBufferInt) screen.getRaster().getDataBuffer()).getData();
Graphics gs = getGraphics();
gs.setColor(Color.white);
// prepare some colours
int[] shades = new int[NOF_SPEEDS+1];
for(int i=0; i<NOF_SPEEDS; i++) {
int j = 50 + i * ((255-50)/NOF_SPEEDS);
shades[NOF_SPEEDS-i] = colour(j, j, j);
}
// arrange our initial data
Random random = new Random();
Arrays.fill(pile, SCREENHEIGHT);
for(int i=0; i<NOF_SNOWFLAKES; i++) {
snow[i][0] = random.nextInt(SCREENWIDTH);
snow[i][1] = random.nextInt(SCREENHEIGHT);
snow[i][2] = random.nextInt(4) + 1;
}
// loop forever (well, until an ArrayOutOfBoundsException...)
double fps = 0;
int frameCount = 0;
long startTime = System.nanoTime();
int throttle = NOF_SPEEDS;
while(true) {
Arrays.fill(screenData, BACKGROUND);
// For each pile
for(int x=0; x<SCREENWIDTH; x++) {
for(int y=pile[x], j=x+pile[x]*SCREENWIDTH; y<SCREENHEIGHT; y++, j+=SCREENWIDTH) {
screenData[j] = WHITE;
}
}
// For each snow flake
for(int i=0; i<NOF_SNOWFLAKES; i++) {
// Render the snow flake to the off-screen buffer
int j = snow[i][0]+(snow[i][1]*SCREENWIDTH);
screenData[j] = shades[snow[i][2]];
// Update for next render
if(snow[i][2] < throttle) {
// check the next row down
if(snow[i][1]+1 < pile[ snow[i][0] ] && snow[i][1] < SCREENHEIGHT) {
snow[i][1]++;
// slide left
} else if(snow[i][0]>1 && snow[i][1]+1 < pile[ snow[i][0]-1 ] && snow[i][1] < SCREENHEIGHT) {
snow[i][1]++;
snow[i][0]--;
// slide right
} else if(snow[i][0]<SCREENWIDTH-1 && snow[i][1]+1 < pile[ snow[i][0]+1 ] && snow[i][1] < SCREENHEIGHT) {
snow[i][1]++;
snow[i][0]++;
// we hit the pile
} else {
pile[snow[i][0]]--;
snow[i][1] = random.nextInt(SCREENWIDTH);
snow[i][1] = 0;
snow[i][2] = random.nextInt(4) + 1;
}
}
}
// Flip the image buffer across in one go.
if (gs!=null) {
gs.drawImage(screen, 0, 0, null);
}
// Select less snow flakes each loop so we get a parallax effect
throttle--;
if(throttle == 0) {
throttle = NOF_SPEEDS;
}
// Update FPS
frameCount++;
long now = System.nanoTime();
// has it been more than 1 second (1bn nanos)?
long wallclock = now - startTime;
if(wallclock > 1000000000) {
fps = frameCount / (wallclock/1000000000);
startTime = now;
frameCount = 0;
this.setTitle("FPS: " + fps);
}
// You could try calculating a delay to achieve a specific FPS
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/* Convenience method to convert RGB values (in the range 0-255) into a single integer */
private static int colour(int r, int g, int b) {
return (r*65536) + (g*256) + b;
}
}

Using an ArrayList in Another Class to scan through objects

I'm trying to scan though an AraayList created in the main class, in the turtle class to check various criteria. I simplified the code as much as possible for you.
The main class:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.awt.event.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
class TurtleProgram
{
public ArrayList<DynamicTurtle> turtles;
public static void main(String[] args)
{
new TurtleProgram();
}
public TurtleProgram()
{
//INSTANTIATED JFRAME WITH BUTTONS/SLIDER AND CREATED LISTENER METHODS
turtles = new ArrayList<DynamicTurtle>(); //THE ARRAYLIST I AM WANTING TO USE IN ANOTHER CLASS
turtles.add(new RandomTurtleB(canvas, 400, 300, 100, 0)); //THIS ARRAYLIST BECOMES LARGER WHEN BUTTONS ON JFRAME TO ADD NEW TURTLES
gameLoop(); //LOOP FOREVER
}
private void gameLoop()
{
int deltaTime = 20;
while(true)
{
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).unDrawTurtle(); //REMOVE FROM CANVAS
(turtles.get(i)).wrapPosition((turtles.get(i)).getPositionX(), (turtles.get(i)).getPositionY()); //MAKE SURE TURTLES NOT OFF SCREEN
}
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).update(1000); //MAKE THE TURTLES MOVE WITH A CHANCE OF TURNING
}
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).drawTurtle(); //DRAW TO CANVAS
}
for(int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).cohesian(); //THIS IS HOW I WOULD LIKE TO ADDRESS THE COHESIAN METHOD
}
Utils.pause(deltaTime/2);
}
}
}
Then I would like to check the current turtle against other turtles to see if it's close in the cohesion() method to perform actions:
class Turtle
{
protected Canvas canvas; // private field reference to a canvas private
private CartesianCoordinate myLocation, oldLocation;
private boolean penDown = true;
private double angle, maxX, maxY, nowPosX, nowPosY, maximumX, maximumY, x, y;
public double d, e, first, second;
private int speed;
public Turtle(Canvas canvas, CartesianCoordinate initLocation)
{
this.canvas = canvas;
this.myLocation = new CartesianCoordinate(0,0);
penDown = true;
myLocation = initLocation.copy();
}
public void cohesian()
{
double flockingDistanceLimit = 200;
double numberOfFlockers = 0;
double combinedX = 0;
double combinedY = 0;
double averageCombinedX, averageCombinedY, averageCombinedY, moveToFlock, turnToFlock, distanceToPotentialFlock;
for (DynamicTurtle t : turtles) //CANNOT USE THE ARRAYLIST TO SCAN THROUGH ITS ELEMENTS
{
if(this.getPositionX() != t.getPositionX() && this.getPositionY() != t.getPositionY()) //MAKE SURE TURTLE ISNT SCANNING ITS SELF
{
distanceToPotentialFlock = Math.sqrt(Math.pow((this.getPositionX()-t.getPositionX()),2 ) + Math.pow((this.getPositionY()-this.getPositionY()),2)); //FIND DISTANCE BETWEEN CURRENT AND SCANNED TURTLE
if(distanceToPotentialFlock < flockingDistanceLimit) //MAKE SURE THE FOUND TURTLE IS WITHIN RANGE USING THE DISTANCE BETWEEN POINTS METHOD
{
combinedX = combinedX + t.getPositionX(); //FIND SUMMATION OF X POSITIONS
combinedY = combinedY + t.getPositionY(); //FIND SUMMATION OF Y POSITIONS
numberOfFlockers++; //AS A FLOCKER HAS BEEN FOUND INCREMENT THE NUMBER OF FLOCKERS
}
}
if(numberOfFlockers > 0)
{
averageCombinedX = (combinedX / numberOfFlockers); //FIND AVERAGE X POSITION
averageCombinedY = (combinedY / numberOfFlockers); //FIND AVERAGE Y POSITION
moveToFlock = Math.sqrt(Math.pow(averageCombinedX,2 ) + Math.pow(averageCombinedY, 2)); //CALCULATE DISTANCE TO CENTER OF FLOCKING
turnToFlock = Math.atan(averageCombinedY / averageCombinedX);
if(turnToFlock < 0)
{
turnToFlock = 360 - (-turnToFlock); //ADJUSTING FOR NEGATIVES
}
}
}
}
public void wrapPosition(double x, double y)
{
this.maxX = x;
this.maxY = y;
if(maxX < 0)
{
this.setPositionX(800);
}
else if(maxX > 800)
{
this.setPositionX(0);
}
if(maxY < 0)
{
this.setPositionY(600);
}
else if(maxY > 600)
{
this.setPositionY(0);
}
}
}
If I could have any help with using the ArrayList in the Turtle Class, in the cohesian() method, it would be greatly appreciated. Thank you in advance.
Either pass the arrayList as parameter to cohesian, or declare it as a static field

Parabolas within bounds

I have a JPanel 200x200.
I trying to create a function that will generate random parabola's with the bounds of the JPanel, with a constraint that the height can't be lower than a 100 (middle of the screen), I basically want to move a shape around these parabolas
Here is some code I'm using to get started:
Random random = new Random(); int y; int x;
int size = random.nextInt(10);
int translation = random.nextInt(50);
int height = random.nextInt(100) - 200; //between 100 and 200
//Parabola functions : y = ((x/7 - 30))^2
// x and y are coordiates of where the shape is drawn
while(y != 200){
y = (float)Math.pow((float)xloc / size - translation ,2) + height;
x++;
}
I've been researching about FlatteningPathIterator but not too sure how to use them. my function
y = (float)Math.pow((float)xloc / size - translation ,2) + height;`
prints parabola's sometimes outside the bounds, how would i edit it to print parabola's inside the bounds?
There is a Java Swing shape generator for this called Quad2dCurve. The getPathIterator call gives you an enumerator for points on the curve.
Here is some example code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Random;
import javax.swing.*;
final class TestCanvas extends JComponent {
int size = 200;
int n = 10;
float[] ph = new float[n];
float[] pw = new float[n];
float[] px = new float[n];
Random gen = new Random();
TestCanvas() {
makeRandomParabolas();
setFocusable(true);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
makeRandomParabolas();
repaint();
float [] coords = new float [6];
for (int i = 0; i < n; i++) {
PathIterator pi = getQuadCurve(i).getPathIterator(null, 0.1);
System.out.print(i + ":");
while (!pi.isDone()) {
switch (pi.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
System.out.print(" move to");
break;
case PathIterator.SEG_LINETO:
System.out.print(" line to");
break;
default:
System.out.print(" unexpected");
break;
}
System.out.println(" (" + coords[0] + "," + coords[1]+")");
pi.next();
}
System.out.println();
}
}
});
}
QuadCurve2D.Float getQuadCurve(int i) {
return new QuadCurve2D.Float(px[i] - pw[i], size,
px[i], size - (2 * ph[i]),
px[i] + pw[i], size);
}
void makeRandomParabolas() {
for (int i = 0; i < n; i++) {
float x = 0.2f + 0.6f * gen.nextFloat();
px[i] = size * x;
pw[i] = size * (Math.min(x, 1 - x) * gen.nextFloat());
ph[i] = size * (0.5f + 0.5f * gen.nextFloat());
}
}
#Override
protected void paintComponent(Graphics g0) {
Graphics2D g = (Graphics2D) g0;
for (int i = 0; i < n; i++) {
g.draw(getQuadCurve(i));
}
}
}
public class Main extends JFrame {
public Main() {
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new TestCanvas());
getContentPane().setPreferredSize(new Dimension(200, 200));
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Main().setVisible(true);
}
});
}
}

Extending a JFrame (empty window error)

I'm doing a project that does the following in a nutshell:
reads integers from a file
stores them in an array
creates a bargraph of the numbers with an average line
the numbers above average go up, the numbers below go down (both are also different colors)
It compiles correctly, the JFrame window pops up, but no data is printed out. It's just an empty window.
Here is my code:
package basicgraphicstester;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class BasicGraphicsTester extends JFrame {
private Image fImageBuffer;
private Insets fInsets;
private Graphics g;
private static final int WIDTH = 800, HEIGHT = 600;
private static final Color OVER_AVERAGE = Color.blue,
UNDER_AVERAGE = Color.red;
int[] data;
public BasicGraphicsTester() throws FileNotFoundException
{ ReadInputData();
addWindowListener(new WindowCloser());
setVisible(true);
fInsets = getInsets();
setSize(WIDTH + fInsets.left + fInsets.right, HEIGHT + fInsets.top +fInsets.bottom);
setTitle("Bar Graph");
setResizable(false);
if (((fImageBuffer = createImage(WIDTH, HEIGHT)) != null) &&
((g = fImageBuffer.getGraphics()) != null)) Run();
else System.exit(1);
}
class WindowCloser extends WindowAdapter
{ public void WindowClosing(WindowEvent e )
{ System.exit(0); }
}
private void Run()
{ DrawAverageLine();
DrawBars();
}
private void DrawBars()
{
double arrayAverage = arrayAverage(data);
int average = averageLine(data);
int max = getMaxValue(data);
int min = getMinValue(data);
int barWidth = 57;
double barHeight;
for (int i = 0; i < data.length; i++) {
barHeight = (600 * (max - data[i]))/(max - min);
if (data[i] > average) {
g.setColor(OVER_AVERAGE);
g.fillRect((int)barWidth * i, (int)barHeight, (int)barWidth,
(average - (int)barHeight));
}
else if (barHeight == average) {
g.setColor(Color.green);
g.fillRect((int)barWidth * i, average, (int)barWidth, 0);
}
else {
g.setColor(UNDER_AVERAGE);
g.fillRect((int)barWidth * i, average, (int)barWidth,
((int)barHeight - average));
repaint();
}
} //for loop
} //DrawBar
private void DrawAverageLine()
{
int average = averageLine(data);
g.drawLine(0, average, 800, average);
}
public static int getMaxValue(int[] data) {
int maxValue = data[0];
for (int i=1;i < data.length;i++) {
if (data[i] > maxValue)
maxValue = data[i];
}
return maxValue;
}
public static int getMinValue(int[] data) {
int minValue = data[0];
for (int i = 1; i < data.length; i++) {
if (data[i] < minValue)
minValue = data[i];
}
return minValue;
}
public static double arrayAverage(int[] data) {
double result = 0.0;
for (int i = 0; i < data.length; i++) {
result = result + data[i];
}
result = result/data.length;
return result;
}
public static int averageLine (int[] data) {
int max = getMaxValue(data);
int min = getMinValue(data);
return (HEIGHT * max - (int)arrayAverage(data)) / (max - min);
}
public void paint( Graphics g)
{ if (fImageBuffer != null )
g.drawImage(fImageBuffer, fInsets.left, fInsets.top, null);
}
public void ReadInputData() throws FileNotFoundException {
try {Scanner readFile = new Scanner(new File("BarChart.data"));
data = new int [13];
for (int i = 0; i < data.length; i++)
data[i] = readFile.nextInt();
} //try
catch (FileNotFoundException e) {
System.out.println(e);
}
} // ReadInputData
public static void main(String[] args) throws FileNotFoundException {
new BasicGraphicsTester();
}
}
Please help. Thanks in advance.
A JFrame is an empty frame. You need to put a JPanel inside your frame, and override the latter's paintComponent() method in order to render your data on screen.
This is not how you do graphics or drawing with Swing, and I'd be interested to see what tutorial you've read recommends you to get the Graphics object as you're doing. Instead you should draw in the paintComponent(...) method of a class that extends JComponent such as a JPanel, using the Graphics instance provided as a parameter by the JVM, and then add this component to your JFrame. You will want to read the painting in Swing tutorial which is part of the standard Swing tutorials.
If you want to draw right into the JFrame you still have to override ContentPane's paint, not JFrame's paint method AFAIK.
And yes, a better way would be to implement your own component (for example by extending JPanel) and place it inside the JFrame (remember it has to be placed in ContentPane).
Check JFrame javadocs about ContentPane.
I recently wrote something similar in JavaFX using the BarGraph component. I'll post the source code if it would be helpful, but maybe you need to use swing and the point of your project is to make your own bar graph.
View my javafx bar graph

Categories