Drawing multiple lines with Java Swing - java

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.

Related

Filling triangles without fillpolygon?

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
`

Swing Graphics Not Working In My Line Algorithm?

I'm trying to utilize swing graphics in order to gauge Bresenham's algorithm against a less polished solution (I haven't implemented the timers yet). As things stand, there are no errors when compiling, and it throws a NullPointer exception at basic, drawthoselines, and main. The idea is that the lines will appear in the JFrame, but they don't. It's just a blank frame. I know I have everything set to static, but I get a lot of errors otherwise.
I'm a novice and I would be grateful to anyone who could provide a solution and an explanation.
import java.awt.*;
import javax.swing.*;
public class lines extends JPanel {
static int deltaX;
static int deltaY;
static int DY2;
static int DX2;
static int Di;
public static void main (String[] args) {
JFrame f = new JFrame("Line vs Line");
f.pack();
f.setVisible(true);
f.setSize(300,300);
f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
f.getContentPane().add(p);
Graphics g = null;
drawthoselines(g);
}
public static void basic(int x1, int y1, int x2, int y2, Graphics g){
int deltaX = x2-x1;
int deltaY = y2-y1;
float m = (float)deltaY/(float)deltaX;
float c = y1 - (m*x1);
for (int x=x1; x<x2; x++){
float floatY = (m*x) + c;
int y = Math.round(floatY);
g.drawLine(x,y,x,y);
}
}
public static void brz(int x1, int y1, int x2, int y2, Graphics g){
deltaX = x2-x1;
deltaY = y2-y1;
DY2 = 2* deltaY;
DX2 = 2* deltaX;
Di = DY2 - deltaX;
int x = x1;
int y = y1;
int prevy;
while (x<x2) {
x++;
prevy = y;
if (Di > 0){
y++;
}
g.drawLine(x,y,x,y);
Di = Di + DY2 - (DX2 * (y - prevy));
}
}
public static void drawthoselines(Graphics g){
basic(10,10,40,30,g);
basic(10,10,40,90,g);
brz(50,50,150,60,g);
brz(50,50,150,120,g);
brz(50,50,150,140,g);
}
}
That is not the way you do custom painting. Read the Swing tutorial on Custom Painting for explanations on how painting works and for working examples.
Also, whenever you see all static variables and method you know you are doing something else wrong. I suggest you take time to read other section of the tutorial as well since they all contain examples on a better way to structure your code.
You don't instantiate Graphics because it is passed down from the java.awt.event
Also you have a class that extends JPanel, which means you want to add the class to the JFrame by instantiating the class. Also, the class will implicitly call paintComponent method which you will override to make use of the Graphics g. It's a lot of stuff to take in so go slowly (start from rudimentary examples).
Let me also inform you a bit on static modifier.
Static modifier runs when you load the class. Thus if a method that is not a static is in a static method, the method will need to be called by instantiating the object that holds the method. Because you need the object (class) loaded to be able to use the method.
Below should work:
import java.awt.;
import javax.swing.;
public class lines extends JPanel {
static int deltaX;
static int deltaY;
static int DY2;
static int DX2;
static int Di;
public static void main (String[] args) {
JFrame f = new JFrame("Line vs Line");
f.pack();
f.setVisible(true);
f.setSize(300,300);
f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
lines h = new lines();
f.getContentPane().add(h);
}
public static void basic(int x1, int y1, int x2, int y2, Graphics g){
int deltaX = x2-x1;
int deltaY = y2-y1;
float m = (float)deltaY/(float)deltaX;
float c = y1 - (m*x1);
for (int x=x1; x<x2; x++){
float floatY = (m*x) + c;
int y = Math.round(floatY);
g.drawLine(x,y,x,y);
}
}
public static void brz(int x1, int y1, int x2, int y2, Graphics g){
deltaX = x2-x1;
deltaY = y2-y1;
DY2 = 2* deltaY;
DX2 = 2* deltaX;
Di = DY2 - deltaX;
int x = x1;
int y = y1;
int prevy;
while (x<x2) {
x++;
prevy = y;
if (Di > 0){
y++;
}
g.drawLine(x,y,x,y);
Di = Di + DY2 - (DX2 * (y - prevy));
}
}
public static void drawthoselines(Graphics g){
}
#Override
protected void paintComponent(Graphics g) {
basic(10,10,40,30,g);
basic(10,10,40,90,g);
brz(50,50,150,60,g);
brz(50,50,150,120,g);
brz(50,50,150,140,g);
}
}

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

paintComponent() output error

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.

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

Categories

Resources