SOE GetElevationProfile

<?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:mx="library://ns.adobe.com/flex/mx"
               xmlns:tasks="com.esri.ags.samples.tasks.*"
               xmlns:esri="http://www.esri.com/2008/ags"
               xmlns:components="com.esri.ags.samples.components.*"
               pageTitle="Example - SOE GetElevationProfile">
    <!--
    Description:
    This sample demonstrates the programming patterns to create your own
    custom Task which extends BaseTask.  The sample calculates the elevations
    along a user defined path (polyline), and creates an image of the profile
    chart (this part is done server side).  To use this sample: Select a mountain
    from the list of buttons, next activate the draw tool to sketch a line
    over the mountain surface, the chart represents the profile or terrain over
    the line.

    Documentation:
    For more information, see the API documentation.
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/events/DrawEvent.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/events/DrawEvent.html#graphic
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/events/LocatorEvent.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/BaseTask.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/Locator.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/supportClasses/AddressCandidate.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tasks/supportClasses/AddressToLocationsParameters.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#graphicsLayer
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#map
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#activate()
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#deactivate()
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#event:drawStart
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/tools/DrawTool.html#event:drawEnd
    https://developers.arcgis.com/en/flex/api-reference/com/esri/ags/utils/WebMercatorUtil.html

    http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/formatters/NumberFormatter.html

    http://sampleserver4.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/MapServer/exts/ElevationsSOE "Live service"
    http://blogs.esri.com/Dev/blogs/apl/archive/2010/10/07/Elevation-Server-Object-Extension.aspx "Blog article on SOE"
    http://resources.arcgis.com/gallery/file/arcobjects-net-api/details?entryID=87BEC705-1422-2418-34B5-308930DE323A "Source code for SOE"
    http://www.arcgis.com/home/item.html?id=b9d247c297f144459854751740f59f68 "FlexViewer SOE widgets"

    For more details on the World Geocoding Service follow the link below.
    http://geocode.arcgis.com/arcgis/index.html

    ArcGIS REST API documentation:
    http://sampleserver4.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/MapServer/exts/ElevationsSOE/ElevationLayers/1/GetElevationProfile

    ArcGIS for Server documentation:
    http://resources.arcgis.com/en/help/main/10.1/index.html#/What_is_a_server_object_extension/0154000004s5000000/
    http://resources.arcgis.com/en/help/main/10.1/index.html#/Steps_for_developing_and_deploying_a_server_object_extension/0154000004s7000000/
    http://resources.arcgis.com/en/help/main/10.1/index.html#/Alternatives_to_server_object_extensions/015400000528000000/

    This sample also uses the following files:
    com/esri/ags/samples/tasks/ElevationsSOETask.as
    com/esri/ags/samples/tasks/supportClasses/ElevationsSOEParameters.as
    com/esri/ags/samples/tasks/supportClasses/ElevationsSOEResult.as
    com/esri/ags/samples/tasks/supportClasses/InterpolatedRasterProperties.as
    com/esri/ags/samples/events/ElevationsSOEEvent.as
    -->

    <!-- STATES -->
    <s:states>
        <s:State name="selectionState"/>
        <s:State name="selectionProcessingState"/>
        <s:State name="drawingState"/>
        <s:State name="drawingProcessingState"/>
        <s:State name="resultsState"/>
    </s:states>

    <fx:Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        @namespace mx "library://ns.adobe.com/flex/mx";
        s|Panel
        {
            backgroundColor: #C0C2B7;
            chromeColor: #9D7037;
        }
        s|ButtonBar
        {
            chromeColor: #AF8E56;
        }
        mx|ToolTip
        {
            font-size: 14;
            backgroundColor: #EEEEEE;
        }
    </fx:Style>

    <fx:Script>
        <![CDATA[
            import com.esri.ags.Graphic;
            import com.esri.ags.events.DrawEvent;
            import com.esri.ags.events.LocatorEvent;
            import com.esri.ags.geometry.MapPoint;
            import com.esri.ags.geometry.Polyline;
            import com.esri.ags.samples.events.ElevationsSOEEvent;
            import com.esri.ags.samples.tasks.supportClasses.ElevationsSOEParameters;
            import com.esri.ags.samples.tasks.supportClasses.ElevationsSOEResult;
            import com.esri.ags.tasks.supportClasses.AddressCandidate;
            import com.esri.ags.tasks.supportClasses.AddressToLocationsParameters;
            import com.esri.ags.utils.WebMercatorUtil;

            import mx.controls.Alert;
            import mx.core.IFlexDisplayObject;
            import mx.managers.PopUpManager;
            import mx.managers.PopUpManagerChildList;
            import mx.rpc.events.FaultEvent;

            import spark.events.IndexChangeEvent;

            []private var placeElevation:Number = 0.0;
            []private var placeResultDescription:String = "";

            protected function placeSelectedChangeHandler(event:IndexChangeEvent):void
            {
                var selectedItem:Object = ButtonBar(event.currentTarget).selectedItem as Object;
                if (selectedItem)
                {
                    var params:AddressToLocationsParameters = new AddressToLocationsParameters();
                    var place:Object = { SingleLine: selectedItem.data };
                    params.address = place;
                    params.outFields = [ 'Match_Addr' ];
                    currentState = 'selectionProcessingState';
                    setProgress("Locating " + selectedItem.data + "...", true);
                    placesLocator.addressToLocations(params);
                }
            }

            protected function placesLocator_addressToLocationsCompleteHandler(event:LocatorEvent):void
            {
                placesButtonBar.selectedIndex = -1;
                var placesResults:Array = event.addressCandidates as Array;
                if (placesResults[0])
                {
                    var placeCandidate:AddressCandidate = placesResults[0] as AddressCandidate;
                    placeResultDescription = placeCandidate.attributes["Match_Addr"];
                    var mapPoint:MapPoint = placeCandidate.location as MapPoint;
                    var webMercatorGeom:MapPoint = WebMercatorUtil.geographicToWebMercator(mapPoint) as MapPoint;
                    addPlace(webMercatorGeom);
                    map.level = 11;
                    map.centerAt(webMercatorGeom);
                    currentState = 'drawingState';
                }

            }

            protected function addPlace(value:MapPoint):void
            {
                map.defaultGraphicsLayer.clear();
                var gra:Graphic = new Graphic(value, elevationAtSymbol);
                map.defaultGraphicsLayer.add(gra);
            }

            protected function setProgress(value:String, visible:Boolean):void
            {
                progressBar.visible = visible;
                progressBar.label = value;
            }

            protected function drawTypeSelectedChangeHandler(event:IndexChangeEvent):void
            {
                drawGraphicsLayer.clear();
                var selectedItem:Object = ButtonBar(event.currentTarget).selectedItem as Object;
                if (selectedItem)
                {
                    drawTool.activate(selectedItem.data);
                }
            }

            protected function drawTool_drawEndHandler(event:DrawEvent):void
            {
                var elevationPathPolyline:Polyline = event.graphic.geometry as Polyline;
                drawTool.deactivate();
                drawingButtonBar.selectedIndex = -1;
                var params:ElevationsSOEParameters = new ElevationsSOEParameters();
                params.inputPolyline = elevationPathPolyline;
                params.imageWidth = 450;
                params.imageHeight = 178;
                params.backgroundColorHex = 0xC0C2B7;
                params.isDisplaySegments = true;
                currentState = 'drawingProcessingState';
                setProgress("The server is calculating your profile...", true);
                soeTask.executeGetElevationProfile(params);
            }

            protected function soeTask_executeCompleteHandler(event:ElevationsSOEEvent):void
            {
                var elevationResult:ElevationsSOEResult = event.elevationsSOEResult;
                try
                {

                    chartImageWindow.imageURL = elevationResult.profileImageURL;
                    chartImageWindow.length2D = elevationResult.length2D;
                    chartImageWindow.length3D = elevationResult.length3D;
                    chartImageWindow.processTime = elevationResult.processTime;

                    if (!systemManager.popUpChildren.contains(chartImageWindow))
                    {
                        PopUpManager.addPopUp(chartImageWindow as IFlexDisplayObject, map, false, PopUpManagerChildList.POPUP);
                        PopUpManager.centerPopUp(chartImageWindow);
                    }
                }
                catch (error:Error)
                {
                    Alert.show("A problem occurred while retrieving the returned elevation chart:\n" + error.message.toString());
                }
                currentState = 'resultsState';
            }

            protected function esriService_faultHandler(event:FaultEvent):void
            {
                placesButtonBar.selectedIndex = -1;
                Alert.show("Error: " + event.fault.faultString, "Error code: " + event.fault.faultCode);
                currentState = 'selectionState';
            }


            /**
             * Close chart window and remove user-drawn line graphic
             **/
            private function closeChartWindow():void
            {
                drawGraphicsLayer.clear();
                PopUpManager.removePopUp(chartImageWindow);
            }

            protected function drawAnother_clickHandler(event:MouseEvent):void
            {
                closeChartWindow();
                drawGraphicsLayer.clear();
                currentState = 'drawingState';
            }

            protected function startOver_clickHandler(event:MouseEvent):void
            {
                closeChartWindow();
                map.defaultGraphicsLayer.clear();
                drawGraphicsLayer.clear();
                currentState = 'selectionState';
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
        <esri:SimpleLineSymbol id="drawLineColor"
                               width="3"
                               color="0x1B009F"/>
        <esri:DrawTool id="drawTool"
                       drawEnd="drawTool_drawEndHandler(event)"
                       graphicsLayer="{drawGraphicsLayer}"
                       lineSymbol="{drawLineColor}"
                       map="{map}"/>
        <esri:SimpleMarkerSymbol id="elevationAtSymbol"
                                 color="0xB5804E"
                                 outline="{smsOutline}"
                                 size="30"
                                 style="triangle"/>
        <esri:SimpleLineSymbol id="smsOutline"
                               width="1"
                               color="0x578DB8"
                               style="solid"/>
        <tasks:ElevationsSOETask id="soeTask"
                                 executeComplete="soeTask_executeCompleteHandler(event)"
                                 fault="esriService_faultHandler(event)"
                                 url="http://sampleserver4.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/MapServer/exts/ElevationsSOE/ElevationLayers/1"/>
        <esri:Locator id="placesLocator"
                      addressToLocationsComplete="placesLocator_addressToLocationsCompleteHandler(event)"
                      fault="esriService_faultHandler(event)"
                      url="http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"/>
        <s:NumberFormatter id="numberFormatter" fractionalDigits="0"/>
        <!-- Chart pop-up window -->
        <components:ChartImageWindow id="chartImageWindow"
                                     close="closeChartWindow()"
                                     title="Elevation Profile"/>
    </fx:Declarations>

    <s:controlBarContent>
        <s:RichText width="100%">
            This sample demonstrates the programming patterns to create your own
            custom Task which extends BaseTask.  The sample calculates the elevations
            along a user defined path (polyline), and creates an image of the profile
            chart (this part is done server side).  To use this sample: Select a mountain
            from the list of buttons, next activate the draw tool to sketch a line
            over the mountain surface, the chart represents the profile or terrain over
            the line.
        </s:RichText>
    </s:controlBarContent>

    <esri:Map id="map" wrapAround180="true">
        <esri:ArcGISTiledMapServiceLayer url="http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"/>
        <esri:GraphicsLayer id="drawGraphicsLayer"/>
    </esri:Map>
    <s:Panel width="440" height="130"
             right="20" top="20"
             title="Ask a service to generate an elevation profile">
        <s:layout>
            <s:VerticalLayout gap="10"
                              paddingBottom="7"
                              paddingLeft="10"
                              paddingRight="10"
                              paddingTop="7"/>
        </s:layout>
        <s:Group id="selectionState" includeIn="selectionState">
            <s:ButtonBar id="placesButtonBar" change="placeSelectedChangeHandler(event)">
                <s:ArrayList>
                    <fx:Object data="Mount St. Helens" label="Mount St. Helens"/>
                    <fx:Object data="Gunung Merapi" label="Mount Merapi"/>
                    <fx:Object data="Mount Pinatubo" label="Mount Pinatubo"/>
                    <fx:Object data="Kilauea Volcano" label="Kilauea Volcano"/>
                </s:ArrayList>
            </s:ButtonBar>
        </s:Group>
        <s:Group id="drawingState" includeIn="drawingState">
            <s:layout>
                <s:VerticalLayout gap="10"
                                  paddingBottom="7"
                                  paddingLeft="10"
                                  paddingRight="10"
                                  paddingTop="7"/>
            </s:layout>
            <s:Label id="placeResult"
                     width="100%"
                     fontSize="14"
                     text="{placeResultDescription}"
                     visible="{placeResultDescription != ''}"/>
            <s:ButtonBar id="drawingButtonBar" change="drawTypeSelectedChangeHandler(event)">
                <s:ArrayList>
                    <fx:Object data="{DrawTool.FREEHAND_POLYLINE}" label="Line (Freehand Draw)"/>
                    <fx:Object data="{DrawTool.LINE}" label="Line (Click,Drag,Release)"/>
                </s:ArrayList>
            </s:ButtonBar>
        </s:Group>
        <s:Group id="results" includeIn="resultsState">
            <s:layout>
                <s:VerticalLayout gap="10"
                                  paddingBottom="7"
                                  paddingLeft="10"
                                  paddingRight="10"
                                  paddingTop="7"/>
            </s:layout>
            <s:Button click="drawAnother_clickHandler(event)" label="Click to draw another line over the mountain."/>
            <s:Button click="startOver_clickHandler(event)" label="Click to Start Over"/>
        </s:Group>
        <mx:ProgressBar id="progressBar"
                        width="80%"
                        includeIn="selectionProcessingState,drawingProcessingState"
                        indeterminate="true"
                        visible="false"/>
    </s:Panel>
</s:Application>