Airplane Track Line

Topics: SharpMap v2.0, WinForms Controls
Nov 9, 2011 at 9:04 AM

I've got a map on which I want to show an airplane and it's track as it moves over time.   Using the 'FormMovingObjectOverTileLayer.cs' in the Winforms examples, I was able to successfully get the airplane symbol to move about the map on a VariableLayer.  However, I'm trying to create a linestring on the map to show the plane's track and that part isn't working.  I can get the line to show up on the initial creation of the layer, but unlike the airplane symbol., it doesn't seem to update on the timer tick.  Can linestrings be updated like a point on a variable layer?

Thanks, Dirk

 

My code:

 

        private List<SharpMap.Geometries.Geometry> _geos = new List<SharpMap.Geometries.Geometry>();
        SharpMap.Geometries.Point position;
        SharpMap.Geometries.LineString _AirplaneTrackLineString;

 

 

 

        private void InitMap()
        {
            MapTimer.Enabled = false;

            mapBox1.Map = cGradiantThemeWorld.InitializeMap(0);
            this.Cursor = Cursors.Default;

            List<cTelemetry> oTel = fLayout.Telemetry_Log;

            //Draw the flight path line
            double dMinLon = 99999;
            double dMaxLon = -99999;
            double dMinLat = 99999;
            double dMaxLat = -99999;
            VectorLayer airplaneTrackLayer = new VectorLayer("AirplaneTrack");
            cTelemetry Tel = fLayout.Telemetry_Current;
            //loop through the flight history
            for (int i = 0; i < oTel.Count; i++)
            {
                P.Add(new SharpMap.Geometries.Point(oTel[i].Longitude, oTel[i].Latitude));
                cGraphHelper.CalulateMinMax(oTel[i].Longitude, ref dMinLon, ref dMaxLon);
                cGraphHelper.CalulateMinMax(oTel[i].Latitude, ref dMinLat, ref dMaxLat);
            }
            // Make A New Line from Those Points 
            _AirplaneTrackLineString = new SharpMap.Geometries.LineString(P);
            SharpMap.Data.Providers.GeometryProvider geoTrackProvider = new SharpMap.Data.Providers.GeometryProvider(_AirplaneTrackLineString);
            airplaneTrackLayer.DataSource = geoTrackProvider;
            airplaneTrackLayer.Style.Line = new Pen(Color.Green);
            airplaneTrackLayer.Style.Line.Width = 4;
            this.mapBox1.Map.VariableLayers.Add(airplaneTrackLayer);

            //Adds a moving variable layer for the airplane icon
            VectorLayer airplaneIconLayer = new VectorLayer("Airplane");
            SharpMap.Geometries.Point pt = new SharpMap.Geometries.Point(Tel.Longitude, Tel.Latitude);
            position = pt;
            _geos.Clear();
            _geos.Add(position);
            airplaneIconLayer.Style.Symbol = PACTEC_FlightSimConnect.Properties.Resources.airplane_map;
            SharpMap.Data.Providers.GeometryProvider geoProvider = new SharpMap.Data.Providers.GeometryProvider(_geos);
            airplaneIconLayer.Style.SymbolScale = 0.6F;
            airplaneIconLayer.DataSource = geoProvider;
            this.mapBox1.Map.VariableLayers.Add(airplaneIconLayer);

            //figure out the extents of the view box
            BoundingBox bb = new BoundingBox(dMinLon, dMinLat, dMaxLon, dMaxLat);
            mapBox1.Map.ZoomToBox(bb);

            this.mapBox1.Refresh();
            MapTimer.Enabled = true;
        }

 

 

        private void MapTimer_Tick(object sender, EventArgs e)
        {
            //loop through the updated airplane track history - NOT WORKING
            List<cTelemetry> oTel = fLayout.Telemetry_Log;
            // Create A New List Of Points
            IList<SharpMap.Geometries.Point> P = new List<SharpMap.Geometries.Point>();            
            for (int i = 0; i < oTel.Count; i++)
            {
                P.Add(new SharpMap.Geometries.Point(oTel[i].Longitude, oTel[i].Latitude));
            }
            _AirplaneTrackLineString = new SharpMap.Geometries.LineString(P);

            //update the airplane symbol position - WORKS
            cTelemetry Tel = fLayout.Telemetry_Current;
            position.X = Tel.Longitude;
            position.Y = Tel.Latitude;

            VariableLayerCollection.TouchTimer();
            //this.mapBox1.Refresh();
        }

 

 

Coordinator
Nov 9, 2011 at 10:10 AM

You are not updating the geometry in geoTrackProvider, but simply replacing the initial geometry.

Why don't you just add the last postion to the initial linestring?

_AirplaneTrackLineString.Vertices.Add(...); 

If that does not work either, you might have to get the geometry from the provider and update that:

var track = (LineString)geoTrackProvider.Geometries[0];
track.Vertices.Add(...);

Remark: If your planes are cossing the dateline, you need to use a MultiLineString.

Hth FObermaier

Nov 10, 2011 at 2:40 AM

Thanks FObermaier,

The _AirplaneTrackLineString.Vertices.Add(...); suggestion worked.

 

As a follow up question to this, for "fun" I was trying to take my little plane bitmap and turn it in the direction that the plane is currently flying.  I tried to run a theme by which I could update the airplane symbol with a rotated one by adding in a theme through these lines:

 


            //Adds a moving variable layer for the airplane icon
            VectorLayer airplaneIconLayer = new VectorLayer("Airplane");
            //cTelemetry Tel = fLayout.Telemetry_Current;
            SharpMap.Geometries.Point pt = new SharpMap.Geometries.Point(Tel.Longitude, Tel.Latitude);
            position = pt;
            _geos.Clear();
            _geos.Add(position);
            airplaneIconLayer.Style.Symbol = PACTEC_FlightSimConnect.Properties.Resources.airplane_map;
            SharpMap.Data.Providers.GeometryProvider geoProvider = new SharpMap.Data.Providers.GeometryProvider(_geos);
            airplaneIconLayer.Style.SymbolScale = 0.6F;
            airplaneIconLayer.DataSource = geoProvider;
            SharpMap.Rendering.Thematics.CustomTheme rotationTheme = new SharpMap.Rendering.Thematics.CustomTheme(GetRotationStyle);
            airplaneIconLayer.Theme = rotationTheme;
            this.mapBox1.Map.VariableLayers.Add(airplaneIconLayer);
        private SharpMap.Styles.VectorStyle GetRotationStyle(SharpMap.Data.FeatureDataRow row)
        {

        }

However, if I set a breakpoint on the GetRotationStyle function, it never gets triggered and worse yet, the map doesn't display anything.  Is it not possible to run themes on a VariableLayer?

Thanks, Dirk

Coordinator
Nov 10, 2011 at 8:10 AM

If you want to use theming you need to use GeometryFeatureProvider.

You need a feature data table that holds a bearing value, that you can use to calculate the rotation of the symbol

private SharpMap.Styles.VectorStyle GetRotationStyle(SharpMap.Data.FeatureDataRow row)
{
    if (fdr["Bearing"] == DbNull.Value)
return _defaultStyle;
var bearing = (double)fdr["Bearing]";
var retStyle = new VectorStyle(_defaultStyle);
retStyle.SymbolRotation = bearing;
return retStyle;
}

Warning: Code has not seen a compiler, there may be typos

Hth FObermaier