static int voe_min(int _v) { return (_v & YMASK) ? 2 : 3; }
static int voe_max(int _v) { return (~_v & YMASK) ? V6 : 4; }
- static int voe_degree(int _v) { return (_v & YMASK | ~_v & YMASK) ? 4 : V6; }
+ static int voe_degree(int _v) { return RIM_VERTEX_P(_v) ? 4 : V6; }
};
typedef counting_iterator<int> VertexIterator;
#include "mgraph.h"
-static const unsigned dx[V6]= { +1, +1, 0, -1, -1, 0 },
- dy[V6]= { 0, -Y1, -Y1, 0, +Y1, +Y1 };
+static const unsigned dx[2][V6]= {{ +1, 0, -1, -1, -1, 0 },
+ { +1, +1, 0, -1, 0, +1 }},
+ dy[V6]= { 0, -Y1, -Y1, 0, +Y1, +Y1 };
int edge_end2(unsigned v1, int e) {
unsigned x, y;
y= (v1 & YMASK) + dy[e];
- if (y & ~YMASK) return -1;
+ if (y >= Y*Y1) return -1;
- x= (v1 & XMASK) + dx[e];
+ x= (v1 & XMASK) + dx[(v1 >> YSHIFT) & 1][e];
if (x & ~XMASK) {
+ //int orgy= y;
y= (Y-1)*Y1 - y;
x &= XMASK;;
+ //printf("%40s %02x -%d-> %02x (was %02x) \n", "", v1, e, x|y, x|orgy);
}
+
return x | y;
}
/*
* Vertices in strip are numbered as follows:
*
- * ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 ___ 4 __
- * Y-1 Y-1 0 0 0 0 0
+ * |
+ * ___ X-2 ___ X-1 ___| 0 ___ 1 ___ 2 ___ 3 ___ 4 __
+ * Y-1 Y-1 |0 0 0 0 0
* / \ / \ / \ / \ / \ / \ / \
- * / \ / \ / \ / \ / \ / \ / \
- * X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 ___ 4
- * Y-2 Y-2 Y-2 1 1 1 1 1
- * \ / \ / \ / \ / \ / \ / \ /
+ * / \ / \ /| \ / \ / \ / \ / \
+ * X-3 ___ X-2 ___ X-1|___ 0 ___ 1 ___ 2 ___ 3 ___ 4
+ * Y-2 Y-2 Y-2| 1 1 1 1 1
+ * \ / \ / \| / \ / \ / \ / \ /
* \ / \ / \ / \ / \ / \ / \ /
- * ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 __
- * Y-3 Y-3 Y-3 2 2 2 2
- *
- * . . . . . . . . . . . . . . .
- *
- * X-4 ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3
- * 1 1 1 1 Y-2 Y-2 Y-2 Y-2
- * \ / \ / \ / \ / \ / \ / \ /
- * \ / \ / \ / \ / \ / \ / \ /
- * ___ X-4 ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 __
- * 0 0 0 0 Y-1 Y-1 Y-1
- *
+ * ___ X-2 ___ X-1 ___| 0 ___ 1 ___ 2 ___ 3 __ 4 ___
+ * Y-3 Y-3 |2 2 2 2 2
+ * / \ / \ / \ / \ / \ / \ / \
+ * / \ / \ /| \ / \ / \ / \ / \
+ * X-3 ___ X-2 ___ X-1|___ 0 ___ 1 ___ 2 ___ 3 ___ 4
+ * Y-4 Y-4 Y-4| 3 3 3 3 3
+ * |
+ * . . . . .| . . . . . . . . . .
+ * |
+ * ___ X-2 ___ X-1 ___| 0 ___ 1 ___ 2 ___ 3 ___ 4 ___
+ * 2 2 |Y-3 Y-3 Y-3 Y-3 Y-3
+ * / \ / \ / \ / \ / \ / \ / \
+ * / \ / \ /| \ / \ / \ / \ / \
+ * __ X-2 ___ X-1|___ 0 ___ 1 ___ 2 ___ 3 ___ 3 ___ 4
+ * 1 1 | Y-2 Y-2 Y-2 Y-2 Y-2 Y-2
+ * / \ / \ / \| / \ / \ / \ / \ /
+ * / \ / \ / \ / \ / \ / \ / \ /
+ * -3 ___ X-2 ___ X-1 ___| 0 ___ 1 ___ 2 ___ 3 ___ 4 ___
+ * 0 0 0 |Y-1 Y-1 Y-1 Y-1 Y-1
+ * |
* Node x,y for
* 0 <= x < X x = distance along
* 0 <= y < Y y = distance across
*
* We label edges as follows: Or in the square view:
*
- * \2 /1 2 1
- * \ / | /
- * ___ 0 __ |/
- * 3 1 0 3--*--0
- * / \ /|
- * 4/ 5\ / |
+ * \2 /1 2 1
+ * \ / | /
+ * ___ 0 __ |/
+ * 3 1 0 3--*--0
+ * / \ /|
+ * 4/ 5\ / |
* 4 5
*
* (This makes the numbering
#include "common.h"
-#define DIMBITS 5
+#define DIMBITS 4
#define XBITS DIMBITS
#define X (1<<XBITS)
#define YBITS DIMBITS
-#define Y (1<<YBITS)
+#define Y ((1<<YBITS) - 1)
/* vertex number: 0000 | y | x
* YBITS XBITS
#define XMASK (X-1)
#define YSHIFT XBITS
#define Y1 (1 << YSHIFT)
-#define YMASK ((Y-1) << YSHIFT)
+#define YMASK (Y << YSHIFT)
#define DIM (N*D3)
extern int edge_end2(unsigned v1, int e);
#define EDGE_END2 edge_end2
+#define RIM_VERTEX_P(v) (((v) & YMASK) == 0 || ((v) & YMASK) == (Y-1)*Y1)
+
#define FOR_VEDGE_X(v1,e,v2,init,otherwise) \
FOR_VPEDGE((v1),(e)) \
if (((v2)= EDGE_END2((v1),(e)), \
/* SGT's v runs 0..pi along the strip, where the join is at 0==pi.
* So that corresponds to 0..X (since 0==X in our scheme). */
- double v= x * M_PI / X;
-
+ double v= (x*2 + (y&1)) * M_PI / (X*2);
+
K printf("print %c%c( %-*.*g, %-*.*g); # %03x %2d %2d\n",
"+-+"[k], "xyz"[k],
prec+5,prec,u, prec+5,prec,v,
}
}
+static int vertex_in_triangles[N], vertex_in_triangles_checked;
+
static void addtriangle(int va, int vb, int vc) {
Triangle *t= &trisbuffer[ntris];
int k;
t->vertex[1][k]= conformation[vb][k];
t->vertex[2][k]= conformation[vc][k];
}
+ if (!vertex_in_triangles_checked) {
+ vertex_in_triangles[va]++;
+ vertex_in_triangles[vb]++;
+ vertex_in_triangles[vc]++;
+ }
displaylist[ntris++]= t;
}
static void generate_display_list(void) {
- int vb, ve[3], e;
+ int vb, ve[V6], e;
ntris= 0;
FOR_VERTEX(vb) {
- /* We use the two triangles in the parallelogram vb, vb+e0, vb+e1, vb+e2.
+ /* We use the two triangles in the parallelogram vb, vb+e5, vb+e0, vb+e1.
* We go round each triangle clockwise (although our surface is non-
- * orientable so it shouldn't matter).
+ * orientable so it shouldn't matter). Picking the parallelogram
+ * to our right avoids getting it wrong at the join.
*/
- for (e=0; e<3; e++) ve[e]= EDGE_END2(vb,e);
- if (ve[1]>=0) {
- if (ve[0]>=0) addtriangle(vb,ve[0],ve[1]);
- if (ve[2]>=0) addtriangle(vb,ve[1],ve[2]);
+ for (e=0; e<V6; e++) ve[e]= EDGE_END2(vb,e);
+ assert(ve[0]>=0);
+ if (ve[5]>=0) addtriangle(vb,ve[0],ve[5]);
+ if (ve[1]>=0) addtriangle(vb,ve[1],ve[0]);
+ }
+
+ if (!vertex_in_triangles_checked) {
+ int v, expd;
+ FOR_VERTEX(v) {
+ expd= RIM_VERTEX_P(v) ? 3 : 6;
+ if (vertex_in_triangles[v] != expd) {
+ fprintf(stderr,"vertex %02x used for %d triangles, expected %d\n",
+ v, vertex_in_triangles[v], expd);
+ abort();
+ }
}
+ vertex_in_triangles_checked= 1;
}
}
show();
}
+static void topocheck(void) {
+ int v1,e,v2,eprime,v1prime, count;
+ FOR_EDGE(v1,e,v2) {
+ count= 0;
+ FOR_VEDGE(v2,eprime,v1prime)
+ if (v1prime==v1) count++;
+ if (count!=1) {
+ fprintf(stderr,"%02x -%d-> %02x reverse edge count = %d!\n",
+ v1,e,v2, count);
+ FOR_VEDGE(v2,eprime,v1prime)
+ fprintf(stderr,"%02x -%d-> %02x -> %d -> %02x\n",
+ v1,e,v2,eprime,v1prime);
+ exit(-1);
+ }
+ }
+}
+
int main(int argc, const char *const *argv) {
static const int wantedevents= POLLIN|POLLPRI|POLLERR|POLLHUP;
int k, i, r, *xfds, nxfds, polls_alloc=0;
struct pollfd *polls=0;
int motion_deferred=0, motion_x=-1, motion_y=-1;
+
+ topocheck();
+ if (argc==1) { printf("topology self-consistent, ok\n"); exit(0); }
if (argc != 2 || argv[1][0]=='-') {
fputs("need filename\n",stderr); exit(8);