Select to view content in your preferred language

Lat/Long to XY conversion with Geometry Service

5338
8
11-26-2013 12:24 PM
BrandonIves
Emerging Contributor
Hi,

I am attempting to make a simple map that will allow users to see a truck's GPS location on top of a tiled map service. I am having difficulty getting the graphic symbol to overlap my tiled service because the spatial systems do not match.

Is there a good example or could someone help me conversion through a geometry service? Is a geometry service even the correct method to use for plotting my graphics?

Here is my code so far.

Xaml:

<UserControl x:Class="TruckGPS_Test.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
    xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client">
<Grid x:Name="LayoutRoot" Background="White">
  
 
  <Grid.Resources>
    <esri:SimpleMarkerSymbol x:Key="RedMarkerSymbol" Color="Red" Size="12" Style="Circle" />
   <esri:SimpleMarkerSymbol x:Key="YellowMarkerSymbol" Color="Yellow" Size="25" Style="Circle" />
   <esriSymbols:PictureMarkerSymbol x:Name="TRUCK" Source="images/bucket-truck-box.png" />
  </Grid.Resources>


  <esri:Map x:Name="MyMap" WrapAround="True" Margin="0,0,-325,-506" MouseMove="MyMap_MouseMove">
   <!--<esri:ArcGISTiledMapServiceLayer ID="MyLayer"
    Url="http://gisaprd/ArcGIS/rest/services/BaseMap_ArcReader_Cached/MapServer" />-->
   <!--<esri:ArcGISTiledMapServiceLayer ID="MyLayer"
    Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />-->
            <esri:ArcGISTiledMapServiceLayer ID="Aerials" Url="http://gisaprd/ArcGIS/rest/services/AerialCoordinateTest/MapServer" Visible="False"  />
   <esri:ArcGISDynamicMapServiceLayer Url="http://gisaprd/ArcGIS/rest/services/BaseMapCool__WebViewer/MapServer" />

   <esri:GraphicsLayer ID="TruckGPS" >

    <esri:GraphicsLayer.MapTip>
     <Grid Background="#FFD65555" >
      <Border BorderBrush="#FFFF0000" BorderThickness="1" CornerRadius="5" />
      <StackPanel Orientation="Vertical" >
       <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding [USER_NAME]}" FontWeight="Bold" Foreground="White"  HorizontalAlignment="Left"/>
       </StackPanel>
       <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding [SYSTIME]}" FontWeight="Bold" Foreground="White"  HorizontalAlignment="Left"/>
       </StackPanel>
      </StackPanel>
     </Grid>
    </esri:GraphicsLayer.MapTip>
   </esri:GraphicsLayer>

  </esri:Map>

  <Grid MinWidth="300" HorizontalAlignment="Right" Background="White" VerticalAlignment="Top" Margin="0,15,15,0" >
   <StackPanel Margin="5">
    <TextBlock x:Name="ScreenCoordsTextBlock"
     HorizontalAlignment="Left" VerticalAlignment="Center" Text="Screen Coords: "
         TextWrapping="Wrap" />
    <TextBlock x:Name="MapCoordsTextBlock"
     HorizontalAlignment="Left" VerticalAlignment="Center" Text="Map Coords: "
         TextWrapping="Wrap" />
   </StackPanel>
  </Grid>


</Grid>
</UserControl>


C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Symbols;
using System.Runtime.Serialization;
using ESRI.ArcGIS.Client.Tasks;
using System.Windows.Threading;
using ESRI.ArcGIS.Client.Bing;


namespace TruckGPS_Test
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
             //AddMarkerGraphics();

            QueryTask queryTaskTruckGPS = new QueryTask("http://gisaprd/ArcGIS/rest/services/TruckGPS/MapServer/8");
            queryTaskTruckGPS.ExecuteCompleted += QueryTask_ExecuteCompletedTruckGPS;
            ESRI.ArcGIS.Client.Tasks.Query queryTruckGPS = new ESRI.ArcGIS.Client.Tasks.Query();
            queryTruckGPS.OutFields.Add("*");
            queryTruckGPS.ReturnGeometry = false;
            queryTruckGPS.Where = "1=1";
            queryTaskTruckGPS.ExecuteAsync(queryTruckGPS, "initial");

            //This timer updates the outage feature count after a 30 second wait
            System.Windows.Threading.DispatcherTimer myDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
            myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 10, 0);
            myDispatcherTimer.Tick += new EventHandler(Each_Tick);
            myDispatcherTimer.Start();

        }
       
        public void Each_Tick(object o, EventArgs sender)
        {
            QueryTask queryTaskTruckGPS = new QueryTask("http://gisaprd/ArcGIS/rest/services/TruckGPS/MapServer/8");
            queryTaskTruckGPS.ExecuteCompleted += QueryTask_ExecuteCompletedTruckGPS;
            ESRI.ArcGIS.Client.Tasks.Query queryTruckGPS = new ESRI.ArcGIS.Client.Tasks.Query();
            queryTruckGPS.OutFields.Add("*");
            queryTruckGPS.ReturnGeometry = false;
            queryTruckGPS.Where = "1=1";
            queryTaskTruckGPS.ExecuteAsync(queryTruckGPS, "initial");

        }

        private void QueryTask_ExecuteCompletedTruckGPS(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
        {
            //If Counter isn't working check the web service, make sure the table is added to the map service
                          
            FeatureSet featureSet = args.FeatureSet;
            GraphicsLayer graphicsLayer = MyMap.Layers["TruckGPS"] as GraphicsLayer;
            graphicsLayer.ClearGraphics();
            if (featureSet != null && featureSet.Features.Count > 0)
            {

                ////Check the system time and subtract the time amount wanted from the last gps systime read for movement or idle truck
                //System.DateTime dTime = DateTime.Now;
                //// tSpan is 0 days, 0 hours, 0 minutes, and 0 seconds.
                //System.TimeSpan tSpan = new System.TimeSpan(0, 1, 0, 0);
                //System.DateTime result = dTime - tSpan;
              
              
                foreach (ESRI.ArcGIS.Client.Graphic feature in featureSet.Features)
                {
                                       
                    if ((feature.Attributes["LONGITUDE"] != null) && (feature.Attributes["LATITUDE"] != null) )
                        //&& (feature.Attributes["S"])
                    {

                        var Machine_Name = feature.Attributes["MACHINE_NAME"].ToString();
                        var User_Name = feature.Attributes["USER_NAME"].ToString();
                        double x = Convert.ToDouble(feature.Attributes["LONGITUDE"]);
                        double y =Convert.ToDouble(feature.Attributes["LATITUDE"]);

                        feature.Geometry = new MapPoint(x, y);
                        //if (User_Name == "CU656")
                        //{
                            feature.Symbol = LayoutRoot.Resources["TRUCK"] as ESRI.ArcGIS.Client.Symbols.Symbol;
                            graphicsLayer.Graphics.Add(feature);
                        //}
                        //else
                        //{
                        //    feature.Symbol = LayoutRoot.Resources["RedMarkerSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol;
                        //    graphicsLayer.Graphics.Add(feature);
                        //}
                    }
                }
                { (MyMap.Layers["TruckGPS"] as GraphicsLayer).Refresh(); };
            }
            else
            {
                graphicsLayer.ClearGraphics();
                //MessageBox.Show("No features returned from query");
            }
        }
      
    }

}
0 Kudos
8 Replies
DenisT
by
Deactivated User
Is a geometry service even the correct method to use for plotting my graphics?

Looks like you are converting between 4326 and 3857 (102100).
No need to use geometry service for that, it would be much more efficient to use ESRI.ArcGIS.Client.Projection.WebMercator.
Also consider adding timestamp to your data to get rid of "1=1" queries (or maybe it would be better to use a kind of Duplex Services to notify clients, it depends).
Also there is a Tracking server for that kind of tasks.
0 Kudos
BrandonIves
Emerging Contributor
Looks like you are converting between 4326 and 3857 (102100).
No need to use geometry service for that, it would be much more efficient to use ESRI.ArcGIS.Client.Projection.WebMercator.
Also consider adding timestamp to your data to get rid of "1=1" queries (or maybe it would be better to use a kind of Duplex Services to notify clients, it depends).
Also there is a Tracking server for that kind of tasks.



TDenis, Thanks for the reply. I tried your suggestion and I am getting a result when I use the "Mercator.FromGeographic" method but it is still not within my tiled service. Is there a more specific coordinate system I need to explicitly declare?

My Lat/Long value: 37.1223133333333,-93.27893
Mercator.FromGeographic converted value: X=-10382795.4374339, Y=4469266.40579955, WKID=102100
Mercator.ToGeographic converted value: X=-0.000837860806483038, Y=0.000334317600035687, WKID=4326

Neither of these coordinates put my graphics in the correct location. It should be closer to something like this: X=1424565.77, Y=501970.98. I am trying to learn more about coordinate systems, conversions between systems, etc. Any thoughts on what I can try next?
0 Kudos
DenisT
by
Deactivated User
http://gisaprd/ArcGIS/rest/services/AerialCoordinateTest/MapServer
What spatial reference this map service uses? It is not 102100?
0 Kudos
DenisT
by
Deactivated User
If it`s not, then one more question: does the" rel="nofollow" target="_blank">http://gisaprd/ArcGIS/rest/services/TruckGPS/MapServer/8]the map service return geometry, not just attributes?
If yes, then you could just set out" rel="nofollow" target="_blank">http://resources.arcgis.com/en/help/silverlight-api/apiref/ESRI.... spatial reference for your queries.
If it doesn`t return geometry and you can`t make it return geometry (using XY" rel="nofollow" target="_blank">http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//00... event layers, for example) then you need to use Geometry Service indeed.
There are few samples in the API documentation.
http://resources.arcgis.com/en/help/silverlight-api/apiref/ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Tas...
http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#Project

There was a nice class for auto reprojection, but it looks like it`s not available now.
http://blogs2.esri.com/esri/arcgis/2011/02/13/auto-reprojecting-graphics-layers/
0 Kudos
BrandonIves
Emerging Contributor
http://gisaprd/ArcGIS/rest/services/AerialCoordinateTest/MapServer
What spatial reference this map service uses? It is not 102100?


The spatial reference is: 102697 for the tiled service.
0 Kudos
BrandonIves
Emerging Contributor
If it`s not, then one more question: does the map service return geometry, not just attributes?
If yes, then you could just set out spatial reference for your queries.
If it doesn`t return geometry and you can`t make it return geometry (using XY event layers, for example) then you need to use Geometry Service indeed.
There are few samples in the API documentation.
http://resources.arcgis.com/en/help/silverlight-api/apiref/ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Tas...
http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#Project

There was a nice class for auto reprojection, but it looks like it`s not available now.
http://blogs2.esri.com/esri/arcgis/2011/02/13/auto-reprojecting-graphics-layers/


The TruckGPS map service does not return geometry. Just attributes. Thanks for the help I will look into the geometry service more.
0 Kudos
BrandonIves
Emerging Contributor
If it`s not, then one more question: does the map service return geometry, not just attributes? 
If yes, then you could just set out spatial reference for your queries. 
If it doesn`t return geometry and you can`t make it return geometry (using XY event layers, for example) then you need to use Geometry Service indeed. 
There are few samples in the API documentation. 
http://resources.arcgis.com/en/help/silverlight-api/apiref/ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Tas...
http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#Project

There was a nice class for auto reprojection, but it looks like it`s not available now. 
http://blogs2.esri.com/esri/arcgis/2011/02/13/auto-reprojecting-graphics-layers/


TDenis,

Thanks for the links to those examples. I have recreated the example in the API samples successfully. As I have been stepping through the sample code I notice this line of code:

MapPoint inputMapPoint = new MapPoint(x, y, new SpatialReference(4326));



Could I not just add my map points to the map specifying my spatial reference? Like this:

feature.Geometry = new MapPoint(lat, lon, new SpatialReference(102697));
0 Kudos
BrandonIves
Emerging Contributor
TDenis, 

Thanks for the links to those examples. I have recreated the example in the API samples successfully. As I have been stepping through the sample code I notice this line of code: 

MapPoint inputMapPoint = new MapPoint(x, y, new SpatialReference(  4326)); 



Could I not just add my map points to the map specifying my spatial reference? Like this: 

feature.Geometry = new MapPoint(lat, lon, new SpatialReference  (102697));



I found that I can call this method:

geometryService.ProjectAsync(graphicsLayer, new ESRI.ArcGIS.Client.Geometry.SpatialReference(102697));

and then place the graphics correctly on my map. However I can't see the attributes that were with the graphicsLayer when I called the method. Is there a way to carry over the attributes for maptips, etc.?

void geometryService_ProjectCompleted(object sender, GraphicsEventArgs e)
{

// Executes when the GeometryService.ProjectAsync has completed. The e.Results parameters has the new Graphics
// Projected in the WKID 102697 SpatialReference.

// Loop through each Graphic that was returned.
foreach (ESRI.ArcGIS.Client.Graphic myGraphic in e.Results)
{
// Create a new GraphicsLayer for display in the WKID 4326 Spatial Reference.
ESRI.ArcGIS.Client.GraphicsLayer TruckGraphicsLayer_WKID_102697 = new ESRI.ArcGIS.Client.GraphicsLayer();
TruckGraphicsLayer_WKID_102697.ID = "TruckGraphicsLayer";

// Create a new MapPoint.
ESRI.ArcGIS.Client.Geometry.MapPoint myMapPoint_WKID_102697 = (ESRI.ArcGIS.Client.Geometry.MapPoint)myGraphic.Geometry;



// Create a new Graphic, set its Geometry and Symbol and add it to the GraphicsLayer.
ESRI.ArcGIS.Client.Graphic myGraphic_WKID_102697 = new ESRI.ArcGIS.Client.Graphic();
myGraphic_WKID_102697.Geometry = myMapPoint_WKID_102697;
myGraphic_WKID_102697.Symbol = LayoutRoot.Resources["TRUCK"] as ESRI.ArcGIS.Client.Symbols.Symbol;
TruckGraphicsLayer_WKID_102697.Graphics.Add(myGraphic_WKID_102697);

// Add the GraphicsLayer to the Map Control
MyMap.Layers.Add(TruckGraphicsLayer_WKID_102697);

}
}
0 Kudos