home *** CD-ROM | disk | FTP | other *** search
- #include "geom.h"
- #include "polylistP.h"
- #include "discgrpP.h"
- #include "point.h"
- #include "winged_edge.h"
- #include "transform.h"
- #include "math.h"
-
- static WEpolyhedron *wepoly1, **wepoly2;
- HPoint3 DGorigin = {0,0,0,1};
- HPoint3 DGrandom = {.1,.2,.3,.4};
-
- static int
- is_id(Transform t)
- {
- register int i,j;
-
- for (i=0; i<4; ++i)
- for (j=0; j<4; ++j)
- if (fabs(t[i][j] - (i == j)) > .0005) return(0);
- return(1);
- }
-
- /* make sure that the center point attached to the discrete group
- isn't fixed by some generator; if it is; redefine the center
- point to be the center of gravity of the orbit by the generators
- */
- void
- DiscGrpCheckCPoint(register DiscGrp *dg)
- {
- int i, cnt, fixed;
- HPoint3 tmp, out;
- float d;
-
- if (dg->gens == NULL) {
- return;
- }
-
- /* go through the generators, checking for fixed-pointed-ness */
- for (i = 0, fixed = 0 ; i < dg->gens->num_el; ++i )
- {
- HPt3Transform(dg->gens->el_list[i].tform, &dg->cpoint, &tmp);
- d = HPt3SpaceDistance(&dg->cpoint, &tmp, dg->attributes & DG_METRIC_BITS);
- if (fabs(d) < .0005) {
- fixed = 1;
- break;
- }
- }
-
- /* no fixed points */
- if (fixed == 0) return;
-
- /* clean out the special bit */
- for (i = 0 ; i < dg->gens->num_el; ++i )
- dg->gens->el_list[i].attributes &= ~DG_TMP;
-
- out.x = out.y = out.z = out.w = 0.0;
- /* don't average but one of each generator, inverse pair */
- for (cnt = 0, i = 0 ; i < dg->gens->num_el; ++i ) {
- if (!(dg->gens->el_list[i].attributes & DG_TMP)) {
- HPt3Transform(dg->gens->el_list[i].tform, &DGrandom, &tmp);
- HPt3Add(&tmp, &out, &out);
- dg->gens->el_list[i].inverse->attributes |= DG_TMP;
- cnt++;
- }
- }
- HPt3Dehomogenize(&out, &out);
- /* return it or set cpoint?? */
- dg->cpoint = out;
- }
-
- void
- DiscGrpAddInverses(register DiscGrp *discgrp)
- {
- int i, j, found = 0;
- Transform product, inverse;
- DiscGrpElList *newgens;
-
- /* remove all identity matrices */
- for (j=0, i=0; i<discgrp->gens->num_el; ++i) {
- if ( !is_id(discgrp->gens->el_list[i].tform) ) {
- /* ought to have a DiscGrpElCopy() */
- discgrp->gens->el_list[j] = discgrp->gens->el_list[i];
- TmCopy(discgrp->gens->el_list[i].tform,
- discgrp->gens->el_list[j].tform);
- j++;
- }
- }
- /* store the new count */
- discgrp->gens->num_el = j;
-
- for (i=0; i<discgrp->gens->num_el; ++i) {
- if (discgrp->gens->el_list[i].inverse == NULL) {
- /* look for inverse among the existing generators */
- for (j=i; j<discgrp->gens->num_el; ++j) {
- TmConcat(discgrp->gens->el_list[i].tform, discgrp->gens->el_list[j].tform, product);
- if ( is_id(product) ) {
- discgrp->gens->el_list[i].inverse = &discgrp->gens->el_list[j];
- discgrp->gens->el_list[j].inverse = &discgrp->gens->el_list[i];
- found++;
- }
- }
- }
- else found++;
- }
-
- newgens = OOGLNew(DiscGrpElList);
- newgens->num_el = 2 * discgrp->gens->num_el - found;
- newgens->el_list = OOGLNewN(DiscGrpEl, newgens->num_el );
-
- bcopy(discgrp->gens->el_list, newgens->el_list, sizeof(DiscGrpEl) * discgrp->gens->num_el);
-
- /* now go through looking for group elements without inverses */
- {
- char c;
- j = discgrp->gens->num_el;
- for (i=0; i<discgrp->gens->num_el; ++i) {
- if (newgens->el_list[i].inverse == NULL) {
- newgens->el_list[j+i] = newgens->el_list[i];
- /* make the symbol of the inverse be the 'other case' */
- c = newgens->el_list[i].word[0];
- if (c < 'a') newgens->el_list[j+i].word[0] = c + 32;
- else newgens->el_list[j+i].word[0] = c - 32;
- TmInvert( newgens->el_list[i].tform, newgens->el_list[j+i].tform);
- newgens->el_list[j+i].inverse = &newgens->el_list[i];
- newgens->el_list[i].inverse = &newgens->el_list[j+i];
- }
- else j--;
- }
- }
-
- DiscGrpElListDelete(discgrp->gens);
- discgrp->gens = newgens;
- }
-
- void
- DiscGrpSetupDirdom(register DiscGrp *discgrp)
- {
- WEpolyhedron *dd;
-
- if ( discgrp->nhbr_list ) {
- OOGLFree(discgrp->nhbr_list->el_list);
- OOGLFree(discgrp->nhbr_list);
- }
-
- /* worry about fixed points */
- DiscGrpCheckCPoint(discgrp);
- dd = DiscGrpMakeDirdom(discgrp, &discgrp->cpoint, 0);
- discgrp->nhbr_list = DiscGrpExtractNhbrs(dd);
- }
-
- /* find the group element whose 'center point' is closest to the point poi */
- DiscGrpEl *
- DiscGrpClosestGroupEl(register DiscGrp *discgrp, HPoint3 *poi)
- {
- int count, i, closeri;
- int metric;
- float min, d;
- HPoint3 pt0, pt1;
- DiscGrpEl *closer, *closest = OOGLNew(DiscGrpEl);
- Transform cinv;
-
- TmIdentity(closest->tform);
-
- if (!discgrp->nhbr_list) DiscGrpSetupDirdom(discgrp);
-
- metric = discgrp->attributes & (DG_METRIC_BITS);
-
- /* iterate until we're in the fundamental domain */
- count = 0;
- closeri = -1;
- pt0 = *poi;
- while (count < 1000 && closeri != 0) {
- for (i = 0; i<discgrp->nhbr_list->num_el; ++i) {
- HPt3Transform(discgrp->nhbr_list->el_list[i].tform, &discgrp->cpoint, &pt1);
- d = HPt3SpaceDistance(&pt0, &pt1, metric);
- if (i==0) {
- min = d;
- closer = &discgrp->nhbr_list->el_list[i];
- closeri = i;
- }
- else if (d < min) {
- min = d;
- closer = &discgrp->nhbr_list->el_list[i];
- closeri = i;
- }
- }
- count++;
- if (closeri) {
- TmConcat(closer->tform, closest->tform, closest->tform);
- /* move the point of interest by the inverse of the closest nhbr
- and iterate */
- TmInvert(closest->tform, cinv);
- HPt3Transform(cinv, poi, &pt0);
- }
- }
- return (closest);
- }
- static ColorA white = {1,1,1,1};
-
- /* return a list of group elements corresponding to the faces of the
- dirichlet domain */
- DiscGrpElList *
- DiscGrpExtractNhbrs( WEpolyhedron *wepoly )
- {
- register int i,j,k;
- int flag = 0, wl;
- WEface *fptr;
- DiscGrpElList *mylist;
- ColorA GetCmapEntry();
-
- if (!wepoly) return(NULL);
-
- /* should use realloc() here to take care of large groups...*/
- mylist = OOGLNew(DiscGrpElList);
- mylist->el_list = OOGLNewN(DiscGrpEl, wepoly->num_faces + 1);
- mylist->num_el = wepoly->num_faces + 1;
-
- /* include the identity matrix */
- TmIdentity( mylist->el_list[0].tform);
- mylist->el_list[0].color = white;
-
- /* read the matrices corresponding to the faces of dirichlet domain */
- for (fptr = wepoly->face_list, k = 1;
- k<=wepoly->num_faces && fptr != NULL;
- k++, fptr = fptr->next)
- {
- for (i=0; i<4; ++i)
- for (j=0; j<4; ++j)
- /* the group elements stored in fptr are transposed! */
- mylist->el_list[k].tform[j][i] = fptr->group_element[i][j];
- mylist->el_list[k].color = GetCmapEntry(fptr->fill_tone);
- }
- if (mylist->num_el != k)
- OOGLError(1,"Incorrect number of nhbrs.\n");;
-
- return(mylist);
- }
-
- /* attempt to create a scaled copy of fundamental domain for spherical
- groups by taking weighted sum of vertices with the distinguished point */
- static void
- DiscGrpScalePolyList(DiscGrp *dg, PolyList *dirdom, HPoint3 *pt0, float scale)
- {
- PolyList *copy;
- int i, metric;
- HPoint3 tmp1, tmp2, tpt0, tpt1;
- HPt3Copy(pt0, &tpt0);
- metric = dg->attributes & DG_METRIC_BITS;
- if (metric != DG_EUCLIDEAN) {
- HPt3SpaceNormalize(&tpt0, metric);
- HPt3Scale( 1.0 - scale, &tpt0, &tmp2);
- for (i=0; i<dirdom->n_verts; ++i) {
- HPt3Copy(&dirdom->vl[i].pt, &tpt1);
- HPt3SpaceNormalize(&tpt1, metric);
- HPt3SpaceNormalize(&tpt1, metric);
- HPt3Scale( scale, &tpt1, &tmp1);
- HPt3Add(&tmp1, &tmp2, &dirdom->vl[i].pt);
- }
- }
- else {
- Transform T, TT, ITT, tmp;
- static HPoint3 average = {0,0,0,0};
- /* compute average */
- for (i=0; i<dirdom->n_verts; ++i)
- HPt3Add(&average, &dirdom->vl[i].pt, &average);
- HPt3Dehomogenize(&average, &average);
-
- TmTranslate(TT, average.x, average.y, average.z );
- TmInvert(TT, ITT);
- TmScale(T, scale, scale, scale);
- TmConcat(ITT, T, tmp);
- TmConcat(tmp, TT, tmp);
- for (i=0; i<dirdom->n_verts; ++i)
- HPt3Transform(tmp, &dirdom->vl[i].pt, &dirdom->vl[i].pt);
- }
- }
-
- Geom *small_dd, *large_dd;
- Geom *
- DiscGrpDirDom(register DiscGrp *dg)
- {
- Geom *oogldirdom;
- WEpolyhedron *dd;
- HPoint3 pt1;
- extern Geom *WEPolyhedronToPolyList();
- Geom *mylist, *smlist;
-
- if (dg->flag & DG_DDBEAM) {
- WEpolyhedron *poly = DiscGrpMakeDirdom( dg, &dg->cpoint, 0);
- Geom *beams;
- beams = WEPolyhedronToBeams(poly, dg->scale);
- return(beams);
- }
- else {
- float scale;
- /* first a full-size, wireframe version of dd */
- dd = DiscGrpMakeDirdom(dg, &dg->cpoint, 0);
- if (dd) {
- oogldirdom = WEPolyhedronToPolyList(dd);
- scale = 1.0;
- DiscGrpScalePolyList(dg, (PolyList*)oogldirdom, &dg->cpoint, scale);
- large_dd = oogldirdom;
- large_dd->ap = ApCreate(AP_DO, APF_EDGEDRAW, AP_DONT, APF_FACEDRAW, AP_END);
- }
- else return((Geom *) NULL);
- /* next a scaled version with cusps cut off */
- dd = DiscGrpMakeDirdom(dg, &dg->cpoint, 1);
- if (dd) {
- oogldirdom = WEPolyhedronToPolyList(dd);
- DiscGrpScalePolyList(dg, (PolyList*)oogldirdom, &dg->cpoint, dg->scale);
- small_dd = oogldirdom;
- small_dd->ap = ApCreate(AP_DONT, APF_EDGEDRAW, AP_DO, APF_FACEDRAW, AP_END);
- }
- else return(NULL);
- smlist = GeomCreate("list", CR_GEOM, small_dd, CR_END);
- mylist = GeomCreate("list", CR_GEOM, large_dd, CR_CDR, smlist, CR_END);
- return(mylist);
- }
- }
-
- static WEpolyhedron *
- DiscGrpMakeDirdom(DiscGrp *gamma, HPoint3 *poi, int slice)
- {
- int i, j, k;
- WEvertex *vptr;
- Transform tr;
- proj_matrix *gen_list;
- point origin;
- int metric, transp;
-
- transp = gamma->attributes & DG_TRANSPOSED;
- /* transform from floating point to double, essentially */
- gen_list = OOGLNewN(proj_matrix, gamma->gens->num_el);
- /* jeff week's code basically uses transposed matrices, so
- if the transposed flag is set, we do nothing, otherwise we
- have to transpose! */
- for (i=0; i<gamma->gens->num_el; ++i)
- for (j=0; j<4; ++j)
- for (k=0; k<4; ++k)
- {
- if (transp) gen_list[i][j][k] = gamma->gens->el_list[i].tform[j][k];
- else gen_list[i][k][j] = gamma->gens->el_list[i].tform[j][k];
- }
- origin[0] = poi->x;
- origin[1] = poi->y;
- origin[2] = poi->z;
- origin[3] = poi->w;
-
- wepoly2 = &wepoly1;
- metric = (gamma->attributes & DG_METRIC_BITS);
- do_weeks_code(wepoly2, origin, gen_list, gamma->gens->num_el, metric,slice);
-
- free(gen_list);
-
- /* turn off the 'new dirdom' bit */
- gamma->flag &= ~DG_NEWDIRDOM;
- return(*wepoly2);
- }
-
- Geom *
- DiscGrpBeamedDirDom(DiscGrp *dg, float alpha)
- {
- }
-
-