Click or drag to resize
Code Example - GetArea

Allows the user to draw a polygon on the map and calculate the area via several methods.

Code Example
Get Area

This section contains selected code files from a Visual Studio project that emphasize specific ArcGIS Runtime SDK (Windows Desktop) features. For example: some code examples may accomplish the bulk of the work as a configuration property in the .xaml file and hence only the .xaml file will be shown in detail below. In other code examples, the .xaml is used to define the configuration of graphical elements for the application but the application logic is performed in the code behind, hence you may see both the .xaml and .cs/.vb files shown in detail below.

XAML
<Window x:Class="GetArea.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
    Title="MainWindow" Height="600" Width="800">
    <Grid x:Name="LayoutRoot">


        <!-- Define a polygon fill symbol that will be used in the code-behind to draw graphics on the screen. -->
        <Grid.Resources>

            <esri:SimpleFillSymbol x:Key="MyPolygonSymbol" Color="Yellow" Style="Solid">
                <esri:SimpleFillSymbol.Outline>
                    <esri:SimpleLineSymbol Color="Black" Style="Solid" Width="2"/>
                </esri:SimpleFillSymbol.Outline>
            </esri:SimpleFillSymbol>

        </Grid.Resources>

        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Vertical">

                <!-- TextBlock to provide the instructions on how to use the sample code. It will be 
                populated with instructions in the code-behind when the application loads. -->
                <TextBlock Height="58" HorizontalAlignment="Left" Name="TextBlock1" VerticalAlignment="Top" 
                           Width="770" TextWrapping="Wrap"  Margin="10,2,0,0" />

            </StackPanel>
            <StackPanel Orientation="Horizontal">

                <!-- Add a button to allow the user to draw a polygon on the map. -->
                <Button Content="Click me to draw a polygon on the map" Margin="3,3" Width="785"
                        x:Name="ButtonDrawPolygon" Click="ButtonDrawPolygon_Click"/>

            </StackPanel>
            <StackPanel Orientation="Horizontal">

                <!-- A MapView Control to display various GIS layers. -->
                <esri:MapView x:Name="MapView1" Width="476" Height="480" VerticalAlignment="Top" Margin="2,2,2,2">

                    <!-- A Map. Set the initial extent to that of the Central Western US. -->
                    <esri:Map  x:Name="Map1"  InitialViewpoint="-12358689.29, 3783714.46, -10513901.38, 5644004.78">

                        <!-- Add a backdrop ArcGISTiledMapServiceLayer-->
                        <esri:ArcGISTiledMapServiceLayer ID="myArcGISTiledMapServiceLayer" 
                              ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer" />

                        <!-- Add an empty GraphicsLayer to hold graphics that are generated by the user with the Editor control. -->
                        <esri:GraphicsLayer ID="MyGraphicsLayer"/>

                    </esri:Map>
                </esri:MapView>

                <!-- Display area calculation values based upon the user drawn polygon. -->
                <StackPanel Orientation="Vertical">
                    <Label Content="Area calculations:"/>
                    <TextBlock x:Name="TextBlockAreaCalculations" Width="305" Height="456"/>
                </StackPanel>

            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

SPECIAL NOTE: The XAML displayed above comes from a C# project. If you are a VB.NET developer, you will need to modify the text for the x:Class namespace from "GetArea.MainWindow" to be just "MainWindow".

namespace GetArea
{
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // Add instructions on how to use the sample. 
            TextBlock1.Text = "When the application loads, click the button to draw a polygon on the map. Trace the polygon over the boundary of the State" + 
                " of Colorado. Make sure to double click the last vertex to end the polygon. Various area calculations for the polygon drawn will be displayed.";
        }

        private async void ButtonDrawPolygon_Click(object sender, System.Windows.RoutedEventArgs e)
        {

            // Obtain the Esri.ArcGISRuntime.Controls.DrawShape based on a Polygon.
            Esri.ArcGISRuntime.Controls.DrawShape theDrawShape = Esri.ArcGISRuntime.Controls.DrawShape.Polygon;

            // Get the string version of the Esri.ArcGISRuntime.Controls.DrawShape enumeration.
            string theDrawShapeString = theDrawShape.ToString();

            // Obtain the GraphicsLayer by its ID from the LayerCollection of the Map.
            Esri.ArcGISRuntime.Layers.GraphicsLayer myGraphicsLayer = (Esri.ArcGISRuntime.Layers.GraphicsLayer)MapView1.Map.Layers["MyGraphicsLayer"];

            // Clear out the graphics in the GraphicsLayer between sketch operations.
            myGraphicsLayer.Graphics.Clear();

            // Create a new empty graphic to hold the geometry from the RequestShapeAsync Method.
            Esri.ArcGISRuntime.Layers.Graphic myGraphic = null;

            if (theDrawShapeString == "Polygon")
            {

                // Get the Geometry from the Editor.RequestShapeAsync that the user draws in the Map.
                Esri.ArcGISRuntime.Geometry.Geometry myGeometry = await MapView1.Editor.RequestShapeAsync(Esri.ArcGISRuntime.Controls.DrawShape.Polygon);

                // Depending on how the user draws the Polygon: clock-wise, counter clock-wise, overlapping hourglass, etc. the geometry could be
                // considered topologically incorrect and give back negative area results! So to overcome this issue, it is always a good best practice
                // to use the Static GeometryEngine.Simplify Method such that the resulting geometry is topologically correct and will return
                // positive area results. 
                Esri.ArcGISRuntime.Geometry.Geometry myGeometryOrientationCorrect = Esri.ArcGISRuntime.Geometry.GeometryEngine.Simplify(myGeometry);

                // Get the correct Symbol from what was defined in XAML that corresponds to the DrawShape enumeration.
                Esri.ArcGISRuntime.Symbology.SimpleFillSymbol myPolygonSymbol = (Esri.ArcGISRuntime.Symbology.SimpleFillSymbol)LayoutRoot.Resources["MyPolygonSymbol"];

                // Create a graphic using the Geometry and Symbol defined.
                myGraphic = new Esri.ArcGISRuntime.Layers.Graphic(myGeometryOrientationCorrect, myPolygonSymbol);

                // THE FOLLOWING SECTION DEMONSTRATES A FEW DIFFERENT WAYS TO CALCULATE AREA'S OF A POLYGON. DEPENDING ON YOUR SPECIFIC GIS APPLICATION AND NEEDS, CHOOSE 
                // THE ONE THAT WORKS BEST FOR YOU APPLICATION. 

                // [1] Get the area of the Polygon based upon the SpatialReference that was set in the MapView. In the case of this code example, the MapView's SpatialReference 
                // has a WKID of 102100 (Web Mercator) and the map units are in meters. This option is probably not the best for calculating an area since Meb Mercator is not the 
                // best projection for that. However, if in your application the SpatialReference was acceptable for calculating area then this would be a good option.
                double myAreaUnProjectedDouble = Esri.ArcGISRuntime.Geometry.GeometryEngine.Area(myGeometryOrientationCorrect);

                // [2] Get the area of the Polygon based upon a SpatialReference that does a better job of preserving area calculations based upon a projection
                // that is designed to preserve area. In this case, the WKID of 102003 is an Albers Equal Area Conic projection which is very good at getting accurate area measurements.
                // To do this: 1st create a new SpatialRefenrce using WKID of 102003, 2nd Project the original geometry (myGeometryOrientationCorrect) to a new
                // geometry (MyGeometryProjected), and 3rd call the .Area method to get the area.
                Esri.ArcGISRuntime.Geometry.SpatialReference mySpatialReference_AlbersEqualAreaConic = new Esri.ArcGISRuntime.Geometry.SpatialReference(102003);
                Esri.ArcGISRuntime.Geometry.Geometry myGeometryProjected = Esri.ArcGISRuntime.Geometry.GeometryEngine.Project(myGeometryOrientationCorrect, mySpatialReference_AlbersEqualAreaConic);
                double myAreaProjectedDouble = Esri.ArcGISRuntime.Geometry.GeometryEngine.Area(myGeometryProjected);

                // [3] Another option to get an accurate area for a parcel on the Earth surface is to use the GeometryEngine.GeodesicArea Method on the unprojected geometry (myGeometryOrientationCorrect) 
                // which will do it's own internal projection based on the Earth spherical nature. There are several options for specifying the optional Esri.ArcGISRuntime.Geometry.GeodeticCurveType's 
                // input parameter. If no optional Esri.ArcGISRuntime.Geometry.GeodeticCurveType is used, the default Esri.ArcGISRuntime.Geometry.GeodeticCurveType.Geodesic will be used.
                double myAreaGeodesic = Esri.ArcGISRuntime.Geometry.GeometryEngine.GeodesicArea(myGeometryOrientationCorrect, Esri.ArcGISRuntime.Geometry.GeodeticCurveType.ShapePreserving);

                // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                // THE FOLLOWING SECTION SHOWS HOW YOU CAN TRANSFORM THE RAW AREA VALUES INTO OTHER FORMATS THAT ARE MORE COMMON FOR MANY STANDARD APPLICATIONS.
                // FOR THIS EXAMPLE, WE CHOSE TO TRANSFORM THE RESULTS FROM THE myAreaGeodesic CALCUATION. THE OTHER VALUES OF myAreaUnProjectedDouble OR 
                // myAreaProjectedDouble COULD HAVE ALSO BEEN USED IF YOU FELT THOSE CALCULATIONS WERE DEEMED MORE ACCURATE/APPROPRIATE.

                // [A] Calculate the area in Acres. This uses the long version of getting the number.
                Esri.ArcGISRuntime.Geometry.AreaUnit myUnit_Acres = (Esri.ArcGISRuntime.Geometry.AreaUnit)Esri.ArcGISRuntime.Geometry.AreaUnit.Create(Esri.ArcGISRuntime.Geometry.AreaUnits.Acres.Id);
                double myUnit_Acres_Double = myUnit_Acres.ConvertFromSquareMeters(myAreaGeodesic);

                // NOTE: Using this long version you can also obtain information on the AreaUnit Class.
                int myAreaUnit_Acres_ID = myUnit_Acres.Id;
                string myAreaUnit_Acres_Name = myUnit_Acres.Name;
                Esri.ArcGISRuntime.Geometry.UnitType myAreaUnit_Acres_UnitType = myUnit_Acres.UnitType;

                // [B] Calculate the area in SquareMiles. This is a shorter version to obtain the values without using the intermediary AreaUnit Class.
                double mySquareMiles = Esri.ArcGISRuntime.Geometry.AreaUnits.SquareMiles.ConvertFromSquareMeters(myAreaGeodesic);

                // Display the various area values to the user.
                System.Text.StringBuilder myStringBuilder = new System.Text.StringBuilder();
                myStringBuilder.AppendLine("UnProjected Area (Meters): " + myAreaUnProjectedDouble.ToString());
                myStringBuilder.AppendLine("Projected Area (Meters): " + myAreaProjectedDouble.ToString());
                myStringBuilder.AppendLine("Geodesic Area (Meters): " + myAreaGeodesic.ToString());
                myStringBuilder.AppendLine("");
                myStringBuilder.AppendLine("Acres: " + myUnit_Acres_Double.ToString());
                myStringBuilder.AppendLine("AreaUnit Acres ID: " + myAreaUnit_Acres_ID.ToString());
                myStringBuilder.AppendLine("AreaUnit Acres Name: " + myAreaUnit_Acres_Name);
                myStringBuilder.AppendLine("AreaUnit Acres UnitType: " + myAreaUnit_Acres_UnitType.ToString());
                myStringBuilder.AppendLine("");
                myStringBuilder.AppendLine("Square Miles: " + mySquareMiles.ToString());
                TextBlockAreaCalculations.Text = myStringBuilder.ToString();

            }

            // Add the Graphic to the GraphicsLayer. This will automatically cause a refresh of the Map, displaying the graphic visually.
            myGraphicsLayer.Graphics.Add(myGraphic);

        }

    }
}