protected override void OnClick()
        {
            QueuedTask.Run(async() =>
            {
                //get sketch geometry
                var sketchGeom = await MapView.Active.GetCurrentSketchAsync();

                //return if the sketch doesn't have enough points for its geometry type
                if ((sketchGeom.GeometryType == GeometryType.Polygon && sketchGeom.PointCount < 3) || (sketchGeom.GeometryType == GeometryType.Polyline && sketchGeom.PointCount < 2))
                {
                    return;
                }

                //get the sketch as a point collection
                var pointCol = ((Multipart)sketchGeom).Points;

                //get the last point in the sketch based on its geometry type
                var lastSketchPoint = pointCol[(sketchGeom.GeometryType == GeometryType.Polygon) ? pointCol.Count - 2 : pointCol.Count - 1];

                //build a geometry with the last sketch point and set the sketch
                if (sketchGeom.GeometryType == GeometryType.Polygon)
                {
                    //sketch polygons need two points for the initial feedback to work
                    var sketchPoly = new PolygonBuilderEx(new[] { lastSketchPoint, lastSketchPoint }, AttributeFlags.None);
                    await MapView.Active.SetCurrentSketchAsync(sketchPoly.ToGeometry());
                }
                else
                {
                    var sketchPolyline = new PolylineBuilderEx(new[] { lastSketchPoint }, AttributeFlags.None);
                    await MapView.Active.SetCurrentSketchAsync(sketchPolyline.ToGeometry());
                }
            });
        }
        internal static Geometry MakeFishnetPolygon(Polygon inputPoly)
        {
            Envelope envPoly  = inputPoly.Extent;
            var      interval = GetFishnetIntervalDistance(envPoly);
            var      pb       = new PolygonBuilderEx(inputPoly.SpatialReference)
            {
                HasZ = true
            };

            for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
            {
                for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
                {
                    var cutEnv = EnvelopeBuilderEx.CreateEnvelope(dX, dY, dX + interval, dY + interval, envPoly.SpatialReference);
                    if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
                    {
                        var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv) as Polygon;
                        if (addPolygonPart.Area < 0)
                        {
                            System.Diagnostics.Debug.WriteLine($@"area: {addPolygonPart.Area}");
                        }
                        pb.AddPart(addPolygonPart.Points);
                    }
                }
            }
            return(pb.ToGeometry());
        }
        /// <summary>
        /// The methods retrieves the outer ring(s) of the input polygon.
        /// This method must be called on the MCT. Use QueuedTask.Run.
        /// </summary>
        /// <param name="inputPolygon">Input Polygon.</param>
        /// <returns>The outer most (exterior, clockwise) ring(s) of the polygon. If the input is null or empty, a null pointer is returned.</returns>
        /// <remarks>This method must be called on the MCT. Use QueuedTask.Run.</remarks>
        public Polygon GetOutermostRings(Polygon inputPolygon)
        {
            if (inputPolygon == null || inputPolygon.IsEmpty)
            {
                return(null);
            }

            // create a polygonbuilder - ensure it has the same spatial reference as the source polygon
            var            outerRings    = new PolygonBuilderEx(inputPolygon.SpatialReference);
            List <Polygon> internalRings = new List <Polygon>();

            // explode the parts of the polygon into a list of individual geometries
            var parts = MultipartToSinglePart(inputPolygon);

            // get an enumeration of clockwise geometries (area > 0) ordered by the area
            var clockwiseParts = parts.Where(geom => ((Polygon)geom).Area > 0).OrderByDescending(geom => ((Polygon)geom).Area);

            // for each of the exterior rings
            foreach (var part in clockwiseParts)
            {
                // add the first (the largest) ring into the internal collection
                if (internalRings.Count == 0)
                {
                    internalRings.Add(part as Polygon);
                }

                // use flag to indicate if current part is within the already selection polygons
                bool isWithin = false;

                foreach (var item in internalRings)
                {
                    if (GeometryEngine.Instance.Within(part, item))
                    {
                        isWithin = true;
                    }
                }

                // if the current polygon is not within any polygon of the internal collection
                // then it is disjoint and needs to be added to
                if (isWithin == false)
                {
                    internalRings.Add(part as Polygon);
                }
            }

            // now assemble a new polygon geometry based on the internal polygon collection
            foreach (var ring in internalRings)
            {
                outerRings.AddParts(ring.Parts);
            }

            // return the final geometry of the outer rings
            return(outerRings.ToGeometry());
        }
        /// <summary>
        /// Create a circular polygon around a mappoint for with a radius in pixels.
        /// </summary>
        /// <param name="mapPoint">Center of the circle as a mappoint.</param>
        /// <param name="pixels">Circle radius in screen pixels.</param>
        /// <returns>A polygon geometry.</returns>
        private Polygon CreateSearchPolygon(MapPoint mapPoint, int pixels)
        {
            //get search radius
            var screenPoint       = MapView.Active.MapToScreen(mapPoint);
            var radiusScreenPoint = new System.Windows.Point((screenPoint.X + pixels), screenPoint.Y);
            var radiusMapPoint    = MapView.Active.ScreenToMap(radiusScreenPoint);
            var searchRadius      = GeometryEngine.Instance.Distance(mapPoint, radiusMapPoint);

            //build a search circle geometry
            var cent       = new Coordinate2D(mapPoint);
            var searchGeom = EllipticArcBuilderEx.CreateCircle(cent, searchRadius, ArcOrientation.ArcClockwise, MapView.Active.Map.SpatialReference);
            var searchPB   = new PolygonBuilderEx(new[] { searchGeom }, AttributeFlags.None);

            return(searchPB.ToGeometry());
        }