Rob,
Your code is straightforward and easy to understand, I think you can go ahead to use it for most cases. Here are some possible ways to make it faster under some circumstance though, please have a look and maybe they will be suitable for you.
1, The main draw method accepts a Feature Array as the parameter but every array you passed in has only one item, that means if we have 100 features, we will always call the Draw method 100 times. As every draw has some overhead, it will be faster if we can draw many features together at a same time. You know draw 100 features one time is faster than draw 1 feature 100 times.
Here is the code I change a bit trying to draw bunch of features together at one time. It will save some time on drawing part but will take more memory and do some extra work on other part. So please have a test and make sure it works fine for you before using it.
[Serializable]
public class CustomDataClassBreakStyle : ClassBreakStyle
{
Dictionary<string, double> customData;
public CustomDataClassBreakStyle(string columnName, Dictionary<string, double> customData) :
base(columnName)
{
this.customData = customData;
}
protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
{
// Create and Init the Feature Collections for every ClassBreak
Collection<List<Feature>> ClassBreakFeatures = new Collection<List<Feature>>();
for (int i = 0; i < ClassBreakFeatures.Count; i++)
{
ClassBreakFeatures[i] = new List<Feature>();
}
// Fill in the Feature Collections for every ClassBreak
foreach (Feature feature in features)
{
string key = feature.ColumnValues[this.ColumnName];
if (customData.ContainsKey(key))
{
double value = customData[key];
for (int i = this.ClassBreaks.Count - 1; i >= 0; i--)
{
ClassBreak classBreak = this.ClassBreaks[i];
if (value > classBreak.Value)
{
// Call the draw on all of the default styles of the ClassBreak, and also check if there are custom styles.
ClassBreakFeatures[i].Add(feature);
break;
}
}
}
}
// Draw them out
for (int i = 0; i < this.ClassBreaks.Count; i++)
{
DrawAllFeaturesForOneBreak(ClassBreakFeatures[i].ToArray(), this.ClassBreaks[i], canvas, labelsInThisLayer, labelsInAllLayers);
}
}
private void DrawAllFeaturesForOneBreak(Feature[] features, ClassBreak classBreak, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
{
if (classBreak.CustomStyles.Count == 0)
{
classBreak.DefaultAreaStyle.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
classBreak.DefaultLineStyle.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
classBreak.DefaultPointStyle.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
classBreak.DefaultTextStyle.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
}
else
{
foreach (Style style in classBreak.CustomStyles)
{
style.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
}
}
}
}
NOTE:
With the new method, the result is a bit different. In your original way, as the records will be drawn one by one, if 2 features are overlap, the latter one will be over the former one. So for example I have 2 classbreaks for the features, one is rendered in Green and the other is in Blue, chances is that in your map, some blue feature is over the green one and some green feature is over the blue one. In the new way though, as one group of features is rendered together, the green ones will always be over the green ones (or the other way), that might be the way we prefer.
2, If you have many class breaks, instead of looping them one by one, maybe you can sort them first and do a binary search, which will greatly improve the speed. Sure if you only have 2 or 3 classbreaks, that's not a big deal.
Hope that helps, let me know if you have any issues.
Thanks,
Ben