/*
* Copyright (C) 2002 Stephen F. Booth
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.Color;
import java.awt.Point;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
class ColorPoint
{
public Point p;
public Color c;
public ColorPoint(Point p, Color c)
{ this.p = p; this.c = c; }
};
public class Sierpinski extends Panel implements MouseListener
{
public static void main(String[] args)
{
Frame frame = new Frame("Sierpinski's Gasket");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
Sierpinski s = new Sierpinski(10000);
frame.setSize(800, 800);
frame.add(s);
//frame.addMouseListener(s);
frame.setVisible(true);
}
// ============================================================
Polygon mTriangle = null;
ColorPoint [] mPoints = null;
int mIterations = 0;
int mCount = 0;
public Sierpinski()
{
this(10000);
}
public Sierpinski(int iterations)
{
mIterations = iterations;
addMouseListener(this);
}
private void init()
{
generate_triangle();
mPoints = new ColorPoint [mIterations];
while(mCount < mIterations) {
generate_point();
}
}
private void destroy()
{
mTriangle = null;
mPoints = null;
mCount = 0;
}
public void mouseClicked(MouseEvent e)
{
destroy();
init();
repaint();
}
public void mouseEntered(MouseEvent e)
{}
public void mouseExited(MouseEvent e)
{}
public void mousePressed(MouseEvent e)
{}
public void mouseReleased(MouseEvent e)
{}
public void paint(Graphics g)
{
Color restoreColor = g.getColor();
/* If we haven't inited, so so now */
/* Since initally the frame's size is (0,0), to do this from
the constructor will cause an infinite loop */
if(mTriangle == null)
init();
/* First draw our triangle that is the basis for the whole thing */
g.setColor(Color.BLACK);
g.drawPolygon(mTriangle);
/* Now draw the points */
for(int i = 0; i < mCount; ++i) {
g.setColor(mPoints[i].c);
g.drawLine(mPoints[i].p.x, mPoints[i].p.y,
mPoints[i].p.x, mPoints[i].p.y);
}
g.setColor(restoreColor);
}
public void generate_triangle()
{
double x1, x2, x3;
double y1, y2, y3;
int width = getSize().width;
int height = getSize().height;
/* Generate three points */
x1 = width * Math.random();
x2 = width * Math.random();
x3 = width * Math.random();
y1 = height * Math.random();
y2 = height * Math.random();
y3 = height * Math.random();
/* Three points make a triangle iff the third point is not on
* the line created by the first two points. */
/* y = mx + b, m = dy/dx, and b = y - mx */
/* We can calculate m and b from the two points on the line,
* and use them to determine if the third point lies on the
* line */
double m = (y2 - y1) / (x2 - x1);
double b = y1 - m * x1;
/* Determine if the third point is on the line */
/* Since we are using floating-point arithmetic, nothing will
* match up exactly. Use a small delta to check for
* equality - 0.001 or so */
double delta = 0.001;
/* y = mx + b will rearrange in this case to |y - mx - b| < delta */
while(Math.abs(y3 - m * x3 + b) < delta) {
x3 = width * Math.random();
y3 = height * Math.random();
}
/* Now we have three points that form a triangle */
mTriangle = new Polygon();
mTriangle.addPoint((int) Math.floor(x1 + 0.5),
(int) Math.floor(y1 + 0.5));
mTriangle.addPoint((int) Math.floor(x2 + 0.5),
(int) Math.floor(y2 + 0.5));
mTriangle.addPoint((int) Math.floor(x3 + 0.5),
(int) Math.floor(y3 + 0.5));
}
public void generate_point()
{
double x, y;
Color c;
Point p;
/* If this is the first iteration, generate a starting point */
if(mCount == 0) {
int height = getSize().height;
int width = getSize().width;
/* Generate a point inside our original triangle */
do {
x = width * Math.random();
y = height * Math.random();
} while(mTriangle.contains(x, y) == false);
}
/* Otherwise, use the previous point as our starter */
else {
x = mPoints[mCount - 1].p.x;
y = mPoints[mCount - 1].p.y;
}
/* Generate a number between 1 and 6 */
int roll = ((int) Math.floor(6 * Math.random())) + 1;
double xcorner = 0, ycorner = 0;
double newx = 0, newy = 0;
double xdiff = 0, ydiff = 0;
double xorigin = 0, yorigin = 0;
switch(roll) {
default:
throw new RuntimeException();
//break;
case 1:
case 2:
xcorner = mTriangle.xpoints[0];
ycorner = mTriangle.ypoints[0];
c = Color.RED;
break;
case 3:
case 4:
xcorner = mTriangle.xpoints[1];
ycorner = mTriangle.ypoints[1];
c = Color.GREEN;
break;
case 5:
case 6:
xcorner = mTriangle.xpoints[2];
ycorner = mTriangle.ypoints[2];
c = Color.BLUE;
break;
};
/* Calculate half the distance between the points */
xdiff = Math.abs(xcorner - x)/2;
ydiff = Math.abs(ycorner - y)/2;
/* Add the diffs to the lesser value */
xorigin = Math.min(xcorner, x);
yorigin = Math.min(ycorner, y);
newx = xorigin + xdiff;
newy = yorigin + ydiff;
p = new Point((int) Math.floor(newx + 0.5),
(int) Math.floor(newy + 0.5));
mPoints[mCount++] = new ColorPoint(p, c);
}
};