Maria globe client/Map interaction

From Maria GDK Wiki
Jump to navigation Jump to search

Map utilities

The different map utilities can be turned on/off programatically e.g. through User controlls. For more details about tools and map functionality, see Map interaction client, Map_interaction and Tools interaction

Here is an example of adding check boxes with direct binding to the MariaGlobeMapControl from your main window.

...
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal" 
                Visibility="Visible">
        <GroupBox Header="Map Utilities">
            <StackPanel Orientation="Vertical" Visibility="Visible" Margin="5">
                <CheckBox Content="Ruler" Margin="3"
                          ToolTip="Ruler" 
                          IsChecked="{Binding IsRulerVisible, ElementName=MariaGlobeCtrl}" />
                <CheckBox Content="Pan Navigation" Margin="3"
                          ToolTip="Pan Navigation" 
                          IsChecked="{Binding IsPanNavigationVisible, ElementName=MariaGlobeCtrl}" />
                <CheckBox Content="Scale Bar" Margin="3"
                          ToolTip="Center Position, Scale Bar" 
                          IsChecked="{Binding IsScaleBarVisible, ElementName=MariaGlobeCtrl}" />
                <CheckBox Content="Center Mark"  Margin="3"
                          ToolTip="Center Position Indicator"
                          IsChecked="{Binding IsCenterPositionIndicatorEnabled, ElementName=MariaGlobeCtrl}" />
                <CheckBox Content="Mini Map" Margin="3"
                          ToolTip="Mini Map" 
                          IsChecked="{Binding IsMiniMapVisible, ElementName=MariaGlobeCtrl}" />                   
            </StackPanel>
        </GroupBox>
    </StackPanel>
    <Grid Grid.Row="1">
        <mariaglobemapcontrol:MariaGlobeMapControl x:Name="MariaGlobeCtrl" 
                                                   Background="#E9ECFA"                                                   
                                                   Layers="{Binding Layers}"
                                                   MiniMapLayer="{Binding MapViewModel.MiniMapLayer, Mode=OneWay}"
                                                   CenterScale="{Binding MapViewModel.CenterScale}" 
                                                   CenterPosition="{Binding MapViewModel.CenterPosition}"
                                                   Is3DMode="False"
                                                   MouseMoveDistanceToStartTracking="0"
                                                   ZoomOnDblClick="False"
                                                   DegreeToLockRotateAndScale="2"
                                                   PercentageToLockScaleOnly="2.0"
                                                   IsRulerVisible="True" 
                                                   IsCenterPositionIndicatorEnabled="True"
                                                   IsMiniMapVisible="True" />
    </Grid>
</Grid>
...

Map settings

Your map service will most likely contain different map templates, and you would like to select the template to be used.
In we will create a list of templates to chose from, display the current center position and scale, and also choose the display mode - 2D or 3D.

Add the following to your Main Window XAML:

...
<GroupBox Header="Map Settings">
    <Grid Margin="3">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />                       
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ComboBox Name="cmbActiveMap" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,5"
                  Width="Auto" Height="Auto" MinWidth="200" 
                  VerticalAlignment="Top"
                  ItemsSource="{Binding MapViewModel.AvailableMapTemplateNames}" 
                  SelectedItem="{Binding MapViewModel.ActiveMapTemplateName}" 
                  IsSynchronizedWithCurrentItem="true" />

        <Label Grid.Row="1" Grid.Column="0"
               Content="Mode" FontWeight="DemiBold"/>
        <StackPanel Grid.Row="1" Grid.Column="1">
                <RadioButton Content="2D" 
                             IsChecked="{Binding MapViewModel.Is2DMode, Mode=OneWay}" />
                <RadioButton Content="3D"                                      
                             IsChecked="{Binding MapViewModel.Is3DMode}" />
        </StackPanel>

        <Label Grid.Row="2" Grid.Column="0"  FontWeight="DemiBold">
            <TextBlock>
                Center<LineBreak/>
                Scale
            </TextBlock>
        </Label>
        <TextBox Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" 
                 Text="{Binding MapViewModel.CenterScale, StringFormat=N1}" 
                 IsReadOnly="True" />

        <Label Grid.Row="3" Grid.Column="0"  FontWeight="DemiBold">
            <TextBlock>
                Center<LineBreak/>
                Position
            </TextBlock>
        </Label>
        <TextBox Grid.Row="3" Grid.Column="1" VerticalAlignment="Center"
                 Text="{Binding MapViewModel.CenterPosition, Mode=OneWay}" 
                 IsReadOnly="True" />
    </Grid>
</GroupBox>
...

And bind the Is3DMode property of the MariaGlobeMapControl to same value as the Radio button.

... 
<mariaglobemapcontrol:MariaGlobeMapControl x:Name="MariaGlobeCtrl" Background="#E9ECFA"  
                                           Is3DMode="{Binding MapViewModel.Is3DMode}"
                                           Layers="{Binding Layers}" 
...

Extend the MapViewModel with:

  • fields and properties to handle display of available map templates and 2D/3D mode selection
  • initialized event handlers with initialisation and selection of templates
  • CenterPosition and CenterScale properties with notification handling.
...
private Dictionary<string, MapTemplate> _availableMapTemplateDictionary = new Dictionary<string, MapTemplate>();

private double _scale;
private GeoPos _pos;
private bool _is3DMode;
...
public bool Is2DMode { get { return !_is3DMode; } }

public bool Is3DMode
{
    get { return _is3DMode; }
    set
    {
        _is3DMode = value;
        NotifyPropertyChanged(() => Is2DMode);
        NotifyPropertyChanged(() => Is3DMode);
    }
}

public GeoPos CenterPosition
{
    get { return _pos; }
    set
    {
        _pos = value;
        NotifyPropertyChanged(() => CenterPosition);
    }
}

public double CenterScale
{
    get { return _scale; }
    set
    {
        _scale = value;
        NotifyPropertyChanged(() => CenterScale);
    }
}

public MapViewModel(IMariaMapLayer mapLayer, IMariaMapLayer miniMapLayer)
{
    _mapLayer = mapLayer;

    if (_mapLayer != null)
        _mapLayer.LayerInitialized += OnMapLayerInitialized;

    MiniMapLayer = miniMapLayer;
    if (MiniMapLayer != null)
        MiniMapLayer.LayerInitialized += OnMiniMapLayerInitialized;
}

private void OnMapLayerInitialized()
{
    foreach (var template in _mapLayer.ActiveMapTemplates)
    {
        _availableMapTemplateDictionary.Add(template.Name, template);
    }

    NotifyPropertyChanged(() => AvailableMapTemplateNames);

    CenterPosition = new GeoPos(59.908358, 10.628190); // TPG - Lysaker
    CenterScale = 3500000;

    _mapLayer.ActiveMapTemplate = _mapLayer.ActiveMapTemplates.Any() ?
                                    _mapLayer.ActiveMapTemplates.First() : null;

    _mapLayer.ActiveMapTemplate = PreferredMapTemplate();
    NotifyPropertyChanged(() => ActiveMapTemplateName);
}

private void OnMiniMapLayerInitialized()
{
    MiniMapLayer.ActiveMapTemplate = _mapLayer.ActiveMapTemplates.Any() ?
                                    _mapLayer.ActiveMapTemplates.First() : null;
    MiniMapLayer.ActiveMapTemplate = PreferredMapTemplate();
}



public IEnumerable<string> AvailableMapTemplateNames
{
    get
    {
        return _availableMapTemplateDictionary.Keys.ToList();
    }
}

public string ActiveMapTemplateName
{
    get
    {
        if (_mapLayer != null && _mapLayer.ActiveMapTemplate != null)
            return _mapLayer.ActiveMapTemplate.Name;
        return "";
    }
    set
    {
        MapTemplate template = null;

        if (_availableMapTemplateDictionary.ContainsKey(value))
        {
            template = _availableMapTemplateDictionary[value];
        }
        else if (_availableMapTemplateDictionary.Any())
        {
            template = _availableMapTemplateDictionary.Values.First();
        }

        _mapLayer.ActiveMapTemplate = template;
        MiniMapLayer.ActiveMapTemplate = template;
        NotifyPropertyChanged(() => ActiveMapTemplateName);
    }
}

private MapTemplate PreferredMapTemplate()
{
    var preferred = "TOPO";

    if (_availableMapTemplateDictionary.ContainsKey(preferred))
        return _availableMapTemplateDictionary[preferred];

    return _availableMapTemplateDictionary.Values.Any() ? _availableMapTemplateDictionary.Values.First() : null;
}
...

Running with map interaction

Running your application, observe the following:

  • the map utilities are shown/hidden according to the corresponding check boxes
  • the center position and scale are updated when panning/zooming the map
  • the map template drop-down list contains available map templates
  • the map display changes according to selected map template
  • the map display changes according to deleted mode


Preferred map, 2D
Preferred map, 2D

Preferred map, 3D
Preferred map, 3D

Another map, 2D
Another map, 2D

Another map, 3D
Another map, 3D