/GPX.FireMap.Workflow/GPX.FireMap.Workflow/CalculateNearestFeature.cs
C# | 316 lines | 202 code | 75 blank | 39 comment | 19 complexity | a1c63f7ec260999c7cac09e852319ba1 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Activities;
- using System.ComponentModel;
- using GPX.Firemap.Workflow.Activities;
- using Geocortex.Logging;
- using Geocortex.Workflow.Activities;
- using ESRI.ArcGIS.Client.Tasks;
- using ESRI.ArcGIS.Client;
- using System.Net;
- using System.IO;
- using ESRI.ArcGIS.Client.Geometry;
- using Newtonsoft.Json.Linq;
-
- namespace GPX.Firemap.Workflow.Activities.Server
- {
-
- [Description("Calculates the nearest feature to a coordinate")]
- [WorkflowDesigner(
- DisplayName = "Calculate nearest feature",
- ToolboxCategory = "Firemap Server Activities")]
- public sealed class CalculateNearestFeature : CodeActivity
- {
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Nearest Feature Definitions")]
- [DisplayName("Nearest Feature Definitions")]
- public InArgument<string> NearestFeatureDefinitions { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Intersect Feature Definitions")]
- [DisplayName("Intersect Feature Definitions")]
- public InArgument<string> IntersectFeatureDefinitions { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Projection Definitions")]
- [DisplayName("Projection Definitions")]
- public InArgument<string> ProjectionDefinitions { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Location")]
- [DisplayName("Location")]
- public InArgument<MapPoint> Location { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Root Service URL")]
- [DisplayName("Root Service URL")]
- public InArgument<string> RootServiceURL { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Nearest Feature Service URL")]
- [DisplayName("Nearest Feature Service URL")]
- public InArgument<string> NearestFeatureServiceURL { get; set; }
-
- [CategoryAttribute("In Arguments")]
- [Description(@"Geometry Service URL")]
- [DisplayName("Geometry Service URL")]
- public InArgument<string> GeometryServiceURL { get; set; }
-
-
- [CategoryAttribute("Out Arguments")]
- [Description(@"Nearest Features")]
- [DisplayName("Nearest Features")]
- public OutArgument<string[]> NearestFeatures { get; set; }
-
- /// <summary>
- /// When implemented in a derived class, performs the execution of the activity.
- /// </summary>
- /// <param name="context">The execution context under which the activity executes.</param>
- protected override void Execute(CodeActivityContext context)
- {
-
- try
- {
- Logger.SystemInfo(this.DisplayName + " beginning activity execute ");
-
- List<string> nearestResults = new List<string>();
-
- // Obtain and validate the runtime values
- string rootServiceUrl = context.GetValue(this.RootServiceURL);
- if (string.IsNullOrEmpty(rootServiceUrl))
- Logger.SystemError("The root service url is not defined");
-
- string nearestFeatureServiceUrl = context.GetValue(this.NearestFeatureServiceURL);
- if (string.IsNullOrEmpty(nearestFeatureServiceUrl))
- Logger.SystemError("The nearest feature service url is not defined");
-
- string geometryServiceUrl = context.GetValue(this.GeometryServiceURL);
- if (string.IsNullOrEmpty(geometryServiceUrl))
- Logger.SystemError("The geometry service url is not defined");
-
- MapPoint location = context.GetValue(this.Location);
- if (location==null)
- Logger.SystemError("The input location is not defined");
-
- SpatialReference sr = location.SpatialReference;
- if (sr == null)
- Logger.SystemError("The location input location does not have a spatial reference");
-
- string nfdsAsJson = context.GetValue(this.NearestFeatureDefinitions);
- string ifdsAsJson = context.GetValue(this.IntersectFeatureDefinitions);
- string pdsAsJson = context.GetValue(this.ProjectionDefinitions);
-
- if (!string.IsNullOrEmpty(nfdsAsJson))
- {
- List<NearestFeatureDefinition> nfds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<NearestFeatureDefinition>>(nfdsAsJson);
- //process the nearest
- ProcessNearestFeatureRequests(nearestResults, location, nfds, rootServiceUrl, nearestFeatureServiceUrl);
- }
-
- if (!string.IsNullOrEmpty(ifdsAsJson))
- {
- List<IntersectFeatureDefinition> ifds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<IntersectFeatureDefinition>>(ifdsAsJson);
- //process the interesting features
- ProcessIntersectingFeatureRequests(nearestResults, location, ifds, rootServiceUrl);
- }
-
- if (!string.IsNullOrEmpty(pdsAsJson))
- {
- List<ProjectionDefinition> pds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectionDefinition>>(pdsAsJson);
-
- ProcessProjectionRequests(nearestResults, location, pds, geometryServiceUrl);
-
- }
-
-
-
- context.SetValue(NearestFeatures, nearestResults.ToArray());
-
- Logger.SystemInfo(this.DisplayName + " ending activity execute ");
- }
- catch (Exception ex)
- {
- Logger.SystemError(ex.Message);
-
- }
-
- }
-
- /// <summary>
- /// Processes the projection requests.
- /// </summary>
- /// <param name="nearestResults">The nearest results.</param>
- /// <param name="location">The location.</param>
- /// <param name="pds">The PDS.</param>
- /// <param name="geometryServiceUrl">The geometry service URL.</param>
- private void ProcessProjectionRequests(List<string> nearestResults, MapPoint location, List<ProjectionDefinition> pds, string geometryServiceUrl)
- {
- try
- {
- foreach (ProjectionDefinition pd in pds)
- {
-
- //request the intersecting feature
- JObject projectedCoordinates;
- AGSServerSupport.CallArcGISServer(AGSServerSupport.CreateProjectGeometryRequest(location, location.SpatialReference.WKID.ToString(), pd.Wkid.ToString(), geometryServiceUrl), out projectedCoordinates);
-
- if (projectedCoordinates != null)
- {
- JArray coordinates = (JArray)projectedCoordinates["geometries"];
-
- foreach (var coordinate in coordinates)
- {
-
- double x = (double)coordinate["x"];
- double y = (double)coordinate["y"];
-
-
- StringBuilder resultBuilder = new StringBuilder();
- resultBuilder.Append(pd.DisplayName + " ");
- resultBuilder.Append("X:" + Math.Round(x, 2).ToString() + " ");
- resultBuilder.Append("Y:" + Math.Round(y, 2).ToString());
-
-
- nearestResults.Add(resultBuilder.ToString());
- }
- }
- }
- }
- catch (Exception ex)
- {
-
- Logger.SystemError(ex.Message);
- }
- }
-
-
- /// <summary>
- /// Processes the intersecting feature requests.
- /// </summary>
- /// <param name="nearestResults">The nearest results.</param>
- /// <param name="location">The location.</param>
- /// <param name="ifds">The intersecting feature definitions.</param>
- /// <param name="rootUrl">The root URL.</param>
- private void ProcessIntersectingFeatureRequests(List<string> nearestResults, MapPoint location, List<IntersectFeatureDefinition> ifds, string rootUrl)
- {
- try
- {
- foreach (IntersectFeatureDefinition ifd in ifds)
- {
- string lyrId = ifd.LyrId.ToString();
-
- //request the intersecting feature
- JObject IntersectingFeature;
- AGSServerSupport.CallArcGISServer(AGSServerSupport.CreateQueryRequest(location, rootUrl, ifd, lyrId), out IntersectingFeature);
-
- if (IntersectingFeature != null)
- {
-
- JArray features = (JArray)IntersectingFeature["features"];
-
- foreach (var feature in features)
- {
- JObject attributes = (JObject)feature["attributes"];
-
-
- string attribute = (string)attributes[ifd.Fields];
-
-
- StringBuilder resultBuilder = new StringBuilder();
- resultBuilder.Append(ifd.Name + " ");
- if (!string.IsNullOrEmpty(attribute))
- resultBuilder.Append(attribute + " ");
-
- nearestResults.Add(resultBuilder.ToString());
- }
-
- }
-
-
- }
- }
- catch (Exception ex)
- {
-
- Logger.SystemError(ex.Message);
- }
- }
-
-
- /// <summary>
- /// Processes the nearest feature requests.
- /// </summary>
- /// <param name="nearestResults">The nearest results.</param>
- /// <param name="location">The location.</param>
- /// <param name="nfds">The nearest feature definitions.</param>
- /// <param name="rootUrl">The root URL.</param>
- /// <param name="nearestFeatureUrl">The nearest feature URL.</param>
- private void ProcessNearestFeatureRequests(List<string> nearestResults, MapPoint location, List<NearestFeatureDefinition> nfds, string rootUrl, string nearestFeatureUrl)
- {
- try
- {
- foreach (NearestFeatureDefinition nfd in nfds)
- {
- string lyrId = nfd.LyrId.ToString();
-
- //request the nearest feature id
- JObject NearestFeatureId;
- AGSServerSupport.CallArcGISServer(AGSServerSupport.CreateNearestFeatureIdRequest(location, lyrId, nearestFeatureUrl), out NearestFeatureId);
-
- //double? distance;
- //NearestFeatureId.TryGetAsDouble("Distance", out distance);
-
- //long? id;
- //NearestFeatureId.TryGetAsLong("NearestFeatureId", out id);
-
- double distance = (double)NearestFeatureId["Distance"];
- int id = (int)NearestFeatureId["NearestFeatureId"];
-
- //send second request for feature itself
- JObject response;
-
- string finalUrl = string.Format(rootUrl + "{0}/{1}?f=json", lyrId, id.ToString());
- AGSServerSupport.CallArcGISServer(finalUrl, out response);
-
- //validate the response - because the Nearest Feature REST endpoint works directly on the feature class it will not honour any
- //definition queries set on the layer in the map service therefore check to see whethe the response inclues an error;
- JObject error = (JObject)response["error"];
- if (error != null)
- {
- Logger.SystemInfo("The following request " + finalUrl + "returned an error");
- response = null;
- }
-
-
- if (response != null)
- {
-
-
- JObject feature = (JObject)response["feature"];
-
- JObject attributes = (JObject)feature["attributes"];
-
- string attribute = (string)attributes[nfd.Fields];
-
- StringBuilder sb = new StringBuilder();
- sb.Append(nfd.Name + " ");
- if (!string.IsNullOrEmpty(attribute))
- sb.Append(attribute + " ");
- sb.Append("Distance: " + distance.ToString());
-
- nearestResults.Add(sb.ToString());
- }
-
- }
- }
- catch (Exception ex)
- {
- Logger.SystemError(ex.Message);
- }
- }
-
- }
- }