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());
                }
            });
        }
        private static Geometry GetGeometryFromBuffer(byte[] geomBuffer, SpatialReference sr)
        {
            var geomType = GetGeometryType(geomBuffer);

            switch (geomType)
            {
            case GeometryType.Point:
            {
                int    offset = 4;
                double x      = DoubleWithNaN(BitConverter.ToDouble(geomBuffer, offset));
                offset += 8;
                double y = DoubleWithNaN(BitConverter.ToDouble(geomBuffer, offset));

                var mp = MapPointBuilderEx.FromEsriShape(geomBuffer, sr);
                //System.Diagnostics.Debug.WriteLine($@"x: {x} = {mp.X} y: {y} = {mp.Y}");
                return(mp);
            }

            case GeometryType.Polyline:
            {
                var line = PolylineBuilderEx.FromEsriShape(geomBuffer, sr);
                return(line);
            }

            case GeometryType.Polygon:
            {
                var poly = PolygonBuilderEx.FromEsriShape(geomBuffer, sr);
                return(poly);
            }
            }
            return(null);
        }
        /// <summary>
        /// Create sample polyline feature using the geometries from the point feature layer.
        /// </summary>
        /// <param name="polylineLayer">Polyline geometry feature layer used to add the new features.</param>
        /// <param name="pointLayer">The geometries from the point layer are used as vertices for the new line features.</param>
        /// <returns></returns>
        private Task <bool> ConstructSamplePolylines(FeatureLayer polylineLayer, FeatureLayer pointLayer)
        {
            // execute the fine grained API calls on the CIM main thread
            return(QueuedTask.Run(() =>
            {
                // get the underlying feature class for each layer
                var polylineFeatureClass = polylineLayer.GetTable() as FeatureClass;
                var pointFeatureClass = pointLayer.GetTable() as FeatureClass;

                // retrieve the feature class schema information for the feature classes
                var polylineDefinition = polylineFeatureClass.GetDefinition() as FeatureClassDefinition;
                var pointDefinition = pointFeatureClass.GetDefinition() as FeatureClassDefinition;

                // construct a cursor for all point features, since we want all feature there is no
                // QueryFilter required
                var pointCursor = pointFeatureClass.Search(null, false);
                var is3D = pointFeatureClass.GetDefinition().HasZ();

                // initialize a counter variable
                int pointCounter = 0;
                // initialize a list to hold 5 coordinates that are used as vertices for the polyline
                var lineMapPoints = new List <MapPoint>(5);

                // set up the edit operation for the feature creation
                var createOperation = new EditOperation()
                {
                    Name = "Create polylines",
                    SelectNewFeatures = false
                };

                // loop through the point features
                while (pointCursor.MoveNext())
                {
                    pointCounter++;

                    var pointFeature = pointCursor.Current as Feature;
                    // add the feature point geometry as a coordinate into the vertex list of the line
                    // - ensure that the projection of the point geometry is converted to match the spatial reference of the line
                    lineMapPoints.Add(((MapPoint)GeometryEngine.Instance.Project(pointFeature.GetShape(), polylineDefinition.GetSpatialReference())));

                    // for every 5 geometries, construct a new polyline and queue a feature create
                    if (pointCounter % 5 == 0)
                    {
                        // construct a new polyline by using the 5 point coordinate in the current list
                        var newPolyline = PolylineBuilderEx.CreatePolyline(lineMapPoints, polylineDefinition.GetSpatialReference());
                        // queue the create operation as part of the edit operation
                        createOperation.Create(polylineLayer, newPolyline);
                        // reset the list of coordinates
                        lineMapPoints = new List <MapPoint>(5);
                    }
                }

                // execute the edit (create) operation
                return createOperation.ExecuteAsync();
            }));
        }
コード例 #4
0
        protected override Task <bool> OnSketchCompleteAsync(Geometry geometry)
        {
            //Run on MCT
            return(QueuedTask.Run(() =>
            {
                //get the templates
                var map = MapView.Active.Map;
                IEnumerable <Layer> layers = map.GetLayersAsFlattenedList().AsEnumerable();
                Layer mainLayer = layers.FirstOrDefault(l => l.Name == "main");
                Layer mhLayer = layers.FirstOrDefault(l => l.Name == "manhole");
                Layer conLayer = layers.FirstOrDefault(l => l.Name == "connector");

                if ((mainLayer == null) || (mhLayer == null) || (conLayer == null))
                {
                    return false;
                }

                var mainTemplate = mainLayer.GetTemplate("main");
                var mhTemplate = mhLayer.GetTemplate("manhole");
                var conTemplate = conLayer.GetTemplate("connector");

                if ((mainTemplate == null) || (mhTemplate == null) || (conTemplate == null))
                {
                    return false;
                }

                var op = new EditOperation()
                {
                    Name = "Create main-connector-manhole",
                    SelectModifiedFeatures = false,
                    SelectNewFeatures = false
                };

                //create the main geom
                var mainGeom = GeometryEngine.Instance.Move(geometry, 0, 0, -20);
                op.Create(mainTemplate, mainGeom);

                //create manhole points and connector
                foreach (var pnt in ((Polyline)geometry).Points)
                {
                    //manhole point at sketch vertex
                    op.Create(mhTemplate, pnt);

                    //vertical connector between mahole and main
                    var conPoints = new List <MapPoint>
                    {
                        pnt,                                                     //top of vertical connector
                        GeometryEngine.Instance.Move(pnt, 0, 0, -20) as MapPoint //bottom of vertical connector
                    };
                    var conPolyLine = PolylineBuilderEx.CreatePolyline(conPoints);
                    op.Create(conTemplate, conPolyLine);
                }
                return op.Execute();
            }));
        }
        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);
        }
コード例 #6
0
        /// <summary>
        /// When the active map view changes, update the graphic overlay on the map control
        /// </summary>
        /// <param name="args"></param>
        private void OnMapViewCameraChanged(MapViewCameraChangedEventArgs args)
        {
            if (MapView.Active == null)
            {
                return;
            }
            if (MapView.Active.Extent == null)
            {
                return;
            }
            if (MapView.Active.ViewingMode != ArcGIS.Core.CIM.MapViewingMode.Map)
            {
                return;
            }

            //get the Map view's extent
            var viewExtent = MapView.Active.Extent.Clone() as Envelope;

            QueuedTask.Run(() =>
            {
                //Line symbol to be used to draw the overview rectangle.
                if (_lineSymbol == null)
                {
                    _lineSymbol =
                        SymbolFactory.Instance.ConstructLineSymbol(ColorFactory.Instance.RedRGB, 2.0, SimpleLineStyle.Solid);
                }

                _graphic?.Dispose();            //Clear out the old overlay

                _overviewEnvelope = viewExtent; //overview envelope based on active map view

                if (_overviewEnvelope == null)
                {
                    return;
                }
                //Creating the overview rectangle
                IList <MapPoint> segments = new List <MapPoint>
                {
                    MapPointBuilderEx.CreateMapPoint(_overviewEnvelope.XMin, _overviewEnvelope.YMin, _overviewEnvelope.SpatialReference),
                    MapPointBuilderEx.CreateMapPoint(_overviewEnvelope.XMax, _overviewEnvelope.YMin, _overviewEnvelope.SpatialReference),
                    MapPointBuilderEx.CreateMapPoint(_overviewEnvelope.XMax, _overviewEnvelope.YMax, _overviewEnvelope.SpatialReference),
                    MapPointBuilderEx.CreateMapPoint(_overviewEnvelope.XMin, _overviewEnvelope.YMax, _overviewEnvelope.SpatialReference),
                    MapPointBuilderEx.CreateMapPoint(_overviewEnvelope.XMin, _overviewEnvelope.YMin, _overviewEnvelope.SpatialReference)
                };
                _polyLine = PolylineBuilderEx.CreatePolyline(segments, AttributeFlags.None, _overviewEnvelope.SpatialReference);

                _graphic = _mapControl.AddOverlay(_polyLine, _lineSymbol.MakeSymbolReference());
            });
        }
コード例 #7
0
        /// <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);
        }
        /// <summary>
        /// Implement the on-click behavior of the individual menu items. Alternatively, addins can
        /// implement on-click behavior via a delegate assigned to each menu item (refer to the dynamic
        /// menu Add method overloads).
        /// </summary>
        /// <param name="index">The 0-based index of the clicked menu item</param>
        /// <remarks>Retrieve the feature geometry (for the clicked menu item) and
        /// append it into the sketch.</remarks>
        protected override void OnClick(int index)
        {
            if (_featureInfo == null)
            {
                return;
            }
            var fl = MapView.Active.Map.FindLayer(_featureInfo.Item1) as FeatureLayer;

            QueuedTask.Run(() =>
            {
                //Use inspector to retrieve the feature shape
                var insp = new Inspector();
                insp.Load(fl, _featureInfo.Item2[index]);

                //Project
                var temp_line =
                    GeometryEngine.Instance.Project(insp["SHAPE"] as Polyline,
                                                    MapView.Active.Map.SpatialReference) as Polyline;

                //Move the beginning of the shape to the right-click
                //location...
                var first_point = temp_line.Points[0];
                var dx          = _insertPoint.X - first_point.X;
                var dy          = _insertPoint.Y - first_point.Y;
                var mv_line     = GeometryEngine.Instance.Move(temp_line, dx, dy);

                //match the geometry sr with the sketch sr
                Polyline finalLine =
                    GeometryEngine.Instance.Project(mv_line,
                                                    _sketch.SpatialReference) as Polyline;

                //Sketch might be empty but it is never null...
                //assumes single part polyline here...
                var points = ((Polyline)_sketch).Points.ToList();
                points.AddRange(finalLine.Points);
                var bldr = new PolylineBuilderEx(points.Select(p => p.Coordinate3D).ToList(),
                                                 _sketch.SpatialReference);
                //ensure the geometry is Z enabled to be used as for
                //the sketch
                bldr.HasZ = true;
                _sketch   = bldr.ToGeometry();
                MapView.Active.SetCurrentSketchAsync(_sketch);
            });
        }
        /// <summary>
        /// Create sample polygon feature using the point geometries from the multi-point feature using the
        /// ConvexHull method provided by the GeometryEngine.
        /// </summary>
        /// <param name="polygonLayer">Polygon geometry feature layer used to add the new feature.</param>
        /// <param name="lineLayer">The polyline feature layer containing the features used to construct the polygon.</param>
        /// <returns></returns>
        private Task <bool> ConstructSamplePolygon(FeatureLayer polygonLayer, FeatureLayer lineLayer)
        {
            // execute the fine grained API calls on the CIM main thread
            return(QueuedTask.Run(() =>
            {
                // get the underlying feature class for each layer
                var polygonFeatureClass = polygonLayer.GetTable() as FeatureClass;
                var polygonDefinition = polygonFeatureClass.GetDefinition() as FeatureClassDefinition;
                var lineFeatureClass = lineLayer.GetTable() as FeatureClass;

                // construct a cursor to retrieve the line features
                var lineCursor = lineFeatureClass.Search(null, false);

                // set up the edit operation for the feature creation
                var createOperation = new EditOperation()
                {
                    Name = "Create polygons",
                    SelectNewFeatures = false
                };

                var polylineBuilder = new PolylineBuilderEx(polygonDefinition.GetSpatialReference());

                while (lineCursor.MoveNext())
                {
                    // retrieve the first feature
                    using (var lineFeature = lineCursor.Current as Feature)
                    {
                        // add the coordinate collection of the current geometry into our overall list of collections
                        var polylineGeometry = lineFeature.GetShape() as Polyline;
                        polylineBuilder.AddParts(polylineGeometry.Parts);
                    }
                }

                // use the ConvexHull method from the GeometryEngine to construct the polygon geometry
                var newPolygon = GeometryEngine.Instance.ConvexHull(polylineBuilder.ToGeometry()) as Polygon;

                // queue the polygon creation
                createOperation.Create(polygonLayer, newPolygon);

                // execute the edit (polygon create) operation
                return createOperation.ExecuteAsync();
            }));
        }
コード例 #10
0
        /// <summary>
        /// Called when the sketch finishes. This is where we will create the sketch operation and then execute it.
        /// </summary>
        /// <param name="geometry">The geometry created by the sketch.</param>
        /// <returns>A Task returning a Boolean indicating if the sketch complete event was successfully handled.</returns>
        protected override Task <bool> OnSketchCompleteAsync(Geometry geometry)
        {
            if (CurrentTemplate == null || geometry == null)
            {
                return(Task.FromResult(false));
            }

            return(QueuedTask.Run(() =>
            {
                //build a circular arc
                var cent = new Coordinate2D(geometry as MapPoint);
                var circleEAB = EllipticArcBuilderEx.CreateCircle(cent, Radius, ArcOrientation.ArcClockwise, MapView.Active.Map.SpatialReference);

                // find the source layer and determine whether polyline/polygon.  Create the appropriate shape
                var lyr = CurrentTemplate.Layer as BasicFeatureLayer;
                Geometry circleGeom = null;
                if (lyr.ShapeType == esriGeometryType.esriGeometryPolygon)
                {
                    circleGeom = PolygonBuilderEx.CreatePolygon(new[] { circleEAB }, AttributeFlags.None);
                }
                else
                {
                    circleGeom = PolylineBuilderEx.CreatePolyline(circleEAB, AttributeFlags.None);
                }

                // Create an edit operation
                var createOperation = new EditOperation();
                createOperation.Name = string.Format("Create circular {0}", CurrentTemplate.Layer.Name);
                createOperation.SelectNewFeatures = true;

                // Queue feature creation
                createOperation.Create(CurrentTemplate, circleGeom);

                // Execute the operation
                return createOperation.ExecuteAsync();
            }));
        }
コード例 #11
0
        /// <summary>
        /// This method takes an input multi part geometry and breaks the parts into individual standalone geometries.
        /// This method must be called on the MCT. Use QueuedTask.Run.
        /// </summary>
        /// <param name="inputGeometry">The geometry to be exploded into the individual parts.</param>
        /// <returns>An enumeration of individual parts as standalone geometries. The type of geometry is maintained, i.e.
        /// if the input geometry is of type Polyline then each geometry in the return is of type Polyline as well.
        /// If the input geometry is of type Unknown then an empty list is returned.</returns>
        /// <remarks>This method must be called on the MCT. Use QueuedTask.Run.</remarks>
        public IEnumerable <Geometry> MultipartToSinglePart(Geometry inputGeometry)
        {
            // list holding the part(s) of the input geometry
            List <Geometry> singleParts = new List <Geometry>();

            // check if the input is a null pointer or if the geometry is empty
            if (inputGeometry == null || inputGeometry.IsEmpty)
            {
                return(singleParts);
            }

            // based on the type of geometry, take the parts/points and add them individually into a list
            switch (inputGeometry.GeometryType)
            {
            case GeometryType.Envelope:
                singleParts.Add(inputGeometry.Clone() as Envelope);
                break;

            case GeometryType.Multipatch:
                singleParts.Add(inputGeometry.Clone() as Multipatch);
                break;

            case GeometryType.Multipoint:
                var multiPoint = inputGeometry as Multipoint;

                foreach (var point in multiPoint.Points)
                {
                    // add each point of collection as a standalone point into the list
                    singleParts.Add(point);
                }
                break;

            case GeometryType.Point:
                singleParts.Add(inputGeometry.Clone() as MapPoint);
                break;

            case GeometryType.Polygon:
                var polygon = inputGeometry as Polygon;

                foreach (var polygonPart in polygon.Parts)
                {
                    // use the PolygonBuilder turning the segments into a standalone
                    // polygon instance
                    singleParts.Add(PolygonBuilderEx.CreatePolygon(polygonPart));
                }
                break;

            case GeometryType.Polyline:
                var polyline = inputGeometry as Polyline;

                foreach (var polylinePart in polyline.Parts)
                {
                    // use the PolylineBuilder turning the segments into a standalone
                    // polyline instance
                    singleParts.Add(PolylineBuilderEx.CreatePolyline(polylinePart));
                }
                break;

            case GeometryType.Unknown:
                break;

            default:
                break;
            }

            return(singleParts);
        }
        protected override async Task <bool> OnSketchCompleteAsync(Geometry geometry)
        {
            // get the embedded control
            var vm = this.EmbeddableControl as ChooseTemplateViewModel;

            if (vm == null)
            {
                return(false);
            }

            // ensure there's a template chosen
            if (vm.SelectedTemplate == null)
            {
                vm.ShowMessage("Please choose a layer and template");
                return(false);
            }
            // clear any message
            vm.ClearMessage();

            var template = vm.SelectedTemplate;
            BasicFeatureLayer templateLayer = template.Layer as BasicFeatureLayer;

            if (templateLayer == null)
            {
                return(false);
            }

            bool result = await QueuedTask.Run(() =>
            {
                // find the target feature from the geometry click
                var targetFeatures = MapView.Active.GetFeatures(geometry);
                if ((targetFeatures == null) || (targetFeatures.ToDictionary().Keys.Count == 0))
                {
                    return(false);
                }

                // we will use the first feature returned
                var targetLayer = targetFeatures.ToDictionary().Keys.First();
                var targetOID   = targetFeatures[targetLayer][0];

                // At 2.4, EditOperation.TransferAttributes method is one of the few functions which honors the field mapping.
                // The only method signature for EditOperation.TransferAttributes requires a source and target feature
                // So our workflow will be
                // 1.  Create a temporary feature using the chosen template and empty geometry
                // 2.  Call TransferAttributes from the temporary feature to the target feature
                // 3.  Delete the temporary feature

                // build an empty geometry according to the correct template layer type
                Geometry emptyGeometry = null;
                switch (templateLayer.ShapeType)
                {
                case esriGeometryType.esriGeometryPoint:
                    emptyGeometry = MapPointBuilderEx.CreateMapPoint();
                    break;

                case esriGeometryType.esriGeometryPolyline:
                    emptyGeometry = PolylineBuilderEx.CreatePolyline();
                    break;

                case esriGeometryType.esriGeometryPolygon:
                    emptyGeometry = PolygonBuilderEx.CreatePolygon();
                    break;
                }

                // some other geometry type
                if (emptyGeometry == null)
                {
                    return(false);
                }

                // create the temporary feature using the empty geometry
                var op  = new EditOperation();
                op.Name = "Transfer attributes from template";

                // note Create signature.. we are interested in the new ObjectID
                var rowToken = op.Create(template, emptyGeometry);
                // execute
                var opResult = op.Execute();

                // if create was successful
                if (opResult)
                {
                    var newObjectID = rowToken.ObjectID.Value;
                    // chain to create a new operation
                    var opChain = op.CreateChainedOperation();
                    // transfer the attributes between the temporary feature and the target feature
                    opChain.TransferAttributes(templateLayer, newObjectID, targetLayer, targetOID);
                    // and now delete the temporary feature
                    opChain.Delete(templateLayer, newObjectID);
                    opResult = opChain.Execute();
                }

                return(opResult);
            });

            return(result);
        }
        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
                    });
                }
            });
        }
        private void CreateTable(string tableName, string filePath)
        {
            _dataTable.TableName = tableName;
            var oidCol = new DataColumn(ObjectIdFieldName, typeof(Int32))
            {
                AutoIncrement     = true,
                AutoIncrementSeed = 1
            };

            _dataTable.Columns.Add(oidCol);
            _dataTable.PrimaryKey = new DataColumn[] { oidCol };
            _dataTable.Columns.Add(new DataColumn(GeometryFieldName, typeof(ArcGIS.Core.Geometry.Geometry)));
            _dataTable.Columns.Add(new DataColumn(LongFieldName, typeof(Double)));
            _dataTable.Columns.Add(new DataColumn(LatFieldName, typeof(Double)));
            _dataTable.Columns.Add(new DataColumn(AltFieldName, typeof(Double)));
            if (_geomType == GeometryType.Polyline)
            {
                _dataTable.Columns.Add(new DataColumn(TypeFieldName, typeof(string)));
                _dataTable.Columns.Add(new DataColumn(DateTimeFieldName, typeof(DateTime)));
                _dataTable.Columns.Add(new DataColumn(NameFieldName, typeof(string)));
                _dataTable.Columns.Add(new DataColumn(CreatorFieldName, typeof(string)));
                _dataTable.Columns.Add(new DataColumn(CreatorVersionFieldName, typeof(string)));
            }
            else
            {
                _dataTable.Columns.Add(new DataColumn(TrkPntTime, typeof(DateTime)));
                _dataTable.Columns.Add(new DataColumn(TrkPntHr, typeof(Int32)));
                _dataTable.Columns.Add(new DataColumn(TrkPntCad, typeof(Int32)));
            }
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.Load(filePath);
            string xmlns             = xmlDoc.DocumentElement.NamespaceURI;
            XmlNamespaceManager nmsp = new XmlNamespaceManager(xmlDoc.NameTable);

            nmsp.AddNamespace("x", xmlns);
            DateTime    dateValue = DateTime.Now;
            XmlNodeList nodeList  = xmlDoc.DocumentElement.SelectNodes(@"//x:gpx/x:metadata/x:time", nmsp);

            if (nodeList.Count > 0)
            {
                var dateStr = nodeList[0].InnerText;
                try
                {
                    dateValue = DateTime.Parse(dateStr);
                    Console.WriteLine("'{0}' converted to {1}.", dateStr, dateValue);
                }
                catch (FormatException)
                {
                    Console.WriteLine("Unable to convert '{0}'.", dateStr);
                }
            }
            var creator        = string.Empty;
            var creatorVersion = string.Empty;

            nodeList = xmlDoc.DocumentElement.SelectNodes(@"//x:gpx", nmsp);
            if (nodeList.Count > 0)
            {
                var node = nodeList[0];
                foreach (XmlAttribute attr in node.Attributes)
                {
                    switch (attr.Name)
                    {
                    case "creator":
                        creator = attr.Value;
                        break;

                    case "version":
                        creatorVersion = attr.Value;
                        break;
                    }
                }
            }
            var activityName = string.Empty;
            var activityType = string.Empty;

            nodeList = xmlDoc.DocumentElement.SelectNodes("/x:gpx/x:trk/x:name", nmsp);
            if (nodeList.Count > 0)
            {
                activityName = nodeList[0].InnerText;
            }
            nodeList = xmlDoc.DocumentElement.SelectNodes("/x:gpx/x:trk/x:type", nmsp);
            if (nodeList.Count > 0)
            {
                activityType = nodeList[0].InnerText;
            }

            var newRow   = _dataTable.NewRow();
            var objectid = 1;
            // let's make a 3d line shape
            List <Coordinate3D> lst3DCoords = new List <Coordinate3D>();
            double   lng = 0.0, lat = 0.0, ele = 0.0;
            Int32    cad = -1, hr = -1;
            DateTime?trkTime = null;

            nodeList = xmlDoc.DocumentElement.SelectNodes("/x:gpx/x:trk/x:trkseg/x:trkpt", nmsp);
            foreach (XmlNode node in nodeList)
            {
                lng = double.Parse(node.Attributes["lon"].Value);
                lat = double.Parse(node.Attributes["lat"].Value);
                foreach (XmlNode childNode in node.ChildNodes)
                {
                    switch (childNode.Name)
                    {
                    case "ele":
                        ele = double.Parse(childNode.InnerText);
                        break;

                    case "time":
                        trkTime = DateTime.Parse(childNode.InnerText);
                        break;

                    case "extensions":
                        if (childNode.HasChildNodes)
                        {
                            foreach (XmlNode extNode in childNode.ChildNodes[0].ChildNodes)
                            {
                                switch (extNode.LocalName)
                                {
                                case "hr":
                                    hr = Int32.Parse(extNode.InnerText);
                                    break;

                                case "cad":
                                    cad = Int32.Parse(extNode.InnerText);
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }

                if (_geomType == GeometryType.Polyline)
                {
                    lst3DCoords.Add(new Coordinate3D(lng, lat, ele));
                }
                else
                {   // for the point variety we only have many rows
                    newRow[ObjectIdFieldName] = objectid++;
                    var mp = MapPointBuilderEx.CreateMapPoint(new Coordinate3D(lng, lat, ele), _spatialReference);
                    newRow[GeometryFieldName] = mp;
                    newRow[LongFieldName]     = lng;
                    newRow[LatFieldName]      = lat;
                    newRow[AltFieldName]      = ele;
                    if (trkTime.HasValue)
                    {
                        newRow[TrkPntTime] = trkTime.Value;
                    }
                    newRow[TrkPntHr]  = hr;
                    newRow[TrkPntCad] = cad;
                    _dataTable.Rows.Add(newRow);
                    _gisExtent = _gisExtent == null
                        ? mp.Extent : _gisExtent.Union(mp.Extent);
                    newRow = _dataTable.NewRow();
                }
            }
            if (_geomType == GeometryType.Polyline)
            {   // for the line variety we only have one row
                newRow[ObjectIdFieldName] = objectid;
                var pl = PolylineBuilderEx.CreatePolyline(lst3DCoords, _spatialReference);
                newRow[GeometryFieldName]       = pl;
                newRow[LongFieldName]           = lng;
                newRow[LatFieldName]            = lat;
                newRow[AltFieldName]            = ele;
                newRow[TypeFieldName]           = activityType;
                newRow[DateTimeFieldName]       = dateValue;
                newRow[NameFieldName]           = activityName;
                newRow[CreatorFieldName]        = creator;
                newRow[CreatorVersionFieldName] = creatorVersion;
                _dataTable.Rows.Add(newRow);
                _gisExtent = _gisExtent == null
                    ? pl.Extent : _gisExtent.Union(pl.Extent);
            }
        }
コード例 #15
0
        /// <summary>
        /// Creates keyframes along the path using the user defined settings.
        /// </summary>
        /// <param name="line">The geometry of the line to fly along.</param>
        /// <param name="verticalUnit">The elevation unit of the 3D layer</param>
        internal Task CreateKeyframesAlongPath(Polyline line, Unit verticalUnit)
        {
            return(QueuedTask.Run(() =>
            {
                var mapView = MapView.Active;
                if (mapView == null)
                {
                    return;
                }

                //Get the camera track from the active map's animation.
                //There will always be only one camera track in the animation.
                var cameraTrack = mapView.Map.Animation.Tracks.OfType <CameraTrack>().First();

                //Get some of the user settings for constructing the keyframes alone the path.
                var densifyDistance = Animation.Settings.KeyEvery;
                var verticalOffset = Animation.Settings.HeightAbove / ((mapView.Map.SpatialReference.IsGeographic) ? 1.0 : mapView.Map.SpatialReference.Unit.ConversionFactor); //1 meter
                double currentTimeSeconds = GetInsertTime(mapView.Map.Animation);

                //We need to project the line to a projected coordinate system to calculate the line's length in 3D
                //as well as more accurately calculated heading and pitch along the path.
                if (line.SpatialReference.IsGeographic)
                {
                    if (mapView.Map.SpatialReference.IsGeographic)
                    {
                        var transformation = ProjectionTransformation.Create(line.SpatialReference, SpatialReferences.WebMercator, line.Extent);
                        line = GeometryEngine.Instance.ProjectEx(line, transformation) as Polyline;
                    }
                    else
                    {
                        var transformation = ProjectionTransformation.Create(line.SpatialReference, mapView.Map.SpatialReference, line.Extent);
                        line = GeometryEngine.Instance.ProjectEx(line, transformation) as Polyline;
                    }
                }

                //If the user has specified to create keyframes at additional locations than just the vertices
                //we will densify the line by the distance the user specified.
                if (!Animation.Settings.VerticesOnly)
                {
                    line = GeometryEngine.Instance.DensifyByLength(line, densifyDistance / line.SpatialReference.Unit.ConversionFactor) as Polyline;
                }

                //To maintain a constant speed we need to divide the total time we want the animation to take by the length of the line.
                var duration = Animation.Settings.Duration;
                var secondsPerUnit = duration / line.Length3D;
                Camera prevCamera = null;

                //Loop over each vertex in the line and create a new keyframe at each.
                for (int i = 0; i < line.PointCount; i++)
                {
                    #region Camera

                    MapPoint cameraPoint = line.Points[i];

                    //If the point is not in the same spatial reference of the map we need to project it.
                    if (cameraPoint.SpatialReference.Wkid != mapView.Map.SpatialReference.Wkid)
                    {
                        var transformation = ProjectionTransformation.Create(cameraPoint.SpatialReference, mapView.Map.SpatialReference);
                        cameraPoint = GeometryEngine.Instance.Project(cameraPoint, mapView.Map.SpatialReference) as MapPoint;
                    }

                    //Construct a new camera from the point.
                    var camera = new Camera(cameraPoint.X, cameraPoint.Y, cameraPoint.Z,
                                            Animation.Settings.Pitch, 0.0, cameraPoint.SpatialReference, CameraViewpoint.LookFrom);

                    //Convert the Z unit to meters if the camera is not in a geographic coordinate system.
                    if (!camera.SpatialReference.IsGeographic)
                    {
                        camera.Z /= camera.SpatialReference.Unit.ConversionFactor;
                    }

                    //Convert the Z to the unit of the layer's elevation unit and then add the user defined offset from the line.
                    camera.Z *= verticalUnit.ConversionFactor;
                    camera.Z += verticalOffset;

                    //If this is the last point in the collection use the same heading and pitch from the previous camera.
                    if (i + 1 == line.Points.Count)
                    {
                        camera.Heading = prevCamera.Heading;
                        camera.Pitch = prevCamera.Pitch;
                    }
                    else
                    {
                        var currentPoint = line.Points[i];
                        var nextPoint = line.Points[i + 1];

                        #region Heading

                        //Calculate the heading from the current point to the next point in the path.
                        var difX = nextPoint.X - currentPoint.X;
                        var difY = nextPoint.Y - currentPoint.Y;
                        var radian = Math.Atan2(difX, difY);
                        var heading = radian * -180 / Math.PI;
                        camera.Heading = heading;

                        #endregion

                        #region Pitch

                        //If the user doesn't want to hardcode the pitch, calculate the pitch based on the current point to the next point.
                        if (Animation.Settings.UseLinePitch)
                        {
                            var hypotenuse = Math.Sqrt(Math.Pow(difX, 2) + Math.Pow(difY, 2));
                            var difZ = nextPoint.Z - currentPoint.Z;
                            //If the line's unit is not the same as the elevation unit of the layer we need to convert the Z so they are in the same unit.
                            if (line.SpatialReference.Unit.ConversionFactor != verticalUnit.ConversionFactor)
                            {
                                difZ *= (verticalUnit.ConversionFactor / line.SpatialReference.Unit.ConversionFactor);
                            }
                            radian = Math.Atan2(difZ, hypotenuse);
                            var pitch = radian * 180 / Math.PI;
                            camera.Pitch = pitch;
                        }
                        else
                        {
                            camera.Pitch = Animation.Settings.Pitch;
                        }

                        #endregion
                    }

                    #endregion

                    #region Time

                    //The first point will have a time of 0 seconds, after that we need to set the time based on the 3D distance between the points.
                    if (i > 0)
                    {
                        var lineSegment = PolylineBuilderEx.CreatePolyline(new List <MapPoint>()
                        {
                            line.Points[i - 1], line.Points[i]
                        },
                                                                           AttributeFlags.HasZ,
                                                                           line.SpatialReference);
                        var length = lineSegment.Length3D;
                        currentTimeSeconds += length * secondsPerUnit;
                    }

                    #endregion

                    //Create a new keyframe using the camera and the time.
                    cameraTrack.CreateKeyframe(camera, TimeSpan.FromSeconds(currentTimeSeconds), AnimationTransition.Linear);
                    prevCamera = camera;
                }
            }));
        }