Skip to content

ProSnippets Annotation

uma2526 edited this page Jun 26, 2019 · 15 revisions
Language:              C#  
Subject:               Annotation  
Contributor:           ArcGIS Pro SDK Team <arcgisprosdk@esri.com>  
Organization:          esri, http://www.esri.com  
Date:                  6/23/2019  
ArcGIS Pro:            2.4  
Visual Studio:         2017, 2019  
.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
    ArcGIS.Desktop.Editing.Attributes.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

    var rowCursor = annoLayer.Search(qf);
    rowCursor.MoveNext();
    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;
    // rotate the shape 90 degrees
    var origin = GeometryEngine.Instance.Centroid(textLine);
    Geometry rotatedPolyline = GeometryEngine.Instance.Rotate(textLine, origin, System.Math.PI / 2);
    //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();
});

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
        var rowCursor = annoLayer.GetTable().Search(qf, false);
        rowCursor.MoveNext();
        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;

        // change the text and the color
        textGraphic.Text = "hello world";
        var symbol = textGraphic.Symbol.Symbol;
        symbol.SetColor(ColorFactory.Instance.RedRGB);
        textGraphic.Symbol = symbol.MakeSymbolReference();
        // update the graphic
        annoFeature.SetGraphic(textGraphic);
        // store is required
        annoFeature.Store();
        //refresh layer cache
        context.Invalidate(annoFeature);

    }, annoLayer.GetTable());

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