ThinkGeo.com    |     Documentation    |     Premium Support

Saving Multiple Shape Files as FeatureLayers

Hi,


In order to avoid packaging shape files with my saved projects, I am looking at reading shape files and converting them to feature layers before adding them to an overlay.  That way, the saved project does not include any paths to the original shape file on the users system.


The code for this was pretty simple and the relevant bit is below.  However, when I serialize the overlay, it plugs on for ages and I end up with a huge file.  The test I did was using the Countries02.shp and another tiny shape file of 100kb.  Both shape files are WGS-84 lat/long projection.  The resultant saved file was 192 MB and it took 17 minutes to save the file!


Am I doing something wrong in the code below to cause the serialized output to be so huge?  Perhaps the feature needs to be indexed prior to loading it to the overlay?  If so, I'm not sure how to go about doing that.


Regards,


Damian


 


ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(fileName);


// ... do some intermediate processing on the shapefile to determine projection, etc.


// Now, convert the shapefile features into In Memory features.

InMemoryFeatureLayer featureLayer = new InMemoryFeatureLayer();

ExplorerHelper.SetStyleByWellKnownType(featureLayer);

featureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


// Add the column names to the FeatureLayer

Collection<FeatureSourceColumn> columnValues = layer.FeatureSource.GetColumns();

featureLayer.Open();

featureLayer.EditTools.BeginTransaction();

foreach (FeatureSourceColumn column in columnValues)

{

    featureLayer.Columns.Add(new FeatureSourceColumn(column.ColumnName));

}

featureLayer.EditTools.CommitTransaction();

featureLayer.Close();


// Add each feature to the featurelayer

foreach (Feature feature in layer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns))

{

    Feature tempFeature = new Feature();

    switch (feature.GetWellKnownType())

    {

 case WellKnownType.GeometryCollection:

     break;

 case WellKnownType.Invalid:

     break;

 case WellKnownType.Line:

     LineShape tempLine = new LineShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempLine, feature.ColumnValues);

     break;

 case WellKnownType.Multiline:

     MultilineShape tempMLine = new MultilineShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempMLine, feature.ColumnValues);

     break;

 case WellKnownType.Multipoint:

     MultipointShape tempMPoint = new MultipointShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempMPoint, feature.ColumnValues);

     break;

 case WellKnownType.Multipolygon:

     MultipolygonShape tempMPoly = new MultipolygonShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempMPoly, feature.ColumnValues);

     break;

 case WellKnownType.Point:

     PointShape tempPoint = new PointShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempPoint, feature.ColumnValues);

     break;

 case WellKnownType.Polygon:

     PolygonShape tempPoly = new PolygonShape(feature.GetWellKnownText());

     tempFeature = new Feature(tempPoly, feature.ColumnValues);


     break;

 default:

     break;

    }

    featureLayer.Open();

    featureLayer.EditTools.BeginTransaction();

    featureLayer.FeatureSource.AddFeature(tempFeature);

    featureLayer.EditTools.CommitTransaction();

    featureLayer.Close();

    

    layerOverlay.Layers.Add(layerName, featureLayer);

    

}



Damian,


  I don't know what your motives are exactely but it sounds like that what you need is an encryption capability for your shapefile. We have already developed a Code Community project on that topic, Shapefile Encryption wiki.thinkgeo.com/wiki/Map_Suite_De...Encryption


 Or maybe, if you want to simply serialize and deserialize ShapeFileFeatureLayers, I think that you would need to use the GeoSerializer class in Map Suite Core API. See the info on how to use that class in the Wiki. I think this is what you are going to need instead of having to write it from scratch as you are doing it right now.


Look at the Serialization Guide in ThinkGeo Wiki:


wiki.thinkgeo.com/wiki/Map_Suite_Serialization_Guide



Val, 
  
 You misunderstand me.  I don’t need to encrypt shape files and I am already using Geoserializer to save project data.  Rather, I am reporting a potential problem with the Geoserializer class. 
  
 My motivation for the above code is as follows.  My software is designed so that a user can create and save a project in a single file using the Geoserializer class.  Then the user is able to send that single file to other users so they can continue working on the project file.   
  
 I am using the Geoserializer currently, but when you serialize a ShapeFileFeatureLayer, the path reference to the original shape file is stored in the XML and not the shapes and column data themselves.  The values written to the XML are the indexPathFileName and shapePathFileName.  This is not preferred as it would mean that users have to send the shape files and the project file together and then recreate the directory structure.  My motivation with the above code is to first translate the shape file the user selects to display into a FeatureLayer and then save that FeatureLayer using the Geoserializer into the single project file.  This means the original shape file is not part of my project file. 
  
 Using the above code, I am able to load the shapes and column data into an in memory layer and display it without problem.  The issue occurs when I use the Geoserializer to save the data to XML.  The files become huge and it takes ages to write the file.  This should not happen in my opinion and this is what I would like for you to investigate. 
  
 If you look at my recent posts with Cui, you will see the code we have written for serializing complete overlays.  If you apply the above code to that sample by dropping it into the AddShapeFileFeatureLayer routine, you should see what is happening. 
  
 Regards, 
 Damian

Damian,


  Thank you for your further explanation and I now completely understand your case and the predicament you are currently in with serialization. On monday, I will meet with Cui and some guys from the Development team who are responsible for serialization and we will discuss your case and do the necessary investigation. I will keep you posted. Thank you.



Damian, 
  
   We will take a look at that in more detail and until then here are my off the cuff thoughts.  My suspicion is that it is slow because at some point the byte array that holds the feature’s actual data is being serialized byte by byte where each byte is an element.  You could see where this would create an explosion in time and memory.  The GeoSerializer is pretty new and we have not had a chance to add all the optimizations yet.  Thank you very much for passing this along as this is an optimization we will need to make.   
  
   On the other hand I think it would be better to keep the original files intact and when you create your serialized setting file you use a relative path to the data and include the data along with your serialized XML in a zip file.  Then you can extract the shape files in a sub directory that you know the path to, using the relative path.  This way you get the zip during transport and the real shapefile for things like editing and not having to have all of the layer in memory, which is what you are forced to do with a InMemeoryFeatureLayer. 
  
 David

Hi David,


Thanks for the reply. 


I am glad it is to be investigated and hopefully some optimization can be made so that this option can be realized in the not too distant future.  In general, shapefiles are small so I tend to feel that saving them as in memory layers is not too much overhead for a desktop application.


In the meantime, my fallback is of course your option 2 of saving the files in a subdirectory and setting the relative path name.


Regards,


Damian


 


 



Damian,


  I let you know that the Development team did some speed improvments to the serialization. Since it is a breaking change, it was only added to the DEV branch. Please, get the dev build 5.5.122.0 or higher to test. While your fallback is still the safest solution at this point, you can test the new improvment in serialization. Thank you.


 



Hi Val, 
  
 I’ve uploaded 5.5.128.0 and it is working well now.  Saves are much quicker.  The file sizes are still bigger than the original shape files, but once I compress the XML, it seems manageable. 
  
 So far, no technical issues have cropped up.  I will try several other types of shape files to further test. 
  
 Thanks to everyone for the help. 
  
 Thanks, 
 Damian

Damian,


  Yes, you can thank the Development Team on that one. We also thank you for helping us make our products better. Let us know if you find some issues with serialization while testing the other types of shapefiles.