Wednesday, 10 May 2017

raster - How to get values to create world file format?


i have researched regarding making world file format and tried to create one using c++ in windows, can somebody confirm if where i am getting the values from are correct? the literature regarding world file formats are quite vague. i don't use rotation so i assume value D and E are always zero..


Line 1: A: pixel size in the x-direction in map units/pixel.



p->GetDeviceCaps(HORZRES); // HORZRES is defined in wingdi.h as Horizontal width in
pixels


Line 2: D: rotation about y-axis // always 0 as i don't use rotation


Line 3: B: rotation about x-axis // always 0 as i don't use rotation


Line 4: E: pixel size in the y-direction in map units, almost always negative


p->GetDeviceCaps(VERTRES); // VERTRES is defined in wingdi.h as Horizontal width in
pixels


Line 5: C: x-coordinate of the center of the upper left pixel // how do you get this value?


Line 6: F: y-coordinate of the center of the upper left pixel // how do you get this value?



Answer




World files, as used by Esri, GDAL etc.. have a standard format:


Normally the rotation is 0 for both values (not rotated) but the values form a 6 parameter Affine Transformation between cells and the world; if you understand the maths then you could conceivably populate those numbers for a fine rotation. Here is some code for a GDAL GeoTransform array that is very similar to a world file:


double GeoTransform[6];
GeoTransform[0] = Xmin; // Upper Left X
GeoTransform[1] = CellSize; // W-E pixel size
GeoTransform[2] = 0; // Rotation, 0 if 'North Up'
GeoTransform[3] = Ymax; // Upper Left Y
GeoTransform[4] = 0; // Rotation, 0 if 'North Up'
GeoTransform[5] = -CellSize; // N-S pixel size


Whereas a world file is populated like:


Cell Width
0
0
Cell Height (negative)
X coordinate of upper left cell (centre)
Y coordinate of upper left cell (centre)

Note that N-S pixel size is always negative as rasters start at the upper left and read downward. All values are in world units (metres, feet, degrees, inches etc.).


Here is an example of how I would calculate/create a world file in Esri objects:



void GetWorldValuesFromActiveView(ESRI.ArcGIS.Framework.IApplication pApp)
{
ESRI.ArcGIS.ArcMapUI.IMxDocument pDoc = (ESRI.ArcGIS.ArcMapUI.IMxDocument)pApp.Document;
ESRI.ArcGIS.Carto.IActiveView pView = pDoc.ActiveView;
ESRI.ArcGIS.Geometry.IEnvelope pExtent = pView.Extent; // the display bounds in world units
ESRI.ArcGIS.esriSystem.tagRECT pPixBnd = pView.ExportFrame; // the display bounds in screen units
// cells wide and high, I am using absolute value
// as (very rarely) a screen can have negative coordinates
int Rows = Math.Abs( pPixBnd.top - pPixBnd.bottom );
int Cols = Math.Abs( pPixBnd.right - pPixBnd.left );


double Width = pExtent.XMax - pExtent.XMin; // width in 'world' units
double Height = pExtent.YMax - pExtent.YMin;
double CellX = Width / Cols;
double CellY = Height / Rows;
double ULX = pExtent.XMin + (CellX / 2);
double ULY = pExtent.YMax - (CellY / 2);

using (System.IO.StreamWriter pWorldWrite = new System.IO.StreamWriter("c:\\path\\to\\world\\file.tfw"))
{

pWorldWrite.WriteLine(CellX.ToString());
pWorldWrite.WriteLine("0");
pWorldWrite.WriteLine("0");
pWorldWrite.WriteLine("-" + CellY.ToString());
pWorldWrite.WriteLine(ULX.ToString());
pWorldWrite.WriteLine(ULY.ToString());
}
}

As you can see from the application you must know how many pixels the window is but also what extent 'on the ground' that those pixels represent. If you are writing your own application you must know these values at some point as it's intrinsic to rendering to display.



No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...