Darin Beaudreau Darin Beaudreau - 1 year ago 52
Java Question

How can I scale a 2D grid to the size of the canvas?

I'm making a simple grid-based variant of Conway's Game of Life in JavaFX, and I'm using an example I found on StackExchange. The problem is that the scaling method in that example doesn't seem to work for me. In this example, you can choose the "size" of the grid, meaning how many rows/columns it is composed of, and then the scale is supposed to determine the size of each cell in that grid, allowing the grid to fit inside the canvas if the user resizes the window.

I tested this by trying to "fill in" the top-left and bottom-right cells, using (0,0) and ((xMax - 1), (yMax - 1)). But the bottom-right one seems to clip way out of the bounds of the canvas, as I have to subtract more than 1 from yMax to get it to appear.

Here is the "scaling factor" method I'm using...

private double getScaleFactor() {
return (canvas.getWidth() + canvas.getHeight()) / (cellsWide + cellsHigh);

Is there anything wrong with this method? Could it be the way I'm constructing the GUI? The canvas is bound to the center of the BorderPane, and there is an HBox bound to the top and VBox bound to the left. However, I've been able to draw things in the center of the canvas using (width / 2) and (height / 2) as usual, so something tells me it's something wrong with how I'm getting the scaling factor.

Can someone help me out?

Answer Source

The formula you are currently using looks like it shouldn't work.

Suppose the following two cases:

  1. You have a canvas that is 100 x 10 with 1 row and 10 columns
  2. You have a canvas that is 100 x 20 with 1 row and 10 columns

In the first case, the scale factor would be (100 + 10) / (1 + 10) = 10, and ideally this would cause the cells to be sized such that they completely fill the canvas. However, in the second case, the scale factor would be (100 + 20) / 1 + 10) = 10.909091, which would imply cells in the second case are larger than those in the first case. Since the width didn't change, and the entire canvas is used in the first case, the larger cells in the second case MUST run off the canvas.

Since I don't know too much about how the scale factor is being used I can't really provide too much more help in the way of what is wrong with what you currently have, but:

Assuming the scale factor is the side length of a cell (in pixels) and that the cells remain square when the window is resized to a different aspect ratio, here is a formula that should work:

private double getScaleFactor()
    double hfactor = canvas.getHeight() / cellsHigh;
    double wfactor = canvas.getWidth() / cellsWide;

    return (hfactor < wfactor ? hfactor : wfactor);

This computes the height of a cell if the cells were to fill the entire height of the screen, and the width of a cell if the cells were to fill the entire width of the screen. It then takes the minimum of the sizes to ensure that all the cells fit on the screen.