#include #include #include using namespace std; const unsigned DIM = 2; /* Triangle point numbering: p1 / \ / \ / \ p0------p2 The s0, s1 and s2 functions below are contraction maps, i.e. they pull the specified point towards the fixed point of the map, by an amount corresponding to the distance between the point and the fixed point scaled by the contraction mapping constant k. The fixed point of s0 is p0, and the fixed point of s1 is p1, etc. For example, the following call to s0: s0(2, 0.5, p0, p1, p2) returns a new point exactly halfway between p0 and p2 in the above triangle diagram. */ vector s0(const int point, const double k, const vector &p0, const vector &p1, const vector &p2){ vector p(DIM, 0.0); switch(point){ case 0: return(p0); // fixed point of the map case 1: p[0] = p0[0] + k*(p1[0] - p0[0]); p[1] = p0[1] + k*(p1[1] - p0[1]); break; case 2: p[0] = p0[0] + k*(p2[0] - p0[0]); p[1] = p0[1] + k*(p2[1] - p0[1]); break; } return(p); } vector s1(const int point, const double k, const vector &p0, const vector &p1, const vector &p2){ vector p(DIM, 0.0); switch(point){ case 0: p[0] = p1[0] + k*(p0[0] - p1[0]); p[1] = p1[1] + k*(p0[1] - p1[1]); break; case 1: return(p1); // fixed point of the map case 2: p[0] = p1[0] + k*(p2[0] - p1[0]); p[1] = p1[1] + k*(p2[1] - p1[1]); break; } return(p); } vector s2(const int point, const double k, const vector &p0, const vector &p1, const vector &p2){ vector p(DIM, 0.0); switch(point){ case 0: p[0] = p2[0] + k*(p0[0] - p2[0]); p[1] = p2[1] + k*(p0[1] - p2[1]); break; case 1: p[0] = p2[0] + k*(p1[0] - p2[0]); p[1] = p2[1] + k*(p1[1] - p2[1]); break; case 2: return(p2); // fixed point of the map } return(p); } // Sierpinski gasket function // // Does the following: // 1. Applies a contraction map to each of three input points. // 2. Saves the newly computed points in a vector. // 3. Recursively calls itself on the resulting three inner triangles. // void sg(const int d, // depth (how many more times do we recurse) const double k, // contraction mapping constant const vector &p0, const vector &p1, const vector &p2, vector< vector > &points){ if(d == 0) return; vector p01, p12, p20; p01 = s0(1,k,p0,p1,p2); p12 = s1(2,k,p0,p1,p2); p20 = s2(0,k,p0,p1,p2); points.push_back(p01); points.push_back(p12); points.push_back(p20); sg(d-1, k, p0, p01, s0(2,k,p0,p1,p2), points); sg(d-1, k, s1(0,k,p0,p1,p2), p1, p12, points); sg(d-1, k, p20, s2(1,k,p0,p1,p2), p2, points); } int main(){ vector p0(DIM), p1(DIM), p2(DIM); // Initialize the three corners of the starting triangle p0[0] = 0.0; p0[1] = 0.0; p1[0] = 1.0/2.0; p1[1] = sqrt(3.0)/2.0; p2[0] = 1.0; p2[1] = 0.0; int depth = 0; double k = 0.5; cerr << "Enter depth (integer > 0, usually 10 is good): "; cin >> depth; cerr << "Enter contraction mapping constant (for example 0.5): "; cin >> k; // This vector holds all data points generated // via recursive calls to sg() vector< vector > points; points.push_back(p0); points.push_back(p1); points.push_back(p2); // Recursively generate Sierpinski's gasket sg(depth-1, k, p0, p1, p2, points); for(vector< vector >::size_type i=0; i < points.size(); ++i){ cout << points[i][0] << ' ' << points[i][1] << endl; } return 0; }