Arc ASCII Grid Export header
Mike,
When I export information to an Arc ASCII Grid file via the GUI, I get a header in the Arc ASCII grid similar to th the following:
ncols 164
nrows 128
xllcorner -116.5440610236
yllcorner 28.9583011811
cellsize 0.016797637795
nodata_value -9999
When trying to do a similar thing programatically, I get the following header:
ncols 164
nrows 128
xllcorner -30.0002340539
yllcorner 59.9997367630
xdim 0.00020590309646876
ydim 0.00026426932853862
nodata_value -9999
When I try to import to ArcMap, I get the message: Invalid Raster Dataset.
Here is essentially how I am calling GM_ExportElevation from c# - any ideas on how to get the desired results?
When I export information to an Arc ASCII Grid file via the GUI, I get a header in the Arc ASCII grid similar to th the following:
ncols 164
nrows 128
xllcorner -116.5440610236
yllcorner 28.9583011811
cellsize 0.016797637795
nodata_value -9999
When trying to do a similar thing programatically, I get the following header:
ncols 164
nrows 128
xllcorner -30.0002340539
yllcorner 59.9997367630
xdim 0.00020590309646876
ydim 0.00026426932853862
nodata_value -9999
When I try to import to ArcMap, I get the message: Invalid Raster Dataset.
Here is essentially how I am calling GM_ExportElevation from c# - any ideas on how to get the desired results?
var filename = "c:\Test.asc"; var format = GM_ElevationExportFormat_t32.GM_Export_Arc_ASCII_Grid; //have to force these in, though in GUI i don't select these manually var pixelWidth = 164; var pixelHeight = 128; var flags = GM_RasterExportFlags_t32.GM_ExportFlags_HideProgress; var elevUnits = = GM_ElevUnits_t8.GM_ElevUnit_Meters; var lastGmError = GlobalMapper.GM_ExportElevation(filename, format, _asciiLayerHandle, ref _currentViewRectangle, pixelWidth, pixelHeight, flags, elevUnits);
Comments
I presume that your first file works in ArcMap and the 2nd doesn't? If you manually change your second to use 'cellsize' instead of 'xdim' and just delete the 'ydim' line (note this will make the position incorrect, but should be fine for testing), does ArcMap then like the file?
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Yes - manually changing the second file "worked" (Import to ArcMap successful) though the sizing was wrong.
So this solution:
"You would have to adjust your export bounding box and pixel dimensions in your call to get identical X and Y sample spacing values for the 'cellsize'"
The bounding box is my _currentviewRectangle which I set to the max bounds of the ASCII file layer that I load like so:
_asciiLayerInfo = (GM_LayerInfo_t)Marshal.PtrToStructure(GlobalMapper.GM_GetLayerInfo(_asciiLayerHandle), typeof(GM_LayerInfo_t))
_currentViewRectangle.mMaxX = _asciiLayerInfo.mGlobalRect.mMaxX;
_currentViewRectangle.mMinX = _asciiLayerInfo.mGlobalRect.mMinX;
_currentViewRectangle.mMaxY = _asciiLayerInfo.mGlobalRect.mMaxY;
_currentViewRectangle.mMinY = _asciiLayerInfo.mGlobalRect.mMinY;
Dumb question - how (specifically) do I set in the x/y pixelwidth/height values to GM_ExportElevation to be "even" and avoid xdim/ydim and instead output cellsize?
Thanks,
Brian
The X sample spacing is going to be the width of the bounding box passed in divided by the pixel width minus 1 (same for the Y dimension), so you can calculate the pixel width and height to pass in to get equal X and Y sample spacings for your bounding box. Note that you will probably have to slightly adjust your bounding box since you can't have non-integer pixel sizes.
If it would make things easier for you, I could add a new export flag to "force square samples", which would adjust your export pixel size automatically for you if passed in.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
I am not opposed to you adding a new flag
I will see if I can get this working in the meantime as you suggested. Thanks.
Brian
On a related note to this I am also exporting a GeoTIF and notice I have to pass in pixel width/height values as well. Is there a good way to determine, automatically, a good pixel width/height for the TIF? I know the GUI does something to a certain degree automatically. Let me know thoughts on this one too.
Brian
I have completed adding a new flag (GM_ExportFlags_ForceSquareSamples) that will automatically adjust your provided pixel dimensions (and possibly a slight expansion of your export bounds) to make the samples square. I have placed the new SDK build with this flag at http://www.globalmapper.com/GlobalMapperSDK_v134_beta.zip for you to try.
For the pixel dimensions, if you just have a single layer, call GM_GetLayerInfo and use the mGlobalPixelWidth and mGlobalPixelHeight values to get good pixel dimensions for the layer in the current projection. For more than one layer, Global Mapper calculates the sample spacing (i.e. resolution) of the most detailed layer, then uses that by default for the export, that way you aren't losing any resolution if you use the default settings.
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Thank you! I was away for
The weekend - will try this out first thing in the am and report back.
Brian
Something is not quite right - I keep getting GM_Error 8 - nothing to export. Here is my c# code and pinvoke wrapper:
Any ideas? I'll keep looking..
Brian
What do the values in your _currentViewRectangle look like and what about the layer info for your _asciiLayerHandle? Was the _asciiLayerHandle layer loaded so it is a gridded elevation layer?
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
_currentViewRectangle = new GM_Rectangle_t();
_currentViewRectangle.mMaxX = _asciiLayerInfo.mGlobalRect.mMaxX;
_currentViewRectangle.mMinX = _asciiLayerInfo.mGlobalRect.mMinX;
_currentViewRectangle.mMaxY = _asciiLayerInfo.mGlobalRect.mMaxY;
_currentViewRectangle.mMinY = _asciiLayerInfo.mGlobalRect.mMinY;
_asciiLayerInfo is loaded like so:
_asciiLayerInfo = (GM_LayerInfo_t)Marshal.PtrToStructure(GlobalMapper.GM_GetLayerInfo(_asciiLayerHandle), typeof(GM_LayerInfo_t));
_asciiLayerHandle well is the layer handle out from loaded ascii layer. here is how i load the ascii layer:
IntPtr layerHandle;
var flags = GM_LoadFlags_t32.GM_LoadFlags_HideAllPrompts | GM_LoadFlags_t32.GM_LoadFlags_HideProgress;
var genericAsciiTextFileImportOptions = new GM_AsciiFormatInfo_t
{
mImportType = GM_AsciiImportType_t8.GM_AsciiImport_Elevation,
mCoordDelim = GM_AsciiCoordDelim_t8.GM_AsciiDelim_AutoDetect,
mYCoordFirst = 1,
mIncludeCoordAttrs = 0,
mColumnHeadersInFirstRow = 0,
mIncludeElevCoords = 1,
mColumnsToSkip = 0,
mCoordLinePrefix = String.Empty,
mAreaType = AreaFeatureClass_t16.AFC_UNKNOWN,
mLineType = LineFeatureClass_t16.LFC_UNKNOWN,
mPointType = PointFeatureClass_t16.PFC_UNKNOWN,
mIgnoreZeroElevations = 1,
mFillToBounds = 0,
mOffsetX = 0,
mOffsetY = 0,
mOffsetZ = 0,
mScaleX = 1,
mScaleY = 1,
mScaleZ = -1,
mNoDataDistanceFactor = 0.0,
mBreakOnColumnIdx = IntPtr.Zero
};
var lastGmError = GlobalMapper.GM_LoadGenericAsciiTextLayer(globalMapperParams.AsciiDepthFilePath, out layerHandle, flags, ref genericAsciiTextFileImportOptions, ref _projection);
Your assignment of the bounding rectangle looks fine as well. Can you perhaps post a screenshot or else list of the values in the GM_LayerInfo_t structure for your ASCII layer so that I can verify that all looks ok?
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
{
public string mDescription; // Description string
public GM_Rectangle_t mNativeRect; // Bounding rect of layer in native coordinates
public GM_Rectangle_t mGlobalRect; // Bounding rect of layer in global coordinates
public uint mPixelWidth; // RASTER/ELEV ONLY: Number of pixels wide layer is
public uint mPixelHeight; // RASTER/ELEV ONLY: Number of pixels tall layer is
public GM_Projection_t mNativeProj; // Native projection of layer
public IntPtr mControlPoints; // RASTER ONLY: Ground control points list. Point to GM_GroundControlPoint_t
public uint mNumGCPs; // RASTER ONLY: Number of ground control points in list
public float mMinElevation; // ELEV ONLY: Minimum elevation in meters
public float mMaxElevation; // ELEV ONLY: Maximum elevation in meters
public uint mNumAreas; // VECTOR ONLY: Number of area features
public uint mNumLines; // VECTOR ONLY: Number of line features
public uint mNumPoints; // VECTOR ONLY: Number of point features
public double mPixelSizeX; // RASTER/ELEV ONLY: Pixel size in meters in the x direction
public double mPixelSizeY; // RASTER/ELEV ONLY: Pixel size in meters in the y direction
public byte mHasRasterData; // Does this layer have raster or elevation data?
public byte mEnabled; // Is this layer enabled for display or it it hidden?
public byte mHasVectorData; // Does this layer have vector data (the features counts can all be 0 for things like map catalogs)
public byte mUsedDefaultPos; // RASTER/ELEV ONLY: Was the default position used for this layer since the file could not be automatically positioned?
public string mFilename; // Filename from which layer was loaded (if this is an archive file, like .zip, then the name of the actual loaded file will be in mArchiveFilename
public string mArchiveFilename; // Filename within archive file (e.g. .zip or .tar.gz) from which layer was loaded, if any (might be NULL)
public string mTypeName; // Layer type name
public uint mGlobalPixelWidth; // RASTER/ELEV ONLY: Approximate number of pixels required in width for a 1:1 pixel mapping in the current projection
public uint mGlobalPixelHeight; // RASTER/ELEV ONLY: Approximate number of pixels required in height for a 1:1 pixel mapping in the current projection
public IntPtr mMetadataList; // List of metadata attributes and values for the layer
public uint mMetadataListSize; // Number of entries in mMetadataList
public uint mNumBands; // Number of bands in a raster image (use GM_SetRasterDisplayOptions to change color band layout)
public string mExtraLoadFlags; // Additional load flags with options selected by user during load. Pass these to GM_LoadLayerListEx to remember options.
public GM_PaletteEntry_t mPalette; // List of palette entries for palette-based raster layer
public uint mPaletteSize; // Number of entries in palette list
public IntPtr mUserData; // Custom data associated with layer provided by user via GM_SetLayerUserData function
public GM_ElevUnits_t8 mElevUnits; // Elevation units for layer
I'm not seeing anything obviously wrong. To get the error code you are getting either the layer being passed in isn't recognized as an elevation layer (it appears to be correct based on your load) or else the export bounding rectangle provided is either empty or the layer passed in doesn't intersect it. Can you check the values of the bounding box being passed in just before you call the GM_ExportElevation function and make sure they look ok there?
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
If I take out that new flag you created, the process works fine just like before - and all of my other functions work as they once did as well.
What is that new GM_RasterExportFlags_t32.GM_ExportFlags_ForceSquareSamples looking for now that I may not be passing in to complain of error 8? I'll keep looking but I can definitely product an Arc ASCII grid without that flag just like before - if for some reason my pixel height and depth are the same, it will even produce a header without separate x/y dims and just do cellsize like the following:
ncols 128
nrows 128
xllcorner -30.0002632370
yllcorner 59.9997367630
cellsize 0.00026426932853865
nodata_value -9999
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Seems like no change - still Error 8.
Brian
Can you check the time stamp on the GlobalMapperInterface.dll file that you are using? I'm guessing maybe you got a cached version of the new SDK built download that didn't have the update.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Hmmm that sounds right, can you provide me with a list of the parameter values (the bounding box in particular) that are being passed in so that I can pass those in and see what happens?
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
Good news bad news! Good news is yes it works! Bad news is that when I compare programatically generating it vs. using the GUI the ASC files are not the same. Here is the Programatic output header:
ncols 129
nrows 128
xllcorner -30.0002632370
yllcorner 59.9997367630
cellsize 0.00026426932853862
nodata_value -9999
Here is the GUI output header (same data):
ncols 128
nrows 128
xllcorner -30.0001311024
yllcorner 59.9998688976
cellsize 0.0002622047244094
nodata_value -9999
Any thoughts? I know you said you forced the bounding box to maybe be bigger but I think something simpler is at play here - let me know what you think. Thank you again.
Brian
I think the issue is the bounding rectangle that you are passing in. The GM_ExportElevation function expects an export rectangle from grid cell center to grid cell center, but the mGlobalRect from the layer info goes from the outer edge of the left-most pixel to the outer edge of the right-most pixel, so it's one sample spacing larger. I think if you shrink your export rectangle by one half of the sample spacing of the layer then you will get the bounds that you want to match what the GUI gets you.
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Support
support@globalmapper.com
I'm going to think this through as well, but just in case you have a faster answer.
Brian