Drive Time Analysis
DriveTimeAnalysis_button.cs
// Copyright 2011 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions at <your ArcGIS Explorer install location>/DeveloperKit/userestrictions.txt.
// 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;

using DriveTimeAnalysisCS.DriveTime;

namespace DriveTimeAnalysisCS
{
  public class DriveTimeAnalysis_Button : ESRI.ArcGISExplorer.Application.Button
  {
    private string sDriveTimes = "3 5"; //Drive times to be used with the sample

    public override void OnClick()
    {
        //Get the active map display
        MapDisplay mapDisp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;

        //Get a point from the screen to start the analysis from
        ESRI.ArcGISExplorer.Geometry.Point startPt = mapDisp.TrackPoint();
        if (startPt == null) return;

        //Call the routine for generating the drive time polygons
        GPFeatureRecordSetLayer gpOutput = CreateBufferPolys(startPt);
        if (gpOutput == null)
        {
            MessageBox.Show("No results returned from geoprocessing service!  Try location inside United States.");
            return;
        }

        //Add a folder to the contents to hold the results
        Folder fold = new Folder("Drive Time Analysis");
        mapDisp.Map.ChildItems.Add(fold);
        DriveTimeAnalysisCS.DriveTime.RecordSet recs = gpOutput.RecordSet;

        //Figure out which field contains the shape (though it's probably always index 1)
        int shapefld = 0;
        for (int i = 0; i < recs.Fields.FieldArray.Length; i++)
        {
            Field f = recs.Fields.FieldArray[i];
            System.Diagnostics.Debug.WriteLine(f.Name);
            if (f.Name == gpOutput.ShapeFieldName)
            {
                shapefld = i;
                break;
            }
        }

        //Process the results
        for (int j = 0; j < recs.Records.Length; j++)
        {
            Record record = recs.Records[j];
            ESRI.ArcGISExplorer.Geometry.Polygon newPoly =
                SoapConverter.FromSoap<ESRI.ArcGISExplorer.Geometry.Polygon>(record.Values[shapefld]) as ESRI.ArcGISExplorer.Geometry.Polygon;
            newPoly.CoordinateSystem = new CoordinateSystem(4326);  //set coordinate system to WGS 1984 (4326)
            ESRI.ArcGISExplorer.Mapping.Symbol sym = null;
            switch (j)
            {
                case 0:
                    sym = ESRI.ArcGISExplorer.Mapping.Symbol.Fill.Solid.Red;
                    break;
                case 1:
                    sym = ESRI.ArcGISExplorer.Mapping.Symbol.Fill.Solid.Yellow;
                    break;
                default:
                    sym = ESRI.ArcGISExplorer.Mapping.Symbol.Fill.Solid.Green;
                    break;
            }
            Note res = new Note(record.Values[4].ToString() + " to " + record.Values[5].ToString() + " minute zone", newPoly, sym);
            fold.ChildItems.Add(res);
        }
    }

    private GPFeatureRecordSetLayer CreateBufferPolys(ESRI.ArcGISExplorer.Geometry.Point pt)
    {
      //Specify the progress bar
      ProgressHelper prog = new ProgressHelper("Running ...", "Please wait:", "Drive Time polygons being calculated ...");
      prog.Show();

      //Call a Geoprocessing service to calculate the drive time polygons
      DriveTime.ESRI_DriveTime_US_GPServer driveMe = new DriveTime.ESRI_DriveTime_US_GPServer();
      driveMe.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/services/Network/ESRI_DriveTime_US/GPServer";
      GPToolInfo toolInfo = driveMe.GetToolInfo("CreateDriveTimePolygonsDisks");
        
     CoordinateSystem projected = CoordinateSystem.GeographicCoordinateSystems.World.WGS1984;
     ESRI.ArcGISExplorer.Geometry.Point outputPoint = GeometryOperations.Project(pt as ESRI.ArcGISExplorer.Geometry.Geometry, projected)as ESRI.ArcGISExplorer.Geometry.Point;

      //Create input parameters for gp task
      GPParameterInfo[] inParams = toolInfo.ParameterInfo;
      PointN newPT = new PointN();
      newPT.X = outputPoint.X;
      newPT.Y = outputPoint.Y;
      GeographicCoordinateSystem projsr = new GeographicCoordinateSystem();
      projsr.WKID = 4326;  //set the coordinate system to WGS 1984 (4326)
      projsr.WKIDSpecified = true;
      newPT.SpatialReference = projsr;

      GPFeatureRecordSetLayer frsl = (GPFeatureRecordSetLayer)inParams[0].Value;
      Record newRec = new Record();
      Fields flds = frsl.RecordSet.Fields;
      object[] o = new object[flds.FieldArray.Length];
      for (int i = 0; i < flds.FieldArray.Length; i++)
      {
          if (flds.FieldArray[i].Name == frsl.ShapeFieldName)
          {
              o[i] = newPT;
          }
          else if (flds.FieldArray[i].Name == frsl.OIDFieldName)
          {
              o[i] = 1;
          }
          else
          {
              esriFieldType ftype = flds.FieldArray[i].Type;
              if (ftype == esriFieldType.esriFieldTypeString)
              {
                  o[i] = string.Empty;
              }
              else
              {
                  o[i] = 1;
              }
          }
      }
      newRec.Values = o;
      Record[] newRecs = new Record[1];
      newRecs[0] = newRec;
      frsl.RecordSet.Records = newRecs;

      GPString times = (GPString)inParams[1].Value;
      times.Value = sDriveTimes;

      GPValue[] inValues = new GPValue[] { frsl, times };

      //The DriveTime Analysis geoprocessing service in this sample is setup as a synchronous
      //service, hence the use of the Execute statement below.  If you are accessing geoprocessing
      //services that are setup as asynchronous services, then you will need to use the SubmitJob
      //statement instead of Execute.  SubmitJob would then be followed up with code to check the 
      //status of the job (using GetJobStatus), and finally a call (GetJobResults) to retrieve
      //the results when the service has completed execution.
      //
      //Execute the task synchronously, since this geoprocessing service is setup on the server as
      //a synchronous service
      GPFeatureRecordSetLayer gpOutput = null;
      try
      {
        GPResult result = driveMe.Execute(toolInfo.Name, inValues, null, null);
        gpOutput = (GPFeatureRecordSetLayer)result.Values[0];
      }
      catch (Exception ex) 
      {
        MessageBox.Show("Execution of service failed with this message: " + ex.Message);
      }

      //Close progress helper
      prog.Hide();
      prog = null;

      //Send back the results 
      return gpOutput;
    }
  }
}