3D Follow Target

Download Samples Repository

Description

Demonstrates how to follow a target in the SceneView

"Desktop" Available for Desktop

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.FollowTarget"
			 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
			 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
			 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
			 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
			 xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
			 mc:Ignorable="d" >

	<Grid>
		<Grid.Resources>
			<esri:SimpleRenderer x:Key="MyRenderer">
				<esri:SimpleMarkerSymbol Color="Red" Size="20" Style="Circle" />
			</esri:SimpleRenderer>
		</Grid.Resources>
		<esri:SceneView x:Name="MySceneView" >
			<esri:SceneView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="TargetOverlay" Renderer="{StaticResource MyRenderer}" />
			</esri:SceneView.GraphicsOverlays>
			<esri:Scene>
				<esri:Scene.Surface>
					<esri:ServiceElevationSource ServiceUri="http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" />
				</esri:Scene.Surface>
				<esri:ArcGISTiledMapServiceLayer
				ServiceUri="http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer" />
			</esri:Scene>
		</esri:SceneView>
		<Border Background="White"  BorderThickness="1" CornerRadius="5"
				HorizontalAlignment="Right" VerticalAlignment="Top"
				Margin="15" BorderBrush="Black" Padding="10">
			<StackPanel Orientation="Vertical" Height="300" Width="150">
				<TextBlock Text="Pitch (0-90):" />
				<Slider x:Name="sldPitch" Width="100" Minimum="0" Maximum="90" Value="45" 
						ValueChanged="sldInputs_ValueChanged" Margin="0,5,0,10" AutoToolTipPlacement="BottomRight"/>

				<TextBlock Text="Heading (0-360):"/>
				<Slider x:Name="sldHeading" Width="100" Minimum="0" Maximum="360" 
						ValueChanged="sldInputs_ValueChanged" Margin="0,5,0,10" AutoToolTipPlacement="BottomRight"/>

				<TextBlock Text="Distance (10-5000):"/>
				<Slider x:Name="sldDistance" Width="100" Minimum="10" Maximum="5000" Value="500" 
						ValueChanged="sldInputs_ValueChanged" Margin="0,5,0,10" AutoToolTipPlacement="BottomRight"/>

				<TextBlock Text="Speed (1-100):"/>
				<Slider x:Name="sldSpeed" Width="100" Minimum="1" Maximum="100" 
						Margin="0,5,0,10" AutoToolTipPlacement="BottomRight"/>

				<TextBlock Text="Refresh Interval (100-1000):"/>
				<Slider x:Name="sldRefresh" Width="100" Minimum="100" Maximum="1000" Value="1000" 
						ValueChanged="sldRefresh_ValueChanged" Margin="0,5,0,10" AutoToolTipPlacement="BottomRight"/>

				<ToggleButton Height="30" Width="100" Content="Start/Stop" 
							  Checked="FollowTargetChecked" Unchecked="FollowTargetUnchecked"/>
			</StackPanel>
		</Border>
	</Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Layers;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace ArcGISRuntime.Samples.Desktop
{
	/// <summary>
	/// Demonstrates how to follow a target in the SceneView
	/// </summary>
	/// <title>3D Follow Target</title>
	/// <category>Scene</category>
	/// <subcategory>Mapping</subcategory>
	public partial class FollowTarget : UserControl
	{
		private DispatcherTimer _timer;
		private MapPoint _point = new MapPoint(2.3522, 48.856, 1, SpatialReferences.Wgs84);

		public FollowTarget()
		{
			InitializeComponent();

			_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(sldRefresh.Value) };
			_timer.Tick += timerTick;

			MySceneView.GraphicsOverlays["TargetOverlay"].Graphics.Add(new Graphic(_point));
		}

		void timerTick(object sender, EventArgs e)
		{
			_point = new MapPoint(_point.X + sldSpeed.Value / 10000, _point.Y, _point.Z);
			MySceneView.GraphicsOverlays["TargetOverlay"].Graphics[0].Geometry = _point;
			FollowGraphic(_point, sldHeading.Value, sldPitch.Value, sldDistance.Value);
		}

		private void sldInputs_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			// Update the FollowGraphic method as the slider inputs are changed
			if (sldHeading != null && sldPitch != null && sldDistance != null)
				FollowGraphic(_point, sldHeading.Value, sldPitch.Value, sldDistance.Value);
		}

		private async void FollowGraphic(MapPoint point, double heading, double pitch, double distance)
		{
			try
			{
				// Create a new Camera with the specified point and distance values
				var cam = new Camera(new MapPoint(point.X, point.Y, point.Z + distance), 0, 0);

				// Set the camera to RotateAround the specified point with the user-specified values.
				// RotateAround returns a new Camera with changes centered at the specified location.
				cam = cam.RotateAround(point, heading, pitch);

				// Set the SceneView to center the view on the camera's perspective
				await MySceneView.SetViewAsync(cam, TimeSpan.FromMilliseconds(1), false);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Sample Error");
			}
		}

		private void sldRefresh_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			if (_timer != null)
				_timer.Interval = TimeSpan.FromMilliseconds(e.NewValue);
		}

		private void FollowTargetChecked(object sender, RoutedEventArgs e)
		{
			_timer.Start();
		}

		private void FollowTargetUnchecked(object sender, RoutedEventArgs e)
		{
			if (_timer.IsEnabled)
				_timer.Stop();
		}
	}
}
Feedback on this topic?