ArcGISServer开发系列(七)--物流配送2008-12-3115:58byFlyingis,5230visits,作者:FlyingisArcGISServer开发系列的文章至今已经一年多了,虽然文章只有短短六篇,也比较基础,但值得高兴的是帮助了不少第一次接触ArcGISServer的开发者,现在不少都已经完成一两个项目了,相信收获不小,有时间可以和大家一起分享经验。今天开始,我们将继续这个系列教程,争取覆盖ADF开发常用功能,以帮助更多的人轻松入门ADF开发。目标:实现简易的物流配送(VRP)准备工作:1.重新复习《ArcGISServer开发系列(六)--自定义Tasks》2.准备数据%ArcGISInstallDir%\DeveloperKit\SamplesNET\Server\data\SanFranciscoNetwork3.发布NATasks.mxd地图服务,添加NetworkAnalyst功能服务4.MapResourceManager中添加一个ArcGISServerLocal类型服务在这个应用中,多车配送的功能封装为一个自定义的Task,然后生成一个dll添加到ASP.Net工具箱中,由WebMappingApplication的TaskManager调用,更改自定义Task的TaskResultsContainer为模板应用中的TaskResults1控件。WebMappingApplication大家已经非常熟悉,现在的重点就在如何利用ArcGISServer实现VRP功能。VRP全称vehicleroutingproblem,属于NP难问题,基本没有统一的方法来解决所有的VRP问题,只能根据具体的情况采用最合适的算法,咱们下面就利用ArcGISServer模拟一个简单的应用场景,实现多车物流的配送计算。自定义Task,需要构建Task的UI和业务逻辑,UI构建通过重写方法CreateChildControls完成,咱们最终实现的效果:相应的代码比较容易看懂,结合上面实现的UI效果图和代码注释就能明白每部分代码所完成的功能,实现代码:protectedoverridevoidCreateChildControls(){Controls.Clear();base.CreateChildControls();#regionCreatetopleveltableSystem.Web.UI.WebControls.Tabletable=newSystem.Web.UI.WebControls.Table();table.Width=System.Web.UI.WebControls.Unit.Pixel(240);Controls.Add(table);TableRowtr;TableCelltd;#endregion#regionOrdersLabeltr=newTableRow();td=newTableCell();td.Text=Selectorderstoservice;tr.Cells.Add(td);table.Rows.Add(tr);#endregion#regionCreateandpopulateordersListbox_oids=newListint();_ordersCheckBoxList=newCheckBoxList();_ordersCheckBoxList.ID=OrdersCheckBoxList;_ordersCheckBoxList.Width=System.Web.UI.WebControls.Unit.Point(200);IServerContextserverContext=MapResourceLocal.ServerContextInfo.ServerContext;IMapvrpMap=Utility.GetCartoIMap(MapInstance,NA_MapResourceItem);IFeatureLayerordersInputFLayer=Utility.GetFeatureLayer(Stores,vrpMap);IFeatureClassordersInputFClass=ordersInputFLayer.FeatureClass;intnameIndex=ordersInputFClass.FindField(Name);IFeatureCursorordersInputFCursor=ordersInputFClass.Search(null,false);IFeatureorderFeature=ordersInputFCursor.NextFeature();while(orderFeature!=null){ListItemli=newListItem(orderFeature.get_Value(nameIndex).ToString());li.Selected=true;_ordersCheckBoxList.Items.Add(li);_oids.Add(orderFeature.OID);orderFeature=ordersInputFCursor.NextFeature();}#endregion#regionOrdersPaneltr=newTableRow();td=newTableCell();PanelordersPanel=newPanel();ordersPanel.Height=200;ordersPanel.Width=240;ordersPanel.BorderColor=System.Drawing.Color.Black;ordersPanel.BorderStyle=BorderStyle.Inset;ordersPanel.BorderWidth=1;ordersPanel.ScrollBars=ScrollBars.Vertical;ordersPanel.Controls.Add(_ordersCheckBoxList);td.Controls.Add(ordersPanel);tr.Cells.Add(td);table.Rows.Add(tr);#endregion#regionGetDirectionsButtontr=newTableRow();tr.Attributes.Add(align,right);td=newTableCell();td.ColumnSpan=2;HtmlInputButtonbutton=newHtmlInputButton();button.Value=GetDirections;button.ID=execute;td.Controls.Add(button);tr.Cells.Add(td);table.Rows.Add(tr);#endregion#regionOnClickEventforexecutingtaskstringargument=string.Format('selectedIndexes='+getCheckedItemIndexes('{0}','{1}'),_ordersCheckBoxList.ClientID,_ordersCheckBoxList.Items.Count);stringonClick=string.Format(executeTask({0},\{1}\);,argument,CallbackFunctionString);button.Attributes.Add(onclick,onClick);#endregion//AccessthegraphicslayersoitiscreatedandshownintheTOCElementGraphicsLayerpointsGraphicsLayer=PointsGraphicsLayer;}CreateChildControls用于构建VRPTaskUI,除了界面要素之外,还需要从源数据中读取商店信息,如读取商店名称显示在界面上,当VRPTask中的商店被勾选上时,车辆将为该商店送货。商店供货信息存储在数据源中单独的一个图层中stores.shp,包含商店所需的货物数量和预计提供服务的时间。VRPTaskUI完成之后,接下来要设计VRP的业务逻辑,ArcGIS9.3NetworkExtension提供了一个基本的VRP解决方案,因此我们在发布NATasks服务的时候需要勾选NetworkAnalyst功能,通过ServerContext去远程调用AO方法。第一步,获取VRP分析图层。IServerContextserverContext=MapResourceLocal.ServerContextInfo.ServerContext;IMapvrpMap=Utility.GetCartoIMap(MapInstance,NA_MapResourceItem);IGPMessagesgpMessages=serverContext.CreateObject(esriGeodatabase.GPMessages)asIGPMessages;INALayer2vrpNALayer=Utility.GetNALayer(VehicleRoutingProblem,vrpMap);INAContextvrpNAContext=vrpNALayer.CopyContext();INAContextEditvrpNAContextEdit=vrpNAContextasINAContextEdit;vrpNAContextEdit.Bind(vrpNALayer.Context.NetworkDataset,gpMessages);第二步,获取配送中心信息、商店信息、车辆信息和司机午餐时间。IFeatureLayerdepotsInputFLayer=Utility.GetFeatureLayer(DistributionCenters,vrpMap);IFeatureClassdepotsInputFClass=depotsInputFLayer.FeatureClass;IFeatureCursordepotsInputFCursor=depotsInputFClass.Search(null,false);LoadAnalysisClass(serverContext,vrpNAContext,Depots,depotsInputFCursorasICursor);//LoadOrdersIFeatureLayerordersInputFLayer=Utility.GetFeatureLayer(Stores,vrpMap);IFeatureClassordersInputFClass=ordersInputFLayer.FeatureClass;IFeatureCursorordersInputFCursor=ordersInputFClass.GetFeatures(oids,true);LoadAnalysisClass(serverContext,vrpNAContext,Orders,ordersInputFCursorasICursor);//LoadtheRoutesITableroutesInputTable=Utility.GetStandaloneTable(Vehicles,vrpMap).Table;ICursorroutesInputCursor=routesInputTable.Search(null,true);LoadAnalysisClass(serverContext,vrpNAContext,Routes,routesInputCursorasICursor);//LoadtheBreaksITablebreaksInputTable=Utility.GetStandaloneTabl