¿Por qué estas anotaciones aparecen apiladas / superpuestas?

8

He encontrado un problema extraño al intentar completar una clase de entidad de anotación mediante programación (ArcObjects, C #). Como puede ver en la imagen a continuación, los caracteres en cada cadena de texto parecen apilarse unos sobre otros, en lugar de estar dispuestos horizontalmente como esperaba.

Estoy obteniendo varios valores de MySQL (creados por una aplicación diferente), y esos se ven bien en el depurador. Intenté usar una mezcla de sistema de coordenadas desconocido / proyectado, así como algunas interfaces de Elemento diferentes. Si alguien ha visto y conquistado este problema antes, seguramente agradecería un empujón en la dirección correcta.

Aquí está la parte relevante de mi 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();

Y como se prometió, aquí hay un vistazo a los resultados que estoy obteniendo:

ingrese la descripción de la imagen aquí

[Actualizar]

Según el consejo de @ Radar, probé la siguiente revisión, pero aún muestra texto de anotación apilado / superpuesto:

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;

Alguien tiene alguna idea adicional?

[Segunda actualización]

Básicamente, estoy tratando de lograr lo que @murdoch hizo en esta "antigua" publicación de ArcScripts (vea su segunda entrada). Revisé su enfoque nuevamente y noté que está usando la interfaz IFormattedTextSymbol, así que lo intenté, pero sigo experimentando el mismo problema con el texto apilado / superpuesto en las anotaciones colocadas. Aquí está mi ú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();

¿Alguien tiene problemas con esto? o tener una implementación favorecida? Así es como se ve ahora; Como puede ver, el enfoque cambió un poco, pero los resultados son los mismos:

ingrese la descripción de la imagen aquí

[Tercera actualización]

En el análisis final, el problema no era el código que usé para crear las anotaciones individuales, sino como reveló @Kirk Kuykendall, el problema fue cómo inicialmente creé mi AnnotationLayer IAnnotationLayerFactory.CreateAnnotationLayer(). Estaba presentando nullel IGraphicsLayerScaleargumento, suponiendo que se resolvería a valores por defecto funcionales, si no feos. Aparentemente no lo hace. Creé ese objeto de la siguiente manera, y solucionó mi 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!

ingrese la descripción de la imagen aquí

elrobis
fuente

Respuestas:

4

Usando arccatalog 10 sp2, creé una nueva clase de entidad de anotación (sin vinculación de características) con proyección web mercator, tolerancia xy 0.001, escala de referencia 1: 100,000, unidades de mapa metros.

No marqué el "requerir símbolo para seleccionar de la tabla de símbolos". Aceptó todos los valores predeterminados para el resto.

Luego entré en arcmap y pude agregar manualmente, luego ejecuté este código sin ningún problema superpuesto.

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
fuente
Hola Kirk, aprecio tus ideas aquí. Por curiosidad, ¿annoClass está haciendo algo significativo en la parte superior de AddAnno ()? Sin embargo, todavía estás haciendo algunas "cosas de configuración" de manera diferente a las que yo hago. Daré una vuelta a esta recomendación e informaré. Gracias.
elrobis
Uy, no, eso puede ser ignorado. Eso queda de una prueba que hice con una colección de símbolos, que estaba obteniendo de IAnnoClass.
Kirk Kuykendall el
1
Gracias @Kirk Kuykendall, usted expuso el problema real aquí (vea mi tercera actualización en la sección de preguntas). ¡Gracias una tonelada!
elrobis
2

El uso de ISymbolCollectionElement le permitirá establecer propiedades como el espaciado de caracteres.

Este artículo explica cómo debe abordar el uso de un elemento de texto para evitar el problema que describe.

"Si se usa un TextElement, puede hacer referencia a un TextSymbol existente almacenado en SymbolCollection de AnnotationFeatureClassExtension mediante la interfaz ISymbolCollectionElement . Se recomienda encarecidamente que haga referencia a símbolos en SymbolCollection al almacenar TextElements en una clase de entidad de anotación. Consulte la ayuda para ISymbolCollectionElement para más detalles sobre este sistema de almacenamiento ".

"ISymbolCollectionElement proporciona acceso a las propiedades de TextElements que hacen referencia a TextSymbols almacenados en una SymbolCollection como parte de las clases de entidad de anotación de geodatabase. Al editar TextElements de las funciones de anotación, es fundamental que esta interfaz se utilice para mantener el vínculo con el símbolo SymbolCollection. Acceder y actualizar las propiedades del símbolo a través de ITextElement :: Symbol hará que TextElement se desconecte del símbolo SymbolCollection y el símbolo se almacenará en línea con la función en la clase de entidad. Esto no es deseable ya que TextSymbols puede ser de gran tamaño ".

Abordar tus ediciones. Tratar:

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
fuente
Aprecio tu interés, @Radar, de verdad. Sin embargo, creo que el caso que presenta es uno de eficiencia de almacenamiento mejorada, donde el problema que tengo se relaciona con el diseño de los caracteres de texto dentro del elemento de anotación. Creo esto porque ya probé ISymbolCollectionElement y obtuve los mismos resultados.
elrobis
Para asegurarme, intenté nuevamente usar el enfoque que me recomiendan y de hecho obtengo los mismos resultados. Actualizaré la pregunta para incluir mi intento modificado.
elrobis
El segundo párrafo en mi respuesta aborda el caso en el que el enlace ITextElement :: Symbol está roto, lo que resulta en un símbolo de texto sesgado. Este no es un problema de eficiencia de almacenamiento, tiene más que ver con el mantenimiento de la propiedad. Juegue con algunas de las propiedades ISymbolCollectionElement y vea si puede modificar su texto. Por ejemplo, intente cambiar el espaciado o ponerlo en negrita.
Radar
Actualicé la pregunta para reflejar mi intento de incorporar su recomendación. Además, acabo de intentar agregar scElement.Bold = true; (una idea curiosa), y si bien hizo que el texto en negrita, incluso con el conjunto CharacterSpacing a 5, el texto sigue renders apilados. ¿Alguna otra idea?
elrobis
Me pregunto si el envío a IElement (scElement as IElement) está causando un problema para IAnnotationFeature. ¿Se puede enviar directamente a ISymbolCollectionElement? (p. ej. (característica como IAnnotationFeature2) .Annotation = scElement;)
Radar