Wednesday, 26 February 2014

Esri ASCII Grid Format

Session 1

The first session goal was to load an OS Terrain 50 data file into a terrain object.  The existing structure of the terrain object is a simple C# dictionary using a 2D point as a key and the height data as the value.  This was redesigned to allow for multiple tiles and to allow different types of loaders to populate the data, i.e. Perlin noise, GML, ASCII grid etc.

The new structure contains an overarching terrain object.  The terrain object can contain 0..* tiles.  The tile contains 1..1 tile content object. The tile content object is an abstract class that contains 0..* tileData objects and a virtual method, LoadContent. 

First design of the tile loader package
There are two items of note.  The first is that the tile is given the tile content object so that I can use lazy loading, i.e. the tile can exist without any data.  This way I can create all the tiles I require and position them before loading the data of the tile. The second point is the the tile object can be oblivious to where its data came from, i.e. file loaded, auto generated etc.  This is a first draft of the design and I expect to change as things develop.

ESRI ASCII Grid Format

I have decided to start with the simplest format for the first data file which is the ASCII grid format.  The details of the format can be found here but here are the main points:

The format has a header block containing the following items:

ncols - The number of columns in the data
nrows - The number of rows in the data
xllcorner - The X offset from the lower left corner
yllcorner - The Y offset from the lower left corner
cellsize - The cell size in metres
NODATA_value - Value that indicates no data recorded.

After the header block is the main data starting in the upper left corner.

To read the data in I am using the C# stream reader to read the file in line by line.  I have created a new object that inherits from TileContent called ASCIITileContent and implements the LoadContent method.  The load content method creates a background worker thread to read the file and load into the terrainData object.  For this I had to create a new event that tells the tile when its content is loaded which is raised by the background worker thread upon completion.  I added the new event to the TileContent class as I am planning to use the same technique for the rest of the classes.

I have also modified the Perlin algorithm to fit into the new design.  I have created a new class, PerlinTileContent, which inherits from TileContent and generates a random terrain.  This is then saved in the terrainData and an event is raised by the background worker.

For the tile loading I have created a new package in the project called tile loader that contains all the tile classes so that I can keep the data and UI loosely coupled.  

Overall, the first session went very well.  The data can now be read in successfully using the background worker threads and the class design seems to work well.  I think I may tweak it tomorrow to allow more information to be passed back and forth (mainly to report on progress whilst loading the file) but for now I am happy that I have met the objectives of first session.  Reading the ASCII files was very simple job but I may have to think about using a 3rd party zip library so that I don't have to keep unzipping the data files from the master zip but that may be a task for phase 2.  Tomorrow, I am hoping to link it up to the WinForms UI and look at how the UI can be improved.

No comments:

Post a Comment