📄 ellipsoid.c
字号:
/* ellipsoid.c */#include <stdio.h>#include <math.h>#include <malloc.h>#include "ellipsoid.h"#ifndef M_PI_2#define M_PI_2 1.57079632679489661923#endiftypedef struct slot { float cos, sin; enum { None, Only, Done } flag; } slot;static int n_max = 0; /* current maximum degree of subdivision */static slot *table = NULL; /* an array of slots */static vertex *octant = NULL; /* the base octant of the ellipsoid */#define SetP(p,px,py,pz) (p).x=(px), (p).y=(py), (p).z=(pz)#define SetV(v,px,py,pz,nx,ny,nz) SetP((v)->p,px,py,pz), SetP((v)->n,nx,ny,nz)#define SetF(f,i0,i1,i2) (f)->v0 = i0, (f)->v1 = i1, (f)->v2 = i2/*// Compute the necessary cosine and sine values for generating ellipsoids// with the degree of subdivision n, and initialize the array table[].// The largest n becomes n_max, and calls with n <= n_max return immediately.// The memory for the base octant is allocated to cope with any n <= n_max.*/void ellipsoid_init (int n){ int n_table, i, j, k, l, m, h, d; slot *t0, *t1, *t2; float theta; if (n > n_max) { n_max = n; if (table) free (table); if ((n_table = ((n-1)*n)/2) == 0) table = NULL; else table = (slot *) malloc (n_table * sizeof(slot)); if (octant) free (octant); octant = (vertex *) malloc (((n+1)*(n+2))/2 * sizeof(vertex)); for (t0 = table, k = n_table; k > 0; k--, t0++) t0->flag = None; for (t0 = table, k = 0, l = 1, m = 3, i = 2; i <= n_max; i++) { l += m, m += 2, h = n_max / i - 1; for (t1 = t0+i - 2, j = 1; j < i; j++, k++, t0++, t1--) { if (t0->flag == None) { theta = (M_PI_2 * j) / i; t0->cos = t1->sin = cos (theta); t0->sin = t1->cos = sin (theta); t0->flag = t1->flag = Only; } if (t0->flag == Only) { t0->flag = Done; for (d = k+l, t2 = t0; h > 0; h--) { t2 += d, d += l; t2->cos = t0->cos; t2->sin = t0->sin; t2->flag = Done; } } } } }}/*// Construct the base octant of the ellipsoid whose parameters are a, b, and c,// with the degree of subdivision n using the cosine and sine values in table[].// It is assumed that n <= n_max.*/static void ellipsoid_octant (int n, float a, float b, float c){ int i, j; float a_1, b_1, c_1; float cos_ph, sin_ph, px, py, pz, nx, ny, nz, nznz, rnorm, tmp; vertex *o = octant; slot *table_th, *table_ph; a_1 = 1.0 / a; b_1 = 1.0 / b; c_1 = 1.0 / c; o = octant; table_th = table; table_ph = table + ((n-1)*(n-2))/2; SetV (o, 0.0, 0.0, c, 0.0, 0.0, 1.0), o++; /* i = 0, j = 0 */ for (i = 1; i < n; i++, table_ph++) { cos_ph = table_ph->cos; sin_ph = table_ph->sin; pz = cos_ph * c; nz = cos_ph * c_1; nznz = nz * nz; px = sin_ph * a; nx = sin_ph * a_1; rnorm = 1.0 / sqrt (nx*nx + nznz); /* 0 < i < n, j = 0 */ SetV (o, px, 0.0, pz, nx*rnorm, 0.0, nz*rnorm), o++; for (j = i; --j > 0; table_th++) { tmp = table_th->cos * sin_ph; px = tmp * a; nx = tmp * a_1; tmp = table_th->sin * sin_ph; py = tmp * b; ny = tmp * b_1; rnorm = 1.0 / sqrt (nx*nx + ny*ny + nznz); /* 0 < i < n, 0 < j < i */ SetV (o, px, py, pz, nx*rnorm, ny*rnorm, nz*rnorm), o++; } py = sin_ph * b; ny = sin_ph * b_1; rnorm = 1.0 / sqrt (ny*ny + nznz); /* 0 < i < n, j = i */ SetV (o, 0.0, py, pz, 0.0, ny*rnorm, nz*rnorm), o++; } SetV (o, a, 0.0, 0.0, 1.0, 0.0, 0.0), o++; /* i = n, j = 0 */ for (j = i; --j > 0; table_th++) { tmp = table_th->cos; px = tmp * a; nx = tmp * a_1; tmp = table_th->sin; py = tmp * b; ny = tmp * b_1; rnorm = 1.0 / sqrt (nx*nx + ny*ny); /* i = n, 0 < j < i */ SetV (o, px, py, 0.0, nx*rnorm, ny*rnorm, 0.0), o++; } SetV (o, 0.0, b, 0.0, 0.0, 1.0, 0.0); /* i = n, j = i */}/*// Note the following conventions in ellipsoid_seq() and ellipsoid_par():// the north pole: th = 0, ph = 0,// the 1st octant: 0 <= th < 90, 0 < ph <= 90,// the 2nd octant: 90 <= th < 180, 0 < ph <= 90,// the 3rd octant: 180 <= th < 270, 0 < ph <= 90,// the 4th octant: 270 <= th < 360, 0 < ph <= 90,// the 5th octant: 0 <= th < 90, 90 < ph <= 180,// the 6th octant: 90 <= th < 180, 90 < ph <= 180,// the 7th octant: 180 <= th < 270, 90 < ph <= 180,// the 8th octant: 270 <= th < 360, 90 < ph <= 180, and// the south pole: th = 0, ph = 180.*//*// Generate the vertices fot the ellipsoid with parameters a, b, and c// with the degree of subdivision n, by reflecting the base octant.// Also generate triangular faces of the ellipsoid with vertices ordered// counterclockwise when viewed from the outside.*//* sequential version */void ellipsoid_seq (object *ellipsoid, int n, float a, float b, float c){ vertex *v, *o; face *f; int i, j, ko, kv, kw, kv0, kw0; /* Check parameters for validity. */ if (n <= 0 || n_max < n || a <= 0.0 || b <= 0.0 || c <= 0.0) { ellipsoid->nv = 0; ellipsoid->v = NULL; ellipsoid->nf = 0; ellipsoid->f = NULL; return; } /* Initialize the base octant. */ ellipsoid_octant (n, a, b, c); /* Allocate memories for vertices and faces. */ ellipsoid->nv = 4*n*n + 2; ellipsoid->nf = 8*n*n; ellipsoid->v = (vertex *) malloc (ellipsoid->nv * sizeof(vertex)); ellipsoid->f = (face *) malloc (ellipsoid->nf * sizeof(face)); /* Generate vertices of the ellipsoid from octant[]. */ v = ellipsoid->v; o = octant;#define op o->p#define on o->n SetV (v, op.x, op.y, op.z, on.x, on.y, on.z), v++; /* the north pole */ for (i = 0; ++i <= n;) { o += i; for (j = i; --j >= 0; o++, v++) /* 1st octant */ SetV (v, op.x, op.y, op.z, on.x, on.y, on.z); for (j = i; --j >= 0; o--, v++) /* 2nd octant */ SetV (v, -op.x, op.y, op.z, -on.x, on.y, on.z); for (j = i; --j >= 0; o++, v++) /* 3rd octant */ SetV (v, -op.x, -op.y, op.z, -on.x, -on.y, on.z); for (j = i; --j >= 0; o--, v++) /* 4th octant */ SetV (v, op.x, -op.y, op.z, on.x, -on.y, on.z); } for (; --i > 1;) { o -= i; for (j = i; --j > 0; o++, v++) /* 5th octant */ SetV (v, op.x, op.y, -op.z, on.x, on.y, -on.z); for (j = i; --j > 0; o--, v++) /* 6th octant */ SetV (v, -op.x, op.y, -op.z, -on.x, on.y, -on.z); for (j = i; --j > 0; o++, v++) /* 7th octant */ SetV (v, -op.x, -op.y, -op.z, -on.x, -on.y, -on.z); for (j = i; --j > 0; o--, v++) /* 8th octant */ SetV (v, op.x, -op.y, -op.z, on.x, -on.y, -on.z); } o--, SetV (v, -op.x, -op.y, -op.z, -on.x, -on.y, -on.z); /* the south pole */#undef op#undef on /* Generate triangular faces of the ellipsoid. */ f = ellipsoid->f; kv = 0, kw = 1; for (i = 0; i < n; i++) { kv0 = kv, kw0 = kw; for (ko = 1; ko <= 3; ko++) /* the 1st, 2nd, 3rd octants */ for (j = i;; j--) { SetF (f, kv, kw, ++kw), f++; if (j == 0) break; SetF (f, kv, kw, ++kv), f++; } for (j = i;; j--) { /* the 4th octant */ if (j == 0) { SetF (f, kv0, kw, kw0), kv++, kw++, f++; break; } SetF (f, kv, kw, ++kw), f++; if (j == 1) SetF (f, kv, kw, kv0), f++; else SetF (f, kv, kw, ++kv), f++; } } for (; --i >= 0;) { kv0 = kv, kw0 = kw; for (ko = 5; ko <= 7; ko++) /* the 5th, 6th, 7th octants */ for (j = i;; j--) { SetF (f, kv, kw, ++kv), f++; if (j == 0) break; SetF (f, kv, kw, ++kw), f++; } for (j = i;; j--) { /* the 8th octant */ if (j == 0) { SetF (f, kv, kw0, kv0), kv++, kw++, f++; break; } SetF (f, kv, kw, ++kv), f++; if (j == 1) SetF (f, kv, kw, kw0), f++; else SetF (f, kv, kw, ++kw), f++; } }}/* parallel version */void ellipsoid_par (object *ellipsoid, int n, float a, float b, float c){ int nv, nf; vertex *ev; face *ef; /* Check parameters for validity. */ if (n <= 0 || n_max < n || a <= 0.0 || b <= 0.0 || c <= 0.0) { ellipsoid->nv = 0; ellipsoid->v = NULL; ellipsoid->nf = 0; ellipsoid->f = NULL; return; } /* Initialize the base octant. */ ellipsoid_octant (n, a, b, c); /* Allocate memories for vertices and faces. */ nv = ellipsoid->nv = 4*n*n + 2; nf = ellipsoid->nf = 8*n*n; ev = ellipsoid->v = (vertex *) malloc (nv * sizeof(vertex)); ef = ellipsoid->f = (face *) malloc (nf * sizeof(face)); ellipsoid_par_help (n, nv, nf, ev, ef, octant);}/* A utility function that simply outputs the ellipsoid data. */void ellipsoid_print (object *ellipsoid){ int i; vertex *v; face *f; for (v = ellipsoid->v, i = 0; i < ellipsoid->nv; i++, v++) printf ("v %g %g %g %g %g %g\n", v->p.x, v->p.y, v->p.z, v->n.x, v->n.y, v->n.z); for (f = ellipsoid->f, i = 0; i < ellipsoid->nf; i++, f++) printf ("f %d %d %d\n", f->v0, f->v1, f->v2);}/* undo of ellipsoid_init () */void ellipsoid_done (void){ n_max = 0; if (table) free (table), table = NULL; if (octant) free (octant), octant = NULL;}/* undo of ellipsoid_seq () */void ellipsoid_free (object *ellipsoid){ free (ellipsoid->v), ellipsoid->nv = 0, ellipsoid->v = NULL; free (ellipsoid->f), ellipsoid->nf = 0, ellipsoid->f = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -