// Richard A. DeVenezia, Jan. 2000 // www.devenezia.com #include "stdafx.h" #include "mobius.h" #include "mobiusPoints.h" mobiusPoints::mobiusPoints( int height , int width , int length , int nSegments , int nHalfTwists , int nCurlIterations) : OFF() { double h, w, l, x, y, z; int n, m, i, R; double thetaN, cosN, sinN; // initialize the slices of the strip h = (double) height / 2.0 ; w = (double) width / 2.0 ; l = (double) length ; NS = nSegments; k = nHalfTwists; // class variable R = nCurlIterations; // NS is the number of segments // the last segment slice will wrap around to mate the first segment slice for (n=0; n<=NS; n++) { P [n][0].x = (double) n / (double) (NS) * l; P [n][0].y = 0.0; P [n][0].z = 0.0; P [n][1].x = P [n][0].x; P [n][1].y = w; P [n][1].z = h; P [n][2].x = P [n][0].x; P [n][2].y = w; P [n][2].z = - h; P [n][3].x = P [n][0].x; P [n][3].y = - w; P [n][3].z = - h; P [n][4].x = P [n][0].x; P [n][4].y = - w; P [n][4].z = h; } // twist the strip about the x-axis k(pi) times by computing // slice rotational transformations in the y-z plane for (n=0;n<=NS;n++) { thetaN = (double) n / (double) (NS) * (double) k * pi; cosN = cos (thetaN); sinN = sin (thetaN); // rotate slice n thetaN radians for (m=1;m<5;m++) { y = P [n][m].y; z = P [n][m].z; // rotate transform P [n][m].y = y * cosN - z * sinN; P [n][m].z = y * sinN + z * cosN; } } // curl the strip back on itself // perform a series of repetitive translate-rotate-translate transformations // on each slice. rotations are in the x-z plane thetaN = 2.0 * pi / double (NS); cosN = cos (thetaN); sinN = sin (thetaN); // start at 1 since first slice (index 0) will not be rotated // N iterations of this loop total N*thetaN radians, or 2pi. // Note the inner loops transform fewer and fewer slices as i approaches N for (i=1;i<=R;i++) { // rotation will be about center of previous slice double x0 = P [i-1][0].x; double z0 = P [i-1][0].z; for (n=i;n<=NS;n++) { // rotate slice n thetaN radians about center of slice n-1 for (m=0;m<5;m++) { // translate x = P [n][m].x - x0; z = P [n][m].z - z0; // rotate and translate back P [n][m].x = (x * cosN - z * sinN) + x0; P [n][m].z = (x * sinN + z * cosN) + z0; } } } if (R == NS) { if (k & 0x1) { // odd, swap opposite vertices P [NS][0].x = P [0][0].x; P [NS][0].y = P [0][0].y; P [NS][0].z = P [0][0].z; P [NS][1].x = P [0][3].x; P [NS][1].y = P [0][3].y; P [NS][1].z = P [0][3].z; P [NS][2].x = P [0][4].x; P [NS][2].y = P [0][4].y; P [NS][2].z = P [0][4].z; P [NS][3].x = P [0][1].x; P [NS][3].y = P [0][1].y; P [NS][3].z = P [0][1].z; P [NS][4].x = P [0][2].x; P [NS][4].y = P [0][2].y; P [NS][4].z = P [0][2].z; } else { // even P [NS][0].x = P [0][0].x; P [NS][0].y = P [0][0].y; P [NS][0].z = P [0][0].z; P [NS][1].x = P [0][1].x; P [NS][1].y = P [0][1].y; P [NS][1].z = P [0][1].z; P [NS][2].x = P [0][2].x; P [NS][2].y = P [0][2].y; P [NS][2].z = P [0][2].z; P [NS][3].x = P [0][3].x; P [NS][3].y = P [0][3].y; P [NS][3].z = P [0][3].z; P [NS][4].x = P [0][4].x; P [NS][4].y = P [0][4].y; P [NS][4].z = P [0][4].z; } } } mobiusPoints::~mobiusPoints() {} void mobiusPoints::Generate( LPCSTR offFn , BOOL section , BOOL right , BOOL bottom , BOOL left , BOOL top) { int np; // number of points int nf; // number of faces int nl; // number of lines int n,m; // worker bees OFF.open(offFn); np = (NS+1) * 4; nf = NS * (right + bottom + left + top + section) + section; nl = 0; // Output the points OFF << "OFF\n"; OFF << np << " " << nf << " " << nl << "\n\n"; for (n=0;n<=NS;n++) for (m=1;m<5;m++) { double x = P[n][m].x; double y = P[n][m].y; double z = P[n][m].z; if (fabs(x) < 1e-5) x=0; if (fabs(y) < 1e-5) y=0; if (fabs(z) < 1e-5) z=0; OFF << x << " " << y << " " << z << "\n"; } OFF << "\n"; // Output the requested faces in terms of the points // m is point '1' of a slice, at slice n // each face is four points m = 0; for (n=0;n