AO就像是一个万能的神,有了它,ArcGIS才能没有做不到,只有想不到。当你为了某一个功能抓耳挠腮,苦思冥想,废寝忘食的时候,其实解决之路就在AO开发帮助的某个角落痴痴地看着你。AO是ArcGIS产品系列的底层,ArcGIS Desktop、ArcGIS Engine、ArcGIS Server,理论上讲,Desktop里面能够实现的功能,通过ArcGIS Engine和ArcGIS Server也可以实现。
// Get the server context for the analysis layer IServerContext serverContext = MapResourceLocal.ServerContextInfo.ServerContext; IMap map = Utility.GetCartoIMap(MapInstance, "图层"); IGPMessages gpMessages = serverContext.CreateObject("esriGeodatabase.GPMessages") as IGPMessages; INALayer2 routeNALayer = Utility.GetNALayer("Route", map); INAContext routeNAContext = routeNALayer.CopyContext(); INAContextEdit routeNAContextEdit = routeNAContext as INAContextEdit; routeNAContextEdit.Bind(routeNALayer.Context.NetworkDataset, gpMessages); // Set route solver properties INARouteSolver naRouteSolver = routeNAContext.Solver as INARouteSolver; naRouteSolver.FindBestSequence = resequenceStops; naRouteSolver.PreserveFirstStop = false; naRouteSolver.PreserveLastStop = false; // Remove any existing stops IFeatureClass stopsFClass = routeNAContext.NAClasses.get_ItemByName("Stops") as IFeatureClass; INAClass stopsNAClass = stopsFClass as INAClass; stopsNAClass.DeleteAllRows(); // Get locator and initialize variables INALocator2 naLocator = routeNAContext.Locator as INALocator2; INALocation naLocation = serverContext.CreateObject("esriNetworkAnalyst.NALocation") as INALocation; IFeature stopFeature; INALocationObject stopNALocation; IRowSubtypes stopFeatureRowSubtypes; IPoint outPoint = serverContext.CreateObject("esriGeometry.Point") as IPoint; double distanceFromPoint = 0; int sequenceNumber = 0; int sequenceIndex = stopsFClass.FindField("SEQUENCE"); int statusIndex = stopsFClass.FindField("STATUS"); int nameIndex = stopsFClass.FindField("NAME"); // Load the stops ElementGraphicsLayer stopsLayer = PointsGraphicsLayer; foreach (DataRow dr in stopsLayer.Rows) { sequenceNumber++; // Get point ESRI.ArcGIS.ADF.Web.Geometry.Point adfPoint = (ESRI.ArcGIS.ADF.Web.Geometry.Point)stopsLayer.GeometryFromRow(dr); PointN pointN = ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.FromAdfPoint(adfPoint); IPoint point = ESRI.ArcGIS.ADF.ArcGISServer.Converter.ValueObjectToComObject(pointN, serverContext) as IPoint; // Create Stop stopFeature = stopsFClass.CreateFeature(); stopFeatureRowSubtypes = stopFeature as IRowSubtypes; stopNALocation = stopFeature as INALocationObject; stopFeatureRowSubtypes.InitDefaultValues(); // Get Location naLocator.QueryLocationByPoint(point, ref naLocation, ref outPoint, ref distanceFromPoint); // Set Stop properties stopFeature.Shape = point; stopFeature.set_Value(sequenceIndex, sequenceNumber); stopFeature.set_Value(nameIndex, string.Format("{0}, {1}", Math.Round(adfPoint.X, 4), Math.Round(adfPoint.Y, 4))); if (naLocation.IsLocated) { stopNALocation.NALocation = naLocation; stopFeature.set_Value(statusIndex, esriNAObjectStatus.esriNAObjectStatusOK); } else { stopFeature.set_Value(statusIndex, esriNAObjectStatus.esriNAObjectStatusNotLocated); } // Store the Stop stopFeature.Store(); } // Message all of the network analysis agents that the analysis context has changed routeNAContextEdit.ContextChanged(); gpMessages.Clear(); INASolver naSolver = routeNAContext.Solver; //Solve route bool partialResults = naSolver.Solve(routeNAContext, gpMessages, null); // report errors if (partialResults || gpMessages.Count > 0) { StringBuilder sErrors = new StringBuilder(); for (int i = 0; i < gpMessages.Count; i++) sErrors.AppendLine(gpMessages.GetMessage(i).Description); Results = sErrors.ToString(); }
AO的实现过程看上去还挺复杂,但是流程还是很简要的,获取Network Analysis Layer、NAContext->设置分析条件->导入stops->计算->处理结果。结果的处理我们单独看看代码。
//Get route results from “Routes” NAClass IFeatureClass featureClass = naContext.NAClasses.get_ItemByName("Routes") as IFeatureClass; IFeatureCursor featureCursor = featureClass.Search(queryFilter, false); IFeature feature = featureCursor.NextFeature(); while (feature != null) { IPolyline comPolyline = feature.Shape as IPolyline; feature = featureCursor.NextFeature(); }
// Get the directions agent INAStreetDirectionsAgent2 naStreetDirectionsAgent = (INAStreetDirectionsAgent2)routeNAContext.Agents.get_ItemByName("StreetDirectionsAgent"); naStreetDirectionsAgent.Execute(routeSet, null); INAStreetDirections naStreetDirections = null; INAStreetDirection2 naStreetDirection = null; INAStreetDirectionsContainer naStreetDirectionsContainer = naStreetDirectionsAgent.DirectionsContainer; for (int routeIndex = 0; routeIndex < naStreetDirectionsContainer.DirectionsCount; routeIndex++) { naStreetDirections = naStreetDirectionsContainer.get_Directions(routeIndex); }
这几段代码是在ArcGIS Server for .NET环境下实现路径分析的功能,Server下的AO编程和Engine、Desktop有点类似,最大的区别在于创建对象的时候,Engine、Desktop创建新对象用new就可以,但是Server AO的开发必须首先获得IServerContext,然后通过CreateObject的方式。网络分析其它功能,最近设施查询、服务区域分析、OD代价矩阵、车辆路径规划、L-A的实现基本的流程和路径分析类似。