1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
const double PI = 3.141592653589793;
const int NVERT = 20, NFACE = 12; // For a dodecahedron
//================================================
struct Pt{ double x, y, z; };
Pt operator +( Pt p, Pt q ) { return { p.x + q.x, p.y + q.y, p.z + q.z }; }
Pt operator -( Pt p, Pt q ) { return { p.x - q.x, p.y - q.y, p.z - q.z }; }
Pt operator *( double r, Pt p ) { return { r * p.x, r * p.y, r * p.z }; }
Pt operator /( Pt p, double r ) { return { p.x / r, p.y / r, p.z / r }; }
double dot( Pt p, Pt q ) { return p.x * q.x + p.y * q.y + p.z * q.z; }
double abs( Pt p ) { return sqrt( dot( p, p ) ); }
Pt cross( Pt p, Pt q ) { return { p.y * q.z - p.z * q.y, p.z * q.x - p.x * q.z, p.x * q.y - p.y * q.x }; }
//================================================
Pt rotX( Pt p, double angle ) // Rotate about x axis
{
double c = cos( angle ), s = sin( angle );
return { p.x, p.y * c - p.z * s, p.y * s + p.z * c };
}
//================================================
Pt rotZ( Pt p, double angle ) // Rotate about z axis
{
double c = cos( angle ), s = sin( angle );
return { p.x * c - p.y * s, p.x * s + p.y * c, p.z };
}
//================================================
Pt reflectInPlane( Pt p, Pt norm, Pt ref ) // Reflect in plane defined by normal vector and reference point
{
norm = norm / abs( norm ); // Make unit normal
return p - 2.0 * dot( p - ref, norm ) * norm;
}
//================================================
void dodecahedron( Pt vertex[], int pentagon[][5] )
{
double L = 4.0 / ( sqrt( 3.0 ) * ( 1.0 + sqrt( 5.0 ) ) ); // Length of side
double d = 0.5 * L / sin( 0.2 * PI ); // Circumradius of pentagonal face
double ztop = sqrt( 1.0 - d * d ); // z coordinate of flat top
// Initially, dodecahedron with horizontal top, two rows of side pentagons, horizontal bottom
// VERTICES: find a reference vertex in each of 4 tiers (z levels), then rotate in increments of 2 pi / 5
vertex[0] = { 0, -d, ztop };
for ( int i = 1; i <= 4; i++ ) vertex[i] = rotZ( vertex[0], 0.4 * PI * i );
vertex[5] = rotX( vertex[0], 2.0 * asin( 0.5 * L ) );
vertex[10] = reflectInPlane( vertex[1], vertex[0] - vertex[5], 0.5 * ( vertex[0] + vertex[5] ) );
vertex[15] = { vertex[2].x, -vertex[2].y, -vertex[2].z };
for ( int t = 1; t < 4; t++ )
{
for ( int i = 1; i <= 4; i++ ) vertex[5*t+i] = rotZ( vertex[5*t], 0.4 * PI * i );
}
// PENTAGONS (list of vertices; ANTICLOCKWISE when seen from OUTSIDE)
int p = 0;
for ( int i = 0; i < 5; i++ ) pentagon[p][i] = i;
for ( p = 1; p <= 5; p++ )
{
int off1 = (p-1)%5;
int off2 = p %5;
pentagon[p][0] = off1;
pentagon[p][1] = 5 + off1;
pentagon[p][2] = 10 + off1;
pentagon[p][3] = 5 + off2;
pentagon[p][4] = off2;
}
for ( p = 6; p <= 10; p++ )
{
int off1 = (p-6)%5;
int off2 = (p-2)%5;
pentagon[p][0] = 5 + off1;
pentagon[p][1] = 10 + off2;
pentagon[p][2] = 15 + off2;
pentagon[p][3] = 15 + off1;
pentagon[p][4] = 10 + off1;
}
p = 11;
for ( int i = 0; i < 5; i++ ) pentagon[p][i] = 19 - i;
}
//================================================
void output( Pt vertex[], int pentagon[][5] )
{
#define SF << fixed << setprecision( 6 ) << setw( 10 ) <<
#define SI << setw( 2 ) <<
cout << "VERTICES:\n";
for ( int v = 0; v < NVERT; v++ ) cout SF vertex[v].x << ", " SF vertex[v].y << ", " SF vertex[v].z << '\n';
cout << "\nPENTAGONS:\n";
for ( int p = 0; p < NFACE; p++ )
{
for ( int i = 0; i < 5; i++ ) cout SI pentagon[p][i] << " ";
cout << '\n';
}
}
//================================================
int main()
{
Pt vertex[NVERT];
int pentagon[NFACE][5];
dodecahedron( vertex, pentagon );
output( vertex, pentagon );
}
//================================================
|