Rectangular Ranges

Ranges represent rectangular domains of arbitrary dimensions. In principal a range is simply a pair of coordinates and, as such, can be constructed with two coordinates. The Range class takes two template arguments specifying the data type stored in the range and the dimensionality of the range.

  Range<int, 2> range;

The code above creates a two dimensional range of integers. The Range class defines the type LimitType that is used for specifying the lower and upper bounds of the range. An additional third template argument allows for control over argument checking policies. In order to create a two dimensional range from, let’s say, (1,2) to (4,5) we can write the following.

  Range<int, 2>::LimitType low(1, 2);
  Range<int, 2>::LimitType high(4, 5);

  Range<int, 2> range(low, high);

The upper bound of the range is inclusive. This means that the range contains all the points lying in the rectangle spanning from the point (1,2) to, and including, the point (4,5). Note that no check is carried out to ensure that the upper bound is larger than the lower bound. The methods getLo() and getHi() return the lower and upper bounds of the range. The following code assigns the lower bound to low and the upper bound to high.

  low  = range.getLo();
  high = range.getHi();

The getLo() and getHi() also allow write access to the bounds of the range. So we can modify the range as follows.

  range.getLo() = Range<int, 2>::LimitType(5,2);
  range.getHi() = Range<int, 2>::LimitType(9,7);

This will change the range to the rectangle (5,2) to (9,7).

The Range class supplies a utility method that allows you to grow or shrink the range in all directions by the same amount.

Given the range above the following call will shrink the range by 1, resulting in a rectangular range from (6,3) to (8,6).

  range.grow(-1);

For ranges containing integer types we can use the iterator supplied by the Range class to iterate over all coordinates that lie within the range.

  for (Range<int, 2>::iterator it=range.begin(); it!=range.end(); ++it)
  {
    const Range<int, 2>::LimitType &pos = *it;
    std::cout << pos[0] << " " << pos[1] << std::endl;
  }

The code above iterates over the rectangle and prints out all the coordinates. The output of the code is as follows.

6 3
6 4
6 5
6 6
7 3
7 4
7 5
7 6
8 3
8 4
8 5
8 6

The code for this tutorial can be found here.