天津政府应急系统之GIS一张图(arcgis api for flex)讲解(十一)路径导航模块

config.xml文件的配置如下:

         <widget label="路径导航" icon="assets/images/lujingdaohang.png"
            config="widgets/eDriections/eDirectionsWidget.xml" url="widgets/eDriections/eTabDirectionsWidget.swf" />

源代码目录如下:

界面效果:

大概的思路如下:1.文本框输入开始点以及结束点,获取两个点坐标;2.直接在地图上点击两个点,获取两个点坐标;其实两个的最终目的是一样的,都是为了获取两个点坐标。其中用到了地理编码服务,用于根据地名来获取坐标以及根据坐标来获取地名信息。

用到了arcgis api的最短路径分析接口,routeParams以及routeTask,routeParams用来设置一些关于路径分析的参数,routeTask是用来执行路径分析方法的,具体的要看看api的介绍才行。备注:该功能模块的核心前提是要发布网络分析服务,这个在我的博客其他文章有写的

总的来说,获取两个点坐标,保存在一个stops数组里面,然后设置routeParams的属性,routeParams对象有个属性是stops,除了stops之外,还有attributeParameterValues、directionsLengthUnits、returnDirectionsreturnDirections、returnRoutes、returnStops等等;最好是执行routeTask.solve(routeParams);

eDirectionsWidget.xml:配置一些路径分析的信息

<?xml version="1.0" ?>
<configuration>
    <url>http://localhost:6080/ArcGIS/rest/services/gzRoad/NAServer/路径</url>
    <useproxy>false</useproxy> 
<!--     <locatorurl>http://172.16.6.67/ArcGIS/rest/services/guangzhou_loc/GeocodeServer</locatorurl> -->
    <locatorurl>http://localhost:6080/ArcGIS/rest/services/ns_loc_Composite/GeocodeServer</locatorurl>
    <routeoptions />
    <fromTx>广州市南沙区信访局</fromTx>
    <toTx>小虎一桥</toTx>
</configuration>

<!-- See Directions widget tag reference at http://links.esri.com/directionswidget -->

eTabDirectionsWidget.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--
///////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////
-->
<viewer:BaseWidget xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:s="library://ns.adobe.com/flex/spark"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   xmlns:viewer="com.esri.viewer.*"
                   xmlns:esri="http://www.esri.com/2008/ags"
                   xmlns:RichTabNavigator="com.RichTabNavigator.*"
                   initialize="basewidget_initializeHandler(event)"
                   widgetConfigLoaded="basewidget_widgetConfigLoaded()">
    <viewer:states>         
        <s:State name="textInput"/>
        <s:State name="resultsList"/>
    </viewer:states>
    
    <viewer:transitions>
        <s:Transition autoReverse="true" toState="*">
            <s:Fade id="fade"/>
        </s:Transition>
    </viewer:transitions>
    <fx:Script>
        <![CDATA[ 
            import com.esri.ags.FeatureSet;
            import com.esri.ags.Graphic;
            import com.esri.ags.SpatialReference;
            import com.esri.ags.events.DrawEvent;
            import com.esri.ags.events.LocatorEvent;
            import com.esri.ags.events.RouteEvent;
            import com.esri.ags.geometry.Extent;
            import com.esri.ags.geometry.Geometry;
            import com.esri.ags.geometry.MapPoint;
            import com.esri.ags.geometry.Polyline;
            import com.esri.ags.portal.PopUpRenderer;
            import com.esri.ags.portal.supportClasses.PopUpInfo;
            import com.esri.ags.symbols.TextSymbol;
            import com.esri.ags.tasks.supportClasses.AddressCandidate;
            import com.esri.ags.tasks.supportClasses.AddressToLocationsParameters;
            import com.esri.ags.tasks.supportClasses.DirectionsFeatureSet;
            import com.esri.ags.tasks.supportClasses.NAOutputLine;
            import com.esri.ags.tasks.supportClasses.RouteResult;
            
            import mx.collections.ArrayCollection;
            import mx.containers.Panel;
            import mx.containers.TitleWindow;
            import mx.controls.Alert;
            import mx.controls.Text;
            import mx.controls.TextArea;
            import mx.core.IVisualElement;
            import mx.core.UIComponent;
            import mx.events.CloseEvent;
            import mx.events.EffectEvent;
            import mx.events.FlexEvent;
            import mx.events.ListEvent;
            import mx.events.ModuleEvent;
            import mx.events.ResizeEvent;
            import mx.formatters.*;
            import mx.managers.PopUpManager;
            import mx.rpc.AsyncResponder;
            import mx.rpc.Fault;
            import mx.rpc.events.FaultEvent;
            
            import spark.components.NavigatorContent;
            import spark.events.IndexChangeEvent;
            import spark.primitives.Path;
            
            private const ICON_URL:String = "assets/images/";
            private var textsearchLabel:String="路径分析";
            private var resultsLabel:String="分析结果";
            [Bindable]
            private var fromText:String;
            [Bindable]
            private var toText:String;
            protected function basewidget_initializeHandler(event:FlexEvent):void
            {
                if (isPartOfPanel) // if widget is part of "left", "right" or "bottom" panel
                {
                    this.percentWidth = this.percentHeight = 100;
                    wTemplate.percentWidth = wTemplate.percentHeight = 100;
                }
                else
                {
                    wTemplate.height = map.height - map.height / 100 - Number(this.top) - Number(this.bottom);
                    wTemplate.width = 440;
                }
            }
            
            private function basewidget_widgetConfigLoaded():void
            {
                // hide map infowindow if any               
                map.infoWindow.hide();
                if (configXML)
                {
                    sUrl = configXML.url[0];
                    var useProxyForDirections:Boolean = configXML.useproxy[0] && configXML.useproxy == "true";
                    locatorURL = configXML.locatorurl[0];
                    fromText=configXML.fromTx[0];
                    toText=configXML.toTx[0];
                }
                wTemplate.addTitlebarButton(ICON_URL + "i_searchtext.png", textsearchLabel, showStateTextSearch);
                wTemplate.addTitlebarButton(ICON_URL + "i_table.png", resultsLabel, showStateResults);
                fade.targets = [  textInput, resultsList ];
                wTemplate.visible = true;
            }
            
            private function showStateTextSearch():void
            {
                this.currentState = "textInput";
                wTemplate.selectedTitlebarButtonIndex = 0;
            }
            
            private function showStateResults():void
            {
                this.currentState = "resultsList";
                wTemplate.selectedTitlebarButtonIndex = 1;
            }
            
            
            //////////////////////////////////////////////////////
            //路径分析功能部分代码
            [Bindable]
            private var sUrl:String;//="http://172.16.6.67/ArcGIS/rest/services/gzRoad/NAServer/路径";    
            [Bindable]
            private var locatorURL:String;
            private var stopType:String;
            private var fromGraphic:Graphic;
            private var toGraphic:Graphic;
            [Bindable]
            private var startTime:Date=new Date();
            [Bindable]
            private var endTime:Date;
            
            [Bindable]
            private var travelTypeList:ArrayCollection = new ArrayCollection( [   
                { label: "步行", data: 0 },     
                { label: "驾车", data: 1  },
                {label: "自行车", data: 2  }]); 
            
            [Bindable]
            private var attributeParameters:Array = new Array({ 
                "attributeName" : "Time",
                "parameterName" : "TravelType",
                "value" :1});
            
            [Bindable]
            private var impedanceAttributes:ArrayCollection = new ArrayCollection( [   
                { label: "最短距离", data: "Distance" },     
                { label: "最少时间", data: "Time"  }]);
            
            [Bindable]
            private var restrictionAttributes:Array=new Array("walking");
            
            private const NL:String = "
";
            
            [Bindable]private var stopsFS:FeatureSet = new FeatureSet();
            
            private var directionResult:directionResultGroup;
            private var segmentGraphic:Graphic;
            
            private var tabImpactIndex:int = 0;
            private function getDirections():void
            {
                //hanhh
                /* directionResult =new directionResultGroup();
                tabImpact.addChild(directionResult);
                tabImpactIndex = tabImpact.numChildren-1;
                tabImpact.selectedIndex = tabImpactIndex; */
                //add by lizeping ,2014/02/13
                startTime=startDateField.selectedDate;
                startTime.hours=hoursStepper.value;
                startTime.minutes=minutesStepper.value;
                
                stopsFS.features = [];
                segmentGraphic = null;
                //hanhh
//                directionResult.map = map;
                //                map.defaultGraphicsLayer.clear();
                var fromParameters:AddressToLocationsParameters = new AddressToLocationsParameters();
                fromParameters.distance=0.005;
                fromParameters.address = { SingleLine: fromTx.text, CountryCode: 'US' };
                fromParameters.outFields = [ "Loc_name" ];
                locator.addressToLocations(fromParameters, new AsyncResponder(
                    myResultFunction, myFaultFunction, "From"));
                
                var toParameters:AddressToLocationsParameters = new AddressToLocationsParameters();
                toParameters.address = { SingleLine: toTx.text, CountryCode: 'US' };
                toParameters.distance=0.005;
                toParameters.outFields = [ "Loc_name" ];
                locator.addressToLocations(toParameters, new AsyncResponder(
                    myResultFunction, myFaultFunction, "To"));
                
                function myResultFunction(result:Array, token:String = null):void
                {
                    solveRoute(result, token);
                }
                function myFaultFunction(error:Fault, token:Object = null):void
                {
                    Alert.show(error.faultString, "Locator Error");
                }
            }
            
            private function solveRoute(addressCandidates:Array, type:String):void
            {
                if (addressCandidates.length == 0)
                {
                    Alert.show(type + " address not found.", "Missing Result");
                    return;
                }
                
                var stop:AddressCandidate = addressCandidates[0];
                
                if (type == "From")
                {
                    map.defaultGraphicsLayer.remove(fromGraphic);
                    fromGraphic = new Graphic(stop.location, fromSymbol, { address: stop.address, score: stop.score });
                    map.defaultGraphicsLayer.add(fromGraphic);
                    stopsFS.features[0] = fromGraphic;
                    
                }
                else if (type == "To")
                {
                    map.defaultGraphicsLayer.remove(toGraphic);
                    toGraphic = new Graphic(stop.location, toSymbol, { address: stop.address, score: stop.score });
                    map.defaultGraphicsLayer.add(toGraphic);
                    stopsFS.features[1] = toGraphic;
                    
                }
                
                if (stopsFS.features[0] && stopsFS.features[1])
                {
                    routeParams.attributeParameterValues=attributeParameters;
                    
                    routeTask.solve(routeParams);
                }
            }
            
            private function solveCompleteHandler(event:RouteEvent):void
            {
                directionResult =new directionResultGroup();
                tabImpact.addChild(directionResult);
                tabImpactIndex = tabImpact.numChildren-1;
                tabImpact.selectedIndex = tabImpactIndex;
                directionResult.map = map;
                showStateResults();
                var routeResult:RouteResult = event.routeSolveResult.routeResults[0];
                directionResult.directionsFS = routeResult.directions;
                //add at 2014-01-08
                
                //var route:Graphic=routeResult.route;
                directionResult.route=routeResult.route;
                directionResult.graphicLayer.add(fromGraphic);//图标传给动态生成的tab页
                directionResult.graphicLayer.add(toGraphic);//图标传给动态生成的tab页
                map.defaultGraphicsLayer.clear();
                directionResult.showResult();
            }
            
            
            private function faultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.faultString + "

" + event.fault.faultDetail, "Routing Error " + event.fault.faultCode);
            }
            
            
            private function formatDistance(dist:Number, units:String):String
            {
                var result:String = "";
                
                var d:Number = Math.round(dist * 100) / 100;
                
                if (d != 0)
                {
                    result = d + " " + units;
                }
                
                return result;
            }
            
            private function formatTime(time:Number):String
            {
                var result:String;
                
                var hr:Number = Math.floor(time / 60);
                var min:Number = Math.round(time % 60);
                
                if (hr < 1 && min < 1)
                {
                    result = "";
                }
                else if (hr < 1 && min < 2)
                {
                    result = min + " 分钟";
                }
                else if (hr < 1)
                {
                    result = min + " 分钟";
                }
                else
                {
                    result = hr + " 小时 " + min + " 分钟";
                }
                
                return result;
            }
            
            protected function cmbTravelType_changeHandler(event:ListEvent):void
            {
                // TODO Auto-generated method stub                
                attributeParameters = new Array({ 
                    "attributeName" : "Time",
                    "parameterName" : "TravelType",
                    "value" : cmbTravelType.selectedItem.data});
                if(cmbTravelType.selectedItem.data==0){
                    trace("use walking");
                    restrictionAttributes=new Array("walking");
                }else{
                    restrictionAttributes=new Array("driving");
                }
                routeParams.attributeParameterValues=attributeParameters;
            }
            
            protected function cmbImpedance_changeHandler(event:ListEvent):void
            {
                routeParams.impedanceAttribute=cmbImpedance.selectedItem.data;
                
            }
            
            protected function btnFrom_clickHandler(event:MouseEvent):void
            {
                // TODO Auto-generated method stub
                stopType="From";
                myDrawTool.markerSymbol=fromSymbol;
                myDrawTool.activate(DrawTool.MAPPOINT);
                
            }
            
            protected function btnTo_clickHandler(event:MouseEvent):void
            {
                // TODO Auto-generated method stub
                stopType="To";
                myDrawTool.markerSymbol=toSymbol;
                myDrawTool.activate(DrawTool.MAPPOINT);
            }
            
            protected function drawTool_drawEndHandler(event:DrawEvent):void
            {
                // reset after finished drawing a feature
                myDrawTool.deactivate();
                //查询地址信息
                if(stopType=="From"){
                    map.defaultGraphicsLayer.remove(fromGraphic);
                    fromGraphic=event.graphic;
                }else{
                    map.defaultGraphicsLayer.remove(toGraphic);
                    toGraphic=event.graphic;
                }
                var point:MapPoint=event.graphic.geometry as MapPoint;
                locator.locationToAddress(point, 1000);
                
            }
            
            private function onLocationToAddressComplete(event:LocatorEvent):void
            {
                
                var candidate:AddressCandidate = event.addressCandidate;                
                
                if (candidate && candidate.address && candidate.address.Address)
                {
                    var address:Object = candidate.address;                 
                    
                    if(stopType=="From"){
                        fromTx.text=address.Address;    
                    }
                    else{
                        toTx.text=address.Address;
                    }                             
                }
                else
                {
                    Alert.show("This location does not have a known street address.");
                }
            }
            
            private function onFault(event:FaultEvent):void
            {
                if (event.fault.name == 'Error'
                    && event.fault.faultCode == '500'
                    && event.fault.faultString == 'An unexpected error occurred processing the request.')
                {
                    Alert.show("Did you click too far from a road?

" + event.fault.faultDetail, "No result");
                }
                else
                {
                    Alert.show(event.fault.faultString + "

" + event.fault.faultDetail, "Reverse Geocoding Error " + event.fault.faultCode);
                }
            }
            
            private function widgetClosedHandler(event:Event):void
            {
                map.defaultGraphicsLayer.clear();
            }            
            
        ]]>
    </fx:Script>
    
    
    
    <fx:Declarations>
        <!-- Symbol for all point shapes -->
        
        <esri:DrawTool id="myDrawTool" drawEnd="drawTool_drawEndHandler(event)"
                       graphicsLayer="{map.defaultGraphicsLayer}" map="{map}"/>
        <!--http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer-->
        <esri:Locator id="locator" fault="onFault(event)"
                      locationToAddressComplete="onLocationToAddressComplete(event)"
                      outSpatialReference="{map.spatialReference}" showBusyCursor="true"
                      url="{encodeURI(locatorURL)}"/>
        
        <esri:RouteTask id="routeTask" concurrency="last" fault="faultHandler(event)"
                        requestTimeout="30" showBusyCursor="true"
                        solveComplete="solveCompleteHandler(event)" url="{encodeURI(sUrl)}"/>
        
        <esri:RouteParameters id="routeParams" attributeParameterValues="{attributeParameters}"
                              directionsLengthUnits="esriMeters"
                              outputGeometryPrecisionUnits="esriDecimalDegrees"
                              outSpatialReference="{map.spatialReference}"
                              restrictionAttributes="{restrictionAttributes}"
                              returnDirections="true" returnRoutes="true" returnStops="true"
                              startTime="{startTime}" stops="{stopsFS}"/>
        
        <!--<esri:SimpleMarkerSymbol id="fromSymbol" color="0x00FF00"/>-->
        <!--<esri:SimpleMarkerSymbol id="toSymbol" color="0xFF0000"/>-->
        <esri:PictureMarkerSymbol id="fromSymbol" source="assets/skins/directions/green-A.png"/>
        <esri:PictureMarkerSymbol id="toSymbol" source="assets/skins/directions/blue-B.png"/>
        <esri:SimpleLineSymbol id="routeSymbol" width="4" alpha="0.5" color="0x0000FF"/>
        <esri:SimpleLineSymbol id="segmentSymbol" width="8" alpha="0.5" color="0xFF0000"/>
        <esri:SimpleLineSymbol id="tempSymbol" width="8" alpha="0" color="0xFF0000"/>
        <s:DateTimeFormatter id="dtFormatter" dateTimePattern="MM/dd/yy, HH:mm"/>
    </fx:Declarations>
    <viewer:WidgetTemplate id="wTemplate" closed="widgetClosedHandler(event)" width="340" height="520">
        
        <s:Group id="textInput" visible="false" width="100%" height="100%"
                 visible.textInput="true">            
            <s:Form width="100%">
                <!-- 更改垂直间距 -->
                <s:layout>
                    <s:FormLayout gap="-14"/>
                </s:layout>
                <s:FormItem label="起点:">
                    <s:HGroup width="100%">
                        <s:TextInput id="fromTx" text="{fromText}" width="90%"/>             
                        <s:Image id="addFrom" buttonMode="true" click="btnFrom_clickHandler(event)" height="30"
                                 source="@Embed('assets/skins/directions/add-stop.png')"
                                 toolTip="{resourceManager.getString('ESRIMessages', 'directionsAddDestinationByMapClickTooltip')}"
                                 useHandCursor="true"/>        
                    </s:HGroup>
                </s:FormItem>
                <s:FormItem label="终点:">
                    <s:HGroup width="100%">
                        <s:TextInput id="toTx" text="{toText}" width="90%"/>
                        <s:Image id="addTo" buttonMode="true" click="btnTo_clickHandler(event)" height="30"
                                 source="@Embed('assets/skins/directions/add-stop.png')"
                                 toolTip="{resourceManager.getString('ESRIMessages', 'directionsAddDestinationByMapClickTooltip')}"
                                 useHandCursor="true"/>
                    </s:HGroup>
                </s:FormItem>
                <s:FormItem label="出行方式:">
                    <mx:ComboBox id="cmbTravelType" change="cmbTravelType_changeHandler(event)" 
                                 dataProvider="{travelTypeList}" selectedIndex="1"/>
                    
                </s:FormItem>
                <s:FormItem label="路径选择:">
                    <mx:ComboBox id="cmbImpedance" change="cmbImpedance_changeHandler(event)" 
                                 dataProvider="{impedanceAttributes}" selectedIndex="0"/>
                    
                </s:FormItem>
                <s:FormItem label="出发时间:">
                    <s:HGroup><mx:DateField id="startDateField" formatString="YYYY-MM-DD" height="30"
                                            selectedDate="{new Date()}">                                
                              </mx:DateField>
                        <s:NumericStepper id="hoursStepper" width="40" maximum="24" minimum="1">                                 
                        </s:NumericStepper><s:Label text="时"/>                                                             
                        <s:NumericStepper id="minutesStepper" width="40" maximum="59" minimum="0"></s:NumericStepper><s:Label text="分"/>
                    </s:HGroup></s:FormItem>
                <s:FormItem>                             
                    <s:Button label="查询" click="getDirections()" height="30"/>
                </s:FormItem>
            </s:Form>
        </s:Group>
        <s:Group id="resultsList" visible="false" width="100%" height="100%"
                 visible.resultsList="true">            
            <RichTabNavigator:RichTabNavigator id="tabImpact" width="100%" height="100%" backgroundAlpha="0"
                                               cornerRadius="5" dropShadowVisible="false" horizontalAlign="left"
                                               paddingTop="-1" tabHeight="30" tabWidth="110" borderVisible="true">
            </RichTabNavigator:RichTabNavigator>
        </s:Group>
        
        
    </viewer:WidgetTemplate>
</viewer:BaseWidget>

备注:

GIS技术交流QQ群:432512093

WebGIS二次开发培训入门群: 238339408

原文地址:https://www.cnblogs.com/giserhome/p/5136990.html