Skip To Content

Routing around barriers

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:esri="http://www.esri.com/2008/ags"
               initialize="initApp()"
               pageTitle="Routing while avoiding bad spots">
    <!--
    Description:
    This sample demonstrates how to route between two or more
    locations (stops) with the ability to avoid certain locations (barriers)
    when routing.  Click the map to add stops on streets or intersections,
    optionally add barriers in the same manner.  Click the "Clear" button
    to start over.

    The map has a mapClickHandler which is the main function.
    When users click on the map, a "stop" or "barrier" will be added
    as a graphic to the graphics layer called inputsLayer.

    If there are two or more stops, the solve operation on the RouteTask
    will be used to create route between all the stops (taking into account
    any barriers).

    Additional route features you might want to try:
    * optimize the order of stops using findBestSequence.
    * batch routing (group the stops by their names)
    * time windows

    Documentation:
    For more information, see the API documentation.
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/FeatureSet.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/Graphic.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/Map.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/events/MapMouseEvent.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/events/RouteEvent.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/symbols/CompositeSymbol.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/symbols/TextSymbol.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/RouteTask.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/RouteTask.html#solve()
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/supportClasses/RouteParameters.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/supportClasses/RouteSolveResult.html

    http://resources.arcgis.com/en/help/flex-api/concepts/index.html#/Routing_tasks/017p00000012000000/

    ArcGIS REST API documentation:
    http://resources.arcgis.com/en/help/rest/apiref/naserver.html
    http://resources.arcgis.com/en/help/rest/apiref/nalayer.html
    http://resources.arcgis.com/en/help/rest/apiref/index.html?nasolve.html

    ArcGIS for Server documentation:
    http://resources.arcgis.com/en/help/main/10.1/index.html#/Network_analysis_services/015400000276000000/

    ArcGIS for Desktop documentation:
    http://resources.arcgis.com/en/help/main/10.1/index.html#/What_is_the_ArcGIS_Network_Analyst_extension/004700000001000000/
    http://resources.arcgis.com/en/help/main/10.1/index.html#/About_the_ArcGIS_Network_Analyst_extension_tutorial/00470000005r000000/
    http://resources.arcgis.com/en/help/main/10.1/index.html#/Route_analysis/004700000045000000/

    NOTE: In order to support this workflow (author and publish the services) in your own environment,
    you will need a streets network dataset such as StreetMap Premium for ArcGIS,
    ArcGIS Network Analyst for Desktop, and ArcGIS Network Analyst for Server.
    -->

    <fx:Style>
        @namespace mx "library://ns.adobe.com/flex/mx";
        mx|ToolTip
        {
            font-size: 14;
            backgroundColor: #EEEEEE;
        }
    </fx:Style>

    <fx:Script>
        <![CDATA[
            import com.esri.ags.FeatureSet;
            import com.esri.ags.Graphic;
            import com.esri.ags.events.MapMouseEvent;
            import com.esri.ags.events.RouteEvent;
            import com.esri.ags.symbols.CompositeSymbol;
            import com.esri.ags.symbols.TextSymbol;
            import com.esri.ags.tasks.supportClasses.RouteResult;

            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;

            []private var stops:FeatureSet = new FeatureSet([]);

            []private var barriers:FeatureSet = new FeatureSet([]);

            []private var selectedBtn:ToggleButton;

            []private var lastRoute:Graphic;

            private function initApp():void
            {
                selectedBtn = addStopsBtn;
            }

            private function mapClickHandler(event:MapMouseEvent):void
            {
                if (selectedBtn == addStopsBtn)
                {
                    var stopSymbol:CompositeSymbol = new CompositeSymbol();
                    var circleSym:SimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 20, 0x000099);
                    var textSym:TextSymbol = new TextSymbol(String(stops.features.length + 1));
                    textSym.textFormat = new TextFormat("Verdana", null, null, true);
                    textSym.color = 0xFFFFFF;
                    stopSymbol.symbols = [ circleSym, textSym ];
                    var stop:Graphic = new Graphic(event.mapPoint, stopSymbol);
                    inputsLayer.add(stop);
                    stops.features.push(stop);
                }
                else
                {
                    var barrier:Graphic = new Graphic(event.mapPoint, barrierSymbol);
                    inputsLayer.add(barrier);
                    barriers.features.push(barrier);
                }

                if (stops.features.length > 1)
                {
                    routeTask.solve(routeParams);
                }
            }

            private function solveCompleteHandler(event:RouteEvent):void
            {
                var routeResult:RouteResult = event.routeSolveResult.routeResults[0];
                lastRoute = routeResult.route;
                lastRoute.toolTip = routeResult.routeName;
                if (routeResult.route.attributes.Total_Time)
                {
                    lastRoute.toolTip += " in " + Math.round(Number(routeResult.route.attributes.Total_Time)) + " minutes.";
                }
            }

            private function faultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.faultString + "\n\n" + event.fault.faultDetail, "Routing Error " + event.fault.faultCode);
                // remove last stop (or both stops if only two)
                if (stops.features.length <= 2)
                {
                    inputsLayer.clear();
                    stops = new FeatureSet([]);
                }
                else
                {
                    inputsLayer.remove(stops.features.pop());
                }
                routeGraphicsLayer.clear();
                barriers = new FeatureSet([]);
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <esri:RouteTask id="routeTask"
                        concurrency="last"
                        fault="faultHandler(event)"
                        requestTimeout="30"
                        showBusyCursor="true"
                        solveComplete="solveCompleteHandler(event)"
                        url="http://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/Route"/>

        <esri:RouteParameters id="routeParams"
                              outSpatialReference="{myMap.spatialReference}"
                              pointBarriers="{barriers}"
                              stops="{stops}"/>

        <esri:SimpleMarkerSymbol id="barrierSymbol2"
                                 color="0xFF0000"
                                 size="15"
                                 style="x">
            <esri:SimpleLineSymbol width="4"/>
        </esri:SimpleMarkerSymbol>

        <esri:PictureMarkerSymbol id="barrierSymbol" source="assets/road-closed-32x32.png"/>

        <esri:SimpleLineSymbol id="routeSymbol"
                               width="5"
                               alpha="0.6"
                               color="0x000099"/>
    </fx:Declarations>

    <s:controlBarLayout>
        <s:VerticalLayout gap="10"
                          paddingBottom="7"
                          paddingLeft="10"
                          paddingRight="10"
                          paddingTop="7"/>
    </s:controlBarLayout>
    <s:controlBarContent>
        <s:RichText width="100%">
            This sample demonstrates how to route between two or more
            locations (stops) with the ability to avoid certain locations (barriers)
            when routing.  Click the map to add stops on streets or intersections,
            optionally add barriers in the same manner.  Click the "Clear" button
            to start over.
        </s:RichText>
        <s:HGroup width="100%" horizontalAlign="center">
            <s:ToggleButton id="addStopsBtn"
                            click="selectedBtn = addStopsBtn"
                            label="Add Stops"
                            selected="{selectedBtn == addStopsBtn}"/>
            <s:ToggleButton id="addBarriersBtn"
                            click="selectedBtn = addBarriersBtn"
                            label="Add Barriers"
                            selected="{selectedBtn == addBarriersBtn}"/>
            <s:Button label="Clear">
                <s:click>
                    <![CDATA[
                        stops = new FeatureSet([]);
                        barriers = new FeatureSet([]);
                        lastRoute = new Graphic();
                        inputsLayer.clear();
                    ]]>
                </s:click>
            </s:Button>
        </s:HGroup>
    </s:controlBarContent>

    <esri:Map id="myMap" mapClick="mapClickHandler(event)">
        <esri:extent>
            <esri:Extent xmin="-13042947" ymin="3856278" xmax="-13041347" ymax="3857116">
                <esri:SpatialReference wkid="102100"/>
            </esri:Extent>
        </esri:extent>
        <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/>
        <esri:GraphicsLayer id="routeGraphicsLayer"
                            graphicProvider="{lastRoute}"
                            symbol="{routeSymbol}"/>
        <esri:GraphicsLayer id="inputsLayer"/>
    </esri:Map>

</s:Application>