ThinkGeo.com    |     Documentation    |     Premium Support

Map Live Updating

Hi, I have a live map which updates on events being fired from business objects that are being run on background threads.  In 2.0 this seemed like a rather simple task but I am struggling to figure out how to get it to work in 3.0. Below is the 2.0 code and I have also attached what I have for the same method in 3.0, 3.0 is giving me fits with it's validation so there might be some stuff in here that looks odd at the moment.  I had to add the synchronized hashtable in 3.0 because it won't allow me to add a lineshape feature with only 1 point in it, validation issues.  Anyway, the vertex collection seems to be getting updated but nothing draws on the screen, any ideas at the moment or any suggestions on better ways to implement this in 3.0?  This just seems clunky to me...


 Thanks.


Curtis


private void asset_PositionAdded(object sender, AssetPositionAddedEventArgs e) { GeoPen pen = new GeoPen(new GeoSolidBrush(GeoColor.GetRandomGeoColor(ColorType.Bright)), 6); pen.SetLineCap(LineCap.Round, LineCap.Round); if(enableTruckTrack) { LineMapShape lineMapShape = (LineMapShape)Map1.MapShapes[e.Position.Asset.AssetId.ToString()]; if(lineMapShape == null) { LineShape lineShape = new LineShape(); lineShape.Points.Add(new PointShape(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude))); lineMapShape = new LineMapShape(lineShape); lineMapShape.Symbols.Add(new LineSymbol(pen)); Map1.MapShapes.Add(e.Position.Asset.AssetId.ToString(), lineMapShape); } else { LineShape lineShape = (LineShape)lineMapShape.Shape; lineShape.Points.Add(new PointShape(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude))); } } DrawTruck(e.Position); Map1.RefreshDynamic(); } 


 


private void asset_PositionAdded(object sender, AssetPositionAddedEventArgs e) { GeoPen pen = new GeoPen(new GeoSolidBrush(GeoColor.StandardColors.Blue)); pen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round); pen.Width = 6; Hashtable synchronizedAssetLines = Hashtable.Synchronized(assetLines); if (enableTruckTrack) { InMemoryFeatureLayer truckTrackLayer = (InMemoryFeatureLayer)Map.FindFeatureLayer(e.Position.Asset.AssetId.ToString() + "|Track"); if (truckTrackLayer == null) { LineShape lineShape = new LineShape(); lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude))); synchronizedAssetLines.Add(e.Position.Asset.AssetId.ToString(), lineShape); truckTrackLayer = new InMemoryFeatureLayer(); truckTrackLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(pen); truckTrackLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; Map.DynamicOverlay.Layers.Add(e.Position.Asset.AssetId.ToString() + "|Track", truckTrackLayer); } else { // If the hashtable contains the asset then we need to generate the layer and remove the asset from the hashtable. if (synchronizedAssetLines.ContainsKey(e.Position.Asset.AssetId.ToString())) { LineShape lineShape = (LineShape)synchronizedAssetLines[e.Position.Asset.AssetId.ToString()]; synchronizedAssetLines.Remove(e.Position.Asset.AssetId.ToString()); lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude))); truckTrackLayer.InternalFeatures.Add("Track", new ThinkGeo.MapSuite.Core.Feature(lineShape)); } else { LineShape lineShape = (LineShape)truckTrackLayer.InternalFeatures["Track"].GetShape(); lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude))); truckTrackLayer.InternalFeatures["Track"] = new ThinkGeo.MapSuite.Core.Feature(lineShape); } } } DrawTruck(e.Position); Map.RefreshDynamic(); }



Try the code again...


2.0 code:


 



private void asset_PositionAdded(object sender, AssetPositionAddedEventArgs e) {
            GeoPen pen = new GeoPen(new GeoSolidBrush(GeoColor.GetRandomGeoColor(ColorType.Bright)), 6);
            pen.SetLineCap(LineCap.Round, LineCap.Round);

            if(enableTruckTrack) {
                LineMapShape lineMapShape = (LineMapShape)Map1.MapShapes[e.Position.Asset.AssetId.ToString()];
                if(lineMapShape == null) {
                    LineShape lineShape = new LineShape();
                    lineShape.Points.Add(new PointShape(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
                    lineMapShape = new LineMapShape(lineShape);
                    lineMapShape.Symbols.Add(new LineSymbol(pen));
                    Map1.MapShapes.Add(e.Position.Asset.AssetId.ToString(), lineMapShape);
                } else {
                    LineShape lineShape = (LineShape)lineMapShape.Shape;
                    lineShape.Points.Add(new PointShape(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
                }
            }

            DrawTruck(e.Position);
            Map1.RefreshDynamic();
        }


3.0 Code:


 



private void asset_PositionAdded(object sender, AssetPositionAddedEventArgs e) {
GeoPen pen = new GeoPen(new GeoSolidBrush(GeoColor.StandardColors.Blue));
pen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
pen.Width = 6;
Hashtable synchronizedAssetLines = Hashtable.Synchronized(assetLines);

if (enableTruckTrack) {
InMemoryFeatureLayer truckTrackLayer = (InMemoryFeatureLayer)Map.FindFeatureLayer(e.Position.Asset.AssetId.ToString() + "|Track");
if (truckTrackLayer == null) {
LineShape lineShape = new LineShape();
lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
synchronizedAssetLines.Add(e.Position.Asset.AssetId.ToString(), lineShape);

truckTrackLayer = new InMemoryFeatureLayer();
truckTrackLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(pen);
truckTrackLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
Map.DynamicOverlay.Layers.Add(e.Position.Asset.AssetId.ToString() + "|Track", truckTrackLayer);
} else {
// If the hashtable contains the asset then we need to generate the layer and remove the asset from the hashtable.
if (synchronizedAssetLines.ContainsKey(e.Position.Asset.AssetId.ToString())) {
LineShape lineShape = (LineShape)synchronizedAssetLines[e.Position.Asset.AssetId.ToString()];
synchronizedAssetLines.Remove(e.Position.Asset.AssetId.ToString());

lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
truckTrackLayer.InternalFeatures.Add("Track", new ThinkGeo.MapSuite.Core.Feature(lineShape));
} else {
LineShape lineShape = (LineShape)truckTrackLayer.InternalFeatures["Track"].GetShape();
lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
truckTrackLayer.InternalFeatures["Track"] = new ThinkGeo.MapSuite.Core.Feature(lineShape);
}
}
}

DrawTruck(e.Position);
Map.RefreshDynamic();
}


Ok, here is the refined code according to the dynamic shapes sample included with V3.0.  However, now I am constantly getting this exception from somewhere within MS.


"   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)\r\n   at System.Collections.Generic.List`1.Enumerator.MoveNext()\r\n   at ThinkGeo.MapSuite.DesktopEdition.LayerOverlay.xa6cb874f7090c07f(GeoCanvas x31c084515ae9393f)\r\n   at ThinkGeo.MapSuite.DesktopEdition.LayerOverlay.DrawCore(GeoCanvas canvas)\r\n   at ThinkGeo.MapSuite.DesktopEdition.Overlay.Draw(GeoCanvas canvas)\r\n   at ThinkGeo.MapSuite.DesktopEdition.xf0380b1a0bc40ca6.StartDraw()\r\n   at ThinkGeo.MapSuite.DesktopEdition.x601a5561df898600.x7510a5c148e0acfd(Object x19b0b2213afc2289)\r\n   at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)\r\n   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)\r\n   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)"


Here is the refined code, anybody have any ideas?


 



InMemoryFeatureLayer truckLayer = null;

Dictionary<String, String> dictionary = new Dictionary<String, String>();
dictionary.Add("LAT", position.convertToDecimalDegrees(position.Latitude).ToString());
dictionary.Add("LONG", position.convertToDecimalDegrees(position.Longitude).ToString());
dictionary.Add("SPEED", "18mph");
dictionary.Add("HEADING", position.Heading.Trim());
dictionary.Add("NAME", position.Asset.AssetDescription);

if(Map.FindFeatureLayer(position.Asset.AssetId.ToString()) == null){
truckLayer = new InMemoryFeatureLayer();
truckLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.PointType = PointType.Bitmap;
truckLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = new GeoImage("C:\\dumptruck.png");
//truckLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateMaskTextStyle("[NAME]\nHeading: [HEADING]\nSpeed: [SPEED]", "Arial", 8, DrawingFontStyles.Bold, GeoColor.StandardColors.Black, GeoColor.StandardColors.Black, 2, -34, -30);
truckLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
truckLayer.InternalFeatures.Add("Truck", new ThinkGeo.MapSuite.Core.Feature(new PointShape(Convert.ToDouble(dictionary["LONG"]), Convert.ToDouble(dictionary["LAT"])), dictionary));

Map.DynamicOverlay.Layers.Add(position.Asset.AssetId.ToString(), truckLayer);
} else {
truckLayer = (InMemoryFeatureLayer)Map.FindFeatureLayer(position.Asset.AssetId.ToString());
PointShape pointShape = new PointShape(Convert.ToDouble(dictionary["LONG"]), Convert.ToDouble(dictionary["LAT"]));
pointShape.Id = "Truck";

truckLayer.Open();
truckLayer.EditTools.BeginTransaction();
truckLayer.EditTools.Update(pointShape, dictionary);
truckLayer.EditTools.CommitTransaction();
truckLayer.Close();
}


Curtis, 
  
 We introduced multi-threading to the current Beta (3.8.184) but unfortunately we didn’t handle the threading well enough and there are threading conflicts now and then. We are working on the next Beta which we will make the threading an option and by default using a single thread. That new release will be available sometime this week and sorry for the inconvenience now. 
  
 Thanks, 
  
 Ben.