Por que essas anotações aparecem empilhadas / sobrepostas?

8

Encontrei um problema estranho ao tentar preencher uma classe de recurso de anotação programaticamente (ArcObjects, C #). Como você pode ver na imagem abaixo, os caracteres em cada sequência de texto parecem estar empilhados um sobre o outro, em vez de serem dispostos horizontalmente, como eu esperava.

Estou puxando vários valores do MySQL (criados por um aplicativo diferente), e esses ficam bem no depurador. Eu tentei usar uma mistura de sistema de coordenadas desconhecido / projetado, bem como algumas interfaces de elemento diferentes. Se alguém já viu e venceu esse problema antes, eu certamente apreciaria um empurrão na direção certa.

Aqui está a parte relevante do meu 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();

E, como prometido, aqui estão os resultados que estou obtendo:

insira a descrição da imagem aqui

[Atualizar]

De acordo com o conselho do @ Radar, tentei a seguinte revisão, mas ela ainda processa o texto da anotação empilhada / sobreposta:

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;

Alguém tem alguma ideia adicional?

[Segunda atualização]

Basicamente, estou tentando realizar o que o @murdoch fez neste post "antigo" do ArcScripts (veja sua segunda entrada). Revi sua abordagem novamente e notei que ele estava usando a interface IFormattedTextSymbol, então tentei isso, mas continuo tendo o mesmo problema com o texto empilhado / sobreposto nas anotações colocadas. Aqui está o meu último impulso de 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();

Alguém tem problema com isso? ou tem uma implementação favorecida? Aqui está o que parece agora; como você pode ver, a abordagem mudou um pouco, mas os resultados são os mesmos:

insira a descrição da imagem aqui

[Terceira atualização]

Na análise final, o problema não era o código que eu usei para criar as anotações individuais, mas como @Kirk Kuykendall revelou, o problema foi como eu criei meu AnnotationLayer inicialmente IAnnotationLayerFactory.CreateAnnotationLayer(). Eu estava enviando nullpara o IGraphicsLayerScaleargumento, assumindo que ele resolveria valores funcionais, se não feios, padrão. Aparentemente isso não acontece. Eu criei esse objeto da seguinte maneira, e ele corrigiu meu problema:

// 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!

insira a descrição da imagem aqui

elrobis
fonte

Respostas:

4

Usando o arccatalog 10 sp2, criei uma nova classe de anotação (não relacionada ao recurso) com projeção do web mercator, tolerância xy 0,001, escala de referência 1: 100.000, unidades de mapa metros.

Não marquei a opção "exigir que o símbolo seja selecionado na tabela de símbolos". Aceitou todos os padrões para o resto.

Eu entrei no arcmap e fui capaz de adicionar manualmente, depois executei esse código sem nenhum problema de sobreposição.

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();
    }
}
Kirk Kuykendall
fonte
Olá Kirk, agradeço suas idéias aqui. Por curiosidade, esse annoClass está fazendo algo significativo no topo de AddAnno ()? No entanto, você ainda está fazendo algumas "coisas de configuração" de maneira diferente do que eu. Vou dar uma olhada nessa recomendação e relatar de volta. Obrigado.
315 elrobis
Opa, não, isso pode ser ignorado. Sobra de um teste que fiz com uma coleção de símbolos, que eu estava recebendo do IAnnoClass.
Kirk Kuykendall
1
Obrigado @Kirk Kuykendall, você expôs o problema real aqui (veja minha terceira atualização na seção de perguntas). Muito obrigado!
31511 elrobis
2

Usar ISymbolCollectionElement permitirá definir propriedades como espaçamento entre caracteres.

Este artigo explica como você deve abordar o uso de um elemento de texto para evitar o problema descrito.

"Se um TextElement for usado, você poderá fazer referência a um TextSymbol existente armazenado no SymbolCollection da AnnotationFeatureClassExtension usando a interface ISymbolCollectionElement . É altamente recomendável que você faça referência a símbolos no SymbolCollection ao armazenar TextElements em uma classe de recurso de anotação. Consulte a ajuda para ISymbolCollectionElement para obter mais detalhes sobre este sistema de armazenamento. "

"ISymbolCollectionElement fornece acesso às propriedades de TextElements que fazem referência a TextSymbols armazenados em SymbolCollection como parte das Classes de recursos de anotação de banco de dados geográficos. Ao editar os TextElements dos recursos de anotação, é essencial que essa interface seja usada para manter a ligação ao símbolo SymbolCollection. O acesso e a atualização das propriedades do símbolo por meio do ITextElement :: Symbol farão com que o TextElement seja desconectado do símbolo SymbolCollection e o símbolo será armazenado em linha com o recurso na classe de recurso. Isso é indesejável, pois o TextSymbols pode ser grande. "

Endereçando suas edições. Tentar:

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;
Radar
fonte
Agradeço seu interesse, @Radar, verdadeiramente. No entanto, acredito que o caso que você está apresentando é de maior eficiência de armazenamento, onde o problema que estou tendo está relacionado ao layout dos caracteres de texto no elemento de anotação. Acredito nisso porque já tentei ISymbolCollectionElement e obtive os mesmos resultados.
elrobis
Para ter certeza, tentei novamente usar a abordagem recomendada e, de fato, obtenho os mesmos resultados. Vou atualizar a pergunta para incluir minha tentativa modificada.
elrobis
O segundo parágrafo da minha resposta aborda o caso em que o vínculo ITextElement :: Symbol está quebrado, resultando em um símbolo de texto inclinado. Este não é um problema de eficiência de armazenamento, tem mais a ver com a manutenção da propriedade. Brinque com algumas das propriedades ISymbolCollectionElement e veja se você pode modificar seu texto. Por exemplo, tente alterar o espaçamento ou torná-lo em negrito.
Radar
Atualizei a pergunta para refletir minha tentativa de incorporar sua recomendação. Além disso, eu apenas tentei adicionar scElement.Bold = true; (uma idéia curiosa) e, embora tenha tornado o texto em negrito, mesmo com o CharacterSpacing definido como 5, o texto ainda é renderizado. Quaisquer outros pensamentos?
elrobis
Gostaria de saber se a conversão para IElement (scElement como IElement) está causando um problema para IAnnotationFeature. Você pode transmitir diretamente para o ISymbolCollectionElement? (ex .: (recurso como IAnnotationFeature2) .Annotation = scElement;)
Radar