I'm trying to build my first fractal (Pythagoras Tree):
alt text http://img13.imageshack.us/img13/926/lab6e.jpg
in Java using Graphics2D. Here's what I have now :
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int i=0;
Scanner scanner = new Scanner(System.in);
System.out.println("Give amount of steps: ");
i = scanner.nextInt();
new Pitagoras(i);
}
}
class Pitagoras extends JFrame {
private int powt, counter;
public Pitagoras(int i) {
super("Pythagoras Tree.");
setSize(1000, 1000);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
powt = i;
}
private void paintIt(Graphics2D g) {
double p1=450, p2=800, size=200;
for (int i = 0; i < powt; i++) {
if (i == 0) {
g.drawRect((int)p1, (int)p2, (int)size, (int)size);
counter++;
}
else{
if( i%2 == 0){
//here I must draw two squares
}
else{
//here I must draw right triangle
}
}
}
}
#Override
public void paint(Graphics graph) {
Graphics2D g = (Graphics2D)graph;
paintIt(g);
}
So basically I set number of steps, and then draw first square (p1, p2 and size). Then if step is odd I need to build right triangle on the top of square. If step is even I need to build two squares on free sides of the triangle. What method should I choose now for drawing both triangle and squares ? I was thinking about drawing triangle with simple lines transforming them with AffineTransform but I'm not sure if it's doable and it doesn't solve drawing squares.
You do not have to draw triangles, only squares (the edges of the squares are the triangle) in this tree.
You can make things a lot easier looking into recursion (these types of fractals are standard examples for recursion):
In Pseudo-Code
drawSquare(coordinates) {
// Check break condition (e.g. if square is very small)
// Calculate coordinates{1|2} of squares on top of this square -> Pythagoras
drawSquare(coordinates1)
drawSquare(coordinates2)
}
And since I often programmed fractals, a hint: Draw the fractal itself in a BufferedImage and only paint the image in the paint-method. The paint-Method gets called possibly several times per second, so it must be faaaaast.
Also do not directly draw in a JFrame but use a Canvas (if you want to use awt) or a JPanel (if you use swing).
My final solution :
import java.awt.*;
import java.util.Scanner;
import javax.swing.*;
public class Main extends JFrame {;
public Main(int n) {
setSize(900, 900);
setTitle("Pythagoras tree");
add(new Draw(n));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Give amount of steps: ");
new Main(sc.nextInt());
}
}
class Draw extends JComponent {
private int height = 800;
private int width = 800;
private int steps;
public Draw(int n) {
steps = n;
Dimension d = new Dimension(width, height);
setMinimumSize(d);
setPreferredSize(d);
setMaximumSize(d);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.black);
int x1, x2, x3, y1, y2, y3;
int base = width/7;
x1 = (width/2)-(base/2);
x2 = (width/2)+(base/2);
x3 = width/2;
y1 = (height-(height/15))-base;
y2 = height-(height/15);
y3 = (height-(height/15))-(base+(base/2));
g.drawPolygon(new int[]{x1, x1, x2, x2, x1}, new int[]{y1, y2, y2, y1, y1}, 5);
int n1 = steps;
if(--n1 > 0){
g.drawPolygon(new int[] {x1, x3, x2}, new int[] {y1, y3, y1}, 3);
paintMore(n1, g, x1, x3, x2, y1, y3, y1);
paintMore(n1, g, x2, x3, x1, y1, y3, y1);
}
}
public void paintMore(int n1, Graphics g, double x1_1, double x2_1, double x3_1, double y1_1, double y2_1, double y3_1){
int x1, x2, x3, y1, y2, y3;
x1 = (int)(x1_1 + (x2_1-x3_1));
x2 = (int)(x2_1 + (x2_1-x3_1));
x3 = (int)(((x2_1 + (x2_1-x3_1)) + ((x2_1-x3_1)/2)) + ((x1_1-x2_1)/2));
y1 = (int)(y1_1 + (y2_1-y3_1));
y2 = (int)(y2_1 + (y2_1-y3_1));
y3 = (int)(((y1_1 + (y2_1-y3_1)) + ((y2_1-y1_1)/2)) + ((y2_1-y3_1)/2));
g.setColor(Color.green);
g.drawPolygon(new int[] {x1, x2, (int)x2_1, x1}, new int[] {y1, y2, (int)y2_1, y1}, 4);
g.drawLine((int)x1, (int)y1, (int)x1_1, (int)y1_1);
g.drawLine((int)x2_1, (int)y2_1, (int)x2, (int)y2);
g.drawLine((int)x1, (int)y1, (int)x2, (int)y2);
if(--n1 > 0){
g.drawLine((int)x1, (int)y1, (int)x3, (int)y3);
g.drawLine((int)x2, (int)y2, (int)x3, (int)y3);
paintMore(n1, g, x1, x3, x2, y1, y3, y2);
paintMore(n1, g, x2, x3, x1, y2, y3, y1);
}
}
}
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I have a class that is supposed to draw the Sierpinski triangle to a given degree, determined by increase/decrease buttons to alter that degree.
However, the degree (variable x) always reverts to 0 after I process the button press.
Where is my problem?
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Recursion4 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane pane = new BorderPane();
Button plus = new Button("+");
Button minus = new Button("-");
HBox h = new HBox(5);
Pane p = new Pane();
h.getChildren().addAll(plus, minus);
h.setSpacing(10);
pane.setBottom(h);
pane.setCenter(p);
h.setAlignment(Pos.CENTER);
Scene scene = new Scene(pane, 900, 900);
primaryStage.setTitle("Triangles");
primaryStage.setScene(scene);
primaryStage.show();
int x = 0;
draw(450, 300, 300, 600, 600, 600, x, p);
plus.setOnAction(e -> {
plus(x, p);
});
minus.setOnAction(e -> {
minus(x, p);
});
}
public static void main(String[] args) {
launch(args);
int x = 0;
}
public static void plus(int x, Pane p) {
p.getChildren().clear();
++x;
draw(450, 300, 300, 600, 600, 600, x, p);
}
public static void minus(int x, Pane p) {
p.getChildren().clear();
if (x == 0) {
draw(450, 300, 300, 600, 600, 600, x, p);
} else {
x--;
draw(450, 300, 300, 600, 600, 600, x, p);
}
}
public static void draw(int x1, int y1, int x2, int y2, int x3, int y3, Pane p) {
Line l1 = new Line(x1, y1, x2, y2);
Line l2 = new Line(x2, y2, x3, y3);
Line l3 = new Line(x3, y3, x1, y1);
p.getChildren().add(l1);
p.getChildren().add(l2);
p.getChildren().add(l3);
}
public static void draw(int x1, int y1, int x2, int y2, int x3, int y3, int z, Pane p) {
if (z == 0) {
draw(x1, y1, x2, y2, x3, y3, p);
} else {
draw(x1, y1, x2, y2, x3, y3, p);
int xa, ya, xb, yb, xc, yc;
xa = (x1 + x2) / 2;
ya = (y1 + y2) / 2;
xb = (x1 + x3) / 2;
yb = (y1 + y3) / 2;
xc = (x2 + x3) / 2;
yc = (y2 + y3) / 2;
draw(x1, y1, xa, ya, xb, yb, z - 1,p);
draw(xa, ya, x2, y2, xc, yc, z - 1,p);
draw(xb, yb, xc, yc, x3, y3, z - 1,p);
}
}
}
Each of main, plus, and minus has a local variable x (note the local declarations). Nowhere do you refer to the object attribute x, which seems to be what you want to alter. Use this.x instead of declaring a local one.
So I've written a program that compiles, but it won't do what I want it do. It supposed to fill a triangle without using fill polygon. I'm trying to keep the code restricted to loops.
The point is to make the three lines smaller and smaller to fill every part of the triangle.
The way to solve this is, I think would be to figure out where the loop should stop. I took a guess at half the height of the triangle (140).
import javax.swing.*;
import java.awt.*;
public class Tri extends JApplet
{
int x1=0;
int y1 = 140;
int x2 = 120;
int y2 = 140;
int x3 = 60;
int y3;
public void paint (Graphics page)
{
for (y3= 0; y3<=70; y3++)
{
page.drawLine (x1, y1, x2, y2);
page.drawLine (x2, y2, x3, y3);
page.drawLine (x3, y3, x1, y1);
y1++;
x2--;
y2--;
x1++;
}
}
}
change your loop logic, try the following code
int x1=0;
int y1 = 140;
int x2 = 120;
int y2 = 140;
int x3 = 60;
int y3=0;
public void paint (Graphics page)
{
page.drawLine (x1, y1, x2, y2);
page.drawLine (x2, y2, x3, y3);
page.drawLine (x3, y3, x1, y1);
for (x1= 0; x1<=120; x1++)
{
page.drawLine (x3, y3, x1, y1);
} }
keep two lines constant and alter the position of other line by changing its coordinates
for information regarding paint() and repaint follow the link
paint() and repaint() in Java
`
I'm trying to draw Sierpinski's Triangle recursively in Java, but it doesn't work, though to me the logic seems fine. The base case is when the triangles are within 2 pixels of each other, hence the use of the Distance Formula.
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.Canvas;
public class Triangle extends Canvas implements Runnable
{
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
public Triangle()
{
setBackground(Color.WHITE);
}
public void paint( Graphics window )
{
window.setColor(Color.BLUE);
window.setFont(new Font("ARIAL",Font.BOLD,24));
window.drawString("Serpinski's Gasket", 25, 50);
triangle(window, (WIDTH-10)/2, 20, WIDTH-40, HEIGHT-20, 40, HEIGHT-20, 4);
}
public void triangle(Graphics window, int x1, int y1, int x2, int y2, int x3, int y3, int r)
{
//if statement base case
//midpoint = (x1 + x2 / 2), (y1 + y2/ 2)
if(Math.sqrt((double)(Math.pow(x2-x1, 2)) + (double)(Math.pow(y2-y1, 2))) > 2)
//if(r==0)
{
window.drawLine(x1, y1, x2, y2);
window.drawLine(x2, y2, x3, y3);
window.drawLine(x3, y3, x1, y1);
}
int xa, ya, xb, yb, xc, yc; // make 3 new triangles by connecting the midpoints of
xa = (x1 + x2) / 2; //. the previous triangle
ya = (y1 + y2) / 2;
xb = (x1 + x3) / 2;
yb = (y1 + y3) / 2;
xc = (x2 + x3) / 2;
yc = (y2 + y3) / 2;
triangle(window, x1, y1, xa, ya, xb, yb, r-1); // recursively call the function using the 3 triangles
triangle(window, xa, ya, x2, y2, xc, yc, r-1);
triangle(window, xb, yb, xc, yc, x3, y3, r-1);
}
public void run()
{
try{
Thread.currentThread().sleep(3);
}
catch(Exception e)
{
}
}
}
The Runner is
import javax.swing.JFrame;
public class FractalRunner extends JFrame
{
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
public FractalRunner()
{
super("Fractal Runner");
setSize(WIDTH+40,HEIGHT+40);
getContentPane().add(new Triangle());
setVisible(true);
}
public static void main( String args[] )
{
FractalRunner run = new FractalRunner();
}
}
To me this should work but it causes a runtime/StackOverFlow error that I don't know how to correct. Any help?
You need to move the recursive calls to triangle, and the associated math, inside the conditional check on the separation. Right now, it will always call it and therefore you get the stack overflow.
Chances are your base case might not be working properly- what if the distance between two triangles is never two pixels? say we star with y1 and x1 being 0 and 200. their midpoint would be 100, then 50, 25, 12, 6, 3, 1<--- never hits the 2 pixel base case...
"StdDraw" was taken from here:
public class Sierpinski {
public static void sierpinski(int n) {
sierpinski(n, 0, 0, 1);
}
public static void sierpinski(int n, double x, double y, double size) {
if (n == 0) return;
//compute triangle points
double x0 = x;
double y0 = y;
double x1 = x0 + size;
double y1 = y0;
double x2 = x0 + size / 2;
double y2 = y0 + (Math.sqrt(3)) * size / 2;
// draw the triangle
StdDraw.line(x0, y0, x1, y1);
StdDraw.line(x0, y0, x2, y2);
StdDraw.line(x1, y1, x2, y2);
StdDraw.show(100);
//recursive calls
sierpinski(n-1, x0, y0, size / 2);
sierpinski(n-1, (x0 + x1) / 2, (y0 + y1) / 2, size / 2);
sierpinski(n-1, (x0 + x2) / 2, (y0 + y2) / 2, size / 2);
}
// read in a command-line argument n and plot an order Sierpinski Triangle
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
StdDraw.setPenRadius(0.005);
sierpinski(n);
}
}
Guy
I am trying to fill a triangle. I tried to do it myself using
g.fillPolygon(Triangle.x1, Triangle.x2, Triangle.x3, Triangle.y1,
Triangle.y2, Triangle.y3);
but I am getting some errors. Can anyone help me with this?
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Vehicle extends JFrame
{
final int WIDTH = 900; int HEIGHT = 650;
public Vehicle()
{
//the following code creates the JFrame
super("Radical Racing");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g)
{
g.setColor(Color.DARK_GRAY);
g.fillRect(0,0,WIDTH,HEIGHT);
int x1, y1 ,x2, y2, x3,y3;
x1 = x2 = x3 = 200;
y1 = y2 = y3 = 390;
{
triangle (g, x1=174, y1, x2=204, y2, x3=189, y3=360);
}
g.setColor(Color.green);
g.fillPolygon(Triangle.x1, Triangle.x2, Triangle.x3, Triangle.y1, Triangle.y2, Triangle.y3);
triangle(g,x1,y1,x2,y2,x3,y3);
}
void triangle(Graphics g,int x1,int y1,
int x2, int y2, int x3, int y3){
g.drawLine (x1, y1, x2, y2);
g.drawLine (x2, y2, x3, y3);
g.drawLine (x3, y3, x1, y1);
}
public static void main(String[]args)
{
new Vehicle();
}
}
You're welcome and I suggest to use oracle java api sometimes. It's really developers friendly. :)
You don't have any Triangle class with static x1... fields so why Triangle.x1...? :) And why own block to invoke triangle()?
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Vehicle extends JFrame {
final int WIDTH = 900;
int HEIGHT = 650;
public Vehicle() {
// the following code creates the JFrame
super("Radical Racing");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g) {
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, WIDTH, HEIGHT);
int x1, y1, x2, y2, x3, y3;
x1 = x2 = x3 = 200;
y1 = y2 = y3 = 390;
triangle(g, x1 = 174, y1, x2 = 204, y2, x3 = 189, y3 = 360);
g.setColor(Color.green);
g.fillPolygon(new int[] {x1, x2, x3}, new int[] {y1, y2, y3}, 3);
triangle(g, x1, y1, x2, y2, x3, y3);
}
void triangle(Graphics g, int x1, int y1, int x2, int y2, int x3, int y3) {
g.drawLine(x1, y1, x2, y2);
g.drawLine(x2, y2, x3, y3);
g.drawLine(x3, y3, x1, y1);
}
public static void main(String[] args) {
new Vehicle();
}
}
nvrfrgt answer works and fixes any bugs you have (gave him a +1) but there are some other things you could clean up that are worth keeping in mind (and were too long for a comment).
First off, I think you meant for HEIGHT to be final? Otherwise make it lowercase.
A performance thing that might make a difference later if you are drawing a bunch of racing triangles or something - you are drawing the same triangle twice (never change your x and y values), so one of these is wasted.
triangle (g, x1=174, y1, x2=204, y2, x3=189, y3=360);
...
triangle(g, x1, y1, x2, y2, x3, y3);
How you initialized your x and y values isn't the cleanest either. You set them all to specific numbers, and then turn around and change them in the next line. Why have the initial values? The snippet below makes more sense to me anyway (though that still seems a bit too magic numbery)
int x1 = 174; int x2 = 204; int x3 = 189;
int y1 = 390; int y2 = 390; int y3 = 360;
triangle(g, x1, y1, x2, y2, x3, y3);
If you are going to draw the triangle and fill it in the same color, then drawing the lines might be unnecessary for you (makes 1pixel difference?). If that's the case, you can remove the triangle() call, or replace your triangle implementation with the fill polygon. In the end, something like this is a bit more sleek (still can work on it though):
public class Vehicle extends JFrame {
final int WIDTH = 900;
final int HEIGHT = 650; // Made this final
public Vehicle() {
// the following code creates the JFrame
super("Radical Racing");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g) {
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, WIDTH, HEIGHT);
int x1 = 174; int x2 = 204; int x3 = 189;
int y1 = 390; int y2 = 390; int y3 = 360;
g.setColor(Color.green);
// Got rid of redundant drawing
triangle(g, x1, y1, x2, y2, x3, y3);
}
void triangle(Graphics g, int x1, int y1, int x2, int y2, int x3, int y3) {
// Left both the lines and the fill so you could play with color or something.
g.drawLine(x1, y1, x2, y2);
g.drawLine(x2, y2, x3, y3);
g.drawLine(x3, y3, x1, y1);
g.fillPolygon(new int[] {x1, x2, x3}, new int[] {y1, y2, y3}, 3);
}
public static void main(String[] args) {
// Want to save this as something so you can move it around later
Vehicle greenTriangle = new Vehicle();
}
first set color:
g.setColor(R, G, B);
Then fill it:
g.fillTriangle(x1, y1, x2, y2, x3, y3);
i'm trying to make a program that will connect two points that i click in my JPanel. i'm trying to connect the two points with a line. i displayed the values of my (x1, y1) and (x2,y2) coordinates whenever i click using the mouse and there is no error in the values. but when the line is displayed, it the line doesn't seem to follow the coordinates i specify but instead outputs in a different location and is distorted. most of the lines will appear to be cut by something, i think it's the rectangle created by the line because i used setBounds(). also, i add a System.out.println("") inside my paintComponent function and i noticed that it printed multiple times (increasing by 1 after every click) even though it should only print once. can anyone help me with this? thanks!
here are two of the classes which contribute to the error:
CLASS # 1:
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Arch. Don Saborrido
*/
public class twixtBoard extends JPanel implements java.awt.event.MouseListener{
int x1 = 0, x2, y1 = 0, y2;
DrawLine line;
//DrawLine line;
public twixtBoard(){
//requestFocus();
setLayout(null);
setVisible(false);
setBounds(0,0,600,450);
setOpaque(false);
setFocusable(false);
addListener();
}
public void addListener(){
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
if (x1 == 0 || y1 == 0){
x1 = e.getX();
y1 = e.getY();
System.out.println(x1 + " " + y1);
}
else{
x2 = e.getX();
y2 = e.getY();
//System.out.println(x2 + " " + y2);
line = new DrawLine(x1, y1, x2, y2);
line.setBounds(x1, y1, x2, y2);
System.out.println("" + line.getLocation());
//line.setOpaque(false);
add(line);
x1 = x2;
y1 = y2;
repaint();
}
}
public void mousePressed(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseReleased(MouseEvent e) {
///throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseEntered(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void mouseExited(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}
CLASS # 2 (Paint Class):
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Arch. Don Saborrido
*/
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
//import java.awt.geom.Line2D;
import javax.swing.JPanel;
public class DrawLine extends JPanel{
int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
//Line2D line;
Stroke[] s = new Stroke[] {new BasicStroke(10.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND)};
//new BasicStroke(25.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL),
//new BasicStroke(25.0f, BasicStroke.CAP_SQUARE,BasicStroke.JOIN_MITER)
GeneralPath path = new GeneralPath();
public DrawLine(int start_x, int start_y, int end_x, int end_y){
x1 = start_x;
y1 = start_y;
x2 = end_x;
y2 = end_y;
System.out.println(x1+ " " + y1+ " " + x2+ " " + y2+ " ");
}
#Override
protected void paintComponent(Graphics g) {
System.out.println("entered paint");
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.setStroke(s[0]);
path.moveTo(x1,y1);
System.out.println("x1 = " + x1 + " y1 = " + y1);
path.lineTo(x2,y2);
System.out.println("x2 = " + x2 + " y2 = " + y2);
System.out.println("" + path.getBounds2D());
g2.draw(path);
//line = new Line2D.Float(x1, y1, x2, y2);
//if(x1 != x2 && y1 != y2)
//g2.draw(line);
}
}
This is a very complicated approach.
Try the following:
make a class (e.g. LineClass) with four variables: x1, x2, y1 and y2.
keep a ArrayList of your generated lines
draw each line in the ArrayList on your JPanel using g.drawline(line.x1, line.y1, line.x2, line.y2) where line is the element of the ArrayList
class MainClass extends JPanel implements MouseListener {
boolean clickedOnce = false;
ArrayList<Line> lines = new ArrayList<Line>();
int x, y;
MainClass () {
// init...
addMouseListener(this);
}
// more MouseEvent methods
public void mouseClicked(MouseEvent e) {
if (!clickedOnce){
x=e.getX();
y = e.getY();
clickedOnce = true;
}
else{
lines.add(new Line(x,y,e.getX(), e.getY());
clickedOnce = false;
repaint();
}
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
for (Line l: lines)
g.drawLine(l.x1, l.y2, l.x2, l.y2);
}
private class Line {
public int x1, y1, x2, y2;
Line (int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
}
}
}
line = new DrawLine(x1, y1, x2, y2);
ine.setBounds(x1, y1, x2, y2);
add(line);
The basic logic looks wrong to me. You can't just use the 4 values fo the size and location.
The location would be the minimum of the x1/x2 and y1/y2.
The size (width, height) would then be the absolute value of (x1 - x2) and (y1 - y2).
Then when you draw the line you would draw the line from (0, 0) to (width, height).
Maybe the code examples from Custom Painting Approaches will help with a slightly different solution.
One of the problems is that you are calculating the width and height wrong. They would be the difference between x1 and x2 and y1 and y2.
You could also probably do this easier using java's Graphics class. That has methods like drawLine(), which would probably make your life easier.