Select to view content in your preferred language

Callout text overlapping

2691
15
07-08-2011 07:17 AM
JonathanMeyer
Deactivated User
Anyone I have any suggestions on how to add some conflict detection for text callouts? I have a custom tool that labels certain features a user has selected. The problem is when these features are close together the labels overlap and must be moved by the user. I am arbitrarily setting an offset for the callouts from the features when creating them so they will display away from the feature. However, I can???t find an easy way to determine if the callout will overlap another callout before placing it on the map.
0 Kudos
15 Replies
JonathanMeyer
Deactivated User
It seems like ITextBackground.QueryBoundary should work but I'm getting an empty geometry returned.  I appreciate all the help by the way.
0 Kudos
JeffreyHamblin
Occasional Contributor
It seems like ITextBackground.QueryBoundary should work but I'm getting an empty geometry returned.  I appreciate all the help by the way.


I got the same thing (empty geometry) using:

IPolygon poly = new PolygonClass();
textSymLeftAlign.Background.QueryBoundary(ArcMap.Document.ActiveView.ScreenDisplay.get_CacheMemDC(0),
    ArcMap.Document.ActiveView.ScreenDisplay.DisplayTransformation as ITransformation,
    poly);
System.Diagnostics.Debug.WriteLine("Background: " + poly.Envelope.Width + ", " + poly.Envelope.Height);


Looking at the object model, there is another to try: IQueryGeometry.QueryEnvelope. Implemented by BalloonCallout.

I wish I could be more direct help, but I'm trying to figure this one out too. Hopefully we'll nail it in the end.
0 Kudos
JeffreyHamblin
Occasional Contributor
Well... I spent some time with IQueryGeometry.QueryEnvelope and keep getting "method or operation not implemented".

I would think there is a way to get the balloon callout's envelope directly, but if you can't get it to work -- or if someone else doesn't jump into this thread with the solution  -- I found a cludgy way to get it: First place the element without an anchor and get the bounds of the callout. Then add the anchor.

public void PerformTest()
{

    double fromX = 0;
    double fromY = 0;

    ITextElement textElement = new TextElementClass();
    IElement element = textElement as IElement;
    IElementProperties elementProperties = element as IElementProperties;

    textElement.Text = "Sample text to go in a callout to test getting the size. " +
            "\r\nThis adds some text on a second line." +
            "\r\nThis adds some text on a third line.";


    ESRI.ArcGIS.Geometry.Point point = new ESRI.ArcGIS.Geometry.Point();

    double offSetX = 0;
    double offSetY = 0;
    if (ArcMap.Document.ActivatedView is IPageLayout)
    {
        // inches, page layout units
        offSetX = 0.5;
        offSetY = 1;
    }
    else
    {
        // feet. This worked for my test map's scale.
        offSetX = 800;
        offSetY = 1500;
    }

    // Set the location of the callout balloon (lower-left corner of text)
    point.PutCoords(fromX + offSetX, fromY + offSetY);
    element.Geometry = point;


    // Create text symbology
    IFormattedTextSymbol formattedTextSymbol = new TextSymbol() as IFormattedTextSymbol;
    stdole.IFontDisp fontFrom = formattedTextSymbol.Font;
    fontFrom.Size = 8;
    formattedTextSymbol.Font = fontFrom;
    formattedTextSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft;

    ICallout callOut = new BalloonCalloutClass();
    formattedTextSymbol.Background = (ITextBackground)callOut;

    textElement.Symbol = formattedTextSymbol;
    
    IGraphicsContainer graphicsContainer = ArcMap.Document.ActivatedView as IGraphicsContainer;

    // Add the callout element without a leader to an anchor point
    graphicsContainer.AddElement(element, 0);

    // Get the bounds of callout envelope for just the balloon
    IEnvelope elementEnvelope = new EnvelopeClass();
    element.QueryBounds(ArcMap.Document.ActiveView.ScreenDisplay, elementEnvelope);

    System.Diagnostics.Debug.WriteLine("Element (Before Anchor): " + elementEnvelope.Width + ", " + elementEnvelope.Height);
    System.Diagnostics.Debug.WriteLine("  SpatialReference: " + (textElement as IGraphicElement).SpatialReference.Name);
    System.Diagnostics.Debug.WriteLine("  UpperLeft:" + elementEnvelope.UpperLeft.X + ", " + elementEnvelope.UpperLeft.Y);
    System.Diagnostics.Debug.WriteLine("  LowerLeft:" + elementEnvelope.LowerLeft.X + ", " + elementEnvelope.LowerLeft.Y);
    System.Diagnostics.Debug.WriteLine("  UpperRight:" + elementEnvelope.UpperRight.X + ", " + elementEnvelope.UpperRight.Y);
    System.Diagnostics.Debug.WriteLine("  LowerRight:" + elementEnvelope.LowerRight.X + ", " + elementEnvelope.LowerRight.Y);

    // Set the leader anchor point
    ESRI.ArcGIS.Geometry.Point anchorPTFrom = new ESRI.ArcGIS.Geometry.Point();
    anchorPTFrom.PutCoords(fromX, fromY);
    callOut.AnchorPoint = anchorPTFrom;

    // Must re-assign this or leader to anchor is not created on map and querybounds
    // returns same value as before
    textElement.Symbol = formattedTextSymbol;

    // Get the bounds of the entire callout envelope surrounding balloon and leader
    element.QueryBounds(ArcMap.Document.ActiveView.ScreenDisplay, elementEnvelope);

    System.Diagnostics.Debug.WriteLine("Element (After Anchor): " + elementEnvelope.Width + ", " + elementEnvelope.Height);
    System.Diagnostics.Debug.WriteLine("  SpatialReference: " + (textElement as IGraphicElement).SpatialReference.Name);
    System.Diagnostics.Debug.WriteLine("  UpperLeft:" + elementEnvelope.UpperLeft.X + ", " + elementEnvelope.UpperLeft.Y);
    System.Diagnostics.Debug.WriteLine("  LowerLeft:" + elementEnvelope.LowerLeft.X + ", " + elementEnvelope.LowerLeft.Y);
    System.Diagnostics.Debug.WriteLine("  UpperRight:" + elementEnvelope.UpperRight.X + ", " + elementEnvelope.UpperRight.Y);
    System.Diagnostics.Debug.WriteLine("  LowerRight:" + elementEnvelope.LowerRight.X + ", " + elementEnvelope.LowerRight.Y);
}
0 Kudos
JonathanMeyer
Deactivated User
Thats the same thing I was seeing Friday.  I figured I wasn't calling it correctly and was going to look at it again today.
0 Kudos
kyleknoche
Emerging Contributor
Did anyone figure this thing out yet?

I have balloon callouts that I just cannot get the shape for.  I've tried everything and nothing works.
0 Kudos
JonathanMeyer
Deactivated User
Did anyone figure this thing out yet?

I have balloon callouts that I just cannot get the shape for.  I've tried everything and nothing works.


I ended up giving up and using the Maplex extension for what I needed to do.  Everything I tried ended up returning an empty geometry or method not implemented. One would think this should be possible but it's sure not documented anywhere.

If anyone does figure it out I also would be interested to know for future use.
0 Kudos