原来也思考了该如何实现标注动态避让,认为必须得计算字符串所占的大小。如果在屏幕上要计算屏幕象素之类的东西。
今天总算找到了实现方法,在C# WorldWind中的KMLImporter类中有。关键是Font的如下方法:
public Rectangle MeasureString(Sprite sprite, string text, DrawTextFormat format, Color color);
public Rectangle MeasureString(Sprite sprite, string text, DrawTextFormat format, int color);

1 if(icon.Name != null)
2 {
3 // Render name field
4 const int labelWidth = 1000; // Dummy value needed for centering the text
5 if(iconTexture==null)
6 {
7 // Center over target as we have no bitmap
8 Rectangle realrect = drawArgs.defaultDrawingFont.MeasureString(m_sprite, icon.Name, DrawTextFormat.WordBreak, color);
9 realrect.X = (int)projectedPoint.X - (labelWidth>>1);
10 realrect.Y = (int)(projectedPoint.Y - (drawArgs.defaultDrawingFont.Description.Height >> 1));
11
12 bool bDraw = true;
13
14 foreach (Rectangle drawnrect in labelRectangles)
15 {
16 if (realrect.IntersectsWith(drawnrect))
17 {
18 bDraw = false;
19 break;
20 }
21 }
22
23 if (bDraw)
24 {
25 labelRectangles.Add(realrect);
26 drawArgs.defaultDrawingFont.DrawText(m_sprite, icon.Name, realrect, DrawTextFormat.Center, color);
27 }
28 }
29 else
30 {
31 // Adjust text to make room for icon
32 int spacing = (int)(icon.Width * 0.3f);
33 if(spacing>10)
34 spacing = 10;
35 int offsetForIcon = (icon.Width>>1) + spacing;
36
37 // Text to the right
38 Rectangle rightrect = drawArgs.defaultDrawingFont.MeasureString(m_sprite, icon.Name, DrawTextFormat.WordBreak, color);
39 rightrect.X = (int)projectedPoint.X + offsetForIcon;
40 rightrect.Y = (int)(projectedPoint.Y - (drawArgs.defaultDrawingFont.Description.Height >> 1));
41
42 // Text to the left
43 Rectangle leftrect = drawArgs.defaultDrawingFont.MeasureString(m_sprite, icon.Name, DrawTextFormat.WordBreak, color);
44 leftrect.X = (int)projectedPoint.X - offsetForIcon - rightrect.Width;
45 leftrect.Y = (int)(projectedPoint.Y - (drawArgs.defaultDrawingFont.Description.Height >> 1));
46
47 bool bDrawRight = true;
48 bool bDrawLeft = true;
49
50 foreach (Rectangle drawnrect in labelRectangles)
51 {
52 if (rightrect.IntersectsWith(drawnrect))
53 {
54 bDrawRight = false;
55 }
56 if (leftrect.IntersectsWith(drawnrect))
57 {
58 bDrawLeft = false;
59 }
60 if (!bDrawRight && !bDrawLeft)
61 {
62 break;
63 }
64 }
65
66 if (bDrawRight)
67 {
68 labelRectangles.Add(rightrect);
69 drawArgs.defaultDrawingFont.DrawText(m_sprite, icon.Name, rightrect, DrawTextFormat.WordBreak, color);
70 }
71 else if (bDrawLeft)
72 {
73 labelRectangles.Add(leftrect);
74 drawArgs.defaultDrawingFont.DrawText(m_sprite, icon.Name, leftrect, DrawTextFormat.WordBreak, color);
75 }
76 }
77 }
这种方式实现简单,但是会造成先添加到标注字符串集合的文字优先显示。索引靠后的文字始终被隐藏。