Maria globe client/Track interaction: Difference between revisions

From Maria GDK Wiki
Jump to navigation Jump to search
No edit summary
()
 
Line 237: Line 237:
== Track styling ==
== Track styling ==


Add a track style xml file to your project, and include it as a resource. You can find style xml to use [[Track_style_xml| '''here''']]
Add a track style xml file to your project, and include it as a resource.
 
{{Note|You can find style xml to use [[Track_style_xml| '''here''']]}}


Add the resource to the track layer in the '''''LayerInitialized''''' event handler in '''''TrackViewModel'''''.
Add the resource to the track layer in the '''''LayerInitialized''''' event handler in '''''TrackViewModel'''''.

Latest revision as of 11:30, 7 October 2019

General

In this section, we will create and update a track, and observe the presentation in 2D and 3D mode.

, and For more details on track handling, see:

  • Tracks
  • Map interaction client:
Track interaction
Track visualisation


Adding draw object layer and draw object view model

To be able to display tracks, we need to include a track layer in the globe client.

First, add a view model class, TrackViewModel, to handle the draw object interaction:

  • Inheriting ViewModelBase
  • Add a constructor taking a draw layer object as input
  • Create and implement event handlers for:
    • LayerInitialized event
    • ServiceConnected event
public class TrackViewModel : ViewModelBase
{
    private TrackLayer _trackLayer;
    private MariaService _trackService;

    public TrackViewModel(TrackLayer trackLayer)
    {
        _trackLayer = trackLayer;

        _trackLayer.LayerInitialized += TrackLayer_LayerInitialized;
        _trackLayer.ServiceConnected += TrackLayer_ServiceConnected;
    }

    private void TrackLayer_LayerInitialized()
    {
        _trackService = new MariaService("TrackService", "http://localhost:9008/tracks", BindingType.BasicHttp);
        _trackLayer.TrackServices = new ObservableCollection<IMariaService> { _trackService };
    }

    private void TrackLayer_ServiceConnected(object sender, MariaServiceEventArgs args)
    {
        _trackLayer.ActiveTrackService = _trackLayer.TrackServices[0];
        _trackLayer.ExtendedTrackLayer.TrackRefreshInterval = 1000;

        _trackLayer.TrackLists = new ObservableCollection<string>(_trackLayer.GetTrackLists());

        if (!_trackLayer.TrackLists.Contains("globeTest"))
            _trackLayer.TrackLists.Add("globeTest");

        _trackLayer.ActiveTrackList = "globeTest";
    }
}

In the MainViewModel, add a track layer field, and in the constructor, add creation of the layer and TrackViewModel, and add the layer to the Layers list.

...
public TrackViewModel TrackViewModel { get; private set; }

public MainViewModel()
{
    ...
    _trackLayer = new TrackLayer(GlobeMapManager);
    TrackViewModel = new TrackViewModel(_trackLayer);
    Layers.Add(_trackLayer);
}
...

Track utilities

Add the following GUI elements to your main window:

  • Button for adding/updating the track
  • Check box to enable/disable automatic track update (simulate movement)

The XAML could look something like this:

...
<GroupBox Header="Track">
    <StackPanel>
        <Button Margin="3"                         
                Content="Track" 
                Command="{Binding TrackViewModel.TrackTestCmd}"/>
        <CheckBox Margin="3"
                  Content="Auto update" 
                  IsChecked="{Binding TrackViewModel.AutoUpdateActive}"/> 
    </StackPanel>
</GroupBox>
...

In TrackViewModel implement:

  • command handler and command handler delegate in for the track update button
  • auto update property with timer, initialised in during the LayerInitialized event handler.
...
private bool _autoUpdateActive;
Timer _autoUpdateTimer;
...
private void TrackLayer_LayerInitialized()
{
...
    _autoUpdateTimer = new Timer(1000);
    _autoUpdateTimer.Elapsed += OnAutoUpdateTimerTick;
}
...
public ICommand TrackTestCmd { get { return new DelegateCommand(CreateOrUpdateTrack, CheckAutoUpdate); } }

public void CreateOrUpdateTrack(object obj)
{
    if (_trackLayer.ActiveTrackList == null)
        return;

    var currentTime = DateTime.UtcNow;

    var strId = "Globe-Track";
    var itemId = new ItemId(_trackLayer.ActiveTrackList, strId);

    var list = _trackLayer.GetTrackData(strId);

    var speed = RandomProvider.GetRandomDouble(100.0, 250.0);
    var course = RandomProvider.GetRandomDouble(0, 360.0);
    var pos = RandomProvider.GetRandomPosition(_trackLayer.GeoContext.Viewport.GeoRect, 0.9);

    var altitude = RandomProvider.GetRandomDouble(500, 2000);
    var roll = RandomProvider.GetRandomDouble(-45.0, 45.0);
    var pitch = RandomProvider.GetRandomDouble(-30.0, 30.0);

    ITrackData trackData;
    if (!list.Any())
    {
        trackData = new TrackData(itemId, pos, course, speed) { ObservationTime = currentTime };
        InitTrackData(ref trackData, strId);
    }
    else
    {
        trackData = list[0];

        var trackAge = trackData.ObservationTime.HasValue ?
            currentTime - trackData.ObservationTime.Value :
            TimeSpan.MaxValue;

        if (trackAge > new TimeSpan(0, 0, 5))
        {
            trackData = new TrackData(itemId, pos, course, speed) { ObservationTime = currentTime };
            InitTrackData(ref trackData, strId);
        }
        else
        {
            trackData.ObservationTime = currentTime;

            trackData.Speed = trackData.Speed.HasValue ?
                RandomProvider.GetRandomDouble(trackData.Speed.Value * 0.8, trackData.Speed.Value * 1.2) :
                speed;
            trackData.Course = trackData.Course.HasValue ?
                RandomProvider.GetRandomDouble(trackData.Course.Value * 0.9, trackData.Course.Value * 1.1) :
                course;

            trackData.Pos = trackData.Pos.HasValue ?
                CalculateNewPos(trackData.Pos.Value, trackData.Speed.Value, trackData.Course.Value, trackAge) :
                pos;

            if (double.TryParse(trackData.Fields["altitude"], out altitude))
            {
                altitude = RandomProvider.GetRandomDouble(altitude * 0.8, altitude * 1.2);
            }

            if (double.TryParse(trackData.Fields["roll"], out roll))
            {
                roll = RandomProvider.GetRandomDouble(roll * 0.9, roll * 1.1);
            }

            if (double.TryParse(trackData.Fields["pitch"], out pitch))
            {
                pitch = RandomProvider.GetRandomDouble(pitch * 0.9, pitch * 1.1);
            }
        }
    }

    trackData.Fields["altitude"] = altitude.ToString();
    trackData.Fields["roll"] = roll.ToString();
    trackData.Fields["pitch"] = pitch.ToString();
    trackData.Fields["heading"] = course.ToString();

    _trackLayer.SetTrackData(trackData);
}

public bool CheckAutoUpdate(object obj)
{
    return !AutoUpdateActive;
}

public bool AutoUpdateActive
{
    get { return _autoUpdateActive; }
    set
    {
        _autoUpdateActive = value;

        if (_autoUpdateActive)
            _autoUpdateTimer.Start();
        else
            _autoUpdateTimer.Stop();
    }
}

private void OnAutoUpdateTimerTick(object sender, ElapsedEventArgs e)
{
    CreateOrUpdateTrack(null);
}

private void InitTrackData(ref ITrackData td, string id)
{
    td.Fields["name"] = id;
    td.Fields["symbol.2525code"] = "SFAPCF----*****";
    td.Fields["identity"] = "Friendly";
    td.Fields["type"] = "F";
}

private GeoPos CalculateNewPos(GeoPos oldPos, double speed, double course, TimeSpan age)
{
    var distance = speed * age.TotalSeconds;
    var newPos = Earth.BearingRangeToPos(oldPos, new BearingRange(course, distance));
    return newPos;
}
...

Track styling

Add a track style xml file to your project, and include it as a resource.

You can find style xml to use here

Add the resource to the track layer in the LayerInitialized event handler in TrackViewModel.

...
private void TrackLayer_LayerInitialized()
{
    _trackLayer.StyleXml = Properties.Resources.TrackStyle;
...

Running with track interaction

Running your application, observe the following:

  • Pressing the track button, the track is created/moved around in the map area.
  • The track button is disabled while auto-update is activated.

Track in map, 2D
Track in map, 2D

Track in map, 3D
Track in map, 3D