Select to view content in your preferred language

Geometry Service Attribute Retention

3009
7
Jump to solution
12-10-2013 10:56 AM
BrandonIves
Emerging Contributor
Hi,

I am trying to re-project a graphics layer and I want a map tip to pop up for the graphics. I am calling this asynchronous method:

// Call the Asynchronous Geometry.ProjectAsync Method. It will generate Graphics in the WKIS 102697 SpatialReference.
  geometryService.ProjectAsync(graphicsLayer, new ESRI.ArcGIS.Client.Geometry.SpatialReference(102697));

The graphics I get back are missing the attributes I had before the method call. Is there a way to retain the original graphic's attributes for use with the new graphic's maptips?
0 Kudos
1 Solution

Accepted Solutions
TerryGiles
Frequent Contributor
Try using the method overload that allows you to pass in the 3rd 'user token' parameter & pass the graphics layer as that object.  In the handler for your ProjectCompleted event cast that back to a layer and apply the projected geometry to the graphics.  Code below isn't tested & off the top of my head, but might help  -

       .... some other code above sets MyMap, GLayer is a graphics layer on MyMap and gets the URL for a geometry service....              if (MyMap.SpatialReference.WKID != 4326)             {                 GeometryService gserv = new GeometryService(Application.Current.Resources["GeometryURL"].ToString());                 gserv.ProjectCompleted += gserv_ProjectCompleted;                 gserv.ProjectAsync(GLayer.Graphics, MyMap.SpatialReference, GLayer);             }         }          void gserv_ProjectCompleted(object sender, GraphicsEventArgs e)         {             //update rss layer with graphics reprojected to match the map             GraphicsLayer GLayer = MyMap.Layers[(e.UserState as Layer).ID] as GraphicsLayer;             for (int i = 0; i < GLayer.Graphics.Count(); i++)             {                 GLayer.Graphics.Geometry = e.Results.Geometry;             }         } 


Might want to test and make sure the order is maintained by checking an attribute that would easily identify if it's the correct graphic (e.g. name = 'New York' is not showing up in Texas...)

View solution in original post

0 Kudos
7 Replies
TerryGiles
Frequent Contributor
Try using the method overload that allows you to pass in the 3rd 'user token' parameter & pass the graphics layer as that object.  In the handler for your ProjectCompleted event cast that back to a layer and apply the projected geometry to the graphics.  Code below isn't tested & off the top of my head, but might help  -

       .... some other code above sets MyMap, GLayer is a graphics layer on MyMap and gets the URL for a geometry service....              if (MyMap.SpatialReference.WKID != 4326)             {                 GeometryService gserv = new GeometryService(Application.Current.Resources["GeometryURL"].ToString());                 gserv.ProjectCompleted += gserv_ProjectCompleted;                 gserv.ProjectAsync(GLayer.Graphics, MyMap.SpatialReference, GLayer);             }         }          void gserv_ProjectCompleted(object sender, GraphicsEventArgs e)         {             //update rss layer with graphics reprojected to match the map             GraphicsLayer GLayer = MyMap.Layers[(e.UserState as Layer).ID] as GraphicsLayer;             for (int i = 0; i < GLayer.Graphics.Count(); i++)             {                 GLayer.Graphics.Geometry = e.Results.Geometry;             }         } 


Might want to test and make sure the order is maintained by checking an attribute that would easily identify if it's the correct graphic (e.g. name = 'New York' is not showing up in Texas...)
0 Kudos
BrandonIves
Emerging Contributor
Try using the method overload that allows you to pass in the 3rd 'user token' parameter & pass the graphics layer as that object. In the handler for your ProjectCompleted event cast that back to a layer and apply the projected geometry to the graphics. Code below isn't tested & off the top of my head, but might help -  

       .... some other code above sets MyMap, GLayer is a graphics layer on MyMap and gets the URL for a geometry service....

            if (MyMap.SpatialReference.WKID != 4326)
            {
                GeometryService gserv = new GeometryService(Application.Current.Resources["GeometryURL"].ToString());
                gserv.ProjectCompleted += gserv_ProjectCompleted;
                gserv.ProjectAsync(GLayer.Graphics, MyMap.SpatialReference, GLayer);
            }
        }

        void gserv_ProjectCompleted(object sender, GraphicsEventArgs e)
        {
            //update rss layer with graphics reprojected to match the map
            GraphicsLayer GLayer = MyMap.Layers[(e.UserState as Layer).ID] as GraphicsLayer;
            for (int i = 0; i < GLayer.Graphics.Count(); i++)
            {
                GLayer.Graphics.Geometry = e.Results.Geometry;
            }
        }



Might want to test and make sure the order is maintained by checking an attribute that would easily identify if it's the correct graphic (e.g. name = 'New York' is not showing up in Texas...)


Hey Terry,

Thanks for the reply. I am not 100% following your suggestion. Maybe if I provide more info and a couple code snippets it will help.

I have a queryTask that hits a view and grabs the most current position of a truck (Lat/Lon), the machine name, and user name. Because my data is in a State Plane coordinates I need to reproject the graphics.

private void QueryTask_ExecuteCompletedTruckGPS(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
{
FeatureSet featureSet = args.FeatureSet;
GraphicsLayer graphicsLayer = MyMap.Layers["TruckGPS"] as GraphicsLayer;
graphicsLayer.ClearGraphics();
if (featureSet != null && featureSet.Features.Count > 0)
{
foreach (ESRI.ArcGIS.Client.Graphic feature in featureSet.Features)
{
if ((feature.Attributes["LONGITUDE"] != null) && (feature.Attributes["LATITUDE"] != null))
{
var Machine_Name = feature.Attributes["MACHINE_NAME"].ToString();
var User_Name = feature.Attributes["USER_NAME"].ToString();
double lon = Convert.ToDouble(feature.Attributes["LONGITUDE"]);
double lat = Convert.ToDouble(feature.Attributes["LATITUDE"]);

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

feature.Symbol = LayoutRoot.Resources["TRUCK"] as ESRI.ArcGIS.Client.Symbols.Symbol;
graphicsLayer.Graphics.Add(feature);
}
}
{ (MyMap.Layers["TruckGPS"] as GraphicsLayer).Refresh(); };
}

// Call the Asynchronous Geometry.ProjectAsync Method. It will generate Graphics in the WKIS 102697 SpatialReference.
geometryService.ProjectAsync(graphicsLayer, new ESRI.ArcGIS.Client.Geometry.SpatialReference(102697));
}





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.

// Create a new GraphicsLayer for display in the WKID 102697 Spatial Reference.
ESRI.ArcGIS.Client.GraphicsLayer TruckGraphicsLayer_WKID_102697 = new ESRI.ArcGIS.Client.GraphicsLayer();
TruckGraphicsLayer_WKID_102697.ID = "TruckGraphicsLayer";

// Loop through each Graphic that was returned.
foreach (ESRI.ArcGIS.Client.Graphic myGraphic in e.Results)
{
// 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);

}
}



This code is working to create a new graphics layer and create the new map points. But I don't want to re-create the graphics I want to update the existing truck graphicsLayer coordinates.

When I plugged in your code and did some testing I tried typing in my url but I was getting null reference exceptions on this line:

GeometryService gserv = new GeometryService(Application.Current.Resources["GeometryURL"].ToString());

I understand the suggestion you gave just not the execution. Thanks for your help.
0 Kudos
TerryGiles
Frequent Contributor
Do you have the outSpatialReference on the Query the QueryTask is executing set to match your map?  That wy the results from the query task shouldn't need reprojected at all.

e.g.

QueryTask qt = new QueryTask(uriQuery);
            ESRI.ArcGIS.Client.Tasks.Query qry = new ESRI.ArcGIS.Client.Tasks.Query();
            qry.ReturnGeometry = true;
            qry.Where = strWhere;
            qry.OutSpatialReference = MyMap.SpatialReference;




Re: the error on the null reference - my code sets a URL as an Application level resource, try replacing it with a hard coded URL to your geometry service.
0 Kudos
BrandonIves
Emerging Contributor
Terry,

You are a genius. I got it working, thanks for your help.


For anyone else, here is my method call passing my graphics, the spatial reference, and the graphics layer:

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

And in my project completed event I have my graphics with the attributes:

void geometryService_ProjectCompleted(object sender, GraphicsEventArgs e)
        {
            //update rss layer with graphics reprojected to match the map
            GraphicsLayer GLayer = MyMap.Layers[(e.UserState as Layer).ID] as GraphicsLayer;
             .
             .
             .
             .
        }
0 Kudos
BrandonIves
Emerging Contributor
Do you have the outSpatialReference on the Query the QueryTask is executing set to match your map?  That wy the results from the query task shouldn't need reprojected at all.

e.g.

QueryTask qt = new QueryTask(uriQuery);
            ESRI.ArcGIS.Client.Tasks.Query qry = new ESRI.ArcGIS.Client.Tasks.Query();
            qry.ReturnGeometry = true;
            qry.Where = strWhere;
            qry.OutSpatialReference = MyMap.SpatialReference;




Re: the error on the null reference - my code sets a URL as an Application level resource, try replacing it with a hard coded URL to your geometry service.


I am not returning any geometry with my querytask. Would that matter?
0 Kudos
TerryGiles
Frequent Contributor
So you're just hitting a view in a DB not a feature class then?  Sorry I missed that part before.  Setting the output SR on the query will have no effect then, I believe that only works for features w/ geometry.  If you so can use the ProjectAsync(graphics, sr, graphicslayer) method or if you db supports a native geometry type (sql server & oracle definitely do) you could try this -

1). Add a column to you view as a geometry type based on the lat/long fields.  In Sql Server you can use something like this -

SELECT     TOP (100) PERCENT State + '-' + RIGHT('00000' + CONVERT(VARCHAR, FacilityID), 4) AS ID, FacilityName, FacilityType, lat, long, Address1, Address2, City, State, Zip, geography::STGeomFromText('POINT(' + STR(long, 25, 10) + ' ' + STR(lat, 25, 10) + ')', 4326) AS geog
FROM         dbo.uvFacilityAddress
WHERE     (isActive = 1)


2). Add that view as a query layer (assuming you're using v10 or higher) to a map and publish as a map service.
3). You can then point your query task at that service/layer & set the outputSpatialReference on the query to get the results back in state plane.

Another thing you might need look at if this is running often, is to turn the DisableClientCaching to true on the layer.  The default is false which means the client will cache - if the truck has moved but the user hasn't panned/zoomed the querytask results might not show up correctly.
0 Kudos
BrandonIves
Emerging Contributor
Terry,

Good advice and thanks again for the help. People like you make the GIS community.
0 Kudos