Skip to content

ProSnippets Annotation

arcgisprosdk edited this page Jan 16, 2018 · 16 revisions
Language:              C#  
Subject:               Map Authoring
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
Organization:          esri, http://www.esri.com  
Date:                  12/22/2017  
ArcGIS Pro:            2.1  
Visual Studio:         2015, 2017  
.NET Target Framework: 4.6.1  

Create Annotation Construction Tool

//In your config.daml...set the categoryRefID
//<tool id="..." categoryRefID="esri_editing_construction_annotation" caption="Create Anno" ...>

//Sketch type Point or Line or BezierLine in the constructor...
//internal class AnnoConstructionTool : MapTool  {
//  public AnnoConstructionTool()  {
//    IsSketchTool = true;
//    UseSnapping = true;
//    SketchType = SketchGeometryType.Point;
//

  protected async override Task<bool> OnSketchCompleteAsync(Geometry geometry)
  {
    if (CurrentTemplate == null || geometry == null)
      return false;

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

    // update the geometry point into a 2 point line
    //annotation needs at minimum a 2 point line for the text to be placed
    double tol = 0.01;
    var polyline = await CreatePolylineFromPointAsync((MapPoint)geometry, tol);

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

    // Execute the operation
    return await createOperation.ExecuteAsync();
  }

  internal Task<Polyline> CreatePolylineFromPointAsync(MapPoint pt, double tolerance)
  {
    return QueuedTask.Run(() => {
      // create a polyline from a starting point
      //use a tolerance to construct the second point
      MapPoint pt2 = MapPointBuilder.CreateMapPoint(pt.X + tolerance, pt.Y, pt.SpatialReference);
      return PolylineBuilder.CreatePolyline(new List<MapPoint>() { pt, pt2 });
    });
  }

Update Annotation Text via attribute. Caveat: The TEXTSTRING Anno attribute must exist

//See "Change Annotation Text Graphic" for an alternative if TEXTSTRING 
//  is missing from the schema
await QueuedTask.Run(() => {
  //annoLayer is ~your~ Annotation layer...

  // use the inspector methodology
  var insp = new Inspector();
  insp.Load(annoLayer, oid);

  // make sure TextString attribute exists.
  //It is not guaranteed to be in the schema
  Attribute att = insp.FirstOrDefault(a => a.FieldName == "TEXTSTRING");
  if (att != null) {
    insp["TEXTSTRING"] = "Hello World";

    //create and execute the edit operation
    EditOperation op = new EditOperation();
    op.Name = "Update annotation";
    op.Modify(insp);

    //OR using a Dictionary - again TEXTSTRING has to exist in the schema
    //Dictionary<string, object> newAtts = new Dictionary<string, object>();
    //newAtts.Add("TEXTSTRING", "hello world");
    //op.Modify(annoLayer, oid, newAtts);

    op.Execute();
  }
});

Rotate or Move the Annotation

await QueuedTask.Run(() => {
  //Don't use 'Shape'....Shape is the bounding box of the annotation text. This is NOT what you want...
  //
  //var insp = new Inspector();
  //insp.Load(annoLayer, oid);
  //var shape = insp["SHAPE"] as Polygon;
  //...wrong shape...

  //Instead, we must get the TextGraphic from the anno feature.
  //The TextGraphic shape will be the anno baseline...
  //At 2.1 the only way to retrieve this textLine is to obtain the TextGraphic from the AnnotationFeature
  QueryFilter qf = new QueryFilter() {
    WhereClause = "OBJECTID = 1"
  };

  //annoLayer is ~your~ Annotation layer

  using (var rowCursor = annoLayer.Search(qf))
  {
    rowCursor.MoveNext();
    if (rowCursor.Current != null)
    {
      var annoFeature = rowCursor.Current as ArcGIS.Core.Data.Mapping.AnnotationFeature;
      var graphic = annoFeature?.GetGraphic();
      var textGraphic = graphic as CIMTextGraphic;
      var textLine = textGraphic?.Shape as Polyline;

      // baseline geometry of CIMTextGraphic could be point, polyline, multipoint or geometryBag depending upon
      //   how the annotation feature was created 
      if (textLine != null)
      {
        // rotate the shape 90 degrees
        var origin = GeometryEngine.Instance.Centroid(textLine);
        Geometry rotatedPolyline = GeometryEngine.Instance.Rotate(textLine, origin, System.Math.PI / 2);
  
        // OR 
        // Move the line 5 "units" in the x and y direction
        //GeometryEngine.Instance.Move(textLine, 5, 5);

        EditOperation op = new EditOperation();
        op.Name = "Change annotation angle";
        op.Modify(annoLayer, oid, rotatedPolyline);

        op.Execute(); 

        // OR 
        // use the Dictionary methodology

        //Dictionary<string, object> newAtts = new Dictionary<string, object>();
        //newAtts.Add("SHAPE", rotatedBaseline);
        //op.Modify(annoLayer, oid, newAtts);
      }
    }
  }
});

Change Annotation Text Graphic

await QueuedTask.Run(() => {

  EditOperation op = new EditOperation();
  op.Name = "Change annotation graphic";

  //At 2.1 we must use an edit operation Callback...
  op.Callback(context => {
    QueryFilter qf = new QueryFilter() {
      WhereClause = "OBJECTID = 1"
    };

    //Cursor must be non-recycling. Use the table ~not~ the layer..i.e. "GetTable().Search()"
    //annoLayer is ~your~ Annotation layer
    using (var table = annoLayer.GetTable())
    {
      using (var rowCursor = table.Searech(qf, false))
      {
        rowCursor.MoveNext();
        if (rowCursor != null)
        {
          var annoFeature = rowCursor.Current as ArcGIS.Core.Data.Mapping.AnnotationFeature;

          //Get the graphic from the anno feature
          var graphic = annoFeature?.GetGraphic();
          var textGraphic = graphic as CIMTextGraphic;

          if (textGraphic != null)
          {
            // change the text 
            textGraphic.Text = "hello world";

            // change the symbol color
            var symbol = textGraphic.Symbol.Symbol;
            symbol.SetColor(ColorFactory.Instance.RedRGB);

            // change the horizontal alignment
            var cimTextSymbol = symbol as CIMTextSymbol;
            cimTextSymbol.HorizontalAlignment = HorizontalAlignment.Center;

            // update the symbol
            textGraphic.Symbol = symbol.MakeSymbolReference();

            // update the graphic
            annoFeature.SetGraphic(textGraphic);

            // store is required
            annoFeature.Store();

            //refresh cache
            context.Invalidate(annoFeature);
          }
        }
      }
    }
  }, annoLayer.GetTable());

  op.Execute();
});
Clone this wiki locally