Shapefile export - no .dbf for Points
nickgoodliff
Global Mapper UserTrusted User
Hi Mike
Any reason why this code isn't producing a .dbf file?
I get the .shp and .shx but no .dbf, and ONLY when exporting points - exporting lines or areas are working fine.
Using v14.26.0.0
Cheers
Nick
Any reason why this code isn't producing a .dbf file?
gMErrorT32_Points = GlobalMapperDLL.GM_ExportVectorEx(storagePath + "_Points.shp", GlobalMapperDLL.GM_VectorExportFormat_t32.GM_Export_Shapefile, IntPtr.Zero, ref ExportRect, GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportPoints | GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportAttrs, IntPtr.Zero, "");
I get the .shp and .shx but no .dbf, and ONLY when exporting points - exporting lines or areas are working fine.
Using v14.26.0.0
Cheers
Nick
Comments
-
Nick,
Do your point features have any attributes? You are passing in the appropriate flags, but if none of your points had attributes then you wouldn't get a DBF file as there would be nothing to add to it.
Thanks,
Mike
Global Mapper Guru
geohelp@bluemarblegeo.com
Blue Marble Geographics for Coordinate Conversion, Image Reprojection and Vector Translation -
Hi Mike
Right so this is all linked to a big problem I've been having with exporting shapefiles that I have finally been able to fix. The problem is this, and maybe you can shed light on why this has been happening:
My application processes a product that is made up of 2 polygon layers and a point layer saved as shapefiles. When someone orders this product, my app loops through 3 separate folders to separately load in the each set of tiles, set the cropping polygon for the selected area, and then exports to shapefiles. It always exports the first folder absolutely fine (and can be either of the polygon or point source shapefiles), but invariably (99 times out 100) when it gets to the second folder, it loads these shapefiles then when it gets to exporting the selected area it crashes the whole .NET app with no error message!
Some edited code:{[INDENT]GlobalMapperDLL.GM_SetLicenseKey("", IntPtr.Zero); GM_Projection_t gMProjectionT; GlobalMapperDLL.GM_Error_t32 gMErrorT32 = GlobalMapperDLL.GM_Error_t32.GM_Error_None; gMErrorT32 = GlobalMapperDLL.GM_LoadProjectionFile("Default_Projection.PRJ", out gMProjectionT); if (gMErrorT32 != GlobalMapperDLL.GM_Error_t32.GM_Error_None) { throw new Exception(gMErrorT32.ToString()); } GlobalMapperDLL.GM_SetProjection(ref gMProjectionT); GlobalMapperDLL.GM_MessageCallbackDef errorHandler = new GlobalMapperDLL.GM_MessageCallbackDef(ProcessError); GlobalMapperDLL.GM_SetMessageCallback(errorHandler); GlobalMapperDLL.GM_SetMiscOption(GlobalMapperDLL.GM_MiscOpt_t32.GM_MiscOpt_AllowUnlimitedECWExportSize, 1); _ProjectionCallbackDelegate = (GlobalMapperDLL.GM_QueryProjectionCallbackDef)SetProjection; GlobalMapperDLL.GM_SetQueryProjectionCallback(_ProjectionCallbackDelegate); // Loop through folders to process each layer[/INDENT] [INDENT]foreach (var folder in folders)[/INDENT] [INDENT]{[/INDENT] [INDENT][INDENT]var aFeature = cropPolygon.AreaFeature;[/INDENT] [INDENT]GlobalMapperDLL.GM_SetExportCropAreas(ref aFeature, 1, ref gMProjectionT); // work out the tiles required then load them [/INDENT] [INDENT]foreach (var tile in tiles) { LoadLayer(tile.FilePath); } // Export shapefile[/INDENT] [INDENT]GlobalMapperDLL.GM_ExportVectorEx(storagePath + "_Areas.shp",[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFormat_t32.GM_Export_Shapefile,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] ref ExportRect,[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportAreas | GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportAttrs,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] "");[/INDENT] [INDENT]GlobalMapperDLL.GM_ExportVectorEx(storagePath + "_Lines.shp",[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFormat_t32.GM_Export_Shapefile,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] ref ExportRect,[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportLines | GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportAttrs,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] "");[/INDENT] [INDENT]GlobalMapperDLL.GM_ExportVectorEx(storagePath + "_Points.shp",[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFormat_t32.GM_Export_Shapefile,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] ref ExportRect,[/INDENT] [INDENT] GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportPoints | GlobalMapperDLL.GM_VectorExportFlags_t32.GM_VectorExportFlags_ExportAttrs,[/INDENT] [INDENT] IntPtr.Zero,[/INDENT] [INDENT] "");[/INDENT] [/INDENT] [INDENT]// Clear layers for next folder[/INDENT] [INDENT] for (int i = 0; i < clsGlobalVARS.LayerHandles.Count; i++)[/INDENT] { GlobalMapperDLL.GM_CloseLayer((IntPtr)clsGlobalVARS.LayerHandles[i]); } clsGlobalVARS.LayerHandles.Clear(); clsGlobalVARS.LayerInfos.Clear(); clsGlobalVARS.LayerPtrHandles.Clear();[INDENT] GlobalMapperDLL.GM_SetExportCropAreas(IntPtr.Zero, 0, IntPtr.Zero);[/INDENT] [INDENT]}[/INDENT] } public void LoadLayer(string File) { IntPtr theLayerList; UInt32 theNumLayers = 0; var LastGMError = GlobalMapperDLL.GM_LoadLayerListEx(File, out theLayerList, out theNumLayers, GlobalMapperDLL.GM_LoadFlags_t32.GM_LoadFlags_UseDefaultProj, ""); // If the layer loaded successfully then get the layer info. // User the bounding rectangle in the layer info as the curent // view rectangle. if (LastGMError == GlobalMapperDLL.GM_Error_t32.GM_Error_None) { // Add each layer for (Int32 i = 0; i < theNumLayers; i++) { // Extract the layer handle from the list IntPtr theLayerHandlePtr = (IntPtr)((UInt32)theLayerList + i * IntPtr.Size); IntPtr theLayerHandle; theLayerHandle = (IntPtr)Marshal.PtrToStructure(theLayerHandlePtr, typeof(IntPtr)); // Add the layer // Get the layer info and copy it into our structure GlobalMapperDLLWrapper.GM_LayerInfo_t theLayerInfo = new GlobalMapperDLLWrapper.GM_LayerInfo_t(); IntPtr theInfoPtr = GlobalMapperDLL.GM_GetLayerInfo(theLayerHandle); theLayerInfo = (GlobalMapperDLLWrapper.GM_LayerInfo_t)Marshal.PtrToStructure(theInfoPtr, typeof(GlobalMapperDLLWrapper.GM_LayerInfo_t)); clsGlobalVARS.LayerInfos.Add(theLayerInfo); clsGlobalVARS.LayerHandles.Add(theLayerHandle); clsGlobalVARS.LayerPtrHandles.Add(theLayerHandlePtr); } } else { throw new Exception(LastGMError.ToString()); } }
A lot of that code is refactored in my app, but hopefully you can see the flow. I'm pretty sure the crash is due to some memory issue, and the only way I've been able to fix it is to put a lot of the code that deals with the GlobalMapperDLL into a class that I create each time in the loop, then dispose and create again for the next folder. Not the most efficient way of doing things!
Cheers
Nick -
Nick,
It looks like you are loading an entire folder's worth of Shapefiles, exporting to a new file, then closing them all, then moving to the next folder? How many Shapefiles are in the folder that is failing? It's possible you are filling up memory loading all of those at once. If it's possible for you to use the 64-bit SDK rather than the 32-bit that would allow you to use a lot more memory.
You might also check that you are closing everything properly at the end by calling GM_GetLoadedLayerList to make sure the SDK doesn't think anything is still loaded.
Thanks,
Mike
Global Mapper Guru
geohelp@bluemarblegeo.com
Blue Marble Geographics for Coordinate Conversion, Image Reprojection and Vector Translation -
That is correct, though this happens when there is just one 5 sqkm file (3MB-ish shapefile) used per folder so don't think its memory filling up, and I'm already using 64-bit version. There is never any problem with the loading of the files, it only breaks on this call: GM_ExportVectorEx. The progress bar appears and says 0%, then it hangs for a second before exiting.
Good tip about the GM_GetLoadedLayerList - it will be interesting if that throws anything up.
Nick -
Nick,
Based on that it doesn't sound like memory is the issue. Do you know if your SDK agreement allows you to get the v15 SDK? The first thing I would suggest is trying with the latest SDK. The latest build is at http://www.globalmapper.com/GlobalMapperSDK_v15_latest_beta.zip .
Thanks,
Mike
Global Mapper Guru
geohelp@bluemarblegeo.com
Blue Marble Geographics for Coordinate Conversion, Image Reprojection and Vector Translation -
Yes, we are currently trialling v15 to see if it fixes the problem as it was happening with v14, and it is unfortunately happening in v15 aswell.
My work around is ok for now, but would be great to know why no error message gets returned, just exitting the application.
Nick -
Right, so I have tracked down the issue! It is in this:
[COLOR=#333333][FONT=monospace]var aFeature = cropPolygon.AreaFeature; [/FONT][/COLOR][COLOR=#333333][FONT=monospace]GlobalMapperDLL.GM_SetExportCropAreas(ref aFeature, 1, ref gMProjectionT);[/FONT][/COLOR]
When I load the area for export, I save the area feature to crop to in my CropPolygon object. If this crop polygon has been set by a shapefile then it works fine, but where it is just a rectangle I create a GM_AreaFeature manually:GM_Point_t[] theAreaPoints = new GM_Point_t[Points.Count]; int i = 0; foreach (var point in Points) { theAreaPoints[i].mX = point.X; theAreaPoints[i].mY = point.Y; i++; } unsafe { fixed (GM_Point_t* thePointList = &theAreaPoints[0]) { GM_AreaFeature_t af = new GM_AreaFeature_t(); af.mFeatureInfo.mName = "CropAreaBox"; af.mFeatureInfo.mDesc = "CropAreaBox"; af.mFeatureInfo.mClass = (ushort)AreaFeatureClass_t16.AFC_UNKNOWN; af.mPointList = (IntPtr)thePointList; af.mNumPoints = 4; AreaFeature = af; } }
and this gets saved in the object that is used for each export. Some part of this must get Garbage Collected in between each folder being processed and so when each GM_ExportVectorEx call was made, the pointers to the area feature to crop to were missing and so everything crashed.
I have changed it to a method whereby this areaFeature gets created dynamically from my points array for each iteration.
For rectangles, the area feature I am creating is identical to the GM_Rectangle_t that I am using for the World Bounds so I don't really need it, but in the future we will be allowing user-drawn cropping polygons (i.e. not loaded from a shapefile).
Nick -
Nick,
The GM_SetExportCropAreas function will make a copy of whatever area(s) you pass in, so you could just call GM_SetExportCropAreas once at the start of the entire operation and that crop should stay in force and you can get rid of the area feature that you are passing in. If you are getting features from a layer (with GM_GetAreaFeature for example) you need to be sure to call GM_FreeAreaFeature when you are done using the structure so the SDK can free the allocated memory.
Thanks,
Mike
Global Mapper Guru
geohelp@bluemarblegeo.com
http://www.bluemarblegeo.com/ -
Ah yes, I was missing that step to call GM_FreeAreaFeature!
With regards to setting the Crop Areas once, there is another iteration that I didn't show in my edited code above that loops through an array of crop areas. If a user uploads a shapefile with more than one polygon, each polygon is exported separately so I potentially need to set the crop areas differently at various times.
Thanks for your help, much appreciated.
Nick
Categories
- 12.7K All Categories
- 5.6K Features Discussion
- 342 Downloading Imagery
- 1.3K Elevation Data
- 380 Georeferencing Imagery Discussion
- 628 GM Script Language
- 53 User Scripts
- 113 GPS Features
- 414 Projection Questions
- 819 Raster Data
- 1.3K Vector Data
- 6.6K Support
- 177 Announcement and News
- 908 Bug Report
- 558 SDK
- 1.2K Suggestion Box
- 3.7K Technical Support
- 562 Other Discussion
- 129 GIS Data Sources
- 27 Global Mapper Showcase
- 233 How I use Global Mapper
- 107 Global Mapper Forum Website