Introduce CellLayer and CellRegion abstractions.

The next step towards TS/RA2 tileset support (#5350) is to remove the assumption that map coordinates == cell coordinates (the isometric games have cell axes rotated by 45 degrees to the map).

The existing code required each trait that stored something for each cell to roll its own storage, usually via an inefficient 2D array.  The CellLayer class replaces this duplication with a wrapper around a 1D array, and which can transparently convert between cell and map coordinates (see [pchote:isometric](https://github.com/pchote/OpenRA/commits/isometric) for a sneak-peek at where this is going).

The next problem is enumerating over a set of cells on the screen / in the map / etc.  Looping over the x and y axes won't work, as they are rotated relative to the screen for isometric maps.  The CellRegion class introduces a simpler way of enumerating regions that will work for both perspectives.
I find 677b9c515b5a4cf1fd9fa97cc181b2211f8d46be gives a ~20% perf improvement in a naive benchmark (enumerating over the map a bunch of times).  I'm not sure if I can do any better than this without discarding the foreach syntax, which I'd rather not do.