// author Stuart Errol Anderson; // 2015 // stuart.errol.anderson@gmail.com // n-gon equilateral polygons , angles multiples pi/n #include #include #include #include #include #include #include #include #define PI 3.14159265358979323846 ///////////////////////////////// using namespace std; struct Point { double x; double y; }; struct Edge { Point p; Point q; }; // Given three colinear points p, q, r, the function checks if // point q lies on line segment 'pr' bool onSegment(Point p, Point q, Point r) { if (q.x <= std::max(p.x, r.x) && q.x >= std::min(p.x, r.x) && q.y <= std::max(p.y, r.y) && q.y >= std::min(p.y, r.y)) return true; return false; } // To find orientation of ordered triplet (p, q, r). // The function returns following values // 0 --> p, q and r are colinear // 1 --> Clockwise // 2 --> Counterclockwise int orientation(Point p, Point q, Point r) { // See 10th slides from following link for derivation of the formula // http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf double val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); double epsilon = 0.000001; if (abs(val) < epsilon) return 0; // colinear return (val > 0)? 1: 2; // clock or counterclock wise } // The main function that returns true if line segment 'p1q1' // and 'p2q2' intersect. bool doIntersect(Point p1, Point q1, Point p2, Point q2) { // Find the four orientations needed for general and // special cases int o1 = orientation(p1, q1, p2); int o2 = orientation(p1, q1, q2); int o3 = orientation(p2, q2, p1); int o4 = orientation(p2, q2, q1); // General case if (o1 != o2 && o3 != o4) return true; // Special Cases // p1, q1 and p2 are colinear and p2 lies on segment p1q1 if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are colinear and q2 lies on segment p1q1 if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p2, q2 and p1 are colinear and p1 lies on segment p2q2 if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and q1 are colinear and q1 lies on segment p2q2 if (o4 == 0 && onSegment(p2, q1, q2)) return true; return false; // Doesn't fall in any of the above cases } void polygonSearch(std::vector& ixs, const std::vector& endPerIndex, unsigned int currentIndex, unsigned int n) { if (currentIndex == ixs.size()) { // calculate the x,y components of the vertices of the polygon path; polygon is equilateral; add vectors head to tail unsigned int sum = 0; double sx=0.0; double sy=0.0; vector Vx; vector Vy; double d =0.0; double epsilon = 0.000001; string str; string filename; stringstream ss; ofstream myfile; for (unsigned int c = 0 ; c != n-1 ; c++) { // first vertex is always (1,0) Vx.push_back(cos((c*n-sum)*PI/n)); sx += Vx[c]; Vx[c] = sx; Vy.push_back(sin((c*n-sum)*PI/n)); sy += Vy[c]; Vy[c] = sy; sum += ixs[c]; // ixs[c] contains the value of the c-th index. } // the nth loop is not needed as we can use the fact the sum of the interior angles of an n-gon = (n-2)*180, unsigned int li = (n-2)*n-sum; // last index li = (n-2)*n - sum of first n-1 angles [n angle multiples = 180 = pi] if ((sum >= (n-2)*n)||(li > 2*n-1)) return; // reject these cases (get -ve on last index) or angles >= 2pi Vx.push_back(cos((n*(n-1)-sum)*PI/n)); sx += Vx[n-1]; Vx[n-1] = sx; Vy.push_back(sin((n*(n-1)-sum)*PI/n)); sy += Vy[n-1]; Vy[n-1] = sy; sum += li; // ixs[c] contains the value of the c-th index. d = sqrt(sx*sx+sy*sy); if(d angle ; for (unsigned int j = 0;j!= n-1 ; j++) { angle.push_back(ixs[j]); } angle.push_back(li); int temp = 0; long number ; unsigned int index1=0; int min = pow(n,n); for (unsigned int k = 0;k!=n; k++) { //right shift cycle array elements 1 position temp = angle[0]; for (unsigned int j = 0;j!=n; j++) { angle[j] = angle[j+1]; } angle[angle.size()-1] = temp; //make a base 2n-2 number from the array values number = 0; for (unsigned int j = 0;j!=n; j++) { number += angle[j]*pow(n,n-j-1); } //if it's the smallest so far, make minimum, save shift value if (number < min ) { min = number; index1 = k; } number = 0; } //right cycle the array values by b places to get canonical angle ordering for (unsigned int k = 0;k!=index1+1; k++) { //right shift cycle array elements 1 position temp = angle[0]; for (unsigned int j = 0;j!=n; j++) { angle[j] = angle[j+1]; } angle[angle.size()-1] = temp; } for (unsigned int k = 0;k!=n; k++) { cout< edges; for (unsigned int a=0; an) concave = true ; } if (intersect_count>0) { intersect = true; } //center the polygon in the A4 page, 595 x 842, center; (297.5,421) // a polygon has a maximum diameter n/2 ; cannot extend n/2 in any direction (flatten a polygon) double xscale = 330/(n/2); //create the postscript file for the polygon solution - label; knot, concave or convex str="%!PS-Adobe- \n"; str+="% equilateral polygons with pi/"; ss < ixs(n-1, 0); vector endPerIndex; endPerIndex.push_back(n-1); for (unsigned int c = 1 ; c != n ; c++) { endPerIndex.push_back(2*n); } polygonSearch(ixs, endPerIndex, 0, n); return(0); }