ThinkGeo.com    |     Documentation    |     Premium Support

Very Slow Rendering thousands of pointshpaes

I have an application that utilizes Bitmaps to represent points on the map.  The number of these  points is continuously updatings and must be refreshed frequently. ( real time if possible)  My issue is that it takes upwards on 2 minutes to render 1000 points and our system will be processing upwards of 100000 points.


The bitmaps are very small 24x24 pixels and are loaded into an in memoy feature layer


Is there a way to increase the speed?


 



Steve, 
  
   Where are the bitmaps themselves stored exactly.  You mentioned an in memory feature layer but not how you put them inside.  What style are you using do draw the images?  Does each of the 100K points have a completely different image or are there sets like x number of variations.  If you can provide a little sample project it would really help. 
  
 Just some interesting numbers based on your post.  The number of pixels in a 1080p display is 2,073,600.  If you take the 100,000 points and they each draw at 24x24 then you are using 57,600,000 pixels.  Even with 2,000 images at 24x24 pixel the density is 1,152,000 pixels.  I understand you may need to do this however it seems like you are displaying a density of data that is way over what can be understood.  An idea would be to massage the data before display instead of brute forcing it onto the map. 
  
 David

here are the relavent routines. 
  
  
   This creates the Icons which are located in a sub directory  
  
  Public Sub createicons() 
  
  
         Dim rdgicon As PointStyle 
         Dim icopath As String = Application.StartupPath & "\ICONS&#34
  
         OILSStyle.ColumnName = “OIL” 
  
  
         rdgicon = New PointStyle(New GeoImage(icopath & “ur_ly_c.ico”)) 
         rdgicon.PointType = PointType.Bitmap 
         OILSStyle.ValueItems.Add(New ValueItem(“ur_lyc”, rdgicon))  ’ Creates the new style. 
  
         rdgicon = New PointStyle(New GeoImage(icopath & “ur_lg_c.ico”)) 
         OILSStyle.ValueItems.Add(New ValueItem(“ur_lgc”, rdgicon))  ’ Creates the new style. 
  
         rdgicon = New PointStyle(New GeoImage(icopath & “ug_lg_c.ico”)) 
         OILSStyle.ValueItems.Add(New ValueItem(“ug_lgc”, rdgicon))  ’ Creates the new style. 
  
  
         rdgicon = New PointStyle(New GeoImage(icopath & “ur_lr_c.ico”)) 
         OILSStyle.ValueItems.Add(New ValueItem(“ur_lrc”, rdgicon))  ’ Creates the new style. 
  
         rdgicon = New PointStyle(New GeoImage(icopath & “uy_lg_c.ico”)) 
         OILSStyle.ValueItems.Add(New ValueItem(“uy_lgc”, rdgicon))  ’ Creates the new style. 
  
         pointLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(OILSStyle) 
         pointLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20 
         pointLayer.Open() 
  
         pointLayer.Columns.Add(New FeatureSourceColumn(“OIL”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“BOXID”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Lat”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Lon”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Time”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Rdg”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Rtyp”)) 
         pointLayer.Columns.Add(New FeatureSourceColumn(“Units”)) 
  
         pointLayer.Close() 
         pointOverlay.Layers.Add(“rdgLayer”, pointLayer) 
         Form1.WinformsMap1.Overlays.Add(“PointOverlay”, pointOverlay) 
  
         Form1.WinformsMap1.Refresh() 
  End Sub 
  
   This is the routine I call to add the icon to the map.  
  
 Public Sub addIcon(ByVal BOXID As String, ByVal lat As Double, ByVal lon As Double, ByVal Tim As DateTime, ByVal icon As String, ByVal val As Double, ByVal rtyp As String, ByVal units As String) 
         'Creates the feature  with the Longitude and Latitude values and ICON. 
  
         Dim rdgFeature As Feature = New Feature(New PointShape(lon, lat))   ’ ths creates the actual reading 
         rdgFeature.ColumnValues(“OIL”) = icon 
         rdgFeature.ColumnValues(“BOXID”) = BOXID 
         rdgFeature.ColumnValues(“Lat”) = lat 
         rdgFeature.ColumnValues(“Lon”) = lon 
         rdgFeature.ColumnValues(“Time”) = Tim 
         rdgFeature.ColumnValues(“Rdg”) = val 
         rdgFeature.ColumnValues(“Rtyp”) = rtyp 
         rdgFeature.ColumnValues(“Units”) = units 
  
         pointLayer.InternalFeatures.Add(rdgFeature)                          ’ add it to the points layer 
  
         Form1.WinformsMap1.Refresh() 
     
     End Sub 
  
 As for the Dot Density.  The points will be coming from may places at once.  If a vehice is moving slowly then the icons will definitely overlay. Or event be in the same location. The application is time sensitive as well.  one location could have many readings over time. 


Steve, 
  
   I will need to create a small sample for myself to try this out but I see exactly what you are doing.  I assume that you are adding the point styles to the ValueStyle and based on the value it gets a different PointStyle.  One thing I can’t see is if you are adding the 2,000 points via the AddIcon routine?  I mean when you load them up are you calling that in a big 2,000 iteration loop?   This could cause a problem as it is much better to add all 2,000 points at once and then call the refresh.  If you update one point then it is ok to call it like this.  Also one other thing is that if you have other layers or overlays that you display under or on top of this I suggest you call the Form1.WinformsMap1.Refresh() overload that takes an overlay.  If you call the overload with no parameters, as you have, it force all the overlays to refresh including a background one.  If you are just updating that overlay its better to refresh it directly. 
  
 How are you updating these items over time?  My suggestion would be to add all the features to the InternalFeatures collection to seed things and then call the BuildIndex() method.  This will build an r-tree index for the layer.  From then on if you want to add, remove or edit an item I would not use the InternalFeatures collection I would use the EditTools and call the BeginTransaction, then the Add or Edit and then the CommitTransaction.  The reason why is that using the edit tools updates the R-Tree index internally.  If you modify the InternalFeatures directly then the index can get out of sync and you need to call the build index.  However the BuildIndex takes allot of time if there are many points because it has to rebuild it from scratch.  Using the EditTools does this incrementally. 
  
   As an example we have a Silverlight, WPF and Desktop that shows randomly mocing a bunch of points in real-time and changing the color.  You can checkout the online Silverlight Sample at the link below.  Then click on the “Feature” section and pick the sample “Refresh Points Randomly”.  Select 5,000 points and click begin to see how we do it.  I think with a little tweaking we can get your system running well. 
  
 silverlightsamples.thinkgeo.com/default.aspx 
  
 David

I found My Issue. 
 I was doing a map.refresh after each insert.  1:30 to update 1000 
  
 I removed the refresh from the addicon routine and called it once when all icons were added. 
  
 Less than 1 second. 
  
 Sorry for wasting your time.  Very new to this. 


Steve, 
  
   No problem, you saved me from writing the sample. :-)  The good news is that at some point you may start hitting some performance barriers and I want to let you know there are many trick you can use to enhance the speed.  The best way is to tailor the approach based on your situation so I wont talk too much until you start hitting issues.  I just wanted to let you know there are some good ways to eek our more performance if you need it. 
  
 David