Maria globe client/Advanced map settings: Difference between revisions

From Maria GDK Wiki
Jump to navigation Jump to search
()
()
 
(16 intermediate revisions by the same user not shown)
Line 38: Line 38:
public ICommand RotateRightCmnd { get { return new DelegateCommand(OnRotateRight); } }
public ICommand RotateRightCmnd { get { return new DelegateCommand(OnRotateRight); } }


private void OnRotateLeft(object obj)
private void OnRotateLeft(object obj) { Rotation += 1;}
{
private void OnRotateRight(object obj) { Rotation -= 1;}
    Rotation += 1;
}
 
private void OnRotateRight(object obj)
{
    Rotation -= 1;
}


public int Rotation
public int Rotation
Line 59: Line 52:
. . .
. . .
</source>
</source>


=== Running with map rotation ===
=== Running with map rotation ===
Line 109: Line 101:
=== Additional components and code ===
=== Additional components and code ===


To visualise the 3D settings, add display, with ability for modification, for:
To visualise the 3D settings, add display, with ability of modification, for:
;Camera  
;Camera  
:* Yaw
:* Yaw
Line 116: Line 108:
;Target
;Target
:* Follow ground
:* Follow ground
:* Distance
:* Altitude
:* Altitude
::Changes are not applicable while:
::Changes are not applicable while:
Line 124: Line 115:
::Changes are not applicable while:
::Changes are not applicable while:
::* auto follow is active, as the target position is defined by the item followed.
::* auto follow is active, as the target position is defined by the item followed.
:* Distance


{{Note|Example of necessary components, properties and command handlers [[Maria globe client/Advanced map settings/3D_settings_code_sample|''are described separately'' '''''here''''']].}}


Necessary components are described [[3D_map_settings_components|'''''here''''']].
=== Synchronise with map actions ===
 
<source  lang="xml">
. . .
<GroupBox Header="3D Settings"
          IsEnabled="{Binding MapViewModel.Is3DMode}" >
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
 
        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4"
              Content="Camera" FontWeight="DemiBold" />
       
        <Label Grid.Row="1" Grid.Column="0"
              Content="Yaw"  />
        <TextBox Grid.Row="1" Grid.Column="1" Margin="3" Width="60"
                Text="{Binding MapViewModel.CameraYaw, StringFormat=N2}" TextAlignment="Right"                           
                IsReadOnly="True"/>
        <RepeatButton Grid.Row="1" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseYawCmnd}"/>
        <RepeatButton Grid.Row="1" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseYawCmnd}"/>
       
        <Label Grid.Row="2" Grid.Column="0"
              Content="Roll" />
        <TextBox Grid.Row="2" Grid.Column="1" Margin="3" Width="60"
                Text="{Binding MapViewModel.CameraRoll, StringFormat=N2}" TextAlignment="Right"
                IsReadOnly="True"/>
        <RepeatButton Grid.Row="2" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseRollCmnd}"/>
        <RepeatButton Grid.Row="2" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseRollCmnd}"/>
       
        <Label Grid.Row="3" Grid.Column="0"
              Content="Pitch" />
        <TextBox Grid.Row="3" Grid.Column="1" Margin="3" Width="60"
                Text="{Binding MapViewModel.CameraPitch, StringFormat=N2}" TextAlignment="Right"
                IsReadOnly="True"/>
        <RepeatButton Grid.Row="3" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreasePitchCmnd}"/>
        <RepeatButton Grid.Row="3" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreasePitchCmnd}"/>
 
        <Label Grid.Row="4" Grid.Column="0"
              Content="Target" FontWeight="DemiBold" />
        <CheckBox Grid.Row="4"  Grid.Column="1" Grid.ColumnSpan="3" VerticalAlignment="Center" Margin="3"
                  Content="Follow ground"
                  IsChecked="{Binding MapViewModel.FollowGround}"/>
 
        <Label Grid.Row="5" Grid.Column="0"
              Content="Altitude" />
        <TextBox Grid.Row="5" Grid.Column="1" Margin="3" Width="60"
                Text="{Binding MapViewModel.TargetAltitude, StringFormat=N0}" TextAlignment="Right"
                IsReadOnly="True"/>
        <RepeatButton Grid.Row="5" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseTargetAltitudeCmnd}"/>
        <RepeatButton Grid.Row="5" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseTargetAltitudeCmnd}"/>
       
        <Label Grid.Row="6" Grid.Column="0"
              Content="Distance" />
        <TextBox Grid.Row="6" Grid.Column="1" Margin="3" Width="60"
                Text="{Binding MapViewModel.TargetDistance, StringFormat=N0}" TextAlignment="Right"
                IsReadOnly="True"/>
        <RepeatButton Grid.Row="6" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseTargetDistanceCmnd}"/>
        <RepeatButton Grid.Row="6" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseTargetDistanceCmnd}"/>


        <Label Grid.Row="7" Grid.Column="0"
We need to synchronise the 3D map settings when 3D mode is entered, and also whenever altered by mouse actions in the map area.  
              Content="Position" />
        <TextBox Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="3" Margin="3"                             
                Text="{Binding MapViewModel.TargetPosText, Mode=OneWay}" TextAlignment="Right"
                IsReadOnly="True"/>
        <Label Grid.Row="8" Grid.Column="1"
              Content="Latitude"/>
        <RepeatButton Grid.Row="8" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseTargetPosLatCmnd}"/>
        <RepeatButton Grid.Row="8" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseTargetPosLatCmnd}"/>


        <Label Grid.Row="9" Grid.Column="1"
To do that, subscribe to events from:
              Content="Longitude"/>
        <RepeatButton Grid.Row="9" Grid.Column="2" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="+"
                      Command="{Binding MapViewModel.IncreaseTargetPosLonCmnd}"/>
        <RepeatButton Grid.Row="9" Grid.Column="3" Width="12" Margin="3" HorizontalAlignment="Center"
                      Content="-"
                      Command="{Binding MapViewModel.DecreaseTargetPosLonCmnd}"/>
    </Grid>
</GroupBox>
. . .
</source>


:;GlobeMapViewModel
:* Entered2DMode
:* Entered3DMode
:;GlobeMapViewModel.Globe3DViewModel.CameraControl
:* AfterPan
:* TargetDistanceChanged
:* TargetPosChanged
:* OrientationChanged


And add necessary command handlers and properties to '''''MapViewModel'''''
In '''''MapViewModel''''':


<source lang="csharp">
<source lang="C#">
. . .
. . .
public ICommand IncreaseYawCmnd { get { return new DelegateCommand(OnIncreaseCameraYaw); } }
public void SetGlobeMapViewModel(IGlobeMapViewModel globeMapViewModel)
public ICommand DecreaseYawCmnd { get { return new DelegateCommand(OnDecreaseCameraYaw); } }
 
public ICommand IncreaseRollCmnd { get { return new DelegateCommand(OnIncreaseCameraRoll); } }
public ICommand DecreaseRollCmnd { get { return new DelegateCommand(OnDecreaseCameraRoll); } }
 
public ICommand IncreasePitchCmnd { get { return new DelegateCommand(OnIncreaseCameraPitch); } }
public ICommand DecreasePitchCmnd { get { return new DelegateCommand(OnDecreaseCameraPitch); } }
 
public ICommand IncreaseTargetDistanceCmnd { get { return new DelegateCommand(OnIncreaseTargetDistance); } }
public ICommand DecreaseTargetDistanceCmnd { get { return new DelegateCommand(OnDecreaseTargetDistance); } }
 
public ICommand IncreaseTargetAltitudeCmnd { get { return new DelegateCommand(OnIncreaseTargetAlttitude, CanModTargetAltitude); } }
public ICommand DecreaseTargetAltitudeCmnd { get { return new DelegateCommand(OnDecreaseTargetAltitide, CanModTargetAltitude); } }
 
public ICommand IncreaseTargetPosLatCmnd { get { return new DelegateCommand(OnIncreaseTargetPosLat, CanModTargetPosition); } }
public ICommand DecreaseTargetPosLatCmnd { get { return new DelegateCommand(OnDecreaseTargetPosLat, CanModTargetPosition); } }
public ICommand IncreaseTargetPosLonCmnd { get { return new DelegateCommand(OnIncreaseTargetPosLon, CanModTargetPosition); } }
public ICommand DecreaseTargetPosLonCmnd { get { return new DelegateCommand(OnDecreaseTargetPosLon, CanModTargetPosition); } }
 
public bool Autofollow
{
    get { return _autoFollow; }
    set
    {
        _autoFollow = value;
 
        RefreshTargetAndCameraValues();
    }
}
 
private void OnIncreaseCameraYaw(object obj) { CameraYaw += 1; }
private void OnDecreaseCameraYaw(object obj) { CameraYaw -= 1; }
 
private void OnIncreaseCameraRoll(object obj) { CameraRoll += 1; }
private void OnDecreaseCameraRoll(object obj) { CameraRoll -= 1; }
 
private void OnIncreaseCameraPitch(object obj) { CameraPitch += 1; }
private void OnDecreaseCameraPitch(object obj) { CameraPitch -= 1; }
 
private void OnIncreaseTargetAlttitude(object obj) { TargetAltitude += 10; }
private void OnDecreaseTargetAltitide(object obj) { TargetAltitude -= 10; }
 
private void OnIncreaseTargetPosLat(object obj) { TargetPos = new GeoPos(TargetPos.Lat + (1.0 / (60 * 60)), TargetPos.Lon ); }
private void OnDecreaseTargetPosLat(object obj) { TargetPos = new GeoPos(TargetPos.Lat - (1.0 / (60 * 60)), TargetPos.Lon ); }
private void OnIncreaseTargetPosLon(object obj) { TargetPos = new GeoPos(TargetPos.Lat, TargetPos.Lon + (1.0 / (60 * 60))); }
private void OnDecreaseTargetPosLon(object obj) { TargetPos = new GeoPos(TargetPos.Lat, TargetPos.Lon - (1.0 / (60 * 60))); }
 
private bool CanModTargetAltitude(object obj) { return !FollowGround && !Autofollow; }
private bool CanModTargetPosition(object obj) { return !Autofollow; }
 
private void OnIncreaseTargetDistance(object obj) { TargetDistance += 10; }
private void OnDecreaseTargetDistance(object obj) { TargetDistance -= 10; }
 
public double CameraYaw
{
    get
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.Yaw;
        return 0;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.Yaw = value;
        }
 
        NotifyPropertyChanged(() => CameraYaw);
    }
}
 
public double CameraRoll
{
    get
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.Roll;
        return 0;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.Roll = value;
        }
 
        NotifyPropertyChanged(() => CameraRoll);
    }
}
 
public double CameraPitch
{
    get
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.Pitch;
        return 0;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.Pitch = value;
        }
 
        NotifyPropertyChanged(() => CameraPitch);
    }
}
 
public string TargetPosText { get { return TargetPos.ToString(); } }
 
public GeoPos TargetPos
{
    get
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetPos;
 
        return GeoPos.InvalidPos;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetPos = value;
        }
 
        RefreshTargetAndCameraValues();
    }
}
 
public double TargetAltitude
{
{
     get
     _globeMapViewModel = globeMapViewModel;          
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetAltitude;
        return 0;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetAltitude = value;
        }
 
        NotifyPropertyChanged(() => TargetAltitude);
    }
}


public bool FollowGround
    _globeMapViewModel.Globe3DViewModel.CameraControl.AfterPan += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.TargetDistanceChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.TargetPosChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.OrientationChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Entered2DMode += OnModeOrSettingsChanged;
    _globeMapViewModel.Entered3DMode += OnModeOrSettingsChanged;
}
private void OnModeOrSettingsChanged(object sender, EventArgs args)
{
{
     get
     RefreshTargetAndCameraValues();
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.FollowGround;
        return true;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.FollowGround = value;
        }
 
        NotifyPropertyChanged(() => FollowGround);
    }
}
 
public double TargetDistance
{
    get
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
            return GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetDistance;
        return 0;
    }
    set
    {
        if (GlobeMapViewModel?.Globe3DViewModel?.CameraControl != null)
        {
            GlobeMapViewModel.Globe3DViewModel.CameraControl.TargetDistance = value;
        }
 
        NotifyPropertyChanged(() => TargetDistance);
    }
}
. . .
private void RefreshTargetAndCameraValues()
{
    NotifyPropertyChanged(() => FollowGround);
    NotifyPropertyChanged(() => Autofollow);
 
    NotifyPropertyChanged(() => CameraPitch);
    NotifyPropertyChanged(() => CameraRoll);
    NotifyPropertyChanged(() => CameraYaw);
 
    NotifyPropertyChanged(() => TargetAltitude);
    NotifyPropertyChanged(() => TargetPos);
    NotifyPropertyChanged(() => TargetPosText);
    NotifyPropertyChanged(() => TargetDistance);
}
. . .
</source>
 
... and update '''''MapViewModel.Autofollow''''' when auto follow has changed in '''''MainViewModel'''''!
 
<source lang="c#">
. . .
public bool IsAutoFollowActive
{
  . . .
    set
    {
        if (!(value && GlobeMapViewModel.AutoFollow.FollowSelectedItem()))
            GlobeMapViewModel.AutoFollow.TargetItem = null;
 
        MapViewModel.Autofollow = IsAutoFollowActive;
        NotifyPropertyChanged(() => IsAutoFollowActive);
        NotifyPropertyChanged(() => AutoFollowItemName);
    }
}
}
. . .
. . .
</source>
</source>


=== Running with display of 3D settings ===
=== Running with displayed 3D settings ===


Running the '''''Globe client''''' in 3D mode, altering the 3D parameters will give results like this:
Running the '''''Globe client''''' in 3D mode, altering the 3D parameters will give results like this:
Line 502: Line 178:
|
|
[[File:3D_Set_P15_Y120_af_close.png|450px|Auto follow - closer ]] <br>
[[File:3D_Set_P15_Y120_af_close.png|450px|Auto follow - closer ]] <br>
Auto follow - closer
With auto follow, modified target distance (camera closer)
|
|
[[File:3D_Set_P15_Y120_R30_af.png|450px| Modified ''roll'' ]]<br>
[[File:3D_Set_P15_Y120_R30_af.png|450px| Modified ''roll'' ]]<br>

Latest revision as of 11:46, 7 October 2019

Map rotation

As default, 2D maps are displayed with north up, but you may rotate the map by modifying the map layer rotation parameter - GeoContext.RotateValue.

Additional components and code

Add the following components:

  • Text box to display the current rotation value
  • Two buttons, for right (clockwise) add left (counter clockwise).

Add the following to your Main Window XAML:

. . .
<Label Grid.Row="4" Grid.Column="0"
       Content="Rotation" FontWeight="DemiBold"/>

<TextBox Grid.Row="4" Grid.Column="1" Margin="3"
         Text="{Binding MapViewModel.Rotation}" TextAlignment="Right" />

<StackPanel  Grid.Row="5" Grid.Column="1" Orientation="Horizontal" 
             VerticalAlignment="Center" HorizontalAlignment="Center">
    <RepeatButton Margin="3" Width="50" 
                  Content="Left" 
                  Command="{Binding MapViewModel.RotateLeftCmnd}"/>
    <RepeatButton Margin="3" Width="50" 
                  Content="Right" 
                  Command="{Binding MapViewModel.RotateRightCmnd}"/>
</StackPanel>
. . .

And implement corresponding properties and command handlers in MapViewModel:

. . .
public ICommand RotateLeftCmnd { get { return new DelegateCommand(OnRotateLeft); } }
public ICommand RotateRightCmnd { get { return new DelegateCommand(OnRotateRight); } }

private void OnRotateLeft(object obj) { Rotation += 1;}
private void OnRotateRight(object obj) { Rotation -= 1;}

public int Rotation
{
    get { return _mapLayer.GeoContext != null ? (int)_mapLayer.GeoContext.RotateValue : 0; }
    set
    {                
        _mapLayer.GeoContext.RotateValue = value;
        NotifyPropertyChanged(() => Rotation);
    }
}
. . .

Running with map rotation

Pressing the rotation buttons, the map is rotated, and the rotation display is updated accordingly.

Map rotation.


3D map settings

The Globe Client 3D view is the view from a camera towards a target, specified by the following parameters:

Description
Camera yaw Horizontal rotation, degrees - counterclockwise. Roll, pitch and yaw
Camera pitch Front/back rotation, degrees - counterclockwise
Camera roll Left/right rotation, degrees - counterclockwise.
Follow ground

Lock the target altitude is to the elevation of the target position.

Target altitude

Height above sea level (0-elevation) at target position.

Target position

Latitude and longitude.

Target distance Distance from camera to target.


Note
  • 3D rotations are not commutative.
Performing the same rotations in different order will give different results.

Additional components and code

To visualise the 3D settings, add display, with ability of modification, for:

Camera
  • Yaw
  • Pitch
  • Roll
Target
  • Follow ground
  • Altitude
Changes are not applicable while:
  • auto follow is active, as the target elevation is defined by the item followed.
  • follow ground is active.
  • Position
Changes are not applicable while:
  • auto follow is active, as the target position is defined by the item followed.
  • Distance
Example of necessary components, properties and command handlers are described separately here.

Synchronise with map actions

We need to synchronise the 3D map settings when 3D mode is entered, and also whenever altered by mouse actions in the map area.

To do that, subscribe to events from:

GlobeMapViewModel
  • Entered2DMode
  • Entered3DMode
GlobeMapViewModel.Globe3DViewModel.CameraControl
  • AfterPan
  • TargetDistanceChanged
  • TargetPosChanged
  • OrientationChanged

In MapViewModel:

. . .
public void SetGlobeMapViewModel(IGlobeMapViewModel globeMapViewModel)
{
    _globeMapViewModel = globeMapViewModel;           

    _globeMapViewModel.Globe3DViewModel.CameraControl.AfterPan += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.TargetDistanceChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.TargetPosChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Globe3DViewModel.CameraControl.OrientationChanged += OnModeOrSettingsChanged;
    _globeMapViewModel.Entered2DMode += OnModeOrSettingsChanged;
    _globeMapViewModel.Entered3DMode += OnModeOrSettingsChanged;
} 
private void OnModeOrSettingsChanged(object sender, EventArgs args)
{
    RefreshTargetAndCameraValues();
}
. . .

Running with displayed 3D settings

Running the Globe client in 3D mode, altering the 3D parameters will give results like this:

Default 3D setting
Default 3D setting

Modified pitch
Modified pitch

Modified yaw
Modified yaw

With auto follow, track as target
With auto follow, track as target

Auto follow - closer
With auto follow, modified target distance (camera closer)

Modified roll
Modified roll