private Task OnBeforeSketchCompletedEvent(BeforeSketchCompletedEventArgs arg)
        {
            //replace curved sketch segments with straight segments

            //return if sketch geometry is not polygon or polyline
            if (!(arg.Sketch.GeometryType == GeometryType.Polyline || arg.Sketch.GeometryType == GeometryType.Polygon))
            {
                return(Task.CompletedTask);
            }

            var sketchMP = arg.Sketch as Multipart;

            //if the sketch doesnt have curves then return
            if (!sketchMP.HasCurves)
            {
                return(Task.CompletedTask);
            }

            //itterate through each sketch part
            var newParts = new List <List <Segment> >();

            foreach (var sketchPart in sketchMP.Parts)
            {
                //itterate through each sketch segment
                var newSegments = new List <Segment>();
                foreach (var sketchSegment in sketchPart)
                {
                    if (sketchSegment.IsCurve)
                    {
                        newSegments.Add(LineBuilderEx.CreateLineSegment(sketchSegment.StartPoint, sketchSegment.EndPoint));
                    }
                    else
                    {
                        newSegments.Add(sketchSegment);
                    }
                }
                newParts.Add(newSegments);
            }

            //create the new sketch geometry based on sketch type and set back on the sketch
            if (arg.Sketch.GeometryType == GeometryType.Polyline)
            {
                var polyline = PolylineBuilderEx.CreatePolyline(newParts, AttributeFlags.None);
                arg.SetSketchGeometry(polyline);
            }
            else
            {
                var polygon = PolygonBuilderEx.CreatePolygon(newParts, AttributeFlags.None);
                arg.SetSketchGeometry(polygon);
            }

            return(Task.CompletedTask);
        }
        protected override async void OnClick()
        {
            var map = MapView.Active?.Map;

            if (map == null)
            {
                return;
            }
            try
            {
                var lyr = map.GetLayersAsFlattenedList().FirstOrDefault((fl) => fl.Name == LyrNameImport) as FeatureLayer;
                var msg = await QueuedTask.Run(() =>
                {
                    var attribs = new Dictionary <long, Dictionary <string, object> >();
                    using (var cursor = lyr.Search())
                        while (cursor.MoveNext())
                        {
                            using (var feat = cursor.Current as Feature)
                            {
                                var path = feat.GetShape() as Polyline;
                                var ls   = LineBuilderEx.CreateLineSegment(path.Points[0], path.Points[path.PointCount - 1]);
                                attribs.Add(feat.GetObjectID(), new Dictionary <string, object>()
                                {
                                    { "Direction", ls.Angle }
                                });
                            }
                        }

                    // create an edit operation
                    var editOperation = new EditOperation()
                    {
                        Name = $@"Update {LyrNameImport}"
                    };
                    foreach (var key in attribs.Keys)
                    {
                        editOperation.Modify(lyr, key, attribs[key]);
                    }
                    if (!editOperation.Execute())
                    {
                        return(editOperation.ErrorMessage);
                    }
                    return("update complete");
                });

                MessageBox.Show(msg);
            }
            catch (Exception ex)
            {
                MessageBox.Show($@"Error: {ex}");
            }
        }
        /// <summary>
        /// Creates a new camera offset from the provided camera around an ellipse.
        /// </summary>
        /// <param name="camera">The starting camera.</param>
        /// <param name="ellipse">The ellipse around which the camera will rotate.</param>
        /// <param name="centerPoint">The center point of the ellipse.</param>
        /// <param name="percentAlong">The percentage around the ellipse to create the camera.</param>
        private Camera OffsetCamera(Camera camera, Polyline ellipse, MapPoint centerPoint, double percentAlong)
        {
            camera = CloneCamera(camera);

            var fromPoint = GeometryEngine.Instance.MovePointAlongLine(ellipse, percentAlong, true, 0, SegmentExtensionType.NoExtension);

            var segment = LineBuilderEx.CreateLineSegment(new Coordinate2D(centerPoint.X, centerPoint.Y), new Coordinate2D(fromPoint.X, centerPoint.Y), centerPoint.SpatialReference);
            var difX    = GeometryEngine.Instance.GeodesicLength(PolylineBuilderEx.CreatePolyline(new Segment[] { segment }, AttributeFlags.None, segment.SpatialReference));

            if (centerPoint.X - fromPoint.X < 0)
            {
                difX *= -1;
            }

            segment = LineBuilderEx.CreateLineSegment(new Coordinate2D(centerPoint.X, centerPoint.Y), new Coordinate2D(centerPoint.X, fromPoint.Y), centerPoint.SpatialReference);
            var difY = GeometryEngine.Instance.GeodesicLength(PolylineBuilderEx.CreatePolyline(new Segment[] { segment }, AttributeFlags.None, segment.SpatialReference));

            if (centerPoint.Y - fromPoint.Y < 0)
            {
                difY *= -1;
            }

            var radian  = Math.Atan2(difX, difY);
            var heading = radian * -180 / Math.PI;

            camera.Heading = heading;

            var difZ       = centerPoint.Z - (camera.Z * ((camera.SpatialReference.IsGeographic) ? 1.0 : camera.SpatialReference.Unit.ConversionFactor));
            var hypotenuse = GeometryEngine.Instance.GeodesicDistance(fromPoint, centerPoint);

            radian = Math.Atan2(difZ, hypotenuse);
            var pitch = radian * 180 / Math.PI;

            camera.Pitch = pitch;

            if (fromPoint.SpatialReference.Wkid != camera.SpatialReference.Wkid)
            {
                var transformation = ProjectionTransformation.Create(fromPoint.SpatialReference, camera.SpatialReference);
                fromPoint = GeometryEngine.Instance.ProjectEx(fromPoint, transformation) as MapPoint;
            }

            camera.X = fromPoint.X;
            camera.Y = fromPoint.Y;
            return(camera);
        }
        protected override void OnClick()
        {
            //Selected voxel layer
            var voxelLayer = MapView.Active.GetSelectedLayers().OfType <VoxelLayer>().FirstOrDefault();

            if (voxelLayer == null)
            {
                voxelLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType <VoxelLayer>().FirstOrDefault();
                if (voxelLayer == null)
                {
                    return;
                }
            }

            QueuedTask.Run(() =>
            {
                if (voxelLayer.Visualization != VoxelVisualization.Surface)
                {
                    voxelLayer.SetVisualization(VoxelVisualization.Surface);
                }
                voxelLayer.SetSectionContainerExpanded(true);
                voxelLayer.SetSectionContainerVisibility(true);

                //delete all sections
                var volume = voxelLayer.SelectedVariableProfile.Volume;
                foreach (var section in volume.GetSections())
                {
                    volume.DeleteSection(section);
                }

                var vol_size     = volume.GetVolumeSize();
                var voxel_pos    = new Coordinate3D(0, 0, vol_size.Z);
                var voxel_pos_ur = new Coordinate3D(vol_size.X, vol_size.Y, vol_size.Z);

                //Make the diagonal in voxel space we will be using
                var lineBuilder = new LineBuilderEx(voxel_pos, voxel_pos_ur, null);
                var diagonal    = PolylineBuilderEx.CreatePolyline(lineBuilder.ToSegment());

                var num_sections = 12;
                var spacing      = 1 / (double)num_sections;

                //change as needed
                var orientation = 20.0;
                var tilt        = -15.0;
                var normal      = voxelLayer.GetNormal(orientation, tilt);

                for (int s = 0; s < num_sections; s++)
                {
                    Coordinate2D end_pt = new Coordinate2D(0, 0);
                    if (s > 0)
                    {
                        //position each section along the diagonal
                        var segments = new List <Segment>() as ICollection <Segment>;
                        var part     = GeometryEngine.Instance.GetSubCurve3D(
                            diagonal, 0.0, s * spacing, AsRatioOrLength.AsRatio);
                        part.GetAllSegments(ref segments);
                        end_pt = segments.First().EndCoordinate;
                    }

                    volume.CreateSection(new SectionDefinition()
                    {
                        Name          = $"Diagonal {s + 1}",
                        VoxelPosition = new Coordinate3D(end_pt.X, end_pt.Y, vol_size.Z),
                        Normal        = normal,
                        IsVisible     = true
                    });
                }
            });
        }