Filling triangles without fillpolygon? - java

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
`

Related

Triangle Drawing not repeating for recursion code

I am writing a recursion code for my triangle drawing. For some reason, it wont do the recursion, but it will do the base drawing. Would like some help in figuring out why my code isn't repeating. Also, if someone could help me figure out how to fill the triangles with a color, that would be much appreciated.
public class Triangle {
public static void draw(int n, double size, double x, double y) {
if (n == 0) return;
StdDraw.setPenColor(StdDraw.BLUE);
StdDraw.setPenColor(StdDraw.BLACK);
//StdDraw.line(xy, size/2)
double x1 = x + size/2;
double y1 = y + size/2;
double x2 = x1+ size/2;
// bottom triangle
StdDraw.line(x,y, x1, y1);
StdDraw.line(x1, y1, x2, y );
StdDraw.line(x2, y, x1, y);
//right triangle
StdDraw.line(y, y, x2, x2);
StdDraw.line(x1, x1, x1, y1);
// top triangle and left triangle
StdDraw.line(y1, x1, x, x2);
StdDraw.line(x2, x2, x, y);
draw(n-1, size -3, x, y);
}
public static void main(String[] args) {
double x = 0.0;
double y = 0.0;
double size = 1.0;
int n = 2;
draw(n, size, x, y);
}
}

Recursive Sierpinski's Triangle 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 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);

Pythagoras tree with g2d

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);
}
}
}

Drawing multiple lines with Java Swing

I'm learning drawing lines with Java Swing in order to draw a labyrinth. I can draw one line at a specified position and it shows just fine. But when I want to draw multiple lines, only the last one shows. My code:
public class LabyrinthGUI extends JFrame {
...
Line line;
for (int i = 0; i < 10; i++) {
line = new Line(i*25, 0, (i+1)*25, 50);
this.getContentPane().add(line);
}
}
public class Line extends JPanel{
private int x1, y1, x2, y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void paintComponent (Graphics g) {
g.drawLine(x1, y1, x2, y2);
}
I probably have to refresh something, to display all the lines drawn with for-loop, but don't know what.
Why your example doesn't work is a simple one; Swing uses a layout manager to place every component added to a Container onto the screen. This way, the lines do not overlap.
Instead, use one Component in which every line is drawn. A solution for drawing a maze would be:
public class Labyrinth extends JPanel {
private final ArrayList<Line> lines = new ArrayList<Line>();
public void addLine(int x1, int y1, int x2, int y2) {
this.lines.add(new Line(x1, y1, x2, y2));
}
public void paintComponent(Graphics g) {
for(final Line r : lines) {
r.paint(g);
}
}
}
public static class Line {
public final int x1;
public final int x2;
public final int y1;
public final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
}
public void paint(Graphics g) {
g.drawLine(this.x1, this.y1, this.x2, this.y2);
}
}
And then use Labyrinth.addLine to add lines to your labyrinth. Also; specify a width and height for your Labyrinth, by calling setBounds or similar, because Swing may be cropping the graphics.
Your problem pretty much boils down to this:
public class Line extends JPanel
Think of each JPanel as an opaque card with something drawn on it. You're creating a bunch of these, each with a single line drawn on it, and then stacking them up on top of each other. That's why you can only see the most recent line.
Instead, you should have only one component that draws all of your lines in its paintComponent method.

Categories

Resources