/// <summary> /// Update the CIMPointGraphic location /// </summary> /// <param name="point"></param> public void UpdateLocation(PointN point) { ArcGIS.Core.Geometry.SpatialReference sptlRef = SpatialReferenceBuilder.CreateSpatialReference(point.SpatialReference.WKID); MapPoint mapPoint = MapPointBuilderEx.CreateMapPoint(point.X, point.Y, sptlRef); _graphic.Location = mapPoint; }
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 a CIMPointGaphic which can be added to the MapView overlay. /// </summary> /// <param name="point">The location for the point (as a CIM point)</param> /// <returns></returns> public CIMPointGraphic MakeCIMPointGraphic(PointN point) { CIMMarker marker = SymbolFactory.Instance.ConstructMarker(Red, 10, SimpleMarkerStyle.Star); CIMSymbolLayer[] layers = new CIMSymbolLayer[1]; layers[0] = marker; CIMPointSymbol pointSymbol = new CIMPointSymbol() { SymbolLayers = layers, ScaleX = 1 }; CIMSymbolReference symbolRef = new CIMSymbolReference() { Symbol = pointSymbol }; CIMPointGraphic pointGraphic = new CIMPointGraphic(); ArcGIS.Core.Geometry.SpatialReference spatialRef = SpatialReferenceBuilder.CreateSpatialReference(point.SpatialReference.WKID); MapPoint mapPoint = MapPointBuilderEx.CreateMapPoint(point.X, point.Y, spatialRef); pointGraphic.Location = mapPoint; pointGraphic.Symbol = symbolRef; return(pointGraphic); }
// CreateOffsetMapPoint - creates a new MapPoint offset from a given base point. private MapPoint CreateOffsetMapPoint(MapPoint basePoint, double xOffset, double yOffset) { MapPointBuilderEx mapPointBuilder = new MapPointBuilderEx(); mapPointBuilder.X = basePoint.X + xOffset; mapPointBuilder.Y = basePoint.Y + yOffset; mapPointBuilder.Z = basePoint.Z; mapPointBuilder.HasZ = true; return(mapPointBuilder.ToGeometry()); }
public async Task <MapPoint> ToMapPoint() { if (_mapPoint == null) { await QueuedTask.Run(() => { ArcGIS.Core.Geometry.SpatialReference sr = SpatialReferenceBuilder.CreateSpatialReference(WKID); _mapPoint = MapPointBuilderEx.CreateMapPoint(Feature.Location.X, Feature.Location.Y, sr); }); } return(_mapPoint); }
/// <summary> /// Create random sample points in the extent of the spatial reference /// </summary> /// <param name="pointFeatureLayer">Point geometry feature layer used to the generate the points.</param> /// <returns>Task{bool}</returns> private Task <bool> ConstructSamplePoints(FeatureLayer pointFeatureLayer) { // create a random number generator var randomGenerator = new Random(); // the database and geometry interactions are considered fine-grained and must be executed on // the main CIM thread return(QueuedTask.Run(() => { // start an edit operation to create new (random) point features var createOperation = new EditOperation() { Name = "Generate points", SelectNewFeatures = false }; // get the feature class associated with the layer var featureClass = pointFeatureLayer.GetTable() as FeatureClass; // define an area of interest. Random points are generated in the allowed // confines of the allow extent range var areaOfInterest = MapView.Active.Extent; MapPoint newMapPoint = null; // retrieve the class definition of the point feature class var classDefinition = featureClass.GetDefinition() as FeatureClassDefinition; // store the spatial reference as its own variable var spatialReference = classDefinition.GetSpatialReference(); // create 20 new point geometries and queue them for creation for (int i = 0; i < 20; i++) { // generate either 2D or 3D geometries if (classDefinition.HasZ()) { newMapPoint = MapPointBuilderEx.CreateMapPoint(randomGenerator.NextCoordinate3D(areaOfInterest), spatialReference); } else { newMapPoint = MapPointBuilderEx.CreateMapPoint(randomGenerator.NextCoordinate2D(areaOfInterest), spatialReference); } // queue feature creation createOperation.Create(pointFeatureLayer, newMapPoint); } // execute the edit (feature creation) operation return createOperation.ExecuteAsync(); })); }
/// <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()); }); }
private void CreateTable(string tableName, List <XimgInfo> ximgInfos) { _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))); _dataTable.Columns.Add(new DataColumn(DirectionFieldName, typeof(Double))); _dataTable.Columns.Add(new DataColumn(DateTimeFieldName, typeof(DateTime))); //_dataTable.Columns.Add(new DataColumn(ImageFieldName, typeof(byte[]))); _dataTable.Columns.Add(new DataColumn(PathFieldName, typeof(string))); _dataTable.Columns.Add(new DataColumn(ContentTypeFieldName, typeof(string))); _dataTable.Columns.Add(new DataColumn(NameFieldName, typeof(string))); int objectId = 1; foreach (var ximgInfo in ximgInfos) { var newRow = _dataTable.NewRow(); newRow[ObjectIdFieldName] = objectId++; // let's make a 3d shape var coord = new Coordinate3D(ximgInfo.Longitude, ximgInfo.Latitude, ximgInfo.Altitude); var mp = MapPointBuilderEx.CreateMapPoint(coord, _spatialReference); newRow[GeometryFieldName] = mp; newRow[LongFieldName] = ximgInfo.Longitude; newRow[LatFieldName] = ximgInfo.Latitude; newRow[AltFieldName] = ximgInfo.Altitude; newRow[DirectionFieldName] = ximgInfo.ImageBearing; newRow[DateTimeFieldName] = ximgInfo.DateTimeOriginal; //newRow[ImageFieldName] = ximgInfo.Image; newRow[PathFieldName] = $@"file:///{ximgInfo.Path}"; newRow[ContentTypeFieldName] = @"image/jpeg"; newRow[NameFieldName] = ximgInfo.Name; _dataTable.Rows.Add(newRow); _gisExtent = _gisExtent == null ? mp.Extent : _gisExtent.Union(mp.Extent); } }
/// <summary> /// Custom interface specific to the way the sample is implemented. /// </summary> public PluginRow FindRow(long oid, IEnumerable <string> columnFilter, SpatialReference srout) { Geometry shape = null; List <object> values = new List <object>(); var row = _table.Rows.Find(oid); //The order of the columns in the returned rows ~must~ match //GetFields. If a column is filtered out, an empty placeholder must //still be provided even though the actual value is skipped var columnNames = this.GetFields().Select(col => col.Name.ToUpper()).ToList(); foreach (var colName in columnNames) { if (columnFilter.Contains(colName)) { //special handling for shape if (colName == "SHAPE") { var buffer = row["SHAPE"] as Byte[]; shape = MapPointBuilderEx.FromEsriShape(buffer, _sr); if (srout != null) { if (!srout.Equals(_sr)) { shape = GeometryEngine.Instance.Project(shape, srout); } } values.Add(shape); } else { values.Add(row[colName]); } } else { values.Add(System.DBNull.Value);//place holder } } return(new PluginRow() { Values = values }); }
private void AddTableToLayout(Layout layout, Map theMap, MapFrame mfElm, string layerName, SetPage setPage, double yOffset) { var lyrs = theMap.FindLayers(layerName, true); if (lyrs.Count > 0) { Layer lyr = lyrs[0]; var ptSymbol = GetPointSymbolFromLayer(lyr); if (ptSymbol != null) { Coordinate2D llSym = new Coordinate2D(setPage.XOffsetMapMarginalia, setPage.YOffsetSymbol + yOffset); var geom = MapPointBuilderEx.CreateMapPoint(llSym); var sym = ElementFactory.Instance.CreateGraphicElement(layout, geom, ptSymbol); Coordinate2D llText = new Coordinate2D(setPage.XOffsetMapMarginalia + sym.GetWidth(), setPage.YOffsetSymbol + yOffset - sym.GetHeight() / 2); var geomLLText = MapPointBuilderEx.CreateMapPoint(llText); var text = ElementFactory.Instance.CreateTextGraphicElement(layout, TextType.PointText, geomLLText); text.SetAnchor(Anchor.CenterPoint); text.SetHeight(text.GetHeight()); if (text.GetHeight() > sym.GetHeight()) { sym.SetLockedAspectRatio(true); sym.SetHeight(text.GetHeight()); } else { text.SetLockedAspectRatio(true); text.SetHeight(sym.GetHeight()); } } Coordinate2D llTab1 = new Coordinate2D(setPage.XOffsetMapMarginalia, yOffset - setPage.HeightPartsMarginalia); Coordinate2D urTab1 = new Coordinate2D(setPage.XOffsetMapMarginalia + setPage.XWidthMapMarginalia, yOffset); var tableFrameInfo = new TableFrameInfo() { MapFrameName = mfElm.Name, MapMemberUri = lyr.URI }; var table1 = ElementFactory.Instance.CreateMapSurroundElement(layout, EnvelopeBuilderEx.CreateEnvelope(llTab1, urTab1), tableFrameInfo) as TableFrame; } }
private void DoCreate() { var x1 = 7683671.0; var y1 = 687075.0; var crimes = Module1.Current.Crimes; if (NoCrimes(crimes)) { return; } var editOp = new EditOperation(); editOp.Name = $"Create {Module1.Current.CrimesLayerName}"; editOp.SelectNewFeatures = true; QueuedTask.Run(() => { //do multiple creates if specified for (int i = 0; i < _numCreatesAtOneTime; i++) { x1 += _offset; y1 += _offset; _offset += _delta; var pt = MapPointBuilderEx.CreateMapPoint(x1, y1, crimes.GetSpatialReference()); Dictionary <string, object> attributes = new Dictionary <string, object>(); attributes["SHAPE"] = pt; attributes["OFFENSE_TYPE"] = 4; attributes["MAJOR_OFFENSE_TYPE"] = "DUI"; //do the create editOp.Create(crimes, attributes); } editOp.Execute(); }); }
private void UpdateRowIfNeeded(RowChangedEventArgs args) { // From the ProConcept documentation @https://github.com/esri/arcgis-pro-sdk/wiki/ProConcepts-Editing#row-events // If you need to edit additional tables within the RowEvent you must use the // ArcGIS.Core.Data API to edit the tables directly. // Do not use a new edit operation to create or modify features or rows in your // RowEvent callbacks. // RowEvent callbacks are always called on the QueuedTask so there is no need // to wrap your code within a QueuedTask.Run lambda. try { // prevent re-entrance (only if row.Store() is called) if (_isStoreInOnRowEventEnabled && _currentRowChangedGuid == args.Guid) { UpdateStatusText($@"Re-entrant call - ignored"); return; } var row = args.Row; var rowDefinition = (row.GetTable() as FeatureClass).GetDefinition(); var geom = row[rowDefinition.GetShapeField()] as Geometry; MapPoint pntLogging = null; var rowCursorOverlayPoly = _workedOnPolygonLayer.Search(geom, SpatialRelationship.Intersects); Geometry geomOverlap = null; Geometry geomChangedPolygon = null; while (rowCursorOverlayPoly.MoveNext()) { using (var feature = rowCursorOverlayPoly.Current as Feature) { var geomOverlayPoly = feature.GetShape(); if (geomOverlayPoly == null) { continue; } // exclude the search polygon if (row.GetObjectID() == feature.GetObjectID()) { geomChangedPolygon = geomOverlayPoly.Clone(); continue; } if (geomOverlap == null) { geomOverlap = geomOverlayPoly.Clone(); continue; } geomOverlap = GeometryEngine.Instance.Union(geomOverlap, geomOverlayPoly); } } var description = string.Empty; if (!geomOverlap.IsNullOrEmpty()) { var correctedGeom = GeometryEngine.Instance.Difference(geom, geomOverlap); row["Shape"] = correctedGeom; if (!correctedGeom.IsNullOrEmpty()) { // use the centerpoint of the polygon as the point for the logging entry pntLogging = GeometryEngine.Instance.LabelPoint(correctedGeom); } description = correctedGeom.IsEmpty ? "Polygon can't be inside existing polygon" : "Corrected input polygon"; } else { description = "No overlapping polygons found"; if (!geomChangedPolygon.IsNullOrEmpty()) { pntLogging = GeometryEngine.Instance.LabelPoint(geomChangedPolygon); } } row["Description"] = description; UpdateStatusText($@"Row: {description}"); if (_isStoreInOnRowEventEnabled) { // calling store will result in a recursive row changed event as long as any // attribute columns have changed // In this case i would need to look at args.Guid to prevent re-entrance _currentRowChangedGuid = args.Guid; row.Store(); _currentRowChangedGuid = Guid.Empty; } // update logging feature class with centerpoint of polygon if (!pntLogging.IsNullOrEmpty()) { var geoDatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))); var loggingFeatureClass = geoDatabase.OpenDataset <FeatureClass>(_pointLayerName); var loggingFCDefinition = loggingFeatureClass.GetDefinition(); using (var rowbuff = loggingFeatureClass.CreateRowBuffer()) { // needs a 3D point rowbuff[loggingFCDefinition.GetShapeField()] = MapPointBuilderEx.CreateMapPoint(pntLogging.X, pntLogging.Y, 0, pntLogging.SpatialReference); rowbuff["Description"] = "OID: " + row.GetObjectID().ToString() + " " + DateTime.Now.ToShortTimeString(); loggingFeatureClass.CreateRow(rowbuff); } } } catch (Exception e) { MessageBox.Show($@"Error in UpdateRowIfNeeded for OID: {args.Row.GetObjectID()} in {_workedOnPolygonLayer.Name}: {e.ToString()}"); } }
/// <summary> /// Updates the report with the new field and the title of the field. /// </summary> /// <remarks> /// New Field: The new field gets added to the ReportDetails section. /// Field title: If the report is grouped, the title goes in the "GroupHeader". If not, the title goes in the PageHeader section. /// </remarks> /// <returns></returns> private async Task UpdateReport() { await GetReportsInProjectAsync(); await QueuedTask.Run(() => { //report to update var reportToUpdate = _reportsInProject.FirstOrDefault(r => r.Name == ReportName); //Create field foreach (var field in _fieldsAddToReport) { //Get the "ReportSectionElement" var mainReportSection = reportToUpdate.Elements.OfType<ReportSection>().FirstOrDefault(); if (mainReportSection == null) return; #region Field content //Get the "ReportDetails" within the ReportSectionElement. ReportDetails is where "fields" are. var reportDetailsSection = mainReportSection?.Elements.OfType<ReportDetails>().FirstOrDefault(); if (reportDetailsSection == null) return; //Within ReportDetails find the envelope that encloses a field. //We get the first CIMParagraphTextGraphic in the collection so that we can add the new field next to it. var lastFieldGraphic = reportDetailsSection.Elements.FirstOrDefault((r) => { var gr = r as GraphicElement; if (gr == null) return false; return (gr.GetGraphic() is CIMParagraphTextGraphic ? true : false); }); //Get the Envelope of the last field var graphicBounds = lastFieldGraphic.GetBounds(); //Min and Max values of the envelope var xMinOfFieldEnvelope = graphicBounds.XMin; var yMinOfFieldEnvelope = graphicBounds.YMin; var xMaxOfFieldEnvelope = graphicBounds.XMax; var YMaxOfFieldEnvelope = graphicBounds.YMax; //create the new Envelope to be offset from the existing field MapPoint newMinPoint = MapPointBuilderEx.CreateMapPoint(xMinOfFieldEnvelope + fieldIncrement, yMinOfFieldEnvelope); MapPoint newMaxPoint = MapPointBuilderEx.CreateMapPoint(xMaxOfFieldEnvelope + fieldIncrement, YMaxOfFieldEnvelope); Envelope newFieldEnvelope = EnvelopeBuilderEx.CreateEnvelope(newMinPoint, newMaxPoint); #endregion //Create field GraphicElement fieldGraphic = ReportElementFactory.Instance.CreateFieldValueTextElement(reportDetailsSection, newFieldEnvelope, field); #region Field title Envelope envelopeOfLastField = null; IElementContainer reportsSection; //Field title in Page Header. //Get the Page header section var pageHeaderSection = mainReportSection?.Elements.OfType<ReportPageHeader>().FirstOrDefault(); //Check if there are any elements in the page header section. If there are none, the report is "Grouped" if (pageHeaderSection.Elements.Count() == 0) //Page header has no child elements. The report is grouped on a field. { //Get Group Header. // the title needs to be in the GroupHeader section. var reportGroupHeader = mainReportSection?.Elements.OfType<ReportGroupHeader>().FirstOrDefault(); List<Element> textGraphicsInReportHeader = new List<Element>(); foreach (var elm in reportGroupHeader.Elements) { var elmGraphic = elm as GraphicElement; if (elmGraphic == null) continue; var graphic = elmGraphic.GetGraphic(); var cimParaGraphic = graphic as CIMParagraphTextGraphic; if (cimParaGraphic != null) textGraphicsInReportHeader.Add(elmGraphic); } //Get the Envelope of the last field header envelopeOfLastField = textGraphicsInReportHeader?.FirstOrDefault().GetBounds(); //The IElementContainer is the "GroupHeader". Needed for the CreateRectangleParagraphGraphicElement method reportsSection = reportGroupHeader; } else //not grouped { //Get the "ReportPageHeader" within the ReportSectionElement. ReportPageHeader is where "fields titles" are. //var reportPageHeader = mainReportSection?.Elements.OfType<ReportPageHeader>().FirstOrDefault(); //Get the paragraph text element (the last title) List<Element> textGraphicsInPageHeader = new List<Element>(); foreach (var elm in pageHeaderSection.Elements) { var elmGraphic = elm as GraphicElement; if (elmGraphic == null) continue; var graphic = elmGraphic.GetGraphic(); var cimParaGraphic = graphic as CIMParagraphTextGraphic; if (cimParaGraphic != null) textGraphicsInPageHeader.Add(elmGraphic); } if (textGraphicsInPageHeader.Count > 0) { //Get the Envelope of the last field header envelopeOfLastField = textGraphicsInPageHeader.FirstOrDefault().GetBounds(); } } if (envelopeOfLastField != null) { //Min and Max values of the envelope var xMinOfHeaderFieldEnvelope = envelopeOfLastField.XMin; var yMinOfHeaderFieldEnvelope = envelopeOfLastField.YMin; var xMaxOfHeaderFieldEnvelope = envelopeOfLastField.XMax; var YMaxOfHeaderFieldEnvelope = envelopeOfLastField.YMax; //create the new Envelope to be offset from the existing field MapPoint newHeaderMinPoint = MapPointBuilderEx.CreateMapPoint(xMinOfHeaderFieldEnvelope + fieldIncrement, yMinOfHeaderFieldEnvelope); MapPoint newHeaderMaxPoint = MapPointBuilderEx.CreateMapPoint(xMaxOfHeaderFieldEnvelope + fieldIncrement, YMaxOfHeaderFieldEnvelope); Envelope newHeaderFieldEnvelope = EnvelopeBuilderEx.CreateEnvelope(newHeaderMinPoint, newHeaderMaxPoint); #endregion //The ILayoutElementContainer is the "PageHeader". Needed for the CreateRectangleParagraphGraphicElement method reportsSection = pageHeaderSection; //Create field header title GraphicElement fieldHeaderGraphic = ReportElementFactory.Instance.CreateRectangleParagraphGraphicElement(reportsSection, newHeaderFieldEnvelope, field.Name); } } }); }
/// <summary>Get the Lat, Long from the Bing StreetSide View to set the location on the Pro Map</summary> public static Task SetMapLocationFromBing(double?longitude, double?latitude, int heading) { #region Process Heading var activeMapView = MapView.Active; if (activeMapView == null) { return(null); } #endregion return(QueuedTask.Run(() => { try { var cam = activeMapView.Camera; var bHeadingChange = Convert.ToInt32(cam.Heading) != heading; cam.Heading = Convert.ToDouble(heading); if (longitude.HasValue && latitude.HasValue) { var pt = MapPointBuilderEx.CreateMapPoint(longitude.Value, latitude.Value, SpatialReferences.WGS84); var center = GeometryEngine.Instance.Project(pt, activeMapView.Map.SpatialReference) as MapPoint; if (center == null) { return; } ShowCurrentBingMapCoord(center); #region Update Map // check if the center is outside the map view extent var env = activeMapView.Extent.Expand(0.75, 0.75, true); var bWithin = GeometryEngine.Instance.Within(center, env); if (!bWithin) { cam.X = center.X; cam.Y = center.Y; } if (_bFirst) { cam.Scale = 2000; activeMapView.ZoomTo(cam, TimeSpan.FromMilliseconds(100)); _bFirst = false; } else { activeMapView.PanTo(cam, TimeSpan.FromMilliseconds(1000)); } bHeadingChange = false; #endregion } if (bHeadingChange) { activeMapView.PanTo(cam, TimeSpan.FromMilliseconds(300)); } } catch (Exception ex) { Debug.WriteLine($@"Error in SetMapLocationFromBing: {ex.Message}"); } })); }
/// <summary> /// Create keyframes centered around a point. /// </summary> /// <param name="point">The center point around which the keyframes are created.</param> internal Task CreateKeyframesAroundPoint(MapPoint point) { return(QueuedTask.Run(() => { var mapView = MapView.Active; var degrees = Animation.Settings.Degrees; if (mapView == null || degrees == 0) { 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(); var camera = mapView.Camera; //Calculate the number of keys to create. var keyEvery = (degrees < 0) ? -10 : 10; //10 degrees var numOfKeys = Math.Floor(degrees / keyEvery); var remainder = degrees % keyEvery; //To maintain a constant speed we need to divide the total time we want the animation to take by the number of degrees of rotation. var duration = Animation.Settings.Duration; double timeInterval = duration / Math.Abs(degrees); double currentTimeSeconds = GetInsertTime(mapView.Map.Animation); //Get the distance from the current location to the point we want to rotate around to get the radius. var cameraPoint = MapPointBuilderEx.CreateMapPoint(camera.X, camera.Y, camera.SpatialReference); var radius = GeometryEngine.Instance.GeodesicDistance(cameraPoint, point); var radian = ((camera.Heading - 90) / 180.0) * Math.PI; //If the spatial reference of the point is projected and the unit is not in meters we need to convert the Z values to meters. if (!point.SpatialReference.IsGeographic && point.SpatialReference.Unit.ConversionFactor != 1.0) { point = MapPointBuilderEx.CreateMapPoint(point.X, point.Y, point.Z * point.SpatialReference.Unit.ConversionFactor, point.SpatialReference); } //For all geodesic calculations we will use WGS84 so we will project the point if it is not already. if (point.SpatialReference.Wkid != SpatialReferences.WGS84.Wkid) { var transformation = ProjectionTransformation.Create(point.SpatialReference, SpatialReferences.WGS84); point = GeometryEngine.Instance.ProjectEx(point, transformation) as MapPoint; } //Create an ellipse around the center point. var parameter = new GeodesicEllipseParameter() { Center = point.Coordinate2D, SemiAxis1Length = radius, SemiAxis2Length = radius, AxisDirection = radian, LinearUnit = LinearUnit.Meters, OutGeometryType = GeometryType.Polyline, VertexCount = 36 }; var ellipse = GeometryEngine.Instance.GeodesicEllipse(parameter, point.SpatialReference) as Polyline; //For each key we will progressively rotate around the ellipse and calculate the camera position at each. for (int i = 0; i <= numOfKeys; i++) { var percentAlong = ((Math.Abs(keyEvery) * i) % 360) / 360.0; if (keyEvery > 0) { percentAlong = 1 - percentAlong; } //Get the camera at the position around the ellipse. camera = OffsetCamera(camera, ellipse, point, percentAlong); //Increment the time by the amount of time per key. if (i != 0) { currentTimeSeconds += (timeInterval * Math.Abs(keyEvery)); } //Create a new keyframe for the camera. cameraTrack.CreateKeyframe(camera, TimeSpan.FromSeconds(currentTimeSeconds), AnimationTransition.FixedArc); } //For any degree rotation left over create a keyframe. For example 155, would have a keyframe every 10 degrees and then one for the final 5 degrees. if (remainder != 0.0) { var percentAlong = ((Math.Abs(keyEvery) * numOfKeys + Math.Abs(remainder)) % 360) / 360.0; if (remainder > 0) { percentAlong = 1 - percentAlong; } OffsetCamera(camera, ellipse, point, percentAlong); //Increment the time and create the keyframe. currentTimeSeconds += (timeInterval * Math.Abs(remainder)); cameraTrack.CreateKeyframe(camera, TimeSpan.FromSeconds(currentTimeSeconds), AnimationTransition.FixedArc); } })); }
public QuakeEventCustomItem(string name, string path, string type, string lastModifiedTime, double longitude, double latitude) : base(name, path, type, lastModifiedTime) { this.DisplayType = "QuakeEvent"; QuakeLocation = MapPointBuilderEx.CreateMapPoint( longitude, latitude, SpatialReferences.WGS84); }
public void GenerateKeyframes(string animationType) { try { QueuedTask.Run(() => { if (VehicleListComboBoxValue.Text == "" || VehicleListComboBoxValue.Text == null) { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("No Vehicle Route selected. Exiting...", "Value Needed"); return; } string VehiclePointsLayer = VehicleListComboBoxValue.Text + "_Route"; // Iterate and list the layers within the group layer // string pointLayerName = System.IO.Path.GetFileName(outfc); var pointLayer = MapView.Active.Map.FindLayers("VehiclePoints_" + VehiclePointsLayer).FirstOrDefault() as BasicFeatureLayer; if (pointLayer == null) { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Can't find the layer: " + "VehiclePoints_" + VehiclePointsLayer + ". Exiting...", "Info"); return; } // Ensure there's a value in the speed edit box if (SpeedValueEditBox.Text == "" && animationType == "use speed") { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("The Speed in MPH value Editbox is empty. Exiting...", "Value Needed"); SpeedValueEditBox.Text = ""; return; } double speedValueMPH; bool isNumeric = Double.TryParse(SpeedValueEditBox.Text, out speedValueMPH); // Ensure there's a value in the speed edit box if (isNumeric != true && animationType == "use speed") { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("The Speed in MPH value Editbox is not invalid. Type in a new value. Exiting...", "Value Needed"); SpeedValueEditBox.Text = ""; return; } // Prompt for confirmation, and if answer is no, return. if (animationType == "use speed") { var result = MessageBox.Show("Confirm building of " + VehicleListComboBoxValue.Text.ToUpper() + " animation simulating vehicle speed of " + SpeedValueEditBox.Text + " MPH?", "Build Animation", System.Windows.MessageBoxButton.OKCancel, System.Windows.MessageBoxImage.Asterisk); // Return if cancel value is chosen if (Convert.ToString(result) == "Cancel") { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Operation Canceled.", "Info"); return; } } else if (animationType == "ten-second") { var result = MessageBox.Show("Confirm building of " + VehicleListComboBoxValue.Text.ToUpper() + " 10-SECOND duration animation?", "Build Animation", System.Windows.MessageBoxButton.OKCancel, System.Windows.MessageBoxImage.Asterisk); // Return if cancel value is chosen if (Convert.ToString(result) == "Cancel") { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Operation Canceled.", "Info"); return; } } int viewDistance = 0; if (VehiclePointsLayer == "Car_Route") { viewDistance = 100; } else if (VehiclePointsLayer == "Boat_Route") { viewDistance = 200; } else if (VehiclePointsLayer == "Helicopter_Route") { viewDistance = 300; } // SET UP 3D MODEL SYMBOL AND SETTINGS // Use the speed value to set keyframe timespan - Calculate distance covered in seconds and milliseconds based on speed and distance between points // NOTE: Assumes map units are in feet. This is key. // Calculate the Timespan using speed: int rowNumber; RowCursor pointsRowcursor; long numPoints; // Tempororily set to empty timespans TimeSpan temp_span = new TimeSpan(0, 0, 0, 0, 0); TimeSpan temp_newTimeSpan = new TimeSpan(0, 0, 0, 0, 0); if (animationType == "use speed") { // Get the value of the distance between features. rowNumber = 0; MapPoint mapPoint1 = null; MapPoint mapPoint2 = null; pointsRowcursor = pointLayer.Search(null); numPoints = pointLayer.GetTable().GetCount(); while (rowNumber < 3) { rowNumber += 1; using (Row currentRow = pointsRowcursor.Current) { if (pointsRowcursor.MoveNext()) { using (var pointFeature = pointsRowcursor.Current as Feature) { if (rowNumber == 1) { mapPoint1 = pointFeature.GetShape().Clone() as MapPoint; } else if (rowNumber == 2) { mapPoint2 = pointFeature.GetShape().Clone() as MapPoint; } } } } } pointsRowcursor.Dispose(); double dblDistBetween = GeometryEngine.Instance.Distance(mapPoint1, mapPoint2); double dblFeetPerSecond = (speedValueMPH * 5280) / 3600; double dblSecondsPerPoint = dblDistBetween / dblFeetPerSecond; Double dblSec = Math.Truncate(dblSecondsPerPoint); Double dblMilliSec = dblSecondsPerPoint - dblSec; // round it dblMilliSec = Math.Round(dblMilliSec, 3); string strFixMilliSec = Convert.ToString(dblMilliSec); strFixMilliSec = strFixMilliSec.Remove(0, 2); Int32 intMilliSec = Convert.ToInt32(strFixMilliSec); Int32 intSec = Convert.ToInt32(dblSec); temp_span = new TimeSpan(0, 0, 0, intSec, intMilliSec); temp_newTimeSpan = new TimeSpan(0, 0, 0, 0, 0); } else if (animationType == "ten-second") { temp_span = new TimeSpan(0, 0, 0, 0, 40); temp_newTimeSpan = new TimeSpan(0, 0, 0, 0, 0); } TimeSpan span = temp_span; TimeSpan newTimeSpan = temp_newTimeSpan; var currentmapview = MapView.Active; var mapAnimation = currentmapview.Map.Animation; var currentcamera = currentmapview.Camera; var newCamera = currentcamera; // Use GetDisconnectedTracks List <Track> tracks = mapAnimation.GetDisconnectedTracks(); var cameraTrack = tracks.OfType <CameraTrack>().First(); var rangeTrack = tracks.OfType <RangeTrack>().First(); int cameraJumpVal = 0; rowNumber = 0; string cameraSetting = "perspective"; Feature prevFeature = null; MapPoint prevPoint = null; pointsRowcursor = pointLayer.Search(null); numPoints = pointLayer.GetTable().GetCount(); while (pointsRowcursor.MoveNext()) { rowNumber += 1; using (var pointFeature = pointsRowcursor.Current as Feature) { var mapPoint = pointFeature.GetShape().Clone() as MapPoint; // if prevPoint == null, skip creation of keyframe if (prevFeature != null) { double bearingRadians = 0; string bearingValForKeyframe = Convert.ToString(pointFeature["BEARING"]); if (rowNumber == 2) // View from behind vehicle to begin animation { double bearingVal = Convert.ToDouble(pointFeature["BEARING"]) + 180; bearingRadians = (Math.PI / 180) * bearingVal; cameraJumpVal = 12; } else if (rowNumber == numPoints) // Last point, build keyframe with camera facing the front of the vehicle: { double bearingVal = Convert.ToDouble(pointFeature["BEARING"]) + 0; bearingRadians = (Math.PI / 180) * bearingVal; cameraJumpVal = 12; } else // View from the side { double bearingVal = Convert.ToDouble(pointFeature["BEARING"]) + 270; bearingRadians = (Math.PI / 270) * bearingVal; } double xNew = mapPoint.X + viewDistance * Math.Cos(Math.PI / 2 - bearingRadians); double yNew = mapPoint.Y + viewDistance * Math.Sin(Math.PI / 2 - bearingRadians); MapPoint newprevPoint = MapPointBuilderEx.CreateMapPoint(xNew, yNew); double headingCalc = CalculateHeading(newprevPoint, mapPoint); newCamera.Heading = headingCalc; newCamera.X = xNew; newCamera.Y = yNew; if (VehiclePointsLayer == "Helicopter_Route") { newCamera.Z = mapPoint.Z + 60; } else { newCamera.Z = 60; } newCamera.Pitch = -5; newCamera.Viewpoint = CameraViewpoint.LookAt; double sequenceVal = Convert.ToDouble(pointFeature["Sequence"]); ArcGIS.Desktop.Mapping.Range newRange = new ArcGIS.Desktop.Mapping.Range { Min = sequenceVal, Max = sequenceVal }; // Create and edit the keyframes rangeTrack.CreateKeyframe(newRange, newTimeSpan, AnimationTransition.Linear); //newTimeSpan = newTimeSpan.Add(span); if (cameraSetting == "perspective" && cameraJumpVal == 12) { // rangeTrack.CreateKeyframe(newRange, newTimeSpan, AnimationTransition.Linear); // Set up side / angle perspective for the camera and create keyframe cameraTrack.CreateKeyframe(newCamera, newTimeSpan, AnimationTransition.Linear); cameraJumpVal = 0; } newTimeSpan = newTimeSpan.Add(span); } prevFeature = pointFeature; prevPoint = prevFeature.GetShape() as MapPoint; } cameraJumpVal += 1; } // Wrap up the animation mapAnimation.Tracks = tracks; // Final calculation for the recommendation on keyframes for video export: // Get decimal seconds of newTimeSpan and use numPoints for number of keyframes double keyframesTotal = Convert.ToDouble(numPoints); double seconds = newTimeSpan.TotalSeconds; double kpsValue = keyframesTotal / seconds; double reccomendedKPS; if (kpsValue > 50) { var kpsDivision = kpsValue / 25; int kpsDivider = Convert.ToInt16(Math.Truncate(kpsDivision)); reccomendedKPS = kpsValue / kpsDivider; } else { reccomendedKPS = kpsValue; } string strReccKPS = Convert.ToString(Math.Round(reccomendedKPS, 0)); MessageBox.Show("Animation built. View timeline and/or export movie. \r\n" + "NOTE: Recommended Frames Per Second setting for Export: \r\n" + strReccKPS + " Frames Per Second", "Info"); }); } catch (Exception ex) { MessageBox.Show("Error in GenerateKeyframes: " + ex.ToString(), "Error"); } } // End of GenerateKeyframes()
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); }
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); } }
public static void ShowPatchLabels(Patch patch) { foreach (var cg in CimGraphics) { cg.Dispose(); } CimGraphics.Clear(); int nodeNumber = 0; int maxCoordCount = patch.Coords.Count; int coordCount = 0; foreach (var coord in patch.Coords) { //MapView.Active.AddOverlay() var textGraphic = new CIMTextGraphic { Symbol = SymbolFactory.Instance.ConstructTextSymbol( ColorFactory.Instance.BlackRGB, 12, "Times New Roman", "Regular").MakeSymbolReference() }; //make the callout for the circle var callOut = new CIMPointSymbolCallout { PointSymbol = new CIMPointSymbol() }; //Circle outline - 40 var circle_outline = SymbolFactory.Instance.ConstructMarker(40, "ESRI Default Marker") as CIMCharacterMarker; //Square - 41 //Triangle - 42 //Pentagon - 43 //Hexagon - 44 //Octagon - 45 circle_outline.Size = 40; //eliminate the outline foreach (var layer in circle_outline.Symbol.SymbolLayers) { if (layer is CIMSolidStroke) { ((CIMSolidStroke)layer).Width = 0; } } //Circle fill - 33 var circle_fill = SymbolFactory.Instance.ConstructMarker(33, "ESRI Default Marker") as CIMCharacterMarker; //Square - 34 //Triangle - 35 //Pentagon - 36 //Hexagon - 37 //Octagon - 38 circle_fill.Size = 40; //eliminate the outline, make sure the fill is white foreach (var layer in circle_fill.Symbol.SymbolLayers) { if (layer is CIMSolidFill) { ((CIMSolidFill)layer).Color = ColorFactory.Instance.WhiteRGB; } else if (layer is CIMSolidStroke) { ((CIMSolidStroke)layer).Width = 0; } } var calloutLayers = new List <CIMSymbolLayer> { circle_outline, circle_fill }; //set the layers on the callout callOut.PointSymbol.SymbolLayers = calloutLayers.ToArray(); //set the callout on the text symbol var textSym = textGraphic.Symbol.Symbol as CIMTextSymbol; textSym.Callout = callOut; textSym.Height = 12;//adjust as needed //now set the text textGraphic.Text = $@"{nodeNumber++}"; // reposition the last two labels // 2 meters up System.Diagnostics.Debug.WriteLine($@"Pnt: {coordCount} {coord.X} {coord.Y} {coord.Z} "); var labelPnt = MapPointBuilderEx.CreateMapPoint(new Coordinate3D(coord.X, coord.Y, coord.Z + 4 * coordCount++)); textGraphic.Shape = labelPnt; CimGraphics.Add(MapView.Active.AddOverlay(textGraphic)); } }
/// <summary> /// Called when the sketch finishes. This is where we will create the edit 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) { // execute on the MCT return(QueuedTask.Run(() => { // find features under the sketch var features = MapView.Active.GetFeatures(geometry); if (features.Count == 0) { return false; } EditOperation op = null; var insp = new Inspector(); foreach (var annoLayer in features.ToDictionary().Keys.OfType <AnnotationLayer>()) { // are there features? var featOids = features[annoLayer]; if (featOids.Count == 0) { continue; } // for each feature foreach (var oid in featOids) { // load an inspector insp.Load(annoLayer, oid); // get the annotation properties var annoProperties = insp.GetAnnotationProperties(); // get the text graphic var cimTextGraphic = annoProperties.TextGraphic; if (cimTextGraphic != null) { // // add a leader point to the text graphic // // get the feature shape var textExtent = insp.Shape; // find the lower left of the text extent var extent = textExtent.Extent; var lowerLeft = MapPointBuilderEx.CreateMapPoint(extent.XMin, extent.YMin, textExtent.SpatialReference); // move it a little to the left and down var newPoint = GeometryEngine.Instance.Move(lowerLeft, -40, -40); // create a leader point CIMLeaderPoint leaderPt = new CIMLeaderPoint(); leaderPt.Point = newPoint as MapPoint; // add to a list List <CIMLeader> leaderArray = new List <CIMLeader>(); leaderArray.Add(leaderPt); // assign to the textGraphic cimTextGraphic.Leaders = leaderArray.ToArray(); // // add the balloon callout // // create the callout CIMBalloonCallout balloon = new CIMBalloonCallout(); // yellow background balloon.BackgroundSymbol = SymbolFactory.Instance.ConstructPolygonSymbol(ColorFactory.Instance.CreateRGBColor(255, 255, 0)); // set the balloon style balloon.BalloonStyle = BalloonCalloutStyle.RoundedRectangle; // add a text margin CIMTextMargin textMargin = new CIMTextMargin() { Left = 4, Right = 4, Bottom = 4, Top = 4 }; balloon.Margin = textMargin; // asign it to the textSymbol var symbol = cimTextGraphic.Symbol.Symbol; var textSymbol = symbol as CIMTextSymbol; textSymbol.Callout = balloon; // assign the text graphic back to the annotation properties annoProperties.LoadFromTextGraphic(cimTextGraphic); // assign the annotation properties back to the inspector insp.SetAnnotationProperties(annoProperties); } // create the edit operation if (op == null) { op = new EditOperation(); op.Name = "Alter symbol to balloon callout"; op.SelectModifiedFeatures = true; op.SelectNewFeatures = false; } // modify the feature op.Modify(insp); } } if ((op != null) && !op.IsEmpty) { bool result = op.Execute(); return result; } return false; })); }
async protected override void OnClick() { //Check to see if the Game Board layout already exists LayoutProjectItem layoutItem = Project.Current.GetItems <LayoutProjectItem>().FirstOrDefault(item => item.Name.Equals("Game Board")); if (layoutItem != null) { Layout lyt = await QueuedTask.Run(() => layoutItem.GetLayout()); //Next check to see if a layout view is already open that referencs the Game Board layout foreach (var pane in ProApp.Panes) { var lytPane = pane as ILayoutPane; if (lytPane == null) //if not a layout view, continue to the next pane { continue; } if (lytPane.LayoutView.Layout == lyt) //if there is a match, activate the view { (lytPane as Pane).Activate(); System.Windows.MessageBox.Show("Activating existing pane"); return; } } //If panes don't exist, then open a new pane await ProApp.Panes.CreateLayoutPaneAsync(lyt); System.Windows.MessageBox.Show("Opening already existing layout"); return; } //The layout does not exist so create a new one Layout layout = await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run <Layout>(() => { //*** CREATE A NEW LAYOUT *** //Set up a page CIMPage newPage = new CIMPage(); //required properties newPage.Width = 17; newPage.Height = 11; newPage.Units = LinearUnit.Inches; //optional rulers newPage.ShowRulers = true; newPage.SmallestRulerDivision = 0.5; layout = LayoutFactory.Instance.CreateLayout(newPage); layout.SetName("Game Board"); //*** INSERT MAP FRAME *** // create a new map with an ArcGIS Online basemap Map map = MapFactory.Instance.CreateMap("World Map", MapType.Map, MapViewingMode.Map, Basemap.NationalGeographic); //Build map frame geometry Coordinate2D ll = new Coordinate2D(4, 0.5); Coordinate2D ur = new Coordinate2D(13, 6.5); Envelope env = EnvelopeBuilderEx.CreateEnvelope(ll, ur); //Create map frame and add to layout MapFrame mfElm = ElementFactory.Instance.CreateMapFrameElement(layout, env, map); mfElm.SetName("Main MF"); //Set the camera Camera camera = mfElm.Camera; camera.X = 3365; camera.Y = 5314468; camera.Scale = 175000000; mfElm.SetCamera(camera); //*** INSERT TEXT ELEMENTS *** //Title text var titleTxt_ll = MapPointBuilderEx.CreateMapPoint(new Coordinate2D(6.5, 10)); CIMTextSymbol arial36bold = SymbolFactory.Instance.ConstructTextSymbol(ColorFactory.Instance.BlueRGB, 36, "Arial", "Bold"); GraphicElement titleTxtElm = ElementFactory.Instance.CreateTextGraphicElement(layout, TextType.PointText, titleTxt_ll, arial36bold, "Feeling Puzzled?"); titleTxtElm.SetName("Title"); //Instuctions text Coordinate2D recTxt_ll = new Coordinate2D(4.25, 6.5); Coordinate2D recTxt_ur = new Coordinate2D(13, 9.75); Envelope recEnv = EnvelopeBuilderEx.CreateEnvelope(recTxt_ll, recTxt_ur); CIMTextSymbol arial18 = SymbolFactory.Instance.ConstructTextSymbol(ColorFactory.Instance.GreyRGB, 20, "Arial", "Regular"); string text = "<bol>Instructions:</bol> " + "\n\n - Activate the map frame below and pan / zoom to desired extent" + "\n\n - Close map frame activation" + "\n\n - Click the 'Scramble Pieces' command" as String; GraphicElement recTxtElm = ElementFactory.Instance.CreateTextGraphicElement(layout, TextType.RectangleParagraph, recEnv, arial18, text); recTxtElm.SetName("Instructions"); //Service layer credits Coordinate2D slcTxt_ll = new Coordinate2D(0.5, 0.2); Coordinate2D slcTxt_ur = new Coordinate2D(16.5, 0.4); Envelope slcEnv = EnvelopeBuilderEx.CreateEnvelope(slcTxt_ll, slcTxt_ur); CIMTextSymbol arial8reg = SymbolFactory.Instance.ConstructTextSymbol(ColorFactory.Instance.BlackRGB, 8, "Arial", "Regular"); String slcText = "<dyn type='layout' name='Game Board' property='serviceLayerCredits'/>"; GraphicElement slcTxtElm = ElementFactory.Instance.CreateTextGraphicElement(layout, TextType.RectangleParagraph, slcEnv, arial8reg, slcText); slcTxtElm.SetName("SLC"); //Status and results text (blank to start) var statusTxt_ll = MapPointBuilderEx.CreateMapPoint(new Coordinate2D(4.5, 7)); CIMTextSymbol arial24bold = SymbolFactory.Instance.ConstructTextSymbol(ColorFactory.Instance.BlackRGB, 24, "Arial", "Bold"); GraphicElement statusTxtElm = ElementFactory.Instance.CreateTextGraphicElement(layout, TextType.PointText, statusTxt_ll, arial24bold, ""); statusTxtElm.SetName("Status"); return(layout); }); //*** OPEN LAYOUT VIEW (must be in the GUI thread) *** var layoutPane = await ProApp.Panes.CreateLayoutPaneAsync(layout); var sel = layoutPane.LayoutView.GetSelectedElements(); if (sel.Count > 0) { layoutPane.LayoutView.ClearElementSelection(); } }