|
|
|
Title:
|
Dynamic Legend Generation
|
Language:
|
C#
|
|
Description:
|
This snippet of code should allow you generate a legend image with the desired specification given the Map Control
|
Views:
|
3100
|
|
Author:
|
Vish Uma
|
Date Added:
|
3/10/2008
|
Copy
|
Code
|
|
1public Bitmap GetLegendImage(Map map, int width, int height, int printResolution, string legendTitle)
2 {
3 Bitmap legendImage = null;
4 #region "Trying to get the legend information" ...
5
6
7 Dictionary<string, KeyValuePair<string, CartoImage>> legendInfo = new Dictionary<string, KeyValuePair<string, CartoImage>>();
8 int layerCounter = 0;
9 foreach (IMapResource item in map.MapResourceManagerInstance.GetResources())
10 {
11 // just in case one of the map services isn't working, but others are...
12 // ...or if the map resource is invisible, skip to next resource
13 IMapTocFunctionality mtoc = item.CreateFunctionality(typeof(IMapTocFunctionality), Guid.NewGuid().ToString()) as IMapTocFunctionality;
14 if (mtoc == null)
15 continue;
16
17 IMapFunctionality mf = null;
18 foreach (IGISFunctionality entry in item.Functionalities)
19 {
20 if (entry is IMapFunctionality)
21 mf = entry as IMapFunctionality;
22 }
23 if (mf == null || !mf.DisplaySettings.Visible)
24 continue;
25
26 TocDataFrame[] tocDataFrames = mtoc.GetMapContents(mf.Name, WebImageFormat.PNG24, true, false);
27 foreach (TocDataFrame tocDataFrame in tocDataFrames)
28 {
29 foreach (TocLayer tocLayer in tocDataFrame)
30 {
31 if (tocLayer.Visible)
32 {
33 List<KeyValuePair<string, CartoImage>> legends = GetLegendImages(tocLayer);
34 if (legends != null && legends.Count > 0)
35 {
36 foreach (KeyValuePair<string, CartoImage> entry in legends)
37 {
38 legendInfo.Add(layerCounter.ToString(), new KeyValuePair<string, CartoImage>(entry.Key, entry.Value));
39 layerCounter++;
40 }
41 }
42
43 }
44 }
45 }
46 }
47 #endregion
48 #region "Create the legend dynamically" ...
49
50
51 if (legendInfo != null && legendInfo.Count > 0)
52 {
53 int legendWidth = width;
54 int legendHeight = height;
55 int marginPadding = 10;
56 int legendEntryPadding = 5;
57
58 legendImage = new Bitmap(legendWidth, legendHeight);
59 legendImage.SetResolution(printResolution, printResolution);
60 Graphics graphics = Graphics.FromImage(legendImage);
61 Font stringFont = new Font("Verdana", 8, System.Drawing.FontStyle.Bold);
62 SolidBrush drawBrush = new SolidBrush(Color.Black);
63 List<Bitmap> legendEntries = new List<Bitmap>();
64
65 foreach (KeyValuePair<string, KeyValuePair<string, CartoImage>> item in legendInfo)
66 {
67 if (item.Value.Value != null)
68 {
69 Bitmap swatch = new Bitmap(new System.IO.MemoryStream(item.Value.Value.MimeData.Bytes));
70 float swatchColumnWidth = (swatch.Width * (printResolution / swatch.HorizontalResolution)) > 100 ? 100 : (swatch.Width * (printResolution / swatch.HorizontalResolution));
71 SizeF textSize = graphics.MeasureString(item.Value.Key, stringFont, (int)(legendWidth - swatchColumnWidth - (marginPadding * 2)));
72 float inidividualHeight = (swatch.Height * (printResolution / swatch.VerticalResolution)) > textSize.Height ? (swatch.Height * (printResolution / swatch.VerticalResolution)) : textSize.Height;
73
74 Bitmap individuallegend = new Bitmap(legendWidth, (int)inidividualHeight);
75 individuallegend.SetResolution(printResolution, printResolution);
76 Graphics g = Graphics.FromImage(individuallegend);
77 g.DrawImage(swatch, marginPadding, 0);
78 RectangleF textArea = new RectangleF(swatchColumnWidth + marginPadding, 0, legendWidth - swatchColumnWidth - (marginPadding * 2), inidividualHeight);
79 g.DrawString(item.Value.Key, stringFont, drawBrush, textArea);
80 g.Dispose();
81 //individuallegend.Save("C:\\arcgisserver\\arcgisoutput\\" + item.Key + ".bmp");
82 legendEntries.Add(individuallegend);
83 }
84 else
85 {
86 SizeF textSize = graphics.MeasureString(item.Value.Key, stringFont, (int)(legendWidth - (marginPadding * 2)));
87 float inidividualHeight = textSize.Height;
88
89 Bitmap individuallegend = new Bitmap(legendWidth, (int)inidividualHeight);
90 individuallegend.SetResolution(printResolution, printResolution);
91 Graphics g = Graphics.FromImage(individuallegend);
92 RectangleF textArea = new RectangleF(marginPadding, 0, legendWidth - (marginPadding * 2), inidividualHeight);
93 g.DrawString(item.Value.Key, stringFont, drawBrush, textArea);
94 g.Dispose();
95 //individuallegend.Save("C:\\arcgisserver\\arcgisoutput\\" + item.Key + ".bmp");
96 legendEntries.Add(individuallegend);
97 }
98 }
99
100 Font legendTitleFont = new Font("Verdana", 10, System.Drawing.FontStyle.Bold);
101 SizeF legendTitleArea = graphics.MeasureString(legendTitle, legendTitleFont);
102
103 float currentY = 0;
104 //Add title to the legend
105 graphics.DrawString("Legend", legendTitleFont, drawBrush, marginPadding, legendEntryPadding);
106 currentY += legendTitleArea.Height + marginPadding;
107
108 //Add the individual legend entries
109 foreach (Bitmap entry in legendEntries)
110 {
111 if ((currentY + entry.Height) < legendHeight)
112 {
113 graphics.DrawImage(entry, 0, currentY);
114 currentY += entry.Height + legendEntryPadding;
115 }
116 }
117
118 //legendImage.Save("C:\\arcgisserver\\arcgisoutput\\Legend.bmp");
119 graphics.Dispose();
120 }
121 #endregion
122
123
124 return legendImage;
125 }
126
127 private List<KeyValuePair<string, CartoImage>> GetLegendImages(TocLayer tocLayer)
128 {
129 List<KeyValuePair<string, CartoImage>> legends = new List<KeyValuePair<string, CartoImage>>();
130 if (tocLayer != null && tocLayer.Visible)
131 {
132 if (tocLayer.TocSymbolGroupCount > 0)
133 {
134 if (tocLayer.TocSymbolGroupCount == 1)
135 {
136 TocSymbolGroup symbolGroupSingle = tocLayer.GetTocSymbolGroup(0);
137
138 //Looks like there is no way to differentiate between a layer with a simple single symbol
139 //and a layer with a group symbol with only one entry
140
141 //So, if we encounter a group symbol with only one entry, assume it is a simple single legend
142 //This actually does not make a difference for people reading the map as both should mean the same thing
143 //The ESRI ADF TOC control works the same way
144 if (symbolGroupSingle.Count == 1)
145 {
146 TocSymbol tocSymbol = symbolGroupSingle[0];
147 legends.Add(new KeyValuePair<string, CartoImage>(tocLayer.LayerName, tocSymbol.Image));
148 }
149 else
150 {
151 System.Collections.IEnumerator e = tocLayer.GetTocSymbolGroups();
152 //add the layer name
153 if(e.MoveNext() && e.Current != null)
154 legends.Add(new KeyValuePair<string, CartoImage>(tocLayer.LayerName, null));
155
156 e.Reset();
157 while (e.MoveNext())
158 {
159 //Add the group name
160 TocSymbolGroup symbolGroup = e.Current as TocSymbolGroup;
161 legends.Add(new KeyValuePair<string, CartoImage>(symbolGroup.Heading, null));
162
163 foreach (TocSymbol tocSymbol in symbolGroup)
164 {
165 //add group entries
166 legends.Add(new KeyValuePair<string, CartoImage>(tocSymbol.Label, tocSymbol.Image));
167 }
168 }
169 }
170 }
171 else
172 {
173 System.Collections.IEnumerator e = tocLayer.GetTocSymbolGroups();
174 if (e.MoveNext() && e.Current != null)
175 legends.Add(new KeyValuePair<string, CartoImage>(tocLayer.LayerName, null));
176 e.Reset();
177 while (e.MoveNext())
178 {
179 TocSymbolGroup symbolGroup = e.Current as TocSymbolGroup;
180 legends.Add(new KeyValuePair<string, CartoImage>(symbolGroup.Heading, null));
181
182 foreach (TocSymbol tocSymbol in symbolGroup)
183 {
184 legends.Add(new KeyValuePair<string, CartoImage>(tocSymbol.Label, tocSymbol.Image));
185 }
186 }
187 }
188 }
189
190 if (tocLayer.TocLayerCount > 0)
191 {
192 System.Collections.IEnumerator subLayers = tocLayer.GetTocLayers();
193 while (subLayers.MoveNext())
194 {
195 List<KeyValuePair<string, CartoImage>> subLayerLegends = GetLegendImages(subLayers.Current as TocLayer);
196 if (subLayerLegends != null)
197 legends.AddRange(subLayerLegends);
198 }
199 }
200 }
201 return legends;
202 }
|
|
Notes
|
|
Please let me know if you have any problems, questions or suggestions for the snippet above.
|
|
|