ArcGIS_Routing_CSharp\Directions.aspx.cs
// 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. // using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Xml; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Location; using ESRI.ArcGIS.Server; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.NetworkAnalyst; using ESRI.ArcGIS.Server.Web.NetworkAnalyst; using System.Collections.Specialized; using ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer; namespace RouteFinder { /// <summary> /// Summary description for Directions. /// </summary> public partial class Directions : System.Web.UI.Page, RouteFinder.IBaseRouteFinderPage { ServerObjectStateModifier serverObjectStateModifier = null; public void Page_PreInit(object sender, EventArgs e) { serverObjectStateModifier = new ServerObjectStateModifier(); } protected void Page_Init(object sender, EventArgs e) { Map1.Load += new EventHandler(Map1_Load); } void Map1_Load(object sender, EventArgs e) { if (Page.IsPostBack) { if (!MapResourceManager1.Initialized) MapResourceManager1.Initialize(); } } protected void Page_PreRender(object sender, System.EventArgs e) { if (!Page.IsPostBack) { #region Get XY and Address parameters string fromAddress = Convert.ToString(Session["FromAddress"]); string toAddress = Convert.ToString(Session["ToAddress"]); double fromX = Convert.ToDouble(Page.Request.Params["FromX"]); double fromY = Convert.ToDouble(Page.Request.Params["FromY"]); double toX = Convert.ToDouble(Page.Request.Params["ToX"]); double toY = Convert.ToDouble(Page.Request.Params["ToY"]); #endregion #region Get Route between Addresses if (fromX == 0.0 && toX == 0.0) return; NetworkAnalystRouteResult result = SolveRoute(fromX, fromY, toX, toY, fromAddress, toAddress); DisplayDirections(result, fromAddress, toAddress); #endregion } } /// <summary> /// Solves route between two geocoded locations /// </summary> public NetworkAnalystRouteResult SolveRoute(double fromX, double fromY, double toX, double toY, string fromAddress, string toAddress) { #region Get a reference to the Map if (!MapResourceManager1.Initialized) MapResourceManager1.Initialize(); MapResourceLocal mapResourceLocal = (MapResourceLocal)MapResourceManager1.GetResource(0); IServerContext serverContext = mapResourceLocal.ServerContextInfo.ServerContext; IMapServerObjects mapServerObjects = (IMapServerObjects)mapResourceLocal.MapServer; IMap map = mapServerObjects.get_Map(mapResourceLocal.DataFrame); #endregion #region Get first Route Layer INALayer2 naLayer = null; int layerID = -1; UID uidINALayer = (UID) serverContext.CreateObject("esriSystem.UID"); uidINALayer.Value = "{667B776B-5905-4450-9C94-18B214ECE8FB}"; IEnumLayer elayers = map.get_Layers(uidINALayer, true); ILayer layer = elayers.Next(); int i = 0; while (layer != null) { if ((layer is INALayer) && (layer.Name == "Route")) { naLayer = layer as INALayer2; layerID = i; break; } ++i; layer = elayers.Next(); } if (layerID == -1) throw new Exception("No Route layers in map"); Session["RouteLayerID"] = layerID; #endregion #region Get a copy of the original NAContext to restore at the end of the request // Only save the original context once string originalContextSerialized = Session["OriginalNAContext"] as string; if (originalContextSerialized == null) { INAContext originalNAContext = naLayer.CopyContext(); originalContextSerialized = serverContext.SaveObject(originalNAContext); Session["OriginalNAContext"] = originalContextSerialized; } INAContext naContext = naLayer.Context; #endregion #region Add From and To Points //delete any old stops INAClass naClass = naContext.NAClasses.get_ItemByName("Stops") as INAClass; naClass.DeleteAllRows(); //add from point IPoint point = serverContext.CreateObject("esriGeometry.Point") as IPoint; point.PutCoords(fromX, fromY); NetworkAnalystUtility.AddLocation(naContext, "Stops", point, fromAddress, 100); //add to point point.PutCoords(toX, toY); NetworkAnalystUtility.AddLocation(naContext, "Stops", point, toAddress, 100); // Message all of the network analysis agents that the analysis context has changed ((INAContextEdit)naContext).ContextChanged(); #endregion #region Solve and Display Route // Solve the route and generated the resulting directions IGPMessages gpMessages = serverContext.CreateObject("esriGeodatabase.GPMessages") as IGPMessages; INASolver solver = naContext.Solver; solver.Solve(naContext, gpMessages, null); NetworkAnalystRouteResult result = NetworkAnalystUtility.GetDirections(naContext, "Routes", serverContext); //Draw the map centered on route Map1.Extent = result.RouteExtent; #endregion #region Store Extents in Session for Use in Zooming to Full Extent or to Each Step Session["PathExtent"] = result.RouteExtent; Session["DirectionExtents"] = result.StepExtents; #endregion #region Store coords for ReverseDirections Session["FromX"] = fromX; Session["FromY"] = fromY; Session["ToX"] = toX; Session["ToY"] = toY; Session["FromAddress"] = fromAddress; Session["ToAddress"] = toAddress; #endregion Session["ModifiedNAContextApplied"] = true; return result; } /// <summary> /// Populates datagrid with directions and javascript array with summary /// </summary> public void DisplayDirections(NetworkAnalystRouteResult result, string fromAdd, string toAdd) { #region Write Summary System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("<b>Starting from:</b> " + fromAdd + "<br>"); sb.Append("<b>Arriving at:</b> " + toAdd + "<br>"); sb.Append("<b>Distance: </b> " + result.Summary["Length"] + "<br>"); sb.Append("<b>Time: </b> " + result.Summary["Time"] + "<br>"); DirectionsSummary.InnerHtml = sb.ToString(); Session["Summary"] = DirectionsSummary.InnerHtml; #endregion #region Populate data grid DataGrid1.DataSource = null; //Get data table and remove unnecessary columns DataTable dataTable = result.Directions; dataTable.Columns.Remove("Summary"); //this column displays the same information found in the columns that follow it dataTable.Columns.Remove("Type"); #region Create Links in Table for Zooming In to Each Step #region Merge 1st and 2nd rows dataTable.Rows[1]["Directions"] = String.Format("{0}. {1}", dataTable.Rows[0]["Directions"], dataTable.Rows[1]["Directions"]); dataTable.Rows[dataTable.Rows.Count - 2]["Directions"] = String.Format("{0}. {1}", dataTable.Rows[dataTable.Rows.Count - 2]["Directions"], dataTable.Rows[dataTable.Rows.Count - 1]["Directions"]); dataTable.Rows.RemoveAt(dataTable.Rows.Count - 1); dataTable.Rows.RemoveAt(0); #endregion #region Create Links DataRow dataRow; for (int i = 0; i < dataTable.Rows.Count; i++) { dataRow = dataTable.Rows[i]; string step = Convert.ToString((i + 1)); //add 1 because 1st row was merged into the second //Link Directions dataRow["Directions"] = "<a href=\"javascript:ZoomTo(" + step + ")\">" + dataRow["Directions"] + "</a>"; //Link Step dataRow["Step"] = "<b><a href=\"javascript:ZoomTo(" + step + ")\">" + step + "</a></b>"; } #endregion // bind new datatable to datagrid DataGrid1.DataSource = dataTable; DataGrid1.DataBind(); #endregion // save to session for print page Session["Directions_DataTable"] = dataTable; return; #endregion } protected void MapResourceManager1_ResourcesDispose(object sender, EventArgs e) { if ((bool)Session["ModifiedNAContextApplied"]) { ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapresourceitem = MapResourceManager1.ResourceItems.Find("MapResourceItem0"); if (mapresourceitem != null) { serverObjectStateModifier.ApplyOriginalNAContext(mapresourceitem); Session["ModifiedNAContextApplied"] = false; } } } protected void MapResourceManager1_ResourceInit(object sender, EventArgs e) { ESRI.ArcGIS.ADF.Web.UI.WebControls.ResourceInitEventArgs riea = e as ESRI.ArcGIS.ADF.Web.UI.WebControls.ResourceInitEventArgs; if (riea.GISResourceItem.Name == "MapResourceItem0") CustomResourceInit(riea.GISResourceItem); } protected void CustomResourceInit(ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItem resource) { object modifiedNAContextApplied = System.Web.HttpContext.Current.Session["ModifiedNAContextApplied"]; if (modifiedNAContextApplied == null || !(bool)modifiedNAContextApplied) { serverObjectStateModifier.ApplySessionNAContext(resource); System.Web.HttpContext.Current.Session["ModifiedNAContextApplied"] = true; } } #region Error Functions protected void Directions_Error(object sender, EventArgs e) { Exception exception = Server.GetLastError(); Server.ClearError(); callErrorPage("Page_Error", exception); } /// <summary> /// Displays the error page. /// </summary> private void callErrorPage(string errorMessage, Exception exception) { Session["ErrorMessage"] = errorMessage; Session["Error"] = exception; Page.Response.Redirect("ErrorPage.aspx", true); } #endregion } }