Supplementary Material Computer model C++ source code.- Annotated source code for one header file, DIJON.H, and one cpp file, DIJCRIN.CPP, written using Borland Turbo C++ ver. 1.0 for DOS. // DIJON.H /* This C++ header file lays out the C++ class named "crinoid" - the core model geometry calculator functions that initiate, calculate, and write to file the coordinates and associated data for the constructed cups. It also includes the required Borland header files and an inline degree to radian conversion function. Function descriptions: void addplate(int jj, double& alpha, double& ph) void ringeom(int jj) These two functions are the primary geometrical calculators. The function addplate(int jj, double& alpha, double& ph) uses the input alpha and plateheight variables to calculate plate shapes. The function ringeom(int jj) uses the data written by the addplate function to calculate the geometry of a ring of plates. void calyxdis() writes the calyx matrix to the screen. void platesplay() writes platecount matrix to the screen. void coordsplay(int jj) writes the coordinate matrix to the screen. These three were originally included for debugging purposes. int crinoid::write_crinoid_file(char* file_name) writes three data matrices single file. In this file each matrix block begins with the statement "BEGIN [MATRIXNAME];", and ends with "ENDBLOCK;". There is a line break between blocks. The first block is called CALYX, the second is called SPHERE, and the third is called COORD. Each row in CALYX contains the data for one plate ring in the cup. Columns contain the following: Column 0: bwid - width of base of plate Column 1: twid - width of top of plate Column 2: tw2 - Column 3: alpha - angle between base and side of plate Column 4: plateheight - height of plate normal to base Columns 5-9: variables used in drawing and branching routines The SPHERE block contains spherical and Cartesian coordinates for each plate vertex in the cup. Each row contains the data for a single vertex. The first row represents the center of the lowermost ring. Columns contain the following data: Column 0: point ID# Column 1: gamma (length of side of plate polygon) Column 2: ringheight Columns 3-5: spherical coordinates of current point Column 3: D Column 4: Phi Column 5: Theta Column 6: Ring number Columns 7-9: Cartesian coordinates of current point Column 7: x coordinate Column 8: y coordinate Column 9: z coordinate The COORD block repeats the last three columns of SPHERE, the Cartesian coordinates of the constructed cup. This separate block is an historical artifact of the way the programs were originally written. */ // Code begins below // ------------------------------------------------------------------------------------ // // interface dependencies // #define __DIJON_H #ifndef __FSTREAM_H #include // streams #endif #ifndef __MATH_H #include // for sqrt, cos, etc #endif #ifndef __CONIO_H #include // for getch() (in matrix display functions) #endif #ifndef __IOMANIP_H #include // for setw(), etc in matrix display functions #endif const int MAX = 5; // max number of crinoids const int RINGNUM = 4; // max number of plate rings const double PI = 3.1415926; const int points = (RINGNUM-1) * 10 + 1; // variable points sets matrix dimensions inline double anglecon(double angle) // converts degrees to radians {return ((PI/180) * angle);} class crinoid { protected: int platecount [RINGNUM][8]; double calyx [RINGNUM][10]; double coord [points][10]; public: crinoid(); // constructor: initiates matrices void addplate(int jj, double& alpha, double& ph); // adds next plate in series void ringeom(int jj); // calculates geometry of calyx void calyxdis(); // displays calyx matrix on screen void platesplay(); // displays platecount matrix on screen void coordsplay(int jj); // displays coord matrix on screen int crinoid::write_crinoid_file(char* file_name); }; // end class crinoid crinoid::crinoid() // constructor: initiates infrabasal polygon { for (int aa=0; aa 3) // i.e. if adding rings above the radials // This is part of an unimplemented branching routine { cout << "\n Enter percent occupation of previous plate (0.0 - 1.0): "; cin >> calyx[cc][9]; calyx[cc][0] = calyx[cc][9] * calyx[cc-1][1]; } else // What happens for the plates in the cup, the ibb, bb, & rr. { calyx[cc][0] = calyx[cc-1][1];} // bwidth = twidth (prev.plate) calyx[cc][9] = 1.0; if (angle > 126 && angle <= 180) // prevents angles > 126 and <= 180 angle = 126; if (angle > 180 && angle < 234) // prevents angles > 180 and < 234 angle = 234; /* Because the plates are defined as planar in this model, angles between 126 and 234 cannot be accommodated. */ calyx[cc][3] = angle; float abstan = (tan(anglecon(angle)) < 0) ? -tan(anglecon(angle)) : tan(anglecon(angle)); if((angle < 90 || angle > 270) && ph > abstan * calyx[cc][0]/2) //if ph > tan(alpha)*bwid/2 ph = abstan * calyx[cc][0]/2; if (0 < angle && angle <= 90) tw2 = calyx[cc][2] = -(ph * tan(anglecon(90 - angle))); else if (90 < angle && angle < 180) tw2 = calyx[cc][2] = (ph * tan(anglecon(angle - 90))); else if (180 < angle && angle <= 270) tw2 = calyx[cc][2] = (ph * tan(anglecon(270 - angle))); else if (270 < angle && angle < 360) tw2 = calyx[cc][2] = -(ph * tan(anglecon(angle - 270))); else if (angle == 0 || angle == 180 || angle == 360) tw2 = calyx[cc][2] = ph = 0; //tw2 = ph = 0 calyx[cc][4] = ph; calyx[cc][1] = calyx[cc][0] + 2 * tw2; //twid = bwid + 2 * tw2 if (calyx[cc][1] < 0) calyx[cc][1] = 0; if(angle == 0 || angle == 360) sidelen = calyx[cc][8] = 0; else if(angle == 270 || angle == 90) sidelen = calyx[cc][8] = ph; else sidelen = calyx[cc][8] = sqrt(tw2 * tw2 + ph * ph); if(angle < 54 || angle > 306) beta = -ph; else beta = calyx[cc][5] = tw2 * tan(anglecon(54)); if(0 < angle && angle < 54) rh = calyx[cc][6] = 0; // plates lying flat if(54 <= angle && angle < 90) rh = calyx[cc][6] = sqrt(ph * ph - beta * beta); else if (90 < angle && angle < 180) rh = calyx[cc][6] = sqrt(ph * ph - beta * beta); else if (180 < angle && angle < 270) rh = calyx[cc][6] = - sqrt(ph * ph - beta * beta); else if (270 < angle && angle <= 306) rh = calyx[cc][6] = - sqrt(ph * ph - beta * beta); else if (306 < angle && angle < 360) rh = calyx[cc][6] = 0; else if (angle == 0 || angle == 180) rh = calyx[cc][6] = 0; else if (angle == 90) rh = calyx[cc][6] = ph; else if (angle == 270) rh = calyx[cc][6] = - ph; if(tw2 == 0 && beta == 0) gamma = calyx[cc][7] = beta; else gamma = calyx[cc][7] = sqrt(tw2 * tw2 + beta * beta); if(angle < 90 || angle > 270) gamma = calyx[cc][7] = - gamma; // set any very small elements to 0 for(int column=0; column<10; column++) { if(calyx[cc][column] < .01 && calyx[cc][column] > -.01) calyx[cc][column] = 0; } } // end crinoid::addplate(int jj, double& angle, double& ph) void crinoid::ringeom(int jj) { double xdis, zdis, DD, phi, theta, ring, xx, yy, zz; int ang = 0; for(int kk = 1; kk < jj+1; kk++) { for(int count=1; count < 10; count += 2, ang++) { int cc = count + ((kk-1) * 10); coord[cc][0] = cc; if(cc <= 10) { coord[cc][1] = xdis = calyx[kk][7]; // gamma coord[cc][2] = zdis = calyx[kk][6]; // ringheight } else if (cc == 11 || cc == 21) { coord[cc][1] = xdis = calyx[kk][7] + coord[cc-1][1]; coord[cc][2] = zdis = calyx[kk][6] + coord[cc-1][2]; } else { coord[cc][1] = xdis = calyx[kk][7] + coord[cc-11][1]; coord[cc][2] = zdis = calyx[kk][6] + coord[cc-11][2]; } coord[cc][3] = DD = sqrt(xdis * xdis + zdis * zdis); coord[cc][4] = phi = (DD == 0) ? acos(0) : acos(zdis/DD); coord[cc][5] = theta = ang * anglecon(72) - (anglecon(36) * (kk-1)); coord[cc][6] = kk; coord[cc][7] = xx = DD * sin(phi) * cos(theta); coord[cc][8] = yy = DD * sin(phi) * sin(theta); coord[cc][9] = zz = DD * cos(phi); coord[cc+1][0] = cc + 1; if (cc <= 10) { coord[cc+1][1] = xdis = calyx[kk][5]; // beta coord[cc+1][2] = zdis = calyx[kk][6]; // ringheight } else if (cc == 11 || cc == 21) { coord[cc+1][1] = xdis = calyx[kk][5] + coord[cc-1][1]; coord[cc+1][2] = zdis = calyx[kk][6] + coord[cc-1][2]; } else { coord[cc+1][1] = xdis = calyx[kk][5] + coord[cc-11][1]; coord[cc+1][2] = zdis = calyx[kk][6] + coord[cc-11][2]; } coord[cc+1][3] = DD = sqrt(xdis * xdis + zdis * zdis); coord[cc+1][4] = phi = (DD == 0) ? acos(0) : acos(zdis/DD); coord[cc+1][5] = theta = ang * anglecon(72) + anglecon(36) - (anglecon(36) * (kk-1)); coord[cc+1][6] = kk; coord[cc+1][7] = xx = DD * sin(phi) * cos(theta); coord[cc+1][8] = yy = DD * sin(phi) * sin(theta); coord[cc+1][9] = zz = DD * cos(phi); /* set any very small exponents to 0 */ for(int column=3; column<10; column++) { if(coord[cc][column] < .01 && coord[cc][column] > -.01) coord[cc][column] = 0; if(coord[cc+1][column] < .01 && coord[cc+1][column] > -.01) coord[cc+1][column] = 0; } } } } // end void crinoid::ringeom(int jj) void crinoid::calyxdis() // writes calyx to screen - for debugging { cout << "\n calyx" << endl; for (int aa=0; aa> alpha1; cout << "\n Enter ph value for ring 1: "; cin >> ph1; cout << "\n Enter alpha value for ring 2: "; cin >> alpha2; cout << "\n Enter ph value for ring 2: "; cin >> ph2; cout << "\n Enter alpha value for ring 3: "; cin >> alpha3; cout << "\n Enter ph value for ring 3: "; cin >> ph3; crinoid crinoid; // create crinoid object for (jj = 0; jj