The Chaos Game

Points to Generate

OperationXYScale Rotate
Red
Green
Blue

Rotation Style:

Vertex Center

The HTML file:

<html>
<head>
    <script type="text/javascript" src="sierpinski.js"></script>
    <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js">
    </script>
</head>
<body>
<center>
<h1>The Chaos Game</h1>
</center>

<table><tr><td>
  <canvas id="myCanvas" width="500", height="500" style="border:1px solid #007777;">
  <script>
       var canvas = new Canvas("myCanvas");
       canvas.Redisplay();
   </script>
</td><td>

    <b>Points to Generate</b>
    <input type="text" maxLength = "5" size = "5" id="PointBox", 
	   onchange="canvas.ChangePoints(this.value), canvas.Redisplay()">
   <p>
   <table>
        <tr><th> Operation</th><th>X</th><th>Y</th><th>Scale</th><th> Rotate</th></tr>


        <tr> <th>Red</th>
	    <td>
                  <input type="text" maxLength = "5" size = "5" id="Rx"
		         onchange="canvas.ChangeCoord(this.value,0,0), canvas.Redisplay()">
            </td><td>
                  <input type="text" maxLength = "5" size = "5" value = "0" id="Ry"
		         onchange="canvas.ChangeCoord(this.value,1,0), canvas.Redisplay()">
            </td><td>
                <input type="text" maxLength = "5" size = "5" id="ScaleR"
		        onchange="canvas.ChangeScale(this.value,0), canvas.Redisplay()">
           </td> <td>
                 <input type="text" maxLength = "5" size = "5" id="RotateRed"
		        onchange="canvas.ChangeRotate(this.value,0), canvas.Redisplay()">
	    </td> </tr>
        <tr> <th>Green</th>
	     <td>
                  <input type="text" maxLength = "5" size = "5" value = "0" id="Gx"
		         onchange="canvas.ChangeCoord(this.value,0,1), canvas.Redisplay()">
            </td><td>
                  <input type="text" maxLength = "5" size = "5" value = "0" id="Gy"
		         onchange="canvas.ChangeCoord(this.value,1,1), canvas.Redisplay()">
            </td><td>
                <input type="text" maxLength = "5" size = "5" id="ScaleG" 
		        onchange="canvas.ChangeScale(this.value,1), canvas.Redisplay()">
           </td><td>
                  <input type="text" maxLength = "5" size = "5" id="RotateGreen" 
		         onchange="canvas.ChangeRotate(this.value,1), canvas.Redisplay()">
	   </td></tr>
	<tr><th> Blue</th>
	    <td>
                  <input type="text" maxLength = "5" size = "5" value = "0" id="Bx"
		         onchange="canvas.ChangeCoord(this.value,0,2), canvas.Redisplay()">
            </td><td>
                  <input type="text" maxLength = "5" size = "5" value = "0" id="By"
		         onchange="canvas.ChangeCoord(this.value,1,2), canvas.Redisplay()">
            </td><td>
                <input type="text" maxLength = "5" size = "5" id="ScaleB" 
		        onchange="canvas.ChangeScale(this.value,2), canvas.Redisplay()">
            </td><td>
                  <input type="text" maxLength = "5" size = "5" id="RotateBlue"
		         onchange="canvas.ChangeRotate(this.value,2), canvas.Redisplay()">
            </td></tr>
	</tr>
</table>


   <p>
   <b>Rotation Style: </b>
   <form >
      <input type="radio" name="rotateStyle" value="0" 
             onchange="canvas.ChangeRotationStyle(this.value), canvas.Redisplay()">
	     Vertex
     </input>
      <input type="radio" name="rotateStyle" value="1" checked
             onchange="canvas.ChangeRotationStyle(this.value), canvas.Redisplay()">
         Center
       </input>
   </form>
   <p>
   <button type="button" onclick=" canvas.Redisplay()">Redraw</button>
   <button type="button" onclick=" canvas.Init(),canvas.Redisplay(),ResetUI()">
      Reset
   </button>
   <p>
   <button type="button" onclick=" canvas.GetNewPoints()">NewPoints</button>
</td></tr>
</table>

<script>
    function ResetUI() {
	 var a;

         a = canvas.GetCoord(0);
	 document.getElementById("Rx").value = a[0];
	 document.getElementById("Ry").value = a[1];

         a = canvas.GetCoord(1);
	 document.getElementById("Gx").value = a[0];
	 document.getElementById("Gy").value = a[1];

         a = canvas.GetCoord(2);
	 document.getElementById("Bx").value = a[0];
	 document.getElementById("By").value = a[1];

	 a = canvas.GetScale(0);
	 document.getElementById("ScaleR").value = a;
	 a = canvas.GetScale(1);
	 document.getElementById("ScaleG").value = a;
	 a = canvas.GetScale(2);
	 document.getElementById("ScaleB").value = a;

	 a = canvas.GetRotate(0);
	 document.getElementById("RotateRed").value = a;
	 a = canvas.GetRotate(1);
	 document.getElementById("RotateGreen").value = a;
	 a = canvas.GetRotate(2);
	 document.getElementById("RotateBlue").value = a;

	 a = canvas.GetPoints();
	 document.getElementById("PointBox").value = a;
    }

    ResetUI();
</script>
</body>

The Javascript file:

var cheat;

function Canvas(name) {
    canvas = document.getElementById(name);
    this.canvas = canvas;
    this.width = canvas.width;
    this.height = canvas.height;
    this.ctx =  canvas.getContext("2d");

    this.Init();

    var rect = canvas.getBoundingClientRect();
    this.x = rect.left;
    this.y = rect.top;

    cheat = this;
    return this;
}

Canvas.prototype = {

    Init: function() {
        this.count = 90000;
        this.scale = [0.5, 0.5, 0.5];
        this.angle  = [0.0, 0.0, 0.0];
        this.color = ["red","green","blue"];
        this.clearColor = "white";

	this.rotationStyle = 1;

	this.start = 0;
        this.Reset();
	this.SetCOR();
    },

    Center: function(a,b,c) {
        var p1, p2;
	var p3= [];
	p1 = this.ScalePoint(a,b,.5);
	p2 = this.ScalePoint(a,c,.5);

	p3.push((a[0]+p1[0]+p2[0])/3);
	p3.push((a[1]+p1[1]+p2[1])/3);
        return p3;
    },

    SetCOR: function() {
        this.cor = [];

        switch (this.rotationStyle) {
           case 1:
	       var tri = this.tri;
	       this.cor.push(this.Center(tri[0],tri[1],tri[2]));
	       this.cor.push(this.Center(tri[1],tri[2],tri[0]));
	       this.cor.push(this.Center(tri[2],tri[0],tri[1]));
	       break;
	   default:
           case 0:
	       this.cor = this.tri;
	       break;
	}
    },

    Reset: function() {
        var shrink = 20;
        switch (this.start) {
	   default:
	   case 0:
               var p1 = [this.width/2.0, shrink];
               var p2 = [shrink, this.height-shrink];
               var p3 = [this.width-shrink, this.height-shrink];
	       this.tri = [p1, p2, p3]
	       break;
	}
    },

    Clear: function() {
        this.ctx.fillStyle=this.clearColor;
        this.ctx.fillRect(0,0,this.width,this.height);

        return;
    },

    Interp: function(a,b,s) {
        return a*s + b*(1-s);
    },

    RandPoint: function(p1, p2) {
        var s = Math.random();
	var x = this.Interp(p1[0],p2[0],s);
	var y = this.Interp(p1[1],p2[1],s);
	return [x,y];
    },

    ScalePoint: function(p1,p2,scale) {
	var x = this.Interp(p1[0],p2[0],scale);
	var y = this.Interp(p1[1],p2[1],scale);
	return [x,y];
    },


    SetColor: function(color) {
        this.color = color;
    },

    ChangePoints: function(points) {
        this.count = parseInt(points);
	if (this.count < 100) {
	   this.count = 100;
	}
	if (this.count > 99999) {
	   this.count = 99999;
	}
    },

    GetPoints: function(){
       return this.count;
    },

    ChangeScale: function(scale, factor) {
        var scale = parseFloat(scale);
	
	if (scale< 0) {
	   scale=0.0;
	}
	if (scale > 1.0) {
	   scale = 1.0;
	}
	this.scale[factor] = scale;
    },

    GetScale: function(color) {
        return this.scale[color];
    },

    ChangeCoord: function(value, coord, color) {
        realValue = parseInt(value);
	this.tri[color][coord] = realValue;
    },

    GetCoord: function(value) {
       var rv=[]
       rv.push(Math.round(this.tri[value][0]));
       rv.push(Math.round(this.canvas.height-this.tri[value][1]));
       return rv; 
    },

    ChangeRotate: function(value, choice) {
        var newValue = -parseFloat(value) * Math.PI/180.0;
	this.angle[choice] = newValue;
    },

    GetRotate: function(color) {
        var angle = Math.round(- this.angle[color] * 180.0/Math.PI);
	return angle;
    },

    ChangeRotationStyle: function(style) {
        this.rotationStyle = parseInt(style);
	this.SetCOR();
    },

    Redisplay: function() {
	this.Clear();

        var p, q, vertex;

        var seed = 200;
	var theta;

        var t1 = this.RandPoint(this.tri[0], this.tri[1]);
	p = this.RandPoint(t1, this.tri[2]);

        for (var i=0; i<this.count+seed; i++) {
	    var c = Math.floor(Math.random()*3);

	    vertex = this.tri[c]
	    q = this.ScalePoint(p,vertex,this.scale[c]);

            this.ctx.fillStyle = this.color[c];

	    q[0] -= this.cor[c][0];
	    q[1] -= this.cor[c][1];

	    theta = this.angle[c];

	    var x,y;

	    x = q[0] * Math.cos(theta) - q[1] * Math.sin(theta);
	    y = q[0] * Math.sin(theta) + q[1] * Math.cos(theta);


	    q[0] = x+this.cor[c][0];
	    q[1] = y+this.cor[c][1];

	    if (i >= seed) {
	        this.ctx.fillRect(q[0],q[1],1,1);
	    }
	    p = q;
	}
        return;
    },

    Redisplay2: function() {
	this.Clear();
	for(var i=0;i<this.point; i++) {
                this.ctx.fillStyle = this.color[i];
	        this.ctx.fillRect(this.tri[i][0],this.tri[i][1],10,10);
	}
    },
    
    GetNewPoints: function() {
        this.point= 0;
	canvas.Redisplay2();
	window.alert("Select three points");
	//register the mouse click function
	this.canvas.addEventListener("click",GetPoint);

    },

    AddAPoint: function(x,y) {
        this.tri[this.point][0] = x;
        this.tri[this.point][1] = y;
	this.point++;
	if (this.point > 2) {
	    // unregister the mouse click function
	    this.canvas.removeEventListener("click",GetPoint);
	    canvas.Redisplay();
	    ResetUI();
	} else {
	    canvas.Redisplay2();
	}
    }

};

function GetPoint(evnt) {
    var x = evnt.clientX-cheat.x;
    var y = evnt.clientY-cheat.y

    cheat.AddAPoint(x,y);
}