Example of how to use GM_GroundControlPoint_t with GM_LoadRectifiedLayer
Hi,
I'm trying to programatically load up MrSID layers using the Global Mapper SDK. I realized that I can load them in using GM_LoadLayerList or GM_LoadLayerListEx, however unless they have an embedded projection, I will receive the popup GUI screen asking to select a projection per layer that I load. This is fine, but I wanted to have this all happen without any user interaction in the background.
So, I realized I can use GM_LoadRectifiedLayer and pass in a projection, however I also need to pass in the ground control point(s) in order to get this to work (vs. using GM_LoadLayerList* which seems to read the .sdw file automatically and grab the ground control point(s) for me).
Assuming I have an .sdw file that only has 1 control point, the way I understand it is I can look for and parse through that text file under the assumption that the 6 lines I need to grab have the following "standard"? world file layout:
Line 1: pixel size in the x-direction in units per pixel
Line 2: rotation about y-axis
Line 3: rotation about x-axis
Line 4: pixel size in the y-direction units per pixel
Line 5: x-coordinate of the center of the upper left pixel
Line 6: y-coordinate of the center of the upper left pixel
And assuming GM_GroundControlPoint_t def looks like this:
typedef struct
{
double mPixelX; // x pixel coordinate of GCP
double mPixelY; // y pixel coordinate of GCP (top is 0, increases down)
double mGroundX; // x ground coordinate of GCP (in provided projection)
double mGroundY; // y ground coordinate of GCP (in provided projection)
} GM_GroundControlPoint_t;
It seems to me that when I create a GM_GroundControlPoint_t to pass to GM_LoadRectifiedLayer, I would pass Line 5 to mPixelX, and Line 6 to mPixelY - but what would I use for mGroundX and mGroundY? Assume a projection of UTM just for discussions-sake. Would that just be 0,0? Or what that be the UTM offset (northing/easting) for that Top-Left corner?
Any help is appreciated just so I know that I'm accomplishing this the right way. Thank you!
Brian
I'm trying to programatically load up MrSID layers using the Global Mapper SDK. I realized that I can load them in using GM_LoadLayerList or GM_LoadLayerListEx, however unless they have an embedded projection, I will receive the popup GUI screen asking to select a projection per layer that I load. This is fine, but I wanted to have this all happen without any user interaction in the background.
So, I realized I can use GM_LoadRectifiedLayer and pass in a projection, however I also need to pass in the ground control point(s) in order to get this to work (vs. using GM_LoadLayerList* which seems to read the .sdw file automatically and grab the ground control point(s) for me).
Assuming I have an .sdw file that only has 1 control point, the way I understand it is I can look for and parse through that text file under the assumption that the 6 lines I need to grab have the following "standard"? world file layout:
Line 1: pixel size in the x-direction in units per pixel
Line 2: rotation about y-axis
Line 3: rotation about x-axis
Line 4: pixel size in the y-direction units per pixel
Line 5: x-coordinate of the center of the upper left pixel
Line 6: y-coordinate of the center of the upper left pixel
And assuming GM_GroundControlPoint_t def looks like this:
typedef struct
{
double mPixelX; // x pixel coordinate of GCP
double mPixelY; // y pixel coordinate of GCP (top is 0, increases down)
double mGroundX; // x ground coordinate of GCP (in provided projection)
double mGroundY; // y ground coordinate of GCP (in provided projection)
} GM_GroundControlPoint_t;
It seems to me that when I create a GM_GroundControlPoint_t to pass to GM_LoadRectifiedLayer, I would pass Line 5 to mPixelX, and Line 6 to mPixelY - but what would I use for mGroundX and mGroundY? Assume a projection of UTM just for discussions-sake. Would that just be 0,0? Or what that be the UTM offset (northing/easting) for that Top-Left corner?
Any help is appreciated just so I know that I'm accomplishing this the right way. Thank you!
Brian
Comments
-
Brian,
To simulate a world file with no projection you would need to pass in 2 control points, but in any case that's not what you need to do. You should use the base GM_LoadLayerList function, but first call GM_SetQueryProjectionCallback to provide a callback function into your own application to be used when a projection is needed. Then when your callback function is called during load just set whatever projection you want for the file.
Let me know if I can be of further assistance.
Thanks,
Mike
Global Mapper Guru
geohelp@bluemarblegeo.com
Blue Marble Geographics for Coordinate Conversion, Image Reprojection and Vector Translation -
Mike,
Thanks yes - I see some further info about that here - http://www.globalmapperforum.com/forums/sdk/4803-avoid-projection-dialog.html
Will try, thank you!
Brian -
And for the lazy or those looking at how to do this in C# - here's what I did:
In my GlobalMapper class wrapper I have defs for the following:[UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void GM_SetQueryProjectionCallback(GM_QueryProjectionCallbackDef aCallBackFunc); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate byte GM_QueryProjectionCallbackDef(ref GM_Projection_t aProj, ref GM_Point_t aInitialPos, ref GM_ElevUnits_t8 aElevUnits);
I call them in my main program and set them like this:var callbackDelegate = (GlobalMapper.GM_QueryProjectionCallbackDef)SetProjection; var setQueryProjectionCallback = (GlobalMapper.GM_SetQueryProjectionCallback)Marshal.GetDelegateForFunctionPointer(NativeMethods.GetProcAddress(GlobalMapperInterfaceDllAddress, typeof(GlobalMapper.GM_SetQueryProjectionCallback).Name), typeof(GlobalMapper.GM_SetQueryProjectionCallback)); setQueryProjectionCallback(callbackDelegate);
And then define SetProjection method with whatever projection as follows:private static byte SetProjection(ref GM_Projection_t aProj, ref GM_Point_t aInitialPos, ref GM_ElevUnits_t8 aElevUnits) { aProj = new GM_Projection_t() { mProjSys = GM_ProjType_t16.GM_PRJ_GEO, mUnit = GM_ProjUnit_t16.GM_PRJ_UNIT_ARC_DEGREES, mDatum = GM_DatumType_t16.GM_DATUM_NAD83, mNumAttrs = 0 }; aElevUnits = GM_ElevUnits_t8.GM_ElevUnit_Meters; return (byte)1; }
and btw, my GlobalMapperInterfaceDllAddress is set as follows:const uint flag = (uint)NativeMethods.LoadLibraryExFlags.LOAD_WITH_ALTERED_SEARCH_PATH; IntPtr GlobalMapperInterfaceDllAddress = NativeMethods.LoadLibraryEx(pathToGlobalMapperDll, IntPtr.Zero, flag);
where LoadLibraryEx is:[DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
-
One other thing - you may need to store your delegate somewhere because GC will make it go out of scope when you leave the method.
private GlobalMapper.GM_QueryProjectionCallbackDef _ProjectionCallbackDelegate;
Then in the call:_ProjectionCallbackDelegate = (GlobalMapper.GM_QueryProjectionCallbackDef)SelectAndSetProjection;
Brian
Categories
- 12.5K All Categories
- 5.5K Features Discussion
- 314 Downloading Imagery
- 1.3K Elevation Data
- 377 Georeferencing Imagery Discussion
- 611 GM Script Language
- 50 User Scripts
- 112 GPS Features
- 397 Projection Questions
- 803 Raster Data
- 1.3K Vector Data
- 6.5K Support
- 161 Announcement and News
- 893 Bug Report
- 557 SDK
- 1.2K Suggestion Box
- 3.7K Technical Support
- 542 Other Discussion
- 128 GIS Data Sources
- 26 Global Mapper Showcase
- 229 How I use Global Mapper
- 104 Global Mapper Forum Website