diff options
| author | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
| commit | badef32037f52f79abc1f1440b786cd71afdf270 (patch) | |
| tree | 412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/polyhedra.c | |
| parent | Delete pre-6.00 files (diff) | |
| download | xscreensaver-master.tar.gz xscreensaver-master.tar.xz xscreensaver-master.zip | |
Diffstat (limited to 'hacks/glx/polyhedra.c')
| -rw-r--r-- | hacks/glx/polyhedra.c | 2458 |
1 files changed, 0 insertions, 2458 deletions
diff --git a/hacks/glx/polyhedra.c b/hacks/glx/polyhedra.c deleted file mode 100644 index 98e6891..0000000 --- a/hacks/glx/polyhedra.c +++ /dev/null @@ -1,2458 +0,0 @@ -/***************************************************************************** - * #ident "Id: main.c,v 3.27 2002-01-06 16:23:01+02 rl Exp " - * kaleido - * - * Kaleidoscopic construction of uniform polyhedra - * Copyright (c) 1991-2002 Dr. Zvi Har'El <rl@math.technion.ac.il> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Dr. Zvi Har'El (http://www.math.technion.ac.il/~rl/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any - * damages arising from the use of this software. - * - * Author: - * Dr. Zvi Har'El, - * Deptartment of Mathematics, - * Technion, Israel Institue of Technology, - * Haifa 32000, Israel. - * E-Mail: rl@math.technion.ac.il - * - * ftp://ftp.math.technion.ac.il/kaleido/ - * http://www.mathconsult.ch/showroom/unipoly/ - * - * Adapted for xscreensaver by Jamie Zawinski <jwz@jwz.org> 25-Apr-2004 - * - ***************************************************************************** - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <math.h> -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> - -#include "polyhedra.h" - -extern const char *progname; - -#ifndef MAXLONG -#define MAXLONG 0x7FFFFFFF -#endif -#ifndef MAXDIGITS -#define MAXDIGITS 10 /* (int)log10((double)MAXLONG) + 1 */ -#endif - -#ifndef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 -#endif -#define BIG_EPSILON 3e-2 -#define AZ M_PI/7 /* axis azimuth */ -#define EL M_PI/17 /* axis elevation */ - -#define Err(x) do {\ - fprintf (stderr, "%s: %s\n", progname, (x)); \ - exit (1); \ - } while(0) - -#define Free(lvalue) do {\ - if (lvalue) {\ - free((char*) lvalue);\ - lvalue=0;\ - }\ - } while(0) - -#define Matfree(lvalue,n) do {\ - if (lvalue) \ - matfree((char*) lvalue, n);\ - lvalue=0;\ - } while(0) - -#define Malloc(lvalue,n,type) do {\ - if (!(lvalue = (type*) calloc((n), sizeof(type)))) \ - abort();\ - } while(0) - -#define Realloc(lvalue,n,type) do {\ - if (!(lvalue = (type*) realloc(lvalue, (n) * sizeof(type)))) \ - abort();\ - } while(0) - -#define Calloc(lvalue,n,type) do {\ - if (!(lvalue = (type*) calloc(n, sizeof(type))))\ - abort();\ - } while(0) - -#define Matalloc(lvalue,n,m,type) do {\ - if (!(lvalue = (type**) matalloc(n, (m) * sizeof(type))))\ - abort();\ - } while(0) - -#define Sprintfrac(lvalue,x) do {\ - if (!(lvalue=sprintfrac(x)))\ - return 0;\ - } while(0) - -#define numerator(x) (frac(x), frax.n) -#define denominator(x) (frac(x), frax.d) -#define compl(x) (frac(x), (double) frax.n / (frax.n-frax.d)) - -typedef struct { - double x, y, z; -} Vector; - -typedef struct { - /* NOTE: some of the int's can be replaced by short's, char's, - or even bit fields, at the expense of readability!!!*/ - int index; /* index to the standard list, the array uniform[] */ - int N; /* number of faces types (atmost 5)*/ - int M; /* vertex valency (may be big for dihedral polyhedra) */ - int V; /* vertex count */ - int E; /* edge count */ - int F; /* face count */ - int D; /* density */ - int chi; /* Euler characteristic */ - int g; /* order of symmetry group */ - int K; /* symmetry type: D=2, T=3, O=4, I=5 */ - int hemi;/* flag hemi polyhedron */ - int onesided;/* flag onesided polyhedron */ - int even; /* removed face in pqr| */ - int *Fi; /* face counts by type (array N)*/ - int *rot; /* vertex configuration (array M of 0..N-1) */ - int *snub; /* snub triangle configuration (array M of 0..1) */ - int *firstrot; /* temporary for vertex generation (array V) */ - int *anti; /* temporary for direction of ideal vertices (array E) */ - int *ftype; /* face types (array F) */ - int **e; /* edges (matrix 2 x E of 0..V-1)*/ - int **dual_e; /* dual edges (matrix 2 x E of 0..F-1)*/ - int **incid; /* vertex-face incidence (matrix M x V of 0..F-1)*/ - int **adj; /* vertex-vertex adjacency (matrix M x V of 0..V-1)*/ - double p[4]; /* p, q and r; |=0 */ - double minr; /* smallest nonzero inradius */ - double gon; /* basis type for dihedral polyhedra */ - double *n; /* number of side of a face of each type (array N) */ - double *m; /* number of faces at a vertex of each type (array N) */ - double *gamma; /* fundamental angles in radians (array N) */ - char *polyform; /* printable Wythoff symbol */ - char *config; /* printable vertex configuration */ - char *group; /* printable group name */ - char *name; /* name, standard or manifuctured */ - char *dual_name; /* dual name, standard or manifuctured */ - char *class; - char *dual_class; - Vector *v; /* vertex coordinates (array V) */ - Vector *f; /* face coordinates (array F)*/ -} Polyhedron; - -typedef struct { - long n,d; -} Fraction; - -static Polyhedron *polyalloc(void); -static Vector rotate(Vector vertex, Vector axis, double angle); - -static Vector sum3(Vector a, Vector b, Vector c); -static Vector scale(double k, Vector a); -static Vector sum(Vector a, Vector b); -static Vector diff(Vector a, Vector b); -static Vector pole (double r, Vector a, Vector b, Vector c); -static Vector cross(Vector a, Vector b); -static double dot(Vector a, Vector b); -static int same(Vector a, Vector b, double epsilon); - -static char *sprintfrac(double x); - -static void frac(double x); -static void matfree(void *mat, int rows); -static void *matalloc(int rows, int row_size); - -static Fraction frax; - - -static const struct { - char *Wythoff, *name, *dual, *group, *class, *dual_class; - short Coxeter, Wenninger; -} uniform[] = { - - /**************************************************************************** - * Dihedral Schwarz Triangles (D5 only) - ***************************************************************************/ - - /* 0 */ {"2 5|2", "Pentagonal Prism", - "Pentagonal Dipyramid", - "Dihedral (D[1/5])", - "", - "", - 0, 0}, - - /* 2 */ {"|2 2 5", "Pentagonal Antiprism", - "Pentagonal Deltohedron", - "Dihedral (D[1/5])", - "", - "", - 0, 0}, - /* (2 2 5/2) (D2/5) */ - /* 4 */ {"2 5/2|2", "Pentagrammic Prism", - "Pentagrammic Dipyramid", - "Dihedral (D[2/5])", - "", - "", - 0, 0}, - - /* 6 */ {"|2 2 5/2", "Pentagrammic Antiprism", - "Pentagrammic Deltohedron", - "Dihedral (D[2/5])", - "", - "", - 0, 0}, - /* (5/3 2 2) (D3/5) */ - - /* 8 */ {"|2 2 5/3", "Pentagrammic Crossed Antiprism", - "Pentagrammic Concave Deltohedron", - "Dihedral (D[3/5])", - "", - "", - 0, 0}, - - /**************************************************************************** - * Tetrahedral - ***************************************************************************/ - - /* (2 3 3) (T1) */ - /* 10 */ {"3|2 3", "Tetrahedron", - "Tetrahedron", - "Tetrahedral (T[1])", - "Platonic Solid", - "Platonic Solid", - 15, 1}, - - /* 12 */ {"2 3|3", "Truncated Tetrahedron", - "Triakistetrahedron", - "Tetrahedral (T[1])", - "Archimedean Solid", - "Catalan Solid", - 16, 6}, - /* (3/2 3 3) (T2) */ - /* 14 */ {"3/2 3|3", "Octahemioctahedron", - "Octahemioctacron", - "Tetrahedral (T[2])", - "", - "", - 37, 68}, - - /* (3/2 2 3) (T3) */ - /* 16 */ {"3/2 3|2", "Tetrahemihexahedron", - "Tetrahemihexacron", - "Tetrahedral (T[3])", - "", - "", - 36, 67}, - - /**************************************************************************** - * Octahedral - ***************************************************************************/ - - /* (2 3 4) (O1) */ - /* 18 */ {"4|2 3", "Octahedron", - "Cube", - "Octahedral (O[1])", - "Platonic Solid", - "Platonic Solid", - 17, 2}, - - /* 20 */ {"3|2 4", "Cube", - "Octahedron", - "Octahedral (O[1])", - "Platonic Solid", - "Platonic Solid", - 18, 3}, - - /* 22 */ {"2|3 4", "Cuboctahedron", - "Rhombic Dodecahedron", - "Octahedral (O[1])", - "Archimedean Solid", - "Catalan Solid", - 19, 11}, - - /* 24 */ {"2 4|3", "Truncated Octahedron", - "Tetrakishexahedron", - "Octahedral (O[1])", - "Archimedean Solid", - "Catalan Solid", - 20, 7}, - - /* 26 */ {"2 3|4", "Truncated Cube", - "Triakisoctahedron", - "Octahedral (O[1])", - "Archimedean Solid", - "Catalan Solid", - 21, 8}, - - /* 28 */ {"3 4|2", "Rhombicuboctahedron", - "Deltoidal Icositetrahedron", - "Octahedral (O[1])", - "Archimedean Solid", - "Catalan Solid", - 22, 13}, - - /* 30 */ {"2 3 4|", "Truncated Cuboctahedron", - "Disdyakisdodecahedron", - "Octahedral (O[1])", - "Archimedean Solid", - "Catalan Solid", - 23, 15}, - - /* 32, 33, 66, and 67 are chiral, existing in both left and right handed - (enantiomeric) forms, so it would make sense to display both versions. - */ - - /* 32 */ {"|2 3 4", "Snub Cube", - "Pentagonal Icositetrahedron", - "Octahedral (O[1]), Chiral", - "Archimedean Solid", - "Catalan Solid", - 24, 17}, - /* (3/2 4 4) (O2b) */ - - /* 34 */ {"3/2 4|4", "Small Cubicuboctahedron", - "Small Hexacronic Icositetrahedron", - "Octahedral (O[2b])", - "", - "", - 38, 69}, - /* (4/3 3 4) (O4) */ - - /* 36 */ {"3 4|4/3", "Great Cubicuboctahedron", - "Great Hexacronic Icositetrahedron", - "Octahedral (O[4])", - "", - "", - 50, 77}, - - /* 38 */ {"4/3 4|3", "Cubohemioctahedron", - "Hexahemioctacron", - "Octahedral (O[4])", - "", - "", - 51, 78}, - - /* 40 */ {"4/3 3 4|", "Cubitruncated Cuboctahedron", - "Tetradyakishexahedron", - "Octahedral (O[4])", - "", - "", - 52, 79}, - /* (3/2 2 4) (O5) */ - - /* 42 */ {"3/2 4|2", "Great Rhombicuboctahedron", - "Great Deltoidal Icositetrahedron", - "Octahedral (O[5])", - "", - "", - 59, 85}, - - /* 44 */ {"3/2 2 4|", "Small Rhombihexahedron", - "Small Rhombihexacron", - "Octahedral (O[5])", - "", - "", - 60, 86}, - /* (4/3 2 3) (O7) */ - - /* 46 */ {"2 3|4/3", "Stellated Truncated Hexahedron", - "Great Triakisoctahedron", - "Octahedral (O[7])", - "", - "", - 66, 92}, - - /* 48 */ {"4/3 2 3|", "Great Truncated Cuboctahedron", - "Great Disdyakisdodecahedron", - "Octahedral (O[7])", - "", - "", - 67, 93}, - /* (4/3 3/2 2) (O11) */ - - /* 50 */ {"4/3 3/2 2|", "Great Rhombihexahedron", - "Great Rhombihexacron", - "Octahedral (O[11])", - "", - "", - 82, 103}, - - /**************************************************************************** - * Icosahedral - ***************************************************************************/ - - /* (2 3 5) (I1) */ - /* 52 */ {"5|2 3", "Icosahedron", - "Dodecahedron", - "Icosahedral (I[1])", - "Platonic Solid", - "Platonic Solid", - 25, 4}, - - /* 54 */ {"3|2 5", "Dodecahedron", - "Icosahedron", - "Icosahedral (I[1])", - "Platonic Solid", - "Platonic Solid", - 26, 5}, - - /* 56 */ {"2|3 5", "Icosidodecahedron", - "Rhombic Triacontahedron", - "Icosahedral (I[1])", - "Archimedean Solid", - "Catalan Solid", - 28, 12}, - - /* 58 */ {"2 5|3", "Truncated Icosahedron", - "Pentakisdodecahedron", - "Icosahedral (I[1])", - "Archimedean Solid", - "Catalan Solid", - 27, 9}, - - /* 60 */ {"2 3|5", "Truncated Dodecahedron", - "Triakisicosahedron", - "Icosahedral (I[1])", - "Archimedean Solid", - "Catalan Solid", - 29, 10}, - - /* 62 */ {"3 5|2", "Rhombicosidodecahedron", - "Deltoidal Hexecontahedron", - "Icosahedral (I[1])", - "Archimedean Solid", - "Catalan Solid", - 30, 14}, - - /* 64 */ {"2 3 5|", "Truncated Icosidodecahedron", - "Disdyakistriacontahedron", - "Icosahedral (I[1])", - "Archimedean Solid", - "Catalan Solid", - 31, 16}, - - /* 32, 33, 66, and 67 are chiral, existing in both left and right handed - (enantiomeric) forms, so it would make sense to display both versions. - */ - - /* 66 */ {"|2 3 5", "Snub Dodecahedron", - "Pentagonal Hexecontahedron", - "Icosahedral (I[1]), Chiral", - "Archimedean Solid", - "Catalan Solid", - 32, 18}, - /* (5/2 3 3) (I2a) */ - - /* 68 */ {"3|5/2 3", "Small Ditrigonal Icosidodecahedron", - "Small Triambic Icosahedron", - "Icosahedral (I[2a])", - "", - "", - 39, 70}, - - /* 70 */ {"5/2 3|3", "Small Icosicosidodecahedron", - "Small Icosacronic Hexecontahedron", - "Icosahedral (I[2a])", - "", - "", - 40, 71}, - - /* 72 */ {"|5/2 3 3", "Small Snub Icosicosidodecahedron", - "Small Hexagonal Hexecontahedron", - "Icosahedral (I[2a])", - "", - "", - 41, 110}, - /* (3/2 5 5) (I2b) */ - - /* 74 */ {"3/2 5|5", "Small Dodecicosidodecahedron", - "Small Dodecacronic Hexecontahedron", - "Icosahedral (I[2b])", - "", - "", - 42, 72}, - /* (2 5/2 5) (I3) */ - - /* 76 */ {"5|2 5/2", "Small Stellated Dodecahedron", - "Great Dodecahedron", - "Icosahedral (I[3])", - "Kepler-Poinsot Solid", - "Kepler-Poinsot Solid", - 43, 20}, - - /* 78 */ {"5/2|2 5", "Great Dodecahedron", - "Small Stellated Dodecahedron", - "Icosahedral (I[3])", - "Kepler-Poinsot Solid", - "Kepler-Poinsot Solid", - 44, 21}, - - /* 80 */ {"2|5/2 5", "Great Dodecadodecahedron", - "Medial Rhombic Triacontahedron", - "Icosahedral (I[3])", - "", - "", - 45, 73}, - - /* 82 */ {"2 5/2|5", "Truncated Great Dodecahedron", - "Small Stellapentakisdodecahedron", - "Icosahedral (I[3])", - "", - "", - 47, 75}, - - /* 84 */ {"5/2 5|2", "Rhombidodecadodecahedron", - "Medial Deltoidal Hexecontahedron", - "Icosahedral (I[3])", - "", - "", - 48, 76}, - - /* 86 */ {"2 5/2 5|", "Small Rhombidodecahedron", - "Small Rhombidodecacron", - "Icosahedral (I[3])", - "", - "", - 46, 74}, - - /* 88 */ {"|2 5/2 5", "Snub Dodecadodecahedron", - "Medial Pentagonal Hexecontahedron", - "Icosahedral (I[3])", - "", - "", - 49, 111}, - /* (5/3 3 5) (I4) */ - - /* 90 */ {"3|5/3 5", "Ditrigonal Dodecadodecahedron", - "Medial Triambic Icosahedron", - "Icosahedral (I[4])", - "", - "", - 53, 80}, - - /* 92 */ {"3 5|5/3", "Great Ditrigonal Dodecicosidodecahedron", - "Great Ditrigonal Dodecacronic Hexecontahedron", - "Icosahedral (I[4])", - "", - "", - 54, 81}, - - /* 94 */ {"5/3 3|5", "Small Ditrigonal Dodecicosidodecahedron", - "Small Ditrigonal Dodecacronic Hexecontahedron", - "Icosahedral (I[4])", - "", - "", - 55, 82}, - - /* 96 */ {"5/3 5|3", "Icosidodecadodecahedron", - "Medial Icosacronic Hexecontahedron", - "Icosahedral (I[4])", - "", - "", - 56, 83}, - - /* 98 */ {"5/3 3 5|", "Icositruncated Dodecadodecahedron", - "Tridyakisicosahedron", - "Icosahedral (I[4])", - "", - "", - 57, 84}, - - /* 100 */ {"|5/3 3 5", "Snub Icosidodecadodecahedron", - "Medial Hexagonal Hexecontahedron", - "Icosahedral (I[4])", - "", - "", - 58, 112}, - /* (3/2 3 5) (I6b) */ - - /* 102 */ {"3/2|3 5", "Great Ditrigonal Icosidodecahedron", - "Great Triambic Icosahedron", - "Icosahedral (I[6b])", - "", - "", - 61, 87}, - - /* 104 */ {"3/2 5|3", "Great Icosicosidodecahedron", - "Great Icosacronic Hexecontahedron", - "Icosahedral (I[6b])", - "", - "", - 62, 88}, - - /* 106 */ {"3/2 3|5", "Small Icosihemidodecahedron", - "Small Icosihemidodecacron", - "Icosahedral (I[6b])", - "", - "", - 63, 89}, - - /* 108 */ {"3/2 3 5|", "Small Dodecicosahedron", - "Small Dodecicosacron", - "Icosahedral (I[6b])", - "", - "", - 64, 90}, - /* (5/4 5 5) (I6c) */ - - /* 110 */ {"5/4 5|5", "Small Dodecahemidodecahedron", - "Small Dodecahemidodecacron", - "Icosahedral (I[6c])", - "", - "", - 65, 91}, - /* (2 5/2 3) (I7) */ - - /* 112 */ {"3|2 5/2", "Great Stellated Dodecahedron", - "Great Icosahedron", - "Icosahedral (I[7])", - "Kepler-Poinsot Solid", - "Kepler-Poinsot Solid", - 68, 22}, - - /* 114 */ {"5/2|2 3", "Great Icosahedron", - "Great Stellated Dodecahedron", - "Icosahedral (I[7])", - "Kepler-Poinsot Solid", - "Kepler-Poinsot Solid", - 69, 41}, - - /* 116 */ {"2|5/2 3", "Great Icosidodecahedron", - "Great Rhombic Triacontahedron", - "Icosahedral (I[7])", - "", - "", - 70, 94}, - - /* 118 */ {"2 5/2|3", "Great Truncated Icosahedron", - "Great Stellapentakisdodecahedron", - "Icosahedral (I[7])", - "", - "", - 71, 95}, - - /* 120 */ {"2 5/2 3|", "Rhombicosahedron", - "Rhombicosacron", - "Icosahedral (I[7])", - "", - "", - 72, 96}, - - /* 122 */ {"|2 5/2 3", "Great Snub Icosidodecahedron", - "Great Pentagonal Hexecontahedron", - "Icosahedral (I[7])", - "", - "", - 73, 113}, - /* (5/3 2 5) (I9) */ - - /* 124 */ {"2 5|5/3", "Small Stellated Truncated Dodecahedron", - "Great Pentakisdodecahedron", - "Icosahedral (I[9])", - "", - "", - 74, 97}, - - /* 126 */ {"5/3 2 5|", "Truncated Dodecadodecahedron", - "Medial Disdyakistriacontahedron", - "Icosahedral (I[9])", - "", - "", - 75, 98}, - - /* 128 */ {"|5/3 2 5", "Inverted Snub Dodecadodecahedron", - "Medial Inverted Pentagonal Hexecontahedron", - "Icosahedral (I[9])", - "", - "", - 76, 114}, - /* (5/3 5/2 3) (I10a) */ - - /* 130 */ {"5/2 3|5/3", "Great Dodecicosidodecahedron", - "Great Dodecacronic Hexecontahedron", - "Icosahedral (I[10a])", - "", - "", - 77, 99}, - - /* 132 */ {"5/3 5/2|3", "Small Dodecahemicosahedron", - "Small Dodecahemicosacron", - "Icosahedral (I[10a])", - "", - "", - 78, 100}, - - /* 134 */ {"5/3 5/2 3|", "Great Dodecicosahedron", - "Great Dodecicosacron", - "Icosahedral (I[10a])", - "", - "", - 79, 101}, - - /* 136 */ {"|5/3 5/2 3", "Great Snub Dodecicosidodecahedron", - "Great Hexagonal Hexecontahedron", - "Icosahedral (I[10a])", - "", - "", - 80, 115}, - /* (5/4 3 5) (I10b) */ - - /* 138 */ {"5/4 5|3", "Great Dodecahemicosahedron", - "Great Dodecahemicosacron", - "Icosahedral (I[10b])", - "", - "", - 81, 102}, - /* (5/3 2 3) (I13) */ - - /* 140 */ {"2 3|5/3", "Great Stellated Truncated Dodecahedron", - "Great Triakisicosahedron", - "Icosahedral (I[13])", - "", - "", - 83, 104}, - - /* 142 */ {"5/3 3|2", "Great Rhombicosidodecahedron", - "Great Deltoidal Hexecontahedron", - "Icosahedral (I[13])", - "", - "", - 84, 105}, - - /* 144 */ {"5/3 2 3|", "Great Truncated Icosidodecahedron", - "Great Disdyakistriacontahedron", - "Icosahedral (I[13])", - "", - "", - 87, 108}, - - /* 146 */ {"|5/3 2 3", "Great Inverted Snub Icosidodecahedron", - "Great Inverted Pentagonal Hexecontahedron", - "Icosahedral (I[13])", - "", - "", - 88, 116}, - /* (5/3 5/3 5/2) (I18a) */ - - /* 148 */ {"5/3 5/2|5/3", "Great Dodecahemidodecahedron", - "Great Dodecahemidodecacron", - "Icosahedral (I[18a])", - "", - "", - 86, 107}, - /* (3/2 5/3 3) (I18b) */ - - /* 150 */ {"3/2 3|5/3", "Great Icosihemidodecahedron", - "Great Icosihemidodecacron", - "Icosahedral (I[18b])", - "", - "", - 85, 106}, - /* (3/2 3/2 5/3) (I22) */ - - /* 152 */ {"|3/2 3/2 5/2","Small Retrosnub Icosicosidodecahedron", - "Small Hexagrammic Hexecontahedron", - "Icosahedral (I[22])", - "", - "", - 91, 118}, - /* (3/2 5/3 2) (I23) */ - - /* 154 */ {"3/2 5/3 2|", "Great Rhombidodecahedron", - "Great Rhombidodecacron", - "Icosahedral (I[23])", - "", - "", - 89, 109}, - - /* 156 */ {"|3/2 5/3 2", "Great Retrosnub Icosidodecahedron", - "Great Pentagrammic Hexecontahedron", - "Icosahedral (I[23])", - "", - "", - 90, 117}, - - /**************************************************************************** - * Last But Not Least - ***************************************************************************/ - - /* 158 */ {"3/2 5/3 3 5/2", "Great Dirhombicosidodecahedron", - "Great Dirhombicosidodecacron", - "Non-Wythoffian", - "", - "", - 92, 119} -}; - -static int last_uniform = sizeof (uniform) / sizeof (uniform[0]); - - - -static int unpacksym(const char *sym, Polyhedron *P); -static int moebius(Polyhedron *P); -static int decompose(Polyhedron *P); -static int guessname(Polyhedron *P); -static int newton(Polyhedron *P, int need_approx); -static int exceptions(Polyhedron *P); -static int count(Polyhedron *P); -static int configuration(Polyhedron *P); -static int vertices(Polyhedron *P); -static int faces(Polyhedron *P); -static int edgelist(Polyhedron *P); - -static Polyhedron * -kaleido(const char *sym, - int need_coordinates, int need_edgelist, int need_approx, - int just_list) -{ - Polyhedron *P; - /* - * Allocate a Polyhedron structure P. - */ - if (!(P = polyalloc())) - return 0; - /* - * Unpack input symbol into P. - */ - if (!unpacksym(sym, P)) - return 0; - /* - * Find Mebius triangle, its density and Euler characteristic. - */ - if (!moebius(P)) - return 0; - /* - * Decompose Schwarz triangle. - */ - if (!decompose(P)) - return 0; - /* - * Find the names of the polyhedron and its dual. - */ - if (!guessname(P)) - return 0; - if (just_list) - return P; - /* - * Solve Fundamental triangles, optionally printing approximations. - */ - if (!newton(P,need_approx)) - return 0; - /* - * Deal with exceptional polyhedra. - */ - if (!exceptions(P)) - return 0; - /* - * Count edges and faces, update density and characteristic if needed. - */ - if (!count(P)) - return 0; - /* - * Generate printable vertex configuration. - */ - if (!configuration(P)) - return 0; - /* - * Compute coordinates. - */ - if (!need_coordinates && !need_edgelist) - return P; - if (!vertices(P)) - return 0; - if (!faces (P)) - return 0; - /* - * Compute edgelist. - */ - if (!need_edgelist) - return P; - if (!edgelist(P)) - return 0; - return P; -} - -/* - * Allocate a blank Polyhedron structure and initialize some of its nonblank - * fields. - * - * Array and matrix field are allocated when needed. - */ -static Polyhedron * -polyalloc() -{ - Polyhedron *P; - Calloc(P, 1, Polyhedron); - P->index = -1; - P->even = -1; - P->K = 2; - return P; -} - -/* - * Free the struture allocated by polyalloc(), as well as all the array and - * matrix fields. - */ -static void -polyfree(Polyhedron *P) -{ - Free(P->Fi); - Free(P->n); - Free(P->m); - Free(P->gamma); - Free(P->rot); - Free(P->snub); - Free(P->firstrot); - Free(P->anti); - Free(P->ftype); - Free(P->polyform); - Free(P->config); - if (P->index < 0) { - Free(P->name); - Free(P->dual_name); - } - Free(P->v); - Free(P->f); - Matfree(P->e, 2); - Matfree(P->dual_e, 2); - Matfree(P->incid, P->M); - Matfree(P->adj, P->M); - free(P); -} - -static void * -matalloc(int rows, int row_size) -{ - void **mat; - int i = 0; - if (!(mat = malloc(rows * sizeof (void *)))) - return 0; - while ((mat[i] = malloc(row_size)) && ++i < rows) - ; - if (i == rows) - return (void *)mat; - while (--i >= 0) - free(mat[i]); - free(mat); - return 0; -} - -static void -matfree(void *mat, int rows) -{ - while (--rows >= 0) - free(((void **)mat)[rows]); - free(mat); -} - -/* - * compute the mathematical modulus function. - */ -static int -mod (int i, int j) -{ - return (i%=j)>=0?i:j<0?i-j:i+j; -} - - -/* - * Find the numerator and the denominator using the Euclidean algorithm. - */ -static void -frac(double x) -{ - static const Fraction zero = {0,1}, inf = {1,0}; - Fraction r0, r; - long f; - double s = x; - r = zero; - frax = inf; - for (;;) { - if (fabs(s) > (double) MAXLONG) - return; - f = (long) floor (s); - r0 = r; - r = frax; - frax.n = frax.n * f + r0.n; - frax.d = frax.d * f + r0.d; - if (x == (double)frax.n/(double)frax.d) - return; - s = 1 / (s - f); - } -} - - -/* - * Unpack input symbol: Wythoff symbol or an index to uniform[]. The symbol is - * a # followed by a number, or a three fractions and a bar in some order. We - * allow no bars only if it result from the input symbol #80. - */ -static int -unpacksym(const char *sym, Polyhedron *P) -{ - int i = 0, n, d, bars = 0; - char c; - while ((c = *sym++) && isspace(c)) - ; - if (!c) Err("no data"); - if (c == '#') { - while ((c = *sym++) && isspace(c)) - ; - if (!c) - Err("no digit after #"); - if (!isdigit(c)) - Err("not a digit"); - n = c - '0'; - while ((c = *sym++) && isdigit(c)) - n = n * 10 + c - '0'; - if (!n) - Err("zero index"); - if (n > last_uniform) - Err("index too big"); - sym--; - while ((c = *sym++) && isspace(c)) - ; - if (c) - Err("data exceeded"); - sym = uniform[P->index = n - 1].Wythoff; - } else - sym--; - - for (;;) { - while ((c = *sym++) && isspace(c)) - ; - if (!c) { - if (i == 4 && (bars || P->index == last_uniform - 1)) - return 1; - if (!bars) - Err("no bars"); - Err("not enough fractions"); - } - if (i == 4) - Err("data exceeded"); - if (c == '|'){ - if (++bars > 1) - Err("too many bars"); - P->p[i++] = 0; - continue; - } - if (!isdigit(c)) - Err("not a digit"); - n = c - '0'; - while ((c = *sym++) && isdigit(c)) - n = n * 10 + c - '0'; - if (c && isspace (c)) - while ((c = *sym++) && isspace(c)) - ; - if (c != '/') { - sym--; - if ((P->p[i++] = n) <= 1) - Err("fraction<=1"); - continue; - } - while ((c = *sym++) && isspace(c)) - ; - if (!c || !isdigit(c)) - return 0; - d = c - '0'; - while ((c = *sym++) && isdigit(c)) - d = d * 10 + c - '0'; - if (!d) - Err("zero denominator"); - sym--; - if ((P->p[i++] = (double) n / d) <= 1) - Err("fraction<=1"); - } -} - -/* - * Using Wythoff symbol (p|qr, pq|r, pqr| or |pqr), find the Moebius triangle - * (2 3 K) (or (2 2 n)) of the Schwarz triangle (pqr), the order g of its - * symmetry group, its Euler characteristic chi, and its covering density D. - * g is the number of copies of (2 3 K) covering the sphere, i.e., - * - * g * pi * (1/2 + 1/3 + 1/K - 1) = 4 * pi - * - * D is the number of times g copies of (pqr) cover the sphere, i.e. - * - * D * 4 * pi = g * pi * (1/p + 1/q + 1/r - 1) - * - * chi is V - E + F, where F = g is the number of triangles, E = 3*g/2 is the - * number of triangle edges, and V = Vp+ Vq+ Vr, with Vp = g/(2*np) being the - * number of vertices with angle pi/p (np is the numerator of p). - */ -static int -moebius(Polyhedron *P) -{ - int twos = 0, j, len = 1; - /* - * Arrange Wythoff symbol in a presentable form. In the same time check the - * restrictions on the three fractions: They all have to be greater then one, - * and the numerators 4 or 5 cannot occur together. We count the ocurrences - * of 2 in `two', and save the largest numerator in `P->K', since they - * reflect on the symmetry group. - */ - P->K = 2; - if (P->index == last_uniform - 1) { - Malloc(P->polyform, ++len, char); - strcpy(P->polyform, "|"); - } else - Calloc(P->polyform, len, char); - for (j = 0; j < 4; j++) { - if (P->p[j]) { - char *s; - Sprintfrac(s, P->p[j]); - if (j && P->p[j-1]) { - Realloc(P->polyform, len += strlen (s) + 1, char); - strcat(P->polyform, " "); - } else - Realloc (P->polyform, len += strlen (s), char); - strcat(P->polyform, s); - free(s); - if (P->p[j] != 2) { - int k; - if ((k = numerator (P->p[j])) > P->K) { - if (P->K == 4) - break; - P->K = k; - } else if (k < P->K && k == 4) - break; - } else - twos++; - } else { - Realloc(P->polyform, ++len, char); - strcat(P->polyform, "|"); - } - } - /* - * Find the symmetry group P->K (where 2, 3, 4, 5 represent the dihedral, - * tetrahedral, octahedral and icosahedral groups, respectively), and its - * order P->g. - */ - if (twos >= 2) {/* dihedral */ - P->g = 4 * P->K; - P->K = 2; - } else { - if (P->K > 5) - Err("numerator too large"); - P->g = 24 * P->K / (6 - P->K); - } - /* - * Compute the nominal density P->D and Euler characteristic P->chi. - * In few exceptional cases, these values will be modified later. - */ - if (P->index != last_uniform - 1) { - int i; - P->D = P->chi = - P->g; - for (j = 0; j < 4; j++) if (P->p[j]) { - P->chi += i = P->g / numerator(P->p[j]); - P->D += i * denominator(P->p[j]); - } - P->chi /= 2; - P->D /= 4; - if (P->D <= 0) - Err("nonpositive density"); - } - return 1; -} - -/* - * Decompose Schwarz triangle into N right triangles and compute the vertex - * count V and the vertex valency M. V is computed from the number g of - * Schwarz triangles in the cover, divided by the number of triangles which - * share a vertex. It is halved for one-sided polyhedra, because the - * kaleidoscopic construction really produces a double orientable covering of - * such polyhedra. All q' q|r are of the "hemi" type, i.e. have equatorial {2r} - * faces, and therefore are (except 3/2 3|3 and the dihedra 2 2|r) one-sided. A - * well known example is 3/2 3|4, the "one-sided heptahedron". Also, all p q r| - * with one even denominator have a crossed parallelogram as a vertex figure, - * and thus are one-sided as well. - */ -static int -decompose(Polyhedron *P) -{ - int j, J, *s, *t; - if (!P->p[1]) { /* p|q r */ - P->N = 2; - P->M = 2 * numerator(P->p[0]); - P->V = P->g / P->M; - Malloc(P->n, P->N, double); - Malloc(P->m, P->N, double); - Malloc(P->rot, P->M, int); - s = P->rot; - for (j = 0; j < 2; j++) { - P->n[j] = P->p[j+2]; - P->m[j] = P->p[0]; - } - for (j = P->M / 2; j--;) { - *s++ = 0; - *s++ = 1; - } - } else if (!P->p[2]) { /* p q|r */ - P->N = 3; - P->M = 4; - P->V = P->g / 2; - Malloc(P->n, P->N, double); - Malloc(P->m, P->N, double); - Malloc(P->rot, P->M, int); - s = P->rot; - P->n[0] = 2 * P->p[3]; - P->m[0] = 2; - for (j = 1; j < 3; j++) { - P->n[j] = P->p[j-1]; - P->m[j] = 1; - *s++ = 0; - *s++ = j; - } - if (fabs(P->p[0] - compl (P->p[1])) < DBL_EPSILON) {/* p = q' */ - /* P->p[0]==compl(P->p[1]) should work. However, MSDOS - * yeilds a 7e-17 difference! Reported by Jim Buddenhagen - * <jb1556@daditz.sbc.com> */ - P->hemi = 1; - P->D = 0; - if (P->p[0] != 2 && !(P->p[3] == 3 && (P->p[0] == 3 || - P->p[1] == 3))) { - P->onesided = 1; - P->V /= 2; - P->chi /= 2; - } - } - } else if (!P->p[3]) { /* p q r| */ - P->M = P->N = 3; - P->V = P->g; - Malloc(P->n, P->N, double); - Malloc(P->m, P->N, double); - Malloc(P->rot, P->M, int); - s = P->rot; - for (j = 0; j < 3; j++) { - if (!(denominator(P->p[j]) % 2)) { - /* what happens if there is more then one even denominator? */ - if (P->p[(j+1)%3] != P->p[(j+2)%3]) { /* needs postprocessing */ - P->even = j;/* memorize the removed face */ - P->chi -= P->g / numerator(P->p[j]) / 2; - P->onesided = 1; - P->D = 0; - } else {/* for p = q we get a double 2 2r|p */ - /* noted by Roman Maeder <maeder@inf.ethz.ch> for 4 4 3/2| */ - /* Euler characteristic is still wrong */ - P->D /= 2; - } - P->V /= 2; - } - P->n[j] = 2 * P->p[j]; - P->m[j] = 1; - *s++ = j; - } - } else { /* |p q r - snub polyhedron */ - P->N = 4; - P->M = 6; - P->V = P->g / 2;/* Only "white" triangles carry a vertex */ - Malloc(P->n, P->N, double); - Malloc(P->m, P->N, double); - Malloc(P->rot, P->M, int); - Malloc(P->snub, P->M, int); - s = P->rot; - t = P->snub; - P->m[0] = P->n[0] = 3; - for (j = 1; j < 4; j++) { - P->n[j] = P->p[j]; - P->m[j] = 1; - *s++ = 0; - *s++ = j; - *t++ = 1; - *t++ = 0; - } - } - /* - * Sort the fundamental triangles (using bubble sort) according to decreasing - * n[i], while pushing the trivial triangles (n[i] = 2) to the end. - */ - J = P->N - 1; - while (J) { - int last; - last = J; - J = 0; - for (j = 0; j < last; j++) { - if ((P->n[j] < P->n[j+1] || P->n[j] == 2) && P->n[j+1] != 2) { - int i; - double temp; - temp = P->n[j]; - P->n[j] = P->n[j+1]; - P->n[j+1] = temp; - temp = P->m[j]; - P->m[j] = P->m[j+1]; - P->m[j+1] = temp; - for (i = 0; i < P->M; i++) { - if (P->rot[i] == j) - P->rot[i] = j+1; - else if (P->rot[i] == j+1) - P->rot[i] = j; - } - if (P->even != -1) { - if (P->even == j) - P->even = j+1; - else if (P->even == j+1) - P->even = j; - } - J = j; - } - } - } - /* - * Get rid of repeated triangles. - */ - for (J = 0; J < P->N && P->n[J] != 2;J++) { - int k, i; - for (j = J+1; j < P->N && P->n[j]==P->n[J]; j++) - P->m[J] += P->m[j]; - k = j - J - 1; - if (k) { - for (i = j; i < P->N; i++) { - P->n[i - k] = P->n[i]; - P->m[i - k] = P->m[i]; - } - P->N -= k; - for (i = 0; i < P->M; i++) { - if (P->rot[i] >= j) - P->rot[i] -= k; - else if (P->rot[i] > J) - P->rot[i] = J; - } - if (P->even >= j) - P->even -= k; - } - } - /* - * Get rid of trivial triangles. - */ - if (!J) - J = 1; /* hosohedron */ - if (J < P->N) { - int i; - P->N = J; - for (i = 0; i < P->M; i++) { - if (P->rot[i] >= P->N) { - for (j = i + 1; j < P->M; j++) { - P->rot[j-1] = P->rot[j]; - if (P->snub) - P->snub[j-1] = P->snub[j]; - } - P->M--; - } - } - } - /* - * Truncate arrays - */ - Realloc(P->n, P->N, double); - Realloc(P->m, P->N, double); - Realloc(P->rot, P->M, int); - if (P->snub) - Realloc(P->snub, P->M, int); - return 1; -} - - -static int dihedral(Polyhedron *P, const char *name, const char *dual_name); - - -/* - * Get the polyhedron name, using standard list or guesswork. Ideally, we - * should try to locate the Wythoff symbol in the standard list (unless, of - * course, it is dihedral), after doing few normalizations, such as sorting - * angles and splitting isoceles triangles. - */ -static int -guessname(Polyhedron *P) -{ - if (P->index != -1) {/* tabulated */ - P->name = uniform[P->index].name; - P->dual_name = uniform[P->index].dual; - P->group = uniform[P->index].group; - P->class = uniform[P->index].class; - P->dual_class = uniform[P->index].dual_class; - return 1; - } else if (P->K == 2) {/* dihedral nontabulated */ - if (!P->p[0]) { - if (P->N == 1) { - Malloc(P->name, sizeof ("Octahedron"), char); - Malloc(P->dual_name, sizeof ("Cube"), char); - strcpy(P->name, "Octahedron"); - strcpy(P->dual_name, "Cube"); - return 1; - } - P->gon = P->n[0] == 3 ? P->n[1] : P->n[0]; - if (P->gon >= 2) - return dihedral(P, "Antiprism", "Deltohedron"); - else - return dihedral(P, "Crossed Antiprism", "Concave Deltohedron"); - } else if (!P->p[3] || - (!P->p[2] && - P->p[3] == 2)) { - if (P->N == 1) { - Malloc(P->name, sizeof("Cube"), char); - Malloc(P->dual_name, sizeof("Octahedron"), char); - strcpy(P->name, "Cube"); - strcpy(P->dual_name, "Octahedron"); - return 1; - } - P->gon = P->n[0] == 4 ? P->n[1] : P->n[0]; - return dihedral(P, "Prism", "Dipyramid"); - } else if (!P->p[1] && P->p[0] != 2) { - P->gon = P->m[0]; - return dihedral(P, "Hosohedron", "Dihedron"); - } else { - P->gon = P->n[0]; - return dihedral(P, "Dihedron", "Hosohedron"); - } - } else {/* other nontabulated */ - static const char *pre[] = {"Tetr", "Oct", "Icos"}; - Malloc(P->name, 50, char); - Malloc(P->dual_name, 50, char); - sprintf(P->name, "%sahedral ", pre[P->K - 3]); - if (P->onesided) - strcat (P->name, "One-Sided "); - else if (P->D == 1) - strcat(P->name, "Convex "); - else - strcat(P->name, "Nonconvex "); - strcpy(P->dual_name, P->name); - strcat(P->name, "Isogonal Polyhedron"); - strcat(P->dual_name, "Isohedral Polyhedron"); - Realloc(P->name, strlen (P->name) + 1, char); - Realloc(P->dual_name, strlen (P->dual_name) + 1, char); - return 1; - } -} - -static int -dihedral(Polyhedron *P, const char *name, const char *dual_name) -{ - char *s; - int i; - Sprintfrac(s, P->gon < 2 ? compl (P->gon) : P->gon); - i = strlen(s) + sizeof ("-gonal "); - Malloc(P->name, i + strlen (name), char); - Malloc(P->dual_name, i + strlen (dual_name), char); - sprintf(P->name, "%s-gonal %s", s, name); - sprintf(P->dual_name, "%s-gonal %s", s, dual_name); - free(s); - return 1; -} - -/* - * Solve the fundamental right spherical triangles. - * If need_approx is set, print iterations on standard error. - */ -static int -newton(Polyhedron *P, int need_approx) -{ - /* - * First, we find initial approximations. - */ - int j; - double cosa; - Malloc(P->gamma, P->N, double); - if (P->N == 1) { - P->gamma[0] = M_PI / P->m[0]; - return 1; - } - for (j = 0; j < P->N; j++) - P->gamma[j] = M_PI / 2 - M_PI / P->n[j]; - errno = 0; /* may be non-zero from some reason */ - /* - * Next, iteratively find closer approximations for gamma[0] and compute - * other gamma[j]'s from Napier's equations. - */ - if (need_approx) - fprintf(stderr, "Solving %s\n", P->polyform); - for (;;) { - double delta = M_PI, sigma = 0; - for (j = 0; j < P->N; j++) { - if (need_approx) - fprintf(stderr, "%-20.15f", P->gamma[j]); - delta -= P->m[j] * P->gamma[j]; - } - if (need_approx) - printf("(%g)\n", delta); - if (fabs(delta) < 11 * DBL_EPSILON) - return 1; - /* On a RS/6000, fabs(delta)/DBL_EPSILON may occilate between 8 and - * 10. Reported by David W. Sanderson <dws@ssec.wisc.edu> */ - for (j = 0; j < P->N; j++) - sigma += P->m[j] * tan(P->gamma[j]); - P->gamma[0] += delta * tan(P->gamma[0]) / sigma; - if (P->gamma[0] < 0 || P->gamma[0] > M_PI) - Err("gamma out of bounds"); - cosa = cos(M_PI / P->n[0]) / sin(P->gamma[0]); - for (j = 1; j < P->N; j++) - P->gamma[j] = asin(cos(M_PI / P->n[j]) / cosa); - if (errno) - Err(strerror(errno)); - } -} - -/* - * Postprocess pqr| where r has an even denominator (cf. Coxeter &al. Sec.9). - * Remove the {2r} and add a retrograde {2p} and retrograde {2q}. - */ -static int -exceptions(Polyhedron *P) -{ - int j; - if (P->even != -1) { - P->M = P->N = 4; - Realloc(P->n, P->N, double); - Realloc(P->m, P->N, double); - Realloc(P->gamma, P->N, double); - Realloc(P->rot, P->M, int); - for (j = P->even + 1; j < 3; j++) { - P->n[j-1] = P->n[j]; - P->gamma[j-1] = P->gamma[j]; - } - P->n[2] = compl(P->n[1]); - P->gamma[2] = - P->gamma[1]; - P->n[3] = compl(P->n[0]); - P->m[3] = 1; - P->gamma[3] = - P->gamma[0]; - P->rot[0] = 0; - P->rot[1] = 1; - P->rot[2] = 3; - P->rot[3] = 2; - } - - /* - * Postprocess the last polyhedron |3/2 5/3 3 5/2 by taking a |5/3 3 5/2, - * replacing the three snub triangles by four equatorial squares and adding - * the missing {3/2} (retrograde triangle, cf. Coxeter &al. Sec. 11). - */ - if (P->index == last_uniform - 1) { - P->N = 5; - P->M = 8; - Realloc(P->n, P->N, double); - Realloc(P->m, P->N, double); - Realloc(P->gamma, P->N, double); - Realloc(P->rot, P->M, int); - Realloc(P->snub, P->M, int); - P->hemi = 1; - P->D = 0; - for (j = 3; j; j--) { - P->m[j] = 1; - P->n[j] = P->n[j-1]; - P->gamma[j] = P->gamma[j-1]; - } - P->m[0] = P->n[0] = 4; - P->gamma[0] = M_PI / 2; - P->m[4] = 1; - P->n[4] = compl(P->n[1]); - P->gamma[4] = - P->gamma[1]; - for (j = 1; j < 6; j += 2) P->rot[j]++; - P->rot[6] = 0; - P->rot[7] = 4; - P->snub[6] = 1; - P->snub[7] = 0; - } - return 1; -} - -/* - * Compute edge and face counts, and update D and chi. Update D in the few - * cases the density of the polyhedron is meaningful but different than the - * density of the corresponding Schwarz triangle (cf. Coxeter &al., p. 418 and - * p. 425). - * In these cases, spherical faces of one type are concave (bigger than a - * hemisphere), and the actual density is the number of these faces less the - * computed density. Note that if j != 0, the assignment gamma[j] = asin(...) - * implies gamma[j] cannot be obtuse. Also, compute chi for the only - * non-Wythoffian polyhedron. - */ -static int -count(Polyhedron *P) -{ - int j, temp; - Malloc(P->Fi, P->N, int); - for (j = 0; j < P->N; j++) { - P->E += temp = P->V * numerator(P->m[j]); - P->F += P->Fi[j] = temp / numerator(P->n[j]); - } - P->E /= 2; - if (P->D && P->gamma[0] > M_PI / 2) - P->D = P->Fi[0] - P->D; - if (P->index == last_uniform - 1) - P->chi = P->V - P->E + P->F; - return 1; -} - -/* - * Generate a printable vertex configuration symbol. - */ -static int -configuration(Polyhedron *P) -{ - int j, len = 2; - for (j = 0; j < P->M; j++) { - char *s; - Sprintfrac(s, P->n[P->rot[j]]); - len += strlen (s) + 2; - if (!j) { - Malloc(P->config, len, char); -/* strcpy(P->config, "(");*/ - strcpy(P->config, ""); - } else { - Realloc(P->config, len, char); - strcat(P->config, ", "); - } - strcat(P->config, s); - free(s); - } -/* strcat (P->config, ")");*/ - if ((j = denominator (P->m[0])) != 1) { - char s[MAXDIGITS + 2]; - sprintf(s, "/%d", j); - Realloc(P->config, len + strlen (s), char); - strcat(P->config, s); - } - return 1; -} - -/* - * Compute polyhedron vertices and vertex adjecency lists. - * The vertices adjacent to v[i] are v[adj[0][i], v[adj[1][i], ... - * v[adj[M-1][i], ordered counterclockwise. The algorith is a BFS on the - * vertices, in such a way that the vetices adjacent to a givem vertex are - * obtained from its BFS parent by a cyclic sequence of rotations. firstrot[i] - * points to the first rotaion in the sequence when applied to v[i]. Note that - * for non-snub polyhedra, the rotations at a child are opposite in sense when - * compared to the rotations at the parent. Thus, we fill adj[*][i] from the - * end to signify clockwise rotations. The firstrot[] array is not needed for - * display thus it is freed after being used for face computations below. - */ -static int -vertices(Polyhedron *P) -{ - int i, newV = 2; - double cosa; - Malloc(P->v, P->V, Vector); - Matalloc(P->adj, P->M, P->V, int); - Malloc(P->firstrot, P->V, int); /* temporary , put in Polyhedron - structure so that may be freed on - error */ - cosa = cos(M_PI / P->n[0]) / sin(P->gamma[0]); - P->v[0].x = 0; - P->v[0].y = 0; - P->v[0].z = 1; - P->firstrot[0] = 0; - P->adj[0][0] = 1; - P->v[1].x = 2 * cosa * sqrt(1 - cosa * cosa); - P->v[1].y = 0; - P->v[1].z = 2 * cosa * cosa - 1; - if (!P->snub) { - P->firstrot[1] = 0; - P->adj[0][1] = -1;/* start the other side */ - P->adj[P->M-1][1] = 0; - } else { - P->firstrot[1] = P->snub[P->M-1] ? 0 : P->M-1 ; - P->adj[0][1] = 0; - } - for (i = 0; i < newV; i++) { - int j, k; - int last, one, start, limit; - if (P->adj[0][i] == -1) { - one = -1; start = P->M-2; limit = -1; - } else { - one = 1; start = 1; limit = P->M; - } - k = P->firstrot[i]; - for (j = start; j != limit; j += one) { - Vector temp; - int J; - temp = rotate (P->v[P->adj[j-one][i]], P->v[i], - one * 2 * P->gamma[P->rot[k]]); - for (J=0; J<newV && !same(P->v[J],temp,BIG_EPSILON); J++) - ;/* noop */ - P->adj[j][i] = J; - last = k; - if (++k == P->M) - k = 0; - if (J == newV) { /* new vertex */ - if (newV == P->V) Err ("too many vertices"); - P->v[newV++] = temp; - if (!P->snub) { - P->firstrot[J] = k; - if (one > 0) { - P->adj[0][J] = -1; - P->adj[P->M-1][J] = i; - } else { - P->adj[0][J] = i; - } - } else { - P->firstrot[J] = !P->snub[last] ? last : - !P->snub[k] ? (k+1)%P->M : k ; - P->adj[0][J] = i; - } - } - } - } - return 1; -} - -/* - * Compute polyhedron faces (dual vertices) and incidence matrices. - * For orientable polyhedra, we can distinguish between the two faces meeting - * at a given directed edge and identify the face on the left and the face on - * the right, as seen from the outside. For one-sided polyhedra, the vertex - * figure is a papillon (in Coxeter &al. terminology, a crossed parallelogram) - * and the two faces meeting at an edge can be identified as the side face - * (n[1] or n[2]) and the diagonal face (n[0] or n[3]). - */ -static int -faces(Polyhedron *P) -{ - int i, newF = 0; - Malloc (P->f, P->F, Vector); - Malloc (P->ftype, P->F, int); - Matalloc (P->incid, P->M, P->V, int); - P->minr = 1 / fabs (tan (M_PI / P->n[P->hemi]) * tan (P->gamma[P->hemi])); - for (i = P->M; --i>=0;) { - int j; - for (j = P->V; --j>=0;) - P->incid[i][j] = -1; - } - for (i = 0; i < P->V; i++) { - int j; - for (j = 0; j < P->M; j++) { - int i0, J; - int pap=0;/* papillon edge type */ - if (P->incid[j][i] != -1) - continue; - P->incid[j][i] = newF; - if (newF == P->F) - Err("too many faces"); - P->f[newF] = pole(P->minr, P->v[i], P->v[P->adj[j][i]], - P->v[P->adj[mod(j + 1, P->M)][i]]); - P->ftype[newF] = P->rot[mod(P->firstrot[i] + ((P->adj[0][i] < - P->adj[P->M - 1][i]) - ? j - : -j - 2), - P->M)]; - if (P->onesided) - pap = (P->firstrot[i] + j) % 2; - i0 = i; - J = j; - for (;;) { - int k; - k = i0; - if ((i0 = P->adj[J][k]) == i) break; - for (J = 0; J < P->M && P->adj[J][i0] != k; J++) - ;/* noop */ - if (J == P->M) - Err("too many faces"); - if (P->onesided && (J + P->firstrot[i0]) % 2 == pap) { - P->incid [J][i0] = newF; - if (++J >= P->M) - J = 0; - } else { - if (--J < 0) - J = P->M - 1; - P->incid [J][i0] = newF; - } - } - newF++; - } - } - Free(P->firstrot); - Free(P->rot); - Free(P->snub); - return 1; -} - -/* - * Compute edge list and graph polyhedron and dual. - * If the polyhedron is of the "hemi" type, each edge has one finite vertex and - * one ideal vertex. We make sure the latter is always the out-vertex, so that - * the edge becomes a ray (half-line). Each ideal vertex is represented by a - * unit Vector, and the direction of the ray is either parallel or - * anti-parallel this Vector. We flag this in the array P->anti[E]. - */ -static int -edgelist(Polyhedron *P) -{ - int i, j, *s, *t, *u; - Matalloc(P->e, 2, P->E, int); - Matalloc(P->dual_e, 2, P->E, int); - s = P->e[0]; - t = P->e[1]; - for (i = 0; i < P->V; i++) - for (j = 0; j < P->M; j++) - if (i < P->adj[j][i]) { - *s++ = i; - *t++ = P->adj[j][i]; - } - s = P->dual_e[0]; - t = P->dual_e[1]; - if (!P->hemi) - P->anti = 0; - else - Malloc(P->anti, P->E, int); - u = P->anti; - for (i = 0; i < P->V; i++) - for (j = 0; j < P->M; j++) - if (i < P->adj[j][i]) - { - if (!u) { - *s++ = P->incid[mod(j-1,P->M)][i]; - *t++ = P->incid[j][i]; - } else { - if (P->ftype[P->incid[j][i]]) { - *s = P->incid[j][i]; - *t = P->incid[mod(j-1,P->M)][i]; - } else { - *s = P->incid[mod(j-1,P->M)][i]; - *t = P->incid[j][i]; - } - *u++ = dot(P->f[*s++], P->f[*t++]) > 0; - } - } - return 1; -} - - -static char * -sprintfrac(double x) -{ - char *s; - frac (x); - if (!frax.d) { - Malloc(s, sizeof ("infinity"), char); - strcpy(s, "infinity"); - } else if (frax.d == 1) { - char n[MAXDIGITS + 1]; - sprintf(n, "%ld", frax.n); - Malloc(s, strlen (n) + 1, char); - strcpy(s, n); - } else { - char n[MAXDIGITS + 1], d[MAXDIGITS + 1]; - sprintf(n, "%ld", frax.n); - sprintf(d, "%ld", frax.d); - Malloc(s, strlen (n) + strlen (d) + 2, char); - sprintf(s, "%s/%s", n, d); - } - return s; -} - -static double -dot(Vector a, Vector b) -{ - return a.x * b.x + a.y * b.y + a.z * b.z; -} - -static Vector -scale(double k, Vector a) -{ - a.x *= k; - a.y *= k; - a.z *= k; - return a; -} - -static Vector -diff(Vector a, Vector b) -{ - a.x -= b.x; - a.y -= b.y; - a.z -= b.z; - return a; -} - -static Vector -cross(Vector a, Vector b) -{ - Vector p; - p.x = a.y * b.z - a.z * b.y; - p.y = a.z * b.x - a.x * b.z; - p.z = a.x * b.y - a.y * b.x; - return p; -} - -static Vector -sum(Vector a, Vector b) -{ - a.x += b.x; - a.y += b.y; - a.z += b.z; - return a; -} - -static Vector -sum3(Vector a, Vector b, Vector c) -{ - a.x += b.x + c.x; - a.y += b.y + c.y; - a.z += b.z + c.z; - return a; -} - -static Vector -rotate(Vector vertex, Vector axis, double angle) -{ - Vector p; - p = scale(dot (axis, vertex), axis); - return sum3(p, scale(cos(angle), diff(vertex, p)), - scale(sin(angle), cross(axis, vertex))); -} - -static Vector x, y, z; - -/* - * rotate the standard frame - */ -static void -rotframe(double azimuth, double elevation, double angle) -{ - static const Vector X = {1,0,0}, Y = {0,1,0}, Z = {0,0,1}; - Vector axis; - - axis = rotate(rotate (X, Y, elevation), Z, azimuth); - x = rotate(X, axis, angle); - y = rotate(Y, axis, angle); - z = rotate(Z, axis, angle); -} - -/* - * rotate an array of n Vectors - */ -static void -rotarray(Vector *new, Vector *old, int n) -{ - while (n--) { - *new++ = sum3(scale(old->x, x), scale(old->y, y), scale(old->z, z)); - old++; - } -} - -static int -same(Vector a, Vector b, double epsilon) -{ - return fabs(a.x - b.x) < epsilon && fabs(a.y - b.y) < epsilon - && fabs(a.z - b.z) < epsilon; -} - -/* - * Compute the polar reciprocal of the plane containing a, b and c: - * - * If this plane does not contain the origin, return p such that - * dot(p,a) = dot(p,b) = dot(p,b) = r. - * - * Otherwise, return p such that - * dot(p,a) = dot(p,b) = dot(p,c) = 0 - * and - * dot(p,p) = 1. - */ -static Vector -pole(double r, Vector a, Vector b, Vector c) -{ - Vector p; - double k; - p = cross(diff(b, a), diff(c, a)); - k = dot(p, a); - if (fabs(k) < 1e-6) - return scale(1 / sqrt(dot(p, p)), p); - else - return scale(r/ k , p); -} - - -/* output */ - - - - -static void rotframe(double azimuth, double elevation, double angle); -static void rotarray(Vector *new, Vector *old, int n); -static int mod (int i, int j); - - -static void -push_point (polyhedron *p, Vector v) -{ - p->points[p->npoints].x = v.x; - p->points[p->npoints].y = v.y; - p->points[p->npoints].z = v.z; - p->npoints++; -} - -static void -push_face3 (polyhedron *p, int x, int y, int z) -{ - p->faces[p->nfaces].npoints = 3; - Malloc (p->faces[p->nfaces].points, 3, int); - p->faces[p->nfaces].points[0] = x; - p->faces[p->nfaces].points[1] = y; - p->faces[p->nfaces].points[2] = z; - p->nfaces++; -} - -static void -push_face4 (polyhedron *p, int x, int y, int z, int w) -{ - p->faces[p->nfaces].npoints = 4; - Malloc (p->faces[p->nfaces].points, 4, int); - p->faces[p->nfaces].points[0] = x; - p->faces[p->nfaces].points[1] = y; - p->faces[p->nfaces].points[2] = z; - p->faces[p->nfaces].points[3] = w; - p->nfaces++; -} - - - - -static polyhedron * -construct_polyhedron (Polyhedron *P, Vector *v, int V, Vector *f, int F, - const char *name, const char *dual, - const char *class, const char *star, - double azimuth, double elevation, double freeze) -{ - int i, j, k=0, l, ll, ii, *hit=0, facelets; - - polyhedron *result; - Vector *temp; - - Malloc (result, 1, polyhedron); - memset (result, 0, sizeof(*result)); - - /* - * Rotate polyhedron - */ - rotframe(azimuth, elevation, freeze); - Malloc(temp, V, Vector); - rotarray(temp, v, V); - v = temp; - Malloc(temp, F, Vector); - rotarray(temp, f, F); - f = temp; - - result->number = P->index + 1; - result->name = strdup (name); - result->dual = strdup (dual); - result->wythoff = strdup (P->polyform); - result->config = strdup (P->config); - result->group = strdup (P->group); - result->class = strdup (class); - - /* - * Vertex list - */ - Malloc (result->points, V + F * 13, point); - result->npoints = 0; - - result->nedges = P->E; - result->logical_faces = F; - result->logical_vertices = V; - result->density = P->D; - result->chi = P->chi; - - for (i = 0; i < V; i++) - push_point (result, v[i]); - - /* - * Auxiliary vertices (needed because current VRML browsers cannot handle - * non-simple polygons, i.e., ploygons with self intersections): Each - * non-simple face is assigned an auxiliary vertex. By connecting it to the - * rest of the vertices the face is triangulated. The circum-center is used - * for the regular star faces of uniform polyhedra. The in-center is used for - * the pentagram (#79) and hexagram (#77) of the high-density snub duals, and - * for the pentagrams (#40, #58) and hexagram (#52) of the stellated duals - * with configuration (....)/2. Finally, the self-intersection of the crossed - * parallelogram is used for duals with form p q r| with an even denominator. - * - * This method do not work for the hemi-duals, whose faces are not - * star-shaped and have two self-intersections each. - * - * Thus, for each face we need six auxiliary vertices: The self intersections - * and the terminal points of the truncations of the infinite edges. The - * ideal vertices are listed, but are not used by the face-list. - * - * Note that the face of the last dual (#80) is octagonal, and constists of - * two quadrilaterals of the infinite type. - */ - - if (*star && P->even != -1) - Malloc(hit, F, int); - for (i = 0; i < F; i++) - if ((!*star && - (frac(P->n[P->ftype[i]]), frax.d != 1 && frax.d != frax.n - 1)) || - (*star && - P->K == 5 && - (P->D > 30 || - denominator (P->m[0]) != 1))) { - /* find the center of the face */ - double h; - if (!*star && P->hemi && !P->ftype[i]) - h = 0; - else - h = P->minr / dot(f[i],f[i]); - push_point(result, scale (h, f[i])); - - } else if (*star && P->even != -1) { - /* find the self-intersection of a crossed parallelogram. - * hit is set if v0v1 intersects v2v3*/ - Vector v0, v1, v2, v3, c0, c1, p; - double d0, d1; - v0 = v[P->incid[0][i]]; - v1 = v[P->incid[1][i]]; - v2 = v[P->incid[2][i]]; - v3 = v[P->incid[3][i]]; - d0 = sqrt(dot(diff(v0, v2), diff(v0, v2))); - d1 = sqrt(dot (diff(v1, v3), diff(v1, v3))); - c0 = scale(d1, sum(v0, v2)); - c1 = scale(d0, sum(v1, v3)); - p = scale(0.5 / (d0 + d1), sum(c0, c1)); - push_point (result, p); - p = cross(diff(p, v2), diff(p, v3)); - hit[i] = (dot(p, p) < 1e-6); - } else if (*star && P->hemi && P->index != last_uniform - 1) { - /* find the terminal points of the truncation and the - * self-intersections. - * v23 v0 v21 - * | \ / \ / | - * | v0123 v0321 | - * | / \ / \ | - * v01 v2 v03 - */ - Vector v0, v1, v2, v3, v01, v03, v21, v23, v0123, v0321 ; - Vector u; - double t = 1.5;/* truncation adjustment factor */ - j = !P->ftype[P->incid[0][i]]; - v0 = v[P->incid[j][i]];/* real vertex */ - v1 = v[P->incid[j+1][i]];/* ideal vertex (unit vector) */ - v2 = v[P->incid[j+2][i]];/* real */ - v3 = v[P->incid[(j+3)%4][i]];/* ideal */ - /* compute intersections - * this uses the following linear algebra: - * v0123 = v0 + a v1 = v2 + b v3 - * v0 x v3 + a (v1 x v3) = v2 x v3 - * a (v1 x v3) = (v2 - v0) x v3 - * a (v1 x v3) . (v1 x v3) = (v2 - v0) x v3 . (v1 x v3) - */ - u = cross(v1, v3); - v0123 = sum(v0, scale(dot(cross(diff(v2, v0), v3), u) / dot(u,u), - v1)); - v0321 = sum(v0, scale(dot(cross(diff(v0, v2), v1), u) / dot(u,u), - v3)); - /* compute truncations */ - v01 = sum(v0 , scale(t, diff(v0123, v0))); - v23 = sum(v2 , scale(t, diff(v0123, v2))); - v03 = sum(v0 , scale(t, diff(v0321, v0))); - v21 = sum(v2 , scale(t, diff(v0321, v2))); - - push_point(result, v01); - push_point(result, v23); - push_point(result, v0123); - push_point(result, v03); - push_point(result, v21); - push_point(result, v0321); - - } else if (*star && P->index == last_uniform - 1) { - /* find the terminal points of the truncation and the - * self-intersections. - * v23 v0 v21 - * | \ / \ / | - * | v0123 v0721 | - * | / \ / \ | - * v01 v2 v07 - * - * v65 v4 v67 - * | \ / \ / | - * | v4365 v4567 | - * | / \ / \ | - * v43 v6 v45 - */ - Vector v0, v1, v2, v3, v4, v5, v6, v7, v01, v07, v21, v23; - Vector v43, v45, v65, v67, v0123, v0721, v4365, v4567; - double t = 1.5;/* truncation adjustment factor */ - Vector u; - for (j = 0; j < 8; j++) - if (P->ftype[P->incid[j][i]] == 3) - break; - v0 = v[P->incid[j][i]];/* real {5/3} */ - v1 = v[P->incid[(j+1)%8][i]];/* ideal */ - v2 = v[P->incid[(j+2)%8][i]];/* real {3} */ - v3 = v[P->incid[(j+3)%8][i]];/* ideal */ - v4 = v[P->incid[(j+4)%8][i]];/* real {5/2} */ - v5 = v[P->incid[(j+5)%8][i]];/* ideal */ - v6 = v[P->incid[(j+6)%8][i]];/* real {3/2} */ - v7 = v[P->incid[(j+7)%8][i]];/* ideal */ - /* compute intersections */ - u = cross(v1, v3); - v0123 = sum(v0, scale(dot(cross(diff(v2, v0), v3), u) / dot(u,u), - v1)); - u = cross(v7, v1); - v0721 = sum(v0, scale(dot(cross(diff(v2, v0), v1), u) / dot(u,u), - v7)); - u = cross(v5, v7); - v4567 = sum(v4, scale(dot(cross(diff(v6, v4), v7), u) / dot(u,u), - v5)); - u = cross(v3, v5); - v4365 = sum(v4, scale(dot(cross(diff(v6, v4), v5), u) / dot(u,u), - v3)); - /* compute truncations */ - v01 = sum(v0 , scale(t, diff(v0123, v0))); - v23 = sum(v2 , scale(t, diff(v0123, v2))); - v07 = sum(v0 , scale(t, diff(v0721, v0))); - v21 = sum(v2 , scale(t, diff(v0721, v2))); - v45 = sum(v4 , scale(t, diff(v4567, v4))); - v67 = sum(v6 , scale(t, diff(v4567, v6))); - v43 = sum(v4 , scale(t, diff(v4365, v4))); - v65 = sum(v6 , scale(t, diff(v4365, v6))); - - push_point(result, v01); - push_point(result, v23); - push_point(result, v0123); - push_point(result, v07); - push_point(result, v21); - push_point(result, v0721); - push_point(result, v45); - push_point(result, v67); - push_point(result, v4567); - push_point(result, v43); - push_point(result, v65); - push_point(result, v4365); - } - - /* - * Face list: - * Each face is printed in a separate line, by listing the indices of its - * vertices. In the non-simple case, the polygon is represented by the - * triangulation, each triangle consists of two polyhedron vertices and one - * auxiliary vertex. - */ - Malloc (result->faces, F * 10, face); - result->nfaces = 0; - - ii = V; - facelets = 0; - for (i = 0; i < F; i++) { - if (*star) { - if (P->K == 5 && - (P->D > 30 || - denominator (P->m[0]) != 1)) { - for (j = 0; j < P->M - 1; j++) { - push_face3 (result, P->incid[j][i], P->incid[j+1][i], ii); - facelets++; - } - - push_face3 (result, P->incid[j][i], P->incid[0][i], ii++); - facelets++; - - } else if (P->even != -1) { - if (hit && hit[i]) { - push_face3 (result, P->incid[3][i], P->incid[0][i], ii); - push_face3 (result, P->incid[1][i], P->incid[2][i], ii); - } else { - push_face3 (result, P->incid[0][i], P->incid[1][i], ii); - push_face3 (result, P->incid[2][i], P->incid[3][i], ii); - } - ii++; - facelets += 2; - - } else if (P->hemi && P->index != last_uniform - 1) { - j = !P->ftype[P->incid[0][i]]; - - push_face3 (result, ii, ii + 1, ii + 2); - push_face4 (result, P->incid[j][i], ii + 2, P->incid[j+2][i], ii + 5); - push_face3 (result, ii + 3, ii + 4, ii + 5); - ii += 6; - facelets += 3; - } else if (P->index == last_uniform - 1) { - for (j = 0; j < 8; j++) - if (P->ftype[P->incid[j][i]] == 3) - break; - push_face3 (result, ii, ii + 1, ii + 2); - push_face4 (result, - P->incid[j][i], ii + 2, P->incid[(j+2)%8][i], ii + 5); - push_face3 (result, ii + 3, ii + 4, ii + 5); - - push_face3 (result, ii + 6, ii + 7, ii + 8); - push_face4 (result, - P->incid[(j+4)%8][i], ii + 8, P->incid[(j+6)%8][i], - ii + 11); - push_face3 (result, ii + 9, ii + 10, ii + 11); - ii += 12; - facelets += 6; - } else { - - result->faces[result->nfaces].npoints = P->M; - Malloc (result->faces[result->nfaces].points, P->M, int); - for (j = 0; j < P->M; j++) - result->faces[result->nfaces].points[j] = P->incid[j][i]; - result->nfaces++; - facelets++; - } - } else { - int split = (frac(P->n[P->ftype[i]]), - frax.d != 1 && frax.d != frax.n - 1); - for (j = 0; j < V; j++) { - for (k = 0; k < P->M; k++) - if (P->incid[k][j] == i) - break; - if (k != P->M) - break; - } - if (split) { - ll = j; - for (l = P->adj[k][j]; l != j; l = P->adj[k][l]) { - for (k = 0; k < P->M; k++) - if (P->incid[k][l] == i) - break; - if (P->adj[k][l] == ll) - k = mod(k + 1 , P->M); - push_face3 (result, ll, l, ii); - facelets++; - ll = l; - } - push_face3 (result, ll, j, ii++); - facelets++; - - } else { - - int *pp; - int pi = 0; - Malloc (pp, 100, int); - - pp[pi++] = j; - ll = j; - for (l = P->adj[k][j]; l != j; l = P->adj[k][l]) { - for (k = 0; k < P->M; k++) - if (P->incid[k][l] == i) - break; - if (P->adj[k][l] == ll) - k = mod(k + 1 , P->M); - pp[pi++] = l; - ll = l; - } - result->faces[result->nfaces].npoints = pi; - result->faces[result->nfaces].points = pp; - result->nfaces++; - facelets++; - } - } - } - - /* - * Face color indices - for polyhedra with multiple face types - * For non-simple faces, the index is repeated as many times as needed by the - * triangulation. - */ - { - int ff = 0; - if (!*star && P->N != 1) { - for (i = 0; i < F; i++) - if (frac(P->n[P->ftype[i]]), frax.d == 1 || frax.d == frax.n - 1) - result->faces[ff++].color = P->ftype[i]; - else - for (j = 0; j < frax.n; j++) - result->faces[ff++].color = P->ftype[i]; - } else { - for (i = 0; i < facelets; i++) - result->faces[ff++].color = 0; - } - } - - if (*star && P->even != -1) - free(hit); - free(v); - free(f); - - return result; -} - - - -/* External interface (jwz) - */ - -void -free_polyhedron (polyhedron *p) -{ - if (!p) return; - Free (p->wythoff); - Free (p->name); - Free (p->group); - Free (p->class); - Free (p->points); - if (p->faces) - { - int i; - for (i = 0; i < p->nfaces; i++) - Free (p->faces[i].points); - Free (p->faces); - } - Free (p); -} - - -int -construct_polyhedra (polyhedron ***polyhedra_ret) -{ - double freeze = 0; - double azimuth = AZ; - double elevation = EL; - int index = 0; - - int count = 0; - polyhedron **result; - Malloc (result, last_uniform * 2 + 3, polyhedron*); - - while (index < last_uniform) { - char sym[4]; - Polyhedron *P; - - sprintf(sym, "#%d", index + 1); - if (!(P = kaleido(sym, 1, 0, 0, 0))) { - Err (strerror(errno)); - } - - result[count++] = construct_polyhedron (P, P->v, P->V, P->f, P->F, - P->name, P->dual_name, - P->class, "", - azimuth, elevation, freeze); - - result[count++] = construct_polyhedron (P, P->f, P->F, P->v, P->V, - P->dual_name, P->name, - P->dual_class, "*", - azimuth, elevation, freeze); - polyfree(P); - index++; - } - - *polyhedra_ret = result; - count++; /* leave room for teapot */ - return count; -} |
