//------------------------------------------------------------------------------ // GridList2D.java //------------------------------------------------------------------------------ package tribble.util; import java.lang.ArrayIndexOutOfBoundsException; import java.lang.IllegalArgumentException; /******************************************************************************* * Provides methods for arranging 1-dimensional array elements into a * 2-dimensional grid. * *

* Consider a 1-dimensional array containing 14 elements, as shown here: *

* * * * * * * * * * * * * * * * * * *
0 1 2 3 4 5 6 7 8 9 10 11 12 13
* *

* We wish to display the elements in a 2-dimensional grid with four columns, * so that the elements are arranged in order from top to bottom down each row, * and then from left to right across rows. Any left-over cells in the grid that * do not correspond to any elements in the array are left empty. Every cell in * each row, except possibly the last row, are filled; any remaining unfilled * cells will be the right-most cells of the last row. * The diagram below illustrates: *

* * * * * * * * * * * *
    Columns (x)

Rows
(y)  
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  0 1 2 3 4
0 0 4 8 11 −1
1 1 5 9 12 −1
2 2 6 10 13 −1
3 3 7 −1 −1 −1
4 −1 −1 −1 −1 −1
*
* *

* Note that cells within the 2-dimensional grid that do not have a corresponding * element in the 1-dimensional source array, as well as cells outside the grid, * have an index of −1. *

* *

* Determing the array indices for each grid cell is accomplished with code * similar to the following: *

* *
*    int         nCols =   4;
*    boolean     printed = true;
*
*    for (int y = 0;  printed;  y++)
*    {
*        printed = false;
*        for (int x = 0;  x < nCols;  x++)
*        {
*            int     i;
*
*            i = GridList2D.{@link #indexFor(int,int,int,int) indexFor}(x, y, nCols, arr.length);
*            if (i < 0)
*                break;
*
*            out.print(arr[i]);
*            printed = true;
*        }
*        if (printed)
*            out.println();
*    } 
* *

* An alternative approach is to initialize a GridList2D object with the * size of the 2-dimensional grid and the length of the 1-dimensional source * array: *

* *
*    int         nCols =   4;
*    GridList2D  grid;
*
*    grid = new {@link #GridList2D(int,int) GridList2D}(nCols, arr.length);
* *

* The indexFor() method of the object can then be called for each grid * cell coordinate to determine its corresponding index in the source array: *

* *
*    boolean     printed = true;
*
*    for (int y = 0;  printed;  y++)
*    {
*        printed = false;
*        for (int x = 0;  ;  x++)
*        {
*            int     i;
*
*            i = grid.{@link #indexFor(int,int) indexFor}(x, y);
*            if (i < 0)
*                break;
*
*            out.print(arr[i]);
*            printed = true;
*        }
*        if (printed)
*            out.println();
*    } 
* * *
*
Source code:
*
* http://david.tribble.com/src/java/tribble/util/GridList2D.java *
*
Documentation:
*
* http://david.tribble.com/docs/tribble/util/GridList2D.html *
*
* * * @version $Revision: 1.3 $ $Date: 2010/10/20 22:41:32 $ * @since 2010-10-17 * @author David R. Tribble (david@tribble.com) *

* Copyright ©2010 by David R. Tribble, all rights reserved.
* Permission is granted to any person or entity except those designated by * by the United States Department of State as a terrorist, or terrorist * government or agency, to use and distribute this source code provided * that the original copyright notice remains present and unaltered.

*/ public class GridList2D { static final String REV = "@(#)tribble/util/GridList2D.java $Revision: 1.3 $ $Date: 2010/10/20 22:41:32 $\n"; // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // Static methods /*************************************************************************** * Determine the index of an element in a 1-dimensional array that is located * at a particular (x, y) coordinate within a 2-dimensional grid. * * @param x * X (horizontal) coordinate within the 2-dimensional grid. * * @param y * Y (vertical) coordinate within the 2-dimensional grid. * * @param cols * Width of the 2-dimensional grid, i.e., the number of columns it contains. * * @param elems * Number of elements in the 1-dimensional array. * * @return * The index of the element of the 1-dimensional array that is located at the * (xy) cell coordinate within the 2-dimensional * grid, or −1 if the grid cell does not contain any array * element (i.e., the cell is empty). This also returns −1 if * the (xy) cell coordinates do not lie within the * grid. * * @since 1.1, 2010-10-17 */ public static int indexFor(int x, int y, int cols, int elems) { int rows; int excess; int j; // Bounds checks if (elems < 0) throw new ArrayIndexOutOfBoundsException( "Array length is negative: " + elems); // Compute the grid size rows = (elems - 1)/cols; excess = elems - cols*rows; // Bounds check if (x < 0 || x >= cols) return -1; // Compute the array index for the grid cell if (x < excess) { // Bounds check if (y < 0 || y > rows) return -1; j = x*(rows + 1) + y; } else { // Bounds check if (y < 0 || y >= rows) return -1; j = x*rows + y + excess; } if (j >= elems) return -1; return j; } // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // Variables /** Number of columns in the 2-D grid. */ private int m_cols; /** Number of rows in the 2-D grid. */ private int m_rows; /** Number of elements in the 1-D array. */ private int m_elems; /** Number of extra cells past the last full grid row. */ private int m_excess; // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // Constructors /*************************************************************************** * Construct an object to determine the indices of the elements in a * 1-dimensional array that are located at particular (x, y) coordinates * within a 2-dimensional grid. * * @param cols * Width of the 2-dimensional grid, i.e., the number of columns it contains. * * @param elems * Number of elements in the 1-dimensional array. * * @since 1.1, 2010-10-17 */ public GridList2D(int cols, int elems) { // Bounds checks if (cols < 1) throw new IllegalArgumentException("Grid columns is less than 1"); if (elems < 0) throw new IllegalArgumentException("Array length is negative"); // Initialize m_cols = cols; m_elems = elems; m_rows = (elems - 1)/cols; m_excess = elems - cols*m_rows; } // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // Methods /*************************************************************************** * Determine the index of an element in a 1-dimensional array that is located * at a particular (x, y) cell coordinate within a 2-dimensional grid. * * @param x * X (horizontal) coordinate within the 2-dimensional grid. * * @param y * Y (vertical) coordinate within the 2-dimensional grid. * * @return * The index of the element of the 1-dimensional array that is located at the * (xy) cell coordinate within the 2-dimensional * grid, or −1 if the grid cell does not contain any array * element (i.e., the cell is empty). This also returns −1 if * the (xy) cell coordinates do not lie within the * grid. * * @since 1.1, 2010-10-17 */ public int indexFor(int x, int y) /*const*/ { int rows; int j; // Bounds check if (x < 0 || x >= m_cols) return -1; // Compute the array index for the grid cell if (x < m_excess) { // Bounds check if (y < 0 || y > m_rows) return -1; j = x*(m_rows + 1) + y; } else { // Bounds check if (y < 0 || y >= m_rows) return -1; j = x*m_rows + y + m_excess; } if (j >= m_elems) return -1; return j; } /*************************************************************************** * Retrieve the number of columns in the 2-dimensional grid. * * @return * Width of the 2-dimensional grid, i.e., the number of columns it contains. * * @since 1.2, 2010-10-18 */ public int getColumns() /*const*/ { return m_cols; } /*************************************************************************** * Retrieve the number of rows in the 2-dimensional grid. * * @return * Height of the 2-dimensional grid, i.e., the number of rows it contains. * Note that the last row may contain empty cells. * * @since 1.2, 2010-10-18 */ public int getRows() /*const*/ { return m_rows; } /*************************************************************************** * Retrieve the number of elements in the 1-dimensional source array. * * @return * Number of elements in the 1-dimensional array. * * @since 1.2, 2010-10-18 */ public int getArrayLength() /*const*/ { return m_elems; } } // End GridList2D.java