I wrote a line drawing algorithm that functions correctly when calculating each point, however when it gets rendered the program skips nearly 20 points, unable to find the issue.
I have tried to mess with the algorithm, specifically the for loop that adds the points to the positions list where the line gets calculated as I have had problems with that in other versions of the code. I just cannot for the life of me find the issue with the code, I am pretty new to Java as you will probably tell from the mess of code below. It says not to post an entire file but I am unable to pinpoint where it is going wrong. I am so incredibly sorry for the mess of code below I just am at that point where I have no clue what is wrong.
package sample;
import com.sun.jdi.ArrayReference;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.ArrayList;
class PositionCounter {
public int position;
public void setPosition(int newPos){
position = newPos;
}
}
public class Main extends Application {
// public void drawRectangle(int x1, int y1, int x2, int y2, Stage primStage, GraphicsContext gc){
// drawLine(x1, y2, x2, y2 , primStage, gc);
// drawLine(x1, y1, x2, y2, primStage, gc);
// drawLine(x1, y1, x1 , y2, primStage, gc);
// drawLine(x2, y1, x2 , y2, primStage, gc);
// drawLine(x1, y1, x2, y1 , primStage, gc);
//
// }
//
public void fillPosition(ArrayList<Integer[]> points, GraphicsContext gc, int positionInArray ){
gc.fillRect(points.get(positionInArray)[0], points.get(positionInArray)[1], squareWidth / 2, squareWidth / 2);
//System.out.println("(" + points.get(positionInArray)[0] + ", " + points.get(positionInArray)[1]);
}
public void drawLine(int x1, int y1, int x2, int y2, Stage primStage, GraphicsContext gc){
ArrayList<Integer[]> points = calculateLine(x1, y1, x2, y2, gc);
PositionCounter position = new PositionCounter();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Runnable updater = new Runnable() {
#Override
public void run() {
fillPosition(points, gc, position.position);
}
};
int dy = Math.abs(y2 - y1);
int dx = Math.abs(x2 - x1);
int m = (dy >= dx) ? dy : dx;
for (int i = 0; i <= points.size(); i++) {
position.setPosition(i);
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
}
Platform.runLater(updater);
}
}
});
thread.setDaemon(true);
thread.start();
}
#Override
public void start(Stage primaryStage) throws Exception{
//STUFF
Group root = new Group();
Scene scene = new Scene(root, 400, 400);
scene.setFill(Color.GOLD);
Canvas canvas = new Canvas(400, 400);
GraphicsContext gc = canvas.getGraphicsContext2D();
root.getChildren().add(canvas);
//////////
gc.fillRect(0, 200, 400, 1);
gc.fillRect(0, 100, 400, 1);
gc.fillRect(0, 300, 400, 1);
gc.fillRect(200, 0, 1, 400);
gc.fillRect(100, 0, 1, 400);
gc.fillRect(300, 0, 1, 400);
// drawRectangle(50, 50, 350, 250, primaryStage, gc);
//drawLine(50, 250, 350, 250 , primaryStage, gc);
//drawLine(50, 50, 350, 250, primaryStage, gc);
//drawLine(50, 50, 50 , 250, primaryStage, gc);
//drawLine(350, 50, 350 , 250, primaryStage, gc);
drawLine(50, 50, 350, 50 , primaryStage, gc);
//////////
primaryStage.setScene(scene);
primaryStage.show();
/////////
}
int squareWidth = 2;
public ArrayList<Integer[]> calculateLine(int x1, int y1, int x2, int y2, GraphicsContext gc){
ArrayList<Integer[]> points = new ArrayList<Integer[]>();
int dy = Math.abs(y2 - y1);
int dx = Math.abs(x2 - x1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx-dy;
int x = x1;
int y = y1;
int e2 = 0;
Integer[] pos = new Integer[2];
pos[0] = x;
pos[1] = y;
points.add(pos);
int m = (dy >= dx) ? dy : dx ;
for (int i = 0; i <= m; i++) {
e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
x = x + sx;
Integer[] position = new Integer[2];
position[0] = x;
position[1] = y;
points.add(position);
}
if (e2 < dx) {
err = err + dx;
y = y + sy;
Integer[] position = new Integer[2];
position[0] = x;
position[1] = y;
points.add(position);
}
}
return points;
}
public static void main(String[] args) {
launch(args);
}
}
The problem is that the calculate line function returns the correct points, it just doesnt render them properly.
I would suggest you use Timeline instead of Thread. It can be done using a Thread, but Timeline is designed for cases like this.
Draw Line Method:
public void drawLine(int x1, int y1, int x2, int y2, Stage primStage, GraphicsContext gc)
{
ArrayList<Integer[]> points = calculateLine(x1, y1, x2, y2, gc);
PositionCounter position = new PositionCounter();
int dy = Math.abs(y2 - y1);
int dx = Math.abs(x2 - x1);
int m = (dy >= dx) ? dy : dx;
AtomicInteger counter = new AtomicInteger();
Timeline animationTimeline = new Timeline(new KeyFrame(Duration.millis(20), (ActionEvent t) -> {
position.setPosition(counter.getAndIncrement());
fillPosition(points, gc, position.position);
}));
animationTimeline.setCycleCount(points.size());
animationTimeline.play();
}
Full Code:
import com.sun.jdi.ArrayReference;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.util.Duration;
class PositionCounter
{
public int position;
public void setPosition(int newPos)
{
position = newPos;
}
}
public class JavaFXTestingGround extends Application
{
// public void drawRectangle(int x1, int y1, int x2, int y2, Stage primStage, GraphicsContext gc){
// drawLine(x1, y2, x2, y2 , primStage, gc);
// drawLine(x1, y1, x2, y2, primStage, gc);
// drawLine(x1, y1, x1 , y2, primStage, gc);
// drawLine(x2, y1, x2 , y2, primStage, gc);
// drawLine(x1, y1, x2, y1 , primStage, gc);
//
// }
//
public void fillPosition(ArrayList<Integer[]> points, GraphicsContext gc, int positionInArray)
{
gc.fillRect(points.get(positionInArray)[0], points.get(positionInArray)[1], squareWidth / 2, squareWidth / 2);
//System.out.println("(" + points.get(positionInArray)[0] + ", " + points.get(positionInArray)[1]);
}
public void drawLine(int x1, int y1, int x2, int y2, Stage primStage, GraphicsContext gc)
{
ArrayList<Integer[]> points = calculateLine(x1, y1, x2, y2, gc);
PositionCounter position = new PositionCounter();
int dy = Math.abs(y2 - y1);
int dx = Math.abs(x2 - x1);
int m = (dy >= dx) ? dy : dx;
AtomicInteger counter = new AtomicInteger();
Timeline animationTimeline = new Timeline(new KeyFrame(Duration.millis(20), (ActionEvent t) -> {
position.setPosition(counter.getAndIncrement());
fillPosition(points, gc, position.position);
}));
animationTimeline.setCycleCount(points.size());
animationTimeline.play();
}
#Override
public void start(Stage primaryStage) throws Exception
{
//STUFF
Group root = new Group();
Scene scene = new Scene(root, 400, 400);
scene.setFill(Color.GOLD);
Canvas canvas = new Canvas(400, 400);
GraphicsContext gc = canvas.getGraphicsContext2D();
root.getChildren().add(canvas);
//////////
gc.fillRect(0, 200, 400, 1);
gc.fillRect(0, 100, 400, 1);
gc.fillRect(0, 300, 400, 1);
gc.fillRect(200, 0, 1, 400);
gc.fillRect(100, 0, 1, 400);
gc.fillRect(300, 0, 1, 400);
// drawRectangle(50, 50, 350, 250, primaryStage, gc);
//drawLine(50, 250, 350, 250 , primaryStage, gc);
//drawLine(50, 50, 350, 250, primaryStage, gc);
//drawLine(50, 50, 50 , 250, primaryStage, gc);
//drawLine(350, 50, 350 , 250, primaryStage, gc);
drawLine(50, 50, 350, 50, primaryStage, gc);
//////////
primaryStage.setScene(scene);
primaryStage.show();
/////////
}
int squareWidth = 2;
public ArrayList<Integer[]> calculateLine(int x1, int y1, int x2, int y2, GraphicsContext gc)
{
ArrayList<Integer[]> points = new ArrayList<Integer[]>();
int dy = Math.abs(y2 - y1);
int dx = Math.abs(x2 - x1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
int x = x1;
int y = y1;
int e2 = 0;
Integer[] pos = new Integer[2];
pos[0] = x;
pos[1] = y;
points.add(pos);
int m = (dy >= dx) ? dy : dx;
for (int i = 0; i <= m; i++) {
e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
x = x + sx;
Integer[] position = new Integer[2];
position[0] = x;
position[1] = y;
points.add(position);
}
if (e2 < dx) {
err = err + dx;
y = y + sy;
Integer[] position = new Integer[2];
position[0] = x;
position[1] = y;
points.add(position);
}
}
return points;
}
public static void main(String[] args)
{
launch(args);
}
}
How can I find xpoints[] and ypoints[], if I want to draw a polygon with the mouse, using getX() and getY() ?
My code at the moment is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Poligonos extends Figura{
public void Poligonos (int[] xPoints, int[] yPoints, int nPoints){
//private int[] xPoints = {(x1/2), x1, (x1+(x1/2))} // {(getX()/2), getX(), (getX()+(getX()/2))};
//private int[] yPoints = {( y1 + y1 ), y1 ,( y1 + y1 )};
}
#Override
public void desenha(Graphics g) {
g.setColor(cor);
g.drawPolygon( xPoints, yPoints, 3);
}
#Override
public void setCoordenadas(int x1, int y1, int x2, int y2) {
p.x = Math.min(x1, x2);
p.y = Math.min(y1, y2);
int xPoints[] = {(p.x /2), p.x , ( p.x +( p.x /2))}; // {(getX()/2), getX(), (getX()+(getX()/2))};
int yPoints[] = {( p.y + p.y ), p.y ,( p.y + p.y )};
}
}
And getX() and getY() part is:
#Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
#Override
public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
r.setCoordenadas(x1, y1, x2, y2);
pEdicao.repaint();
}
How can I make this work? I just want draw a pentagon and a triangle with mouse.
Thanks for your time.
You could make a setup where you do something like
int numCoordinates = /*(get the number of coordinates by getting number of clicks after a certain action, etc.)*/
int[] xCords = new int[numCoordinates];
int[] yCords = new int[numCoordinates];
xCords[index] = e.getX();
yCords[index] = e.getY();
index++;
if(index > numCoordinates){
index = 0;
pEdicao.repaint();
}
I am trying to create a program which creates 9 biomorphs which are evolved somehow from a middle biomorph. Currently, I have 9 showing although these are completely random. What is the best way to store the values of the initial biomorph to be used in the other 8?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.JPanel;
public class BiomorphObject extends JPanel {
Graphics2D g2d;
Dimension size = getSize();
int w = size.width;
int h = size.height;
Random ran = new Random();
int x1;
int x2;
int y1;
int y2;
public BiomorphObject(Graphics g){
g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
Random ran = new Random();
int x = Math.abs(ran.nextInt(100)) % w + 120;
int y = Math.abs(ran.nextInt(100)) % h;
int xMirror = x - 120;
g2d.drawLine(120, 85, x, y);
g2d.drawLine(120, 85, 120 - xMirror, y);
x1 = x;
y1 = y;
x2 = Math.abs(ran.nextInt(50)) % w + 120;
y2 = Math.abs(ran.nextInt(50)) % h;
paintBiomorph(g);
}
public void paintBiomorph(Graphics g) {
super.paintComponent(g);
for (int i = 0; i <= 10; i++) {
int xMirror1 = x1 - 120;
int xMirror2 = x2 - 120;
g2d.drawLine(x1, y1, x2, y2);
g2d.drawLine(120 - xMirror1, y1, 120 - xMirror2, y2);
x1 = x2;
y1 = y2;
x2 = Math.abs(ran.nextInt(100)) % w + 120;
y2 = Math.abs(ran.nextInt(100)) % h;
}
}
}
This is a screenshot of the current GUI I have:
You should not use the Random() method in a painting method. You can't control when Swing will repaint a component and you don't want the painting to randomly change.
Instead you need to create properties in your class that the painting method can use to do the custom painting. So you should create a Biomorph object. This object will contain the information necessary to paint a single Biomorph. It should even contain a method to paint itself. Lets call this method paintBiomorph(Graphics).
When you create the Biomorph object you might have an empty constructor which creates a random Biomorph, then you might have a constructor that takes a Biomporh object as a parameter so you can create "child" Biomorphs based on a "parent" Biomorph.
Then you can create an ArrayList hold multiple Biomorh objects. Then in the paintComponent() method you iterate through the ArrayList and simply invoke the paintBoimorph(GRaphics) method on each Biomorph object.
The Random() method would only be used when you initially create a Biomorph object. After than all the data need to repaint the Biomorph must be part of the object itself.
Edit:
The Biomorph class might look something like:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.JPanel;
public class Biomorph extends JPanel
{
List<Shape> lines = new ArrayList<Shape>();
//Graphics2D g2d;
//Dimension size = getSize();
//int w = size.width;
//int h = size.height;
//Random ran = new Random();
//int x1;
//int x2;
//int y1;
//int y2;
public Biomorph()
{
//g2d = (Graphics2D) g;
//g2d.setColor(Color.BLUE);
setForeground(Color.BLUE);
Random ran = new Random();
int x = Math.abs(ran.nextInt(100)) + 120;
int y = Math.abs(ran.nextInt(100));
int xMirror = x - 120;
// g2d.drawLine(120, 85, x, y);
// g2d.drawLine(120, 85, 120 - xMirror, y);
lines.add( new Line2D.Double(120, 85, x, y);
lines.add( new Line2D.Double(120, 85, -x, y);
int x1 = x;
int y1 = y;
int x2 = Math.abs(ran.nextInt(50)) + 120;
int y2 = Math.abs(ran.nextInt(50));
for (int i = 0; i <= 10; i++) {
int xMirror1 = x1 - 120;
int xMirror2 = x2 - 120;
//g2d.drawLine(x1, y1, x2, y2);
//g2d.drawLine(120 - xMirror1, y1, 120 - xMirror2, y2);
lines.add( new Line2D.Double(x1, y1, x2, y2);
lines.add( new Line2D.Double(-x1, y1, -x2, y2);
x1 = x2;
y1 = y2;
x2 = Math.abs(ran.nextInt(100)) + 120;
y2 = Math.abs(ran.nextInt(100));
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor( getForeground() );
for (Shape line: lines)
{
g2d.fill( line );
//g2d.draw( line );
}
g2d.dispose();
}
}
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class DrawIt
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int width = 400;
final int height = 400;
frame.setSize(width,height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent component = new JComponent()
{
public void paintComponent(Graphics graph){
draw(graph);
}
};
frame.add(component);
frame.setVisible(true);
}
public static void draw(Graphics g)
{
int x1=100;
int y1 = 100;
int length = 10;
for(int i=0;i<=10;i++)
{
int x2 = x1 + length;
int y2 = y1;
g.drawLine(x1,y1,x2,y2);
x1=x2;
y1=y2;
y2=y1-length;
g.drawLine(x1,y1,x2,y2);
x1=x2;
y1=y2;
length+=10;
x2=x1-length;
g.drawLine(x1, y1, x2, y2);
x1=x2;
y1=y2;
y2=y1+length;
g.drawLine(x1, y1, x2, y2);
x1=x2;
y1=y2;
length+=10;
}
}
}
How do I convert this to recursion? This gives me rectangular spiral but not recursive way. Help. if this way I am using 4 variables, with recursion, how will it be?
public class DrawIt {
public static void main(String[] args) {
JFrame frame = new JFrame();
final int width = 400;
final int height = 400;
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent component = new JComponent() {
public void paintComponent(Graphics graph) {
draw(graph);
}
};
frame.add(component);
frame.setVisible(true);
}
public static void drawpuzzle(Graphics g, int x1, int y1, int length, int count) {
if (count> 0) {
int x2 = x1 + length;
int y2 = y1;
g.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
y2 = y1 - length;
g.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
length += 10;
x2 = x1 - length;
g.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
y2 = y1 + length;
g.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
length += 10;
drawpuzzle(g, x1, y1, length, count - 1);
}
}
public static void draw(Graphics g) {
int x1 = 100;
int y1 = 100;
int length = 10;
int count = 10;
drawpuzzle(g, x1, y1, length, count);
}
}