+/* Convert from a board index to a device-pixel coordinate pair, (at
+ * the center of the ring). */
+static void
+layout_board_to_device (layout_t *layout, double *x_ret, double *y_ret)
+{
+ double x = *x_ret, y = *y_ret;
+
+ *x_ret = layout->x_offset + layout->cell_size *
+ (x + (y - DVONN_BOARD_Y_SIZE/2)/2.0 + 0.5);
+ *y_ret = layout->y_offset + layout->cell_size * (M_SQRT1_2 * y + 0.5);
+}
+
+/* Convert from a device-pixel coordinate pair to a board index. */
+static void
+layout_device_to_board (layout_t *layout, int *x_ret, int *y_ret)
+{
+ int x = *x_ret, y = *y_ret;
+ int x1, y1, x2, y2;
+ double x1_dev, y1_dev, x2_dev, y2_dev;
+ double dx, dy, d1, d2;
+
+ /* Because the vertical spacing between adjacent rows is less than
+ * layout->cell_size, the simple calculations here give us two
+ * candidate (x,y) pairs. We then choose the correct one based on
+ * a distance calculation.
+ */
+ y1 = (y - layout->y_offset) / (layout->cell_size * M_SQRT1_2);
+ x1 = (double) (x - layout->x_offset) / layout->cell_size - (y1 - DVONN_BOARD_Y_SIZE/2)/2.0;
+
+ y2 = y1 - 1;
+ x2 = (double) (x - layout->x_offset) / layout->cell_size - (y2 - DVONN_BOARD_Y_SIZE/2)/2.0;
+
+ x1_dev = x1;
+ y1_dev = y1;
+ layout_board_to_device (layout, &x1_dev, &y1_dev);
+
+ x2_dev = x2;
+ y2_dev = y2;
+ layout_board_to_device (layout, &x2_dev, &y2_dev);
+
+ dx = x - x1_dev;
+ dy = y - y1_dev;
+ d1 = sqrt (dx*dx + dy*dy);
+
+ dx = x - x2_dev;
+ dy = y - y2_dev;
+ d2 = sqrt (dx*dx + dy*dy);
+
+ if (d1 < d2) {
+ *x_ret = x1;
+ *y_ret = y1;
+ } else {
+ *x_ret = x2;
+ *y_ret = y2;
+ }
+}
+