Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I've encountered a strange problem while trying to populate an annotation feature class programmatically (ArcObjects, C#). As you can see in the image below, the characters in each text string seem to be stacking upon eachother, rather than laying-out horizontally as I would have expected.

I'm pulling in several values from MySQL (created by a different application), and those look fine in the debugger. I've tried using a mixture of unknown/projected coordinate system, as well a few different Element interfaces. If anyone has seen and conqured this issue before I would sure appreciate a push in the right direction.

Here's the relevant portion of my C#:

IFeature feature = featureClass.CreateFeature();

ITextElement textElement = new TextElementClass();
textElement.Text = textString;                         // value like: '183

IElement element = textElement as IElement;
element.Geometry = pointGeom;                         // Point: x=2986785, y=629058

(feature as IAnnotationFeature2).Annotation = element;
(feature as IAnnotationFeature2).AnnotationClassID = 0;
(feature as IAnnotationFeature2).Status = annoStatus;  // ESRI constant for 0, "placed"

feature.Store();

And as promised, here's a look at the results I'm getting:

enter image description here

[Update]

Per @Radar's advice I tried the following revision, but it still renders stacked/overlapped annotation text:

ISymbolCollectionElement scElement = new TextElementClass(); 
scElement.CharacterSpacing = 5; 
scElement.Geometry = pointGeom; 
scElement.Text = textString; 

(feature as IAnnotationFeature2).Annotation = scElement as IElement; 
(feat as IAnnotationFeature2).AnnotationClassID = 0; 
(feat as IAnnotationFeature2).Status = annoStatus;

Anyone have any additional insights?

[Second Update]

Basically I'm trying to accomplish what @murdoch did in this "old" ArcScripts post (see his second entry). I reviewed his approach again and noticed he's using the IFormattedTextSymbol interface, so I tried that, yet I continue to experience the same problem with stacked/overlapping text in the placed annotations. Here's my latest thrust of C#:

IFeature feature = featureClass.CreateFeature();

IFontDisp font = new StdFontClass() as IFontDisp;
font.Name = "Arial";
font.Bold = true;
// font.Size = 30;

// load in some reasonable default values..
IFormattedTextSymbol fmtTextSymb = new TextSymbolClass();
fmtTextSymb.Font = font;
fmtTextSymb.Size = 30;
fmtTextSymb.VerticalAlignment = esriTextVerticalAlignment.esriTVABottom;
fmtTextSymb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft;
fmtTextSymb.Angle = 0;
fmtTextSymb.CharacterSpacing = 100;
fmtTextSymb.CharacterWidth = 100;
fmtTextSymb.FlipAngle = 90;
fmtTextSymb.Leading = 0;
fmtTextSymb.WordSpacing = 100;
fmtTextSymb.Text = textString;  // my special text value..

ITextElement textElement = new TextElementClass();
textElement.Symbol = fmtTextSymb;
textElement.Text = textString;

IElement element = textElement as IElement;
element.Geometry = pt;

(feature as IAnnotationFeature2).Annotation = element;

feature.Store();

Anyone take issue with this? or have a favored-implementation? Here's what it looks like now; as you can see, the approach changed somewhat, but the results are the same:

enter image description here

[Third Update]

On final analysis, the problem was not the code I used to create the individual annotations but as @Kirk Kuykendall revealed, the problem was how I initially created my AnnotationLayer with IAnnotationLayerFactory.CreateAnnotationLayer(). I was submitting null for the IGraphicsLayerScale argument, assuming it would resolve to functional, if not ugly, default values. Apparently it does not. I created that object as follows, and it fixed my problem:

// Set the map scale and units the annos should be "cooked for".
// To get ReferenceScale, open ArcMap and zoom to an appropriate level. 
// In the Standard toolbar, click the 1:N button (tip says "MapScale").
// It'll output something like 1:1,200. Drop the 1: and the comma
// and that's the value you want for ReferenceScale.

IGraphicsLayerScale graphicsLayerScale = new GraphicsLayerScaleClass();
graphicsLayerScale.ReferenceScale = 1200;
graphicsLayerScale.Units = esriUnits.esriFeet; // this should agree with your proj

Voila!

enter image description here

share|improve this question
add comment

2 Answers 2

up vote 3 down vote accepted

Using arccatalog 10 sp2, I created a new (non-featurelinked) annotation featureclass with web mercator projection, xy tolerance 0.001, reference scale 1:100,000, map units meters.

I did not check the "require symbol to be selected from symbol table". Accepted all defaults for the rest.

I then went into arcmap and was able to add manually, then ran this code without any overlapping problem.

public class TestButton : ESRI.ArcGIS.Desktop.AddIns.Button
{
    public TestButton()
    {
    }

    protected override void OnClick()
    {
        try
        {
            Test();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    protected override void OnUpdate()
    {
    }
    public void Test()
    {
        var editor = ArcMap.Application.FindExtensionByName("ESRI Object Editor") as IEditor;
        if (editor.EditState != esriEditState.esriStateEditing)
        {
            MessageBox.Show("start editing first");
            return;
        }
        var fLayer = ((IEditLayers)editor).CurrentLayer;
        if(!(fLayer is IAnnotationLayer))
        {
            MessageBox.Show("not an anno layer");
            return;
        }
        var pnt = ((IArea)ArcMap.Document.ActiveView.Extent).Centroid;
        string s = Environment.TickCount.ToString();
        try
        {
            editor.StartOperation();
            AddAnno(fLayer.FeatureClass,pnt,s);
            editor.StopOperation("add anno at center of screen");
            ArcMap.Document.ActiveView.Refresh();
        }
        catch
        {
            editor.AbortOperation();
            throw;
        }
    }

    private void AddAnno(IFeatureClass featClass, IPoint pt, string textString)
    {
        IFeature feature = featClass.CreateFeature();
        var annoClass = featClass.Extension as IAnnoClass;

        IFontDisp font = new StdFontClass() as IFontDisp;
        font.Name = "Arial";
        font.Bold = true;
        // font.Size = 30;

        // load in some reasonable default values..
        IFormattedTextSymbol fmtTextSymb = new TextSymbolClass();
        fmtTextSymb.Font = font;
        fmtTextSymb.Size = 30;
        fmtTextSymb.VerticalAlignment = esriTextVerticalAlignment.esriTVABottom;
        fmtTextSymb.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft;
        fmtTextSymb.Angle = 0;
        fmtTextSymb.CharacterSpacing = 100;
        fmtTextSymb.CharacterWidth = 100;
        fmtTextSymb.FlipAngle = 90;
        fmtTextSymb.Leading = 0;
        fmtTextSymb.WordSpacing = 100;
        fmtTextSymb.Text = textString;  // my special text value..

        ITextElement textElement = new TextElementClass();

        textElement.Symbol = fmtTextSymb;
        textElement.Text = textString;

        IElement element = textElement as IElement;
        element.Geometry = pt;

        (feature as IAnnotationFeature2).Annotation = element;

        feature.Store();
    }
}
share|improve this answer
    
Hi Kirk, I appreciate your insights here. Out of curiosity, is that annoClass doing anything significant at the top of AddAnno()? Nevertheless, you're still doing a few "setup things" differently than I am. I'll give this recommendation a spin and report back. Thanks. –  elrobis Dec 1 '11 at 4:46
    
oops, no that can be ignored. That's left over from a test I did with a symbolcollection, which I was getting from IAnnoClass. –  Kirk Kuykendall Dec 1 '11 at 12:50
1  
Thanks @Kirk Kuykendall, you exposed the real problem here (see my third update in the question section). Thanks a ton! –  elrobis Dec 1 '11 at 17:05
add comment

Using ISymbolCollectionElement will allow you to set properties such as character spacing.

This article explains how you should approach using a text element to prevent the issue you describe.

"If a TextElement is used, you may reference an exiting TextSymbol stored in the SymbolCollection of the AnnotationFeatureClassExtension by using the ISymbolCollectionElement interface. It is highly recommended that you reference symbols in the SymbolCollection when storing TextElements in an annotation feature class. See the help for ISymbolCollectionElement for more details on this storage system."

"ISymbolCollectionElement provides access to properties of TextElements which reference TextSymbols stored in a SymbolCollection as part of Geodatabase Annotation Feature Classes. When editing the TextElements of annotation features, it is critical that this interface is used in order to maintain the linkage to the SymbolCollection symbol. Accessing and updating symbol properties through ITextElement::Symbol will cause the TextElement to become disconnected from the SymbolCollection symbol and the symbol will be stored inline with the feature in the feature class. This is undesirable since TextSymbols can be large in size."

Addressing your edits. Try:

ISymbolCollectionElement scElement = new TextElementClass(); 
scElement.CharacterSpacing = 5; 
scElement.Geometry = pointGeom; 
scElement.Text = textString; 

(feature as IAnnotationFeature2).Annotation = scElement; 
(feat as IAnnotationFeature2).AnnotationClassID = 0; 
(feat as IAnnotationFeature2).Status = annoStatus;
share|improve this answer
    
I appreciate you interest, @Radar, truly. However, I believe the case you're presenting is one of improved storage efficiency, where the problem I'm having relates to the layout of the text characters within the annotation element. I believe this because I've already tried ISymbolCollectionElement and it got the same results. –  elrobis Nov 30 '11 at 18:39
    
To make certain, I just tried again using the approach you're recommending and I do indeed get the same results. I'll update the question to include my modified attempt. –  elrobis Nov 30 '11 at 18:50
    
The second paragraph in my answer addresses the case where the ITextElement::Symbol linkage is broken, resulting in a skewed text symbol. This isn't a storage efficiency issue, it has more to do with property maintenance. Play around with some of the ISymbolCollectionElement properties and see if you can modify your text. For example, try to change the spacing or make it bold. –  Nick Ochoski Nov 30 '11 at 18:54
    
I updated the question to reflect my attempt to incorporate your recommendation. Also, I just tried adding scElement.Bold=true; (a curious idea), and while it did make the text bold, even with the CharacterSpacing set to 5, the text still renders stacked. Any other thoughts? –  elrobis Nov 30 '11 at 19:02
    
I wonder if the cast to IElement (scElement as IElement) is causing an issue for IAnnotationFeature. Can you cast directly to the ISymbolCollectionElement? (e.g. (feature as IAnnotationFeature2).Annotation = scElement;) –  Nick Ochoski Nov 30 '11 at 19:26
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.