Marching Squares

UNDER CONSTRUCTION.

Although the algorithm in this project is fairly straightforward and general, I think it is worthwhile to note some minor but non-trivial stuffs.

Scalar field and cells

In this example, periodic boundary is assumed in \(x\) direction, while \(y\) direction is wall-bounded. The input scalar field (two-dimensional array) is defined at each block dot. The number of cells, which are formed by the dashed lines, is decreased by \(1\) in both directions. In \(x\) direction, however, because of the periodicity, cells formed by the right and left bounds should be considered, giving one additional cell.

Thus, the number of cells to be considered leads

\[\begin{split}\begin{cases} \text{Wall-bounded} & N_i - 1, \\ \text{Periodic } & N_i, \end{cases}\end{split}\]

where \(i = x, y\).

This can be seen in the code here:

src/cluster.c
454  const size_t nx = periods[0] ? sizes_[0] : sizes_[0]-1;
455  const size_t ny = periods[1] ? sizes_[1] : sizes_[1]-1;
456  const size_t sizes[2] = {nx, ny};
_images/result.png

Relation between input scalar field and cells for marching squares.

Cell and arrows

_images/result1.png

Possible arrow types in a cell.

There are in total \(18\) arrow types, which are implemented here:

src/cluster.c
271  arrows_t arrows = 0;
272  switch(vertices){
273    case 0:
274      arrows |= 0;
275      break;
276    case 1:
277      arrows |= define_arrow(EDGE_X_NEG, EDGE_Y_NEG) << 0;
278      break;
279    case 2:
280      arrows |= define_arrow(EDGE_Y_NEG, EDGE_X_POS) << 0;
281      break;
282    case 3:
283      arrows |= define_arrow(EDGE_X_NEG, EDGE_X_POS) << 0;
284      break;
285    case 4:
286      arrows |= define_arrow(EDGE_X_POS, EDGE_Y_POS) << 0;
287      break;
288    case 5:
289      arrows |= define_arrow(EDGE_X_POS, EDGE_Y_POS) << 0;
290      arrows |= define_arrow(EDGE_X_NEG, EDGE_Y_NEG) << 4;
291      break;
292    case 6:
293      arrows |= define_arrow(EDGE_Y_NEG, EDGE_Y_POS) << 0;
294      break;
295    case 7:
296      arrows |= define_arrow(EDGE_X_NEG, EDGE_Y_POS) << 0;
297      break;
298    case 8:
299      arrows |= define_arrow(EDGE_Y_POS, EDGE_X_NEG) << 0;
300      break;
301    case 9:
302      arrows |= define_arrow(EDGE_Y_POS, EDGE_Y_NEG) << 0;
303      break;
304    case 10:
305      arrows |= define_arrow(EDGE_Y_NEG, EDGE_X_POS) << 0;
306      arrows |= define_arrow(EDGE_Y_POS, EDGE_X_NEG) << 4;
307      break;
308    case 11:
309      arrows |= define_arrow(EDGE_Y_POS, EDGE_X_POS) << 0;
310      break;
311    case 12:
312      arrows |= define_arrow(EDGE_X_POS, EDGE_X_NEG) << 0;
313      break;
314    case 13:
315      arrows |= define_arrow(EDGE_X_POS, EDGE_Y_NEG) << 0;
316      break;
317    case 14:
318      arrows |= define_arrow(EDGE_Y_NEG, EDGE_X_NEG) << 0;
319      break;
320    case 15:
321      arrows |= 0;
322      break;
323    default:
324      printf("%d: should not be here (%u)\n", __LINE__, vertices);
325      exit(EXIT_FAILURE);
326  }