chiark / gitweb /
stopping point for 64
[moebius2.git] / output.c
index e37aa7c21775c3383381b856685fd7ed1be6370b..f64b22cedc1623cc6769c5b5ad57580a0f00bd8c 100644 (file)
--- a/output.c
+++ b/output.c
  *   - scale the coordinates
  *   - translate the coordinates so they're all positive
  */
+/*
+ *  ./output-64 <dense-64.cfm 0.1 50 >t.stl
+ *  ./output-125 <best-125.cfm >t.stl 0.1 50
+ *  meshlab t.stl
+ */
 /*
  * Re STL, see:
  *  http://www.ennex.com/~fabbers/StL.asp
@@ -45,7 +50,7 @@
  *       /    *B2  2\  / /1   *A    \    /    *A    \    /    *A    \    /
  *   \  /            \/:/     0      \  /            \  /            \  /
  *    *C ____________|*C ____________ *C ___________  *C ___________  *C __
- *    /\          3  | :   0          /\              /\              /\
+ *    /\          3  |/\   0          /\              /\              /\
  *   /  \            / :\            /  \            /  \            /  \
  *       \    *A3  4/ \: \5  5*B    /    \    *B    /    \    *B    /    \
  *        \        /   \  \        /      \        /      \        /
  *
  * The outfacets are:
  *
- *  For each non-rim vertex on each side, the six triangles formed by
- *  its C and the surrounding A's and B's.
- *
- *  For each rim vertex on each side, the two triangles formed by its
- *  D and the nearest As and Bs (two As and one B or vice versa).
- *
- *  For each rim edge on each side, the triangle formed by that edge's
- *  ends' Ds and the corresponding A or B.
+ *  For each input vertex on each side, the six (or perhaps only three)
+ *  triangles formed by its C or D and the surrounding Cs and/or Ds.
  *
  *  For each G, the six triangles formed by that G and the adjacent
  *  four Fs (or two Fs and two Ds) and two Es.
@@ -149,6 +148,10 @@ static double scale;
 static void outfacet(int rev, const OutVertex *a,
                     const OutVertex *b, const OutVertex *c);
 
+typedef int int_map(int);
+static int defs_aroundmap_swap(int around) { return NDEF-1-around; }
+static int int_identity_function(int i) { return i; }
+
 static void normalise_thick(double a[D3]) {
   /* multiplies a by a scalar so that its magnitude is thick */
   int k;
@@ -194,7 +197,7 @@ static double outvertex_coord_check(double value) {
 static void compute_outvertices(void) {
   int v0,k,side,ab,x,y;
 
-  FOR_VERTEX(v0) {
+  FOR_VERTEX(v0, INNER) {
     for (ab=0; ab<2; ab++) {
       int v1= EDGE_END2(v0, ab?5:0);
       int v2= EDGE_END2(v0, ab?0:1);
@@ -208,7 +211,7 @@ static void compute_outvertices(void) {
       K Ok(ovAB[v0][ab][1], centroid[k] - normal[k]);
     }
   }
-  FOR_VERTEX(v0) {
+  FOR_VERTEX(v0, INNER) {
     int vw= EDGE_END2(v0,3);
     int vnw= EDGE_END2(v0,2);
     int vsw= EDGE_END2(v0,4);
@@ -231,7 +234,7 @@ static void compute_outvertices(void) {
       K Ok(ovC[v0][side], in[v0][k] + adjust[k]);
     }
   }
-  FOR_RIM_VERTEX(y,x,v0) {
+  FOR_RIM_VERTEX(y,x,v0, INNER) {
     double rim[D3], inner[D3], radius_cos[D3], radius_sin[D3];
     int vback, vfwd, around;
 
@@ -262,22 +265,26 @@ static void compute_outvertices(void) {
     normalise_thick(radius_cos);
     normalise_thick(radius_sin);
 
+    int_map *around_map= y ? int_identity_function : defs_aroundmap_swap;
+
     for (around=0; around<NDEF; around++) {
-      double angle= around * M_PI / (NDEF-1);
+      double angle= around_map(around) * M_PI / (NDEF-1);
       K Ok(ovDEF[x][!!y][around],
           in[v0][k] +
           cos(angle) * radius_cos[k] +
           sin(angle) * radius_sin[k]);
     }
   }
-  FOR_RIM_VERTEX(y,x,v0) {
+  FOR_RIM_VERTEX(y,x,v0, INNER) {
     int vfwd= EDGE_END2(v0,0);
     assert(vfwd >= 0);
-    int around;
-    for (around=0; around<NG; around++) {
-      K Ok(ovG[x][!!y][around],
-          0.5 * (ovDEF[ x          ][!!y][around*2].p[k] +
-                 ovDEF[vfwd & XMASK][!!y][around*2].p[k]));
+    int aroung;
+    int_map *around_map= vertices_span_join_p(v0,vfwd)
+      ? defs_aroundmap_swap : int_identity_function;
+    for (aroung=0; aroung<NG; aroung++) {
+      K Ok(ovG[x][!!y][aroung],
+          0.5 * (ovDEF[ x          ][!! y             ][aroung*2+1].p[k] +
+                 ovDEF[vfwd & XMASK][!!(vfwd & ~XMASK)][around_map(aroung*2+1)].p[k]));
     }
   }
 }
@@ -297,22 +304,28 @@ static void outfacets_around(int reverse, OutVertex *middle,
   }
 }
 
-static int defs_aroundmap_swap(int around) { return NDEF-around; }
-static int int_identity_function(int i) { return i; }
+static OutVertex *invertex2outvertexcd(v0,side) {
+  if (!RIM_VERTEX_P(v0)) return &ovC[v0][side];
+
+  int around= side ? NDEF-1 : 0;
+  int rimy= !!(v0 & ~XMASK);
+  return &ovDEF[v0 & XMASK][rimy][around];
+}
 
 static void outfacets(void) {
-  int v0,e,side,aroung, k;
+  int v0,e,side,aroung;
   
-  FOR_VERTEX(v0) {
+  FOR_VERTEX(v0, INNER) {
     OutVertex *defs=0, *defs1=0;
-    int (*defs1aroundmap)(int)=0, rimy=-1;
+    int rimy=-1;
+    int_map *defs1aroundmap= 0;
     if (RIM_VERTEX_P(v0)) {
       OutVertex *gs;
       rimy= !!(v0 & ~XMASK);
       int v1= EDGE_END2(v0,0);  assert(v1>=0);
       gs=    ovG  [v0 & XMASK][rimy];
       defs=  ovDEF[v0 & XMASK][rimy];
-      defs1= ovDEF[v1 & XMASK][rimy];
+      defs1= ovDEF[v1 & XMASK][!!(v1 & ~XMASK)];
       defs1aroundmap= vertices_span_join_p(v0,v1)
        ? defs_aroundmap_swap : int_identity_function;
 
@@ -328,23 +341,16 @@ static void outfacets(void) {
     }
 
     FOR_SIDE {
-      OutVertex *cd;
-      if (defs) {
-       int around= side ? NDEF-1 : 0;
-       cd= &defs[around];
-       OutVertex *ab= &ovAB[v0][!rimy][side];
-       OutVertex *cd1= &defs1[defs1aroundmap(around)];
-       outfacet(side^rimy,cd,ab,cd1);
-      } else {
-       cd= &ovC[v0][side];
+      int ab;
+      for (ab=0; ab<2; ab++) {
+       int v1= EDGE_END2(v0, ab ? 5 : 0);
+       int v2= EDGE_END2(v0, ab ? 0 : 1);
+       if (v1<0 || v2<0) continue;
+       outfacet(side,
+                invertex2outvertexcd(v0,side),
+                invertex2outvertexcd(v1,side^vertices_span_join_p(v0,v1)),
+                invertex2outvertexcd(v2,side^vertices_span_join_p(v0,v2)));
       }
-      OutVertex *ab[6];
-      FOR_VPEDGE(e) {
-       ab[e]= invertex2outvertexab(v0,e,side);
-       if (ab[e])
-         K assert(!isnan(ab[e]->p[k]));
-      }
-      outfacets_around(side, cd, 6,ab);
     }
   }
 }     
@@ -368,8 +374,11 @@ static void blank_outvertices(void) {
 
 static void transform_outvertex_array(int n, OutVertex ovX[n]) {
   int i, k;
-  for (i=0; i<n; i++)
+  for (i=0; i<n; i++) {
+    ovX[i].p[0] *= -1;
+    ovX[i].p[1] *= -1;
     K ovX[i].p[k] *= scale;
+  }
   /*
    *   double min[D3]= thick;
    *           if (ovX[i].p[k] < min)
@@ -415,6 +424,7 @@ assert(d >= -1e3 && d <= 1e3);
 
 static uint32_t noutfacets;
 static uint32_t noutfacets_counted;
+static long badfacets;
 
 static void outfacet(int rev, const OutVertex *a,
                     const OutVertex *b, const OutVertex *c) {
@@ -432,8 +442,10 @@ static void outfacet(int rev, const OutVertex *a,
   triangle_normal(normal, a->p, b->p, c->p);
   double multby= 1/magnD(normal);
   
-  if (multby > 1e6)
+  if (multby > 1e6) {
+    badfacets++;
     return;
+  }
 
   noutfacets++;
   if (!~noutfacets_counted) return;
@@ -466,6 +478,11 @@ static void write_file(void) {
   assert(noutfacets == noutfacets_counted);
 
   if (fflush(stdout)) diee("fflush stdout");
+
+  if (badfacets) {
+    fprintf(stderr,"%ld degenerate facets!\n",badfacets);
+    exit(4);
+  }
 }  
   
 
@@ -481,6 +498,7 @@ int main(int argc, const char *const *argv) {
   errno= 0; r= fread(&in,sizeof(in),1,stdin);
   if (r!=1) diee("fread");
 
+  mgraph_prepare();
   blank_outvertices();
   compute_outvertices();
   transform_outvertices();