2 * We try to find an optimal triangle grid
4 * Vertices in strip are numbered as follows:
6 * ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 ___ 4 __
8 * / \ / \ / \ / \ / \ / \ / \
9 * / \ / \ / \ / \ / \ / \ / \
10 * X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 ___ 4
11 * Y-2 Y-2 Y-2 1 1 1 1 1
12 * \ / \ / \ / \ / \ / \ / \ /
13 * \ / \ / \ / \ / \ / \ / \ /
14 * ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3 __
17 * . . . . . . . . . . . . . . .
19 * X-4 ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 ___ 3
20 * 1 1 1 1 Y-2 Y-2 Y-2 Y-2
21 * \ / \ / \ / \ / \ / \ / \ /
22 * \ / \ / \ / \ / \ / \ / \ /
23 * ___ X-4 ___ X-3 ___ X-2 ___ X-1 ___ 0 ___ 1 ___ 2 __
27 * 0 <= x < X x = distance along
28 * 0 <= y < Y y = distance across
30 * Vertices are in reading order from diagram above ie x varies fastest.
32 * Y must be even. The actual location opposite (0,0) is (X-(Y-1)/2,0),
33 * and likewise opposite (0,Y-1) is ((Y-1)/2,0).
35 * To label edges, we counte anticlockwise[*] from to-the-right:
44 * [*] That is, in the direction represented as anticlockwise for
45 * the vertices (0,*)..(4,*) in the diagram above; and of course
46 * that is clockwise for the vertices (X-5,*)..(X-1,*). The
47 * numbering has an actual discontinuity between (X-1,*) and (0,*).
49 * When we iterate over edges, we iterate first over vertices and then
50 * over edges 0 to 2, disregarding edges 3 to 5.
58 /* vertex number: 0000 | y | x
65 #define Y1 (1 << YSHIFT)
66 #define YMASK (Y-1 << YSHIFT)
68 /* Energy has the following parts right now:
71 * Edgewise expected vertex displacement
88 * Find R', the `expected' location of R, by
89 * reflecting S in M (the midpoint of QP).
95 * Giving energy contribution:
103 * By symmetry, this calculation gives the same answer
104 * with R and S exchanged. Looking at the projection in
111 * R' ,' 2d" = |SS'| = |RR'| = 2d
113 * `-._ ,' By congruent triangles,
114 * ` M with M' = midpoint of RS,
115 * ,' `-._ |MM'| = |RR'|/2 = d
118 * ,' M' _ , - ' d = |MM'|
122 * We choose this value for l (rather than |RM|+|MS|, say, or |RM|)
123 * because we want this symmetry and because we're happy to punish
124 * bending more than uneveness in the metric.
126 * In practice to avoid division by zero we'll add epsilon to l^3
127 * and the huge energy ought then to be sufficient for the model to
128 * avoid being close to R=S. */
132 static int edge_end2(unsigned v1, int e) {
133 /* The topology is equivalent to that of a square lattice with only
134 * half of the diagonals. Ie, the result of shearing the triangular
135 * lattice to make the lines of constant x vertical. This gives
136 * these six directions:
146 * This also handily makes vertical the numbering discontinuity,
147 * where the join happens.
149 static const unsigned dx[V6]= { +1, +1, 0, -1, -1, 0 },
150 dy[V6]= { 0, +Y1, +Y1, 0, -Y1, -Y1 };
153 y= (v1 & YMASK) + dy[e];
154 if (y & ~YMASK) return -1;
156 x= (v1 & XMASK) + dx[e];
166 #define FOR_VERTEX(v) \
167 for ((v)=0; (v)<N; (v)++)
169 #define FOR_VPEDGE(v,e) \
170 for ((e)=0; (e)<V6; (e)++)
172 #define EDGE_END2 edge_end2
174 #define FOR_VEDGE(v1,e,v2) \
176 if (((v2)= EDGE_END2((v1),(e))) < 0) ; else
178 #define FOR_EDGE(v1,e,v2) \
180 FOR_VEDGE((v1),(e),(v2))
182 #define FOR_COORD(k) \
183 for ((k)=0; (k)<D3; (k)++)
185 #define K FOR_COORD(k)
187 static double hypotD(const double p[], const double q[]) {
192 K pq[_k]= p[k] - q[k];
196 /* owner and block ought not to be used */
198 return gsl_blas_snrm2(&v);
202 # define ffsqa(factor,term) fma((factor),(factor),(term))
204 # define ffsqu(factor,term) ((factor)*(factor)+(term))
207 static const l3_epsison= 1e-6;
209 static double energy_function(const double vertices[N][D3]) {
210 int pi,e,qi,ri,si, k;
211 double m[D3], mprime[D3], b, d2, l, sigma_bd2_l;
214 ri= EDGE_END2(pi,(e+1)%V6); if (r<0) continue;
215 si= EDGE_END2(pi,(e+5)%V6); if (s<0) continue;
216 assert(ri == EDGE_END2(qi,(e+2)%V6));
217 assert(si == EDGE_END2(qi,(e+4)%V6));
219 K m[k]= (vertices[pi][k] + vertices[qi][k]) * 0.5;
220 K mprime[k]= (vertices[ri][k] + vertices[si][k]) * 0.5;
221 b= hypotD(vertices[pi], vertices[qi]);
222 d2= 0; K d2= ffsqa(m[k] - mprime[k], d2);
223 l= hypotD(vertices[ri][k] - vertices[si][k]);
224 l3 = l*l*l + l3_epsilon;
226 sigma_bd2_l += b * d2 / l3;
231 static gsl_multimin_fminimizer *minimiser;
236 gsl_multimin_fminimizer_alloc(