A Sierpinski triangle is a fractal that can be constructed by first removing the medial triangle or midpoint triangle of a given triangle and then doing so recursively to the three triangles formed due to this removal. I would like to present in this chapter a program for drawing a Sierpinksi triangle (of which a demo can be seen by clicking here). This is also a place for me to advocate the so-called refinement-based programming.
A triangle can be represented as a tuple of three points. Let us introduce an abstract type for points:
Given two points A and B, the following function midpoint returns the middle point lying on the line segment connecting A and B: The use of "mac#" is to indicate to patsopt that the function midpoint should be compiled into a function in C of the same name.Given three points A, B, and C, the following function SierpinskiDraw draws (in some manner) the Sierpinkski triangle inside the triangle ABC:
Note that the first parameter of SierpinskiDraw sets the limit for the recursion depth. An implementation of SierpinskiDraw is given as follows:// implement SierpinskiDraw (n, A, B, C) = ( // if (n > 0) then let // val AB = midpoint(A, B) val BC = midpoint(B, C) val CA = midpoint(C, A) // val () = TriangleRemove(AB, BC, CA) // val () = SierpinskiDraw(n-1, A, AB, CA) val () = SierpinskiDraw(n-1, B, BC, AB) val () = SierpinskiDraw(n-1, C, CA, BC) // in // nothing end // end of [then] else () // end of [else] // ) (* end of [SierpinskiDraw] *) //
ATS source can be compiled into many programming languages, including C, Javascript (JS), PHP, etc. For instance, we may choose JS as the target language for compiling ATS. With this choice, we can implement TriangleRemove in JS directly:
%{ // function TriangleRemove (A, B, C) { theCtx.save(); // theCtx.beginPath(); theCtx.moveTo(A.x, A.y); theCtx.lineTo(B.x, B.y); theCtx.lineTo(C.x, C.y); theCtx.closePath(); // theCtx.fill(); // theCtx.restore(); } // end of [TriangleRemove] // %}
The function midpoint can also be conveniently implemented in JS:
%{ // function midpoint (p1, p2) { // var xmid = (p1.x + p2.x)/2; var ymid = (p1.y + p2.y)/2; // return { x: xmid, y: ymid }; // } // %}
Please find on-line the entirety of the code used in this chapter. The mentioned URL link(s) can be found as follows: