ThinkGeo.com    |     Documentation    |     Premium Support

Urgent!

I would like to create one shape per sales rep that is made of multiple zip.  I think that the code is OK but I am not that sure...


anyway when I execute it I got this exception on the : unionMultipolygonShape = MultipolygonShape.Union(areaBaseShapes);


statement.  The selectedZipFeatures is made of 643 features. (number of zips for a  single sales rep).


thanks for your help!




  foreach (DictionaryEntry s in _repNameList)


                    {


                        inMemoryFeatureLayer_Zips_Colorization.FeatureSource.Open();


                        selectedZipFeatures = inMemoryFeatureLayer_Zips_Colorization.FeatureSource.GetFeaturesByColumnValue(RequestedColumns_RepPerZip[0].ColumnName.ToString(), s.Value.ToString());


                        inMemoryFeatureLayer_Zips_Colorization.FeatureSource.Close();


                        areaBaseShapes = new Collection<AreaBaseShape>();


                        if (selectedZipFeatures.Count > 0)


                        {


                            foreach (Feature feature in selectedZipFeatures)


                            {


                                areaBaseShapes.Add((AreaBaseShape)feature.GetShape());


                            }


                            unionMultipolygonShape = MultipolygonShape.Union(areaBaseShapes);


                            if (unionMultipolygonShape.Polygons.Count > 0)


                                inMemoryFeatureLayer_Zips_Colorization_union.InternalFeatures.Add(new Feature(unionMultipolygonShape));


                        }


                    }




 


 


 System.OutOfMemoryException was unhandled by user code


  Message=Exception of type 'System.OutOfMemoryException' was thrown.
  Source=NetTopologySuite
  StackTrace:
       at GisSharpBlog.NetTopologySuite.Noding.SegmentNodeList.CreateSplitEdge(SegmentNode ei0, SegmentNode ei1)
       at GisSharpBlog.NetTopologySuite.Noding.SegmentNodeList.AddSplitEdges(IList edgeList)
       at GisSharpBlog.NetTopologySuite.Noding.SegmentString.GetNodedSubstrings(IList segStrings, IList resultEdgelist)
       at GisSharpBlog.NetTopologySuite.Noding.SegmentString.GetNodedSubstrings(IList segStrings)
       at GisSharpBlog.NetTopologySuite.Noding.MCIndexNoder.GetNodedSubstrings()
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferBuilder.ComputeNodedEdges(IList bufferSegStrList, IPrecisionModel precisionModel)
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferBuilder.Buffer(IGeometry g, Double distance)
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferOp.BufferOriginalPrecision()
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferOp.ComputeGeometry()
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferOp.GetResultGeometry(Double distance)
       at GisSharpBlog.NetTopologySuite.Operation.Buffer.BufferOp.Buffer(IGeometry g, Double distance)
       at GisSharpBlog.NetTopologySuite.Geometries.Geometry.Buffer(Double distance)
       at ThinkGeo.MapSuite.Core.AreaBaseShape.Union(IEnumerable`1 areaShapes)
       at MapTest.WebForm1.Page_Load(Object sender, EventArgs e) in C:\Users\a09zmzz\Documents\Visual Studio 2010\Projects\MapTest\MapTest\WebForm1.aspx.cs:line 238
       at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       at System.Web.UI.Control.OnLoad(EventArgs e)
       at System.Web.UI.Control.LoadRecursive()
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  InnerException: 
 

Better code view 
  
 

                    foreach (DictionaryEntry s in _repNameList)
                    {
                        inMemoryFeatureLayer_Zips_Colorization.FeatureSource.Open();
                        selectedZipFeatures = inMemoryFeatureLayer_Zips_Colorization.FeatureSource.GetFeaturesByColumnValue(RequestedColumns_RepPerZip[0].ColumnName.ToString(), s.Value.ToString());
                        inMemoryFeatureLayer_Zips_Colorization.FeatureSource.Close();
                        areaBaseShapes = new Collection<AreaBaseShape>();
                        if (selectedZipFeatures.Count > 0)
                        {
                            foreach (Feature feature in selectedZipFeatures)
                            {
                                areaBaseShapes.Add((AreaBaseShape)feature.GetShape());
                            }
                            unionMultipolygonShape = MultipolygonShape.Union(areaBaseShapes);
                            if (unionMultipolygonShape.Polygons.Count > 0)
                                inMemoryFeatureLayer_Zips_Colorization_union.InternalFeatures.Add(new Feature(unionMultipolygonShape));
                        }
                    }
 


Jean-marie, 
  
 Are you necessary to union them? Could you try to find some other solution in your scenario? 
  
 The union operation may have some issue if the shape data not so standard, and we cannot change it because this part we using the 3rd part library. 
  
 Regards, 
  
 Don

Well I have to create a shape made of ZIP5 codes… how should I do that???  My expectation was based on the fact that ThinkGeo was providing a solution to handle this kind of problem!  isn’t it? 
  
 Any ideas on how to make this thing to work? 
  
 Thanks for your help.

Jean Marie,


  One thing I want to make sure first. Are you using the same method for unioning polygons as you can see in those two Code Community samples, Dissolve on Shapefile and Dissolve with Statistics?


wiki.thinkgeo.com/wiki/Map_Suite_We..._Shapefile


wiki.thinkgeo.com/wiki/Map_Suite_We...Statistics


 In those samples, you are going to find a fast and reliable way to union polygons together. The end result is in a shapefile but this is basically the same method in unioning as for InMemoryFeatureLayer. If you are still having problem, I would suggest you send us your zip code shape and we will examine it. Thank you.


 



Hi, 
  
 I was able to make my function to work well but the response time is not good…  for instance if you need to union let say 10 US states (10 features) 
 it takes about 15 seconds to complete!  I ran for 6 hours and generate 41 shapes (one per sales rep) each shape is made of up to 600 zips shapes. 
  
 I really need to find a better way to solve this problem!   the positive side is that the colorized InMemoryFeatureLayer where there is one shape zip is about 831MB… now the InMemoryFeatureLayer with only 41 shapes is 95MB! much better to load. 
  
 any advice on how to optimize the union operation? 
  
 thanks a lot. 
  
 jm   
  
  
 my code: 
  
  
 public InMemoryFeatureLayer unionizedShapes(Collection<FeatureSourceColumn> RequestedColumns, InMemoryFeatureLayer inMemoryFeatureLayer_in, SortedList nameList, string colKey)
        {
            Collection<Feature> selectedFeatures;
            Collection<AreaBaseShape> areaBaseShapes;
            MultipolygonShape unionMultipolygonShape;
            InMemoryFeatureLayer inMemoryFeatureLayer_out = new InMemoryFeatureLayer();

            foreach (DictionaryEntry s in nameList)
            {
                inMemoryFeatureLayer_in.FeatureSource.Open();
                selectedFeatures = inMemoryFeatureLayer_in.FeatureSource.GetFeaturesByColumnValue(RequestedColumns[0].ColumnName.ToString(), s.Value.ToString());
                inMemoryFeatureLayer_in.FeatureSource.Close();
                areaBaseShapes = new Collection<AreaBaseShape>();
                if (selectedFeatures.Count > 0)
                {
                    foreach (Feature feature in selectedFeatures)
                    {
                        areaBaseShapes.Add((AreaBaseShape)feature.GetShape());
                    }
                    unionMultipolygonShape = PolygonShape.Union(areaBaseShapes);
                    if (unionMultipolygonShape.Polygons.Count > 0)
                    {
                        Feature f = new Feature(unionMultipolygonShape);
                        f.ColumnValues.Add(colKey, selectedFeatures[0].ColumnValues[colKey].ToString());
                        inMemoryFeatureLayer_out.InternalFeatures.Add(f);
                    }
                }
            }
            return (inMemoryFeatureLayer_out);
        }


Hi Found a way to go faster and it is working! 
  
  

  public InMemoryFeatureLayer unionizedShapes(Collection<FeatureSourceColumn> RequestedColumns, InMemoryFeatureLayer inMemoryFeatureLayer_in, SortedList nameList, string colKey)
        {
            InMemoryFeatureLayer inMemoryFeatureLayer_out = new InMemoryFeatureLayer();

            Parallel.ForEach(nameList.Cast<DictionaryEntry>(), s =>
            {              
                inMemoryFeatureLayer_in.FeatureSource.Open();
                Collection<Feature> selectedFeatures = inMemoryFeatureLayer_in.FeatureSource.GetFeaturesByColumnValue(RequestedColumns[0].ColumnName.ToString(), s.Value.ToString());
                inMemoryFeatureLayer_in.FeatureSource.Close();
                Collection<AreaBaseShape> areaBaseShapes; areaBaseShapes = new Collection<AreaBaseShape>();
                if (selectedFeatures.Count > 0)
                {
                    foreach (Feature feature in selectedFeatures)
                    {
                        areaBaseShapes.Add((AreaBaseShape)feature.GetShape());
                    }
                    MultipolygonShape unionMultipolygonShape = PolygonShape.Union(areaBaseShapes);
                    if (unionMultipolygonShape.Polygons.Count > 0)
                    {
                        Feature f = new Feature(unionMultipolygonShape);
                        f.ColumnValues.Add(colKey, selectedFeatures[0].ColumnValues[colKey].ToString());
                        inMemoryFeatureLayer_out.InternalFeatures.Add(f);
                    }
                }  
            });
            return (inMemoryFeatureLayer_out);
        }


Jean Marie,


  Yes. You are right. The most efficient way to union polygons together is to first add them into a collection and then use the static function Union of PolygonShape to union them all in one step.


 



//First, add all the polygons into a collection
Collection<AreaBaseShape> polygonShapes = new Collection<AreaBaseShape>();

Collection<Feature> features = shapeFileFeatureLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns);

foreach (Feature feature in features)
{
    AreaBaseShape polygonShape = (AreaBaseShape)feature.GetShape();
    polygonShapes.Add(polygonShape);
}

//Second, uses the PolygonShape.Union static method to union all the shapes in one step.
MultipolygonShape multiPolygonShape = PolygonShape.Union(polygonShapes);