Skip to content

Commit 1b0cd20

Browse files
committed
Add Color property to HistogramItem (#1347)
1 parent 7d6485e commit 1b0cd20

File tree

4 files changed

+94
-11
lines changed

4 files changed

+94
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
1919
- Workaround for text vertical alignment in SVG Export to accomodate viewers which don't support dominant-baseline (#459, #1198)
2020
- Issues Example demonstrating the rendering of Line and Arrow annotations with all LineStyles (#1312)
2121
- Add support for transposed (X and Y axis switched) plots with XYAxisSeries (#1334)
22+
- Add Color property to HistogramItem (#1347)
2223

2324
### Changed
2425
- Let Gtk# PlotView show up in Ui editor ToolBox of MonoDevelop and XamarinStudio (#1071)

Source/Examples/ExampleLibrary/Series/HistogramSeriesExamples.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace ExampleLibrary
1111
{
1212
using System;
13+
using System.Linq;
1314

1415
using ExampleLibrary.Utilities;
1516

@@ -96,6 +97,12 @@ public static PlotModel NormalDistribution()
9697
return CreateNormalDistribution();
9798
}
9899

100+
[Example("Individual Bin Colors")]
101+
public static PlotModel IndividualBinColors()
102+
{
103+
return CreateIndividualBinColors();
104+
}
105+
99106
public static PlotModel CreateExponentialDistribution(double mean = 1, int n = 10000)
100107
{
101108
var model = new PlotModel { Title = "Exponential Distribution", Subtitle = "Uniformly distributed bins (" + n + " samples)" };
@@ -186,6 +193,28 @@ public static PlotModel CreateDisconnectedBins()
186193
return model;
187194
}
188195

196+
public static PlotModel CreateIndividualBinColors(double mean = 1, int n = 10000)
197+
{
198+
var model = new PlotModel { Title = "Individual Bin Colors", Subtitle = "Minimum is Red, Maximum is Green" };
199+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Frequency" });
200+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Observation" });
201+
202+
Random rnd = new Random(1);
203+
204+
HistogramSeries chs = new HistogramSeries() { FillColor = OxyColors.Gray, RenderInLegend = true, Title = "Measurements" };
205+
206+
var binningOptions = new BinningOptions(BinningOutlierMode.CountOutliers, BinningIntervalType.InclusiveLowerBound, BinningExtremeValueMode.ExcludeExtremeValues);
207+
var binBreaks = HistogramHelpers.CreateUniformBins(0, 10, 20);
208+
var bins = HistogramHelpers.Collect(SampleUniform(rnd, 0, 10, 1000), binBreaks, binningOptions).OrderBy(b => b.Count).ToArray();
209+
bins.First().Color = OxyColors.Red;
210+
bins.Last().Color = OxyColors.Green;
211+
chs.Items.AddRange(bins);
212+
chs.StrokeThickness = 1;
213+
model.Series.Add(chs);
214+
215+
return model;
216+
}
217+
189218
private static IEnumerable<double> SampleExps(Random rnd, double mean, int count)
190219
{
191220
for (int i = 0; i < count; i++)
@@ -214,5 +243,13 @@ private static double SampleNormal(Random rnd, double mean, double std)
214243
var u2 = rnd.NextDouble();
215244
return Math.Sqrt(-2 * Math.Log(u1)) * Math.Cos(2 * Math.PI * u2);
216245
}
246+
247+
private static IEnumerable<double> SampleUniform(Random rnd, double min, double max, int count)
248+
{
249+
for (int i = 0; i < count; i++)
250+
{
251+
yield return rnd.NextDouble() * (max - min) + min;
252+
}
253+
}
217254
}
218255
}

Source/OxyPlot/Series/HistogramItem.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,25 @@ public class HistogramItem : ICodeGenerating
2222
/// <param name="area">The area.</param>
2323
/// <param name="count">The count.</param>
2424
public HistogramItem(double rangeStart, double rangeEnd, double area, int count)
25+
: this(rangeStart, rangeEnd, area, count, OxyColors.Automatic)
26+
{
27+
}
28+
29+
/// <summary>
30+
/// Initializes a new instance of the <see cref="HistogramItem" /> class.
31+
/// </summary>
32+
/// <param name="rangeStart">The range start.</param>
33+
/// <param name="rangeEnd">The range end.</param>
34+
/// <param name="area">The area.</param>
35+
/// <param name="count">The count.</param>
36+
/// <param name="color">The color.</param>
37+
public HistogramItem(double rangeStart, double rangeEnd, double area, int count, OxyColor color)
2538
{
2639
this.RangeStart = rangeStart;
2740
this.RangeEnd = rangeEnd;
2841
this.Area = area;
2942
this.Count = count;
43+
this.Color = color;
3044
}
3145

3246
/// <summary>
@@ -52,11 +66,19 @@ public HistogramItem(double rangeStart, double rangeEnd, double area, int count)
5266
/// </summary>
5367
public double RangeCenter => this.RangeStart + ((this.RangeEnd - this.RangeStart) / 2);
5468

69+
/// <summary>
5570
/// Gets or sets the count.
5671
/// </summary>
5772
/// <value>The count.</value>
5873
public int Count { get; set; }
5974

75+
/// <summary>
76+
/// Gets or sets the color.
77+
/// </summary>
78+
/// <value>The color.</value>
79+
/// <remarks>If set to Automatic, the FillColor of the RectangleBarSeries will be used.</remarks>
80+
public OxyColor Color { get; set; }
81+
6082
/// <summary>
6183
/// Gets the computed width of the item.
6284
/// </summary>
@@ -65,11 +87,11 @@ public HistogramItem(double rangeStart, double rangeEnd, double area, int count)
6587
/// <summary>
6688
/// Gets the computed height of the item.
6789
/// </summary>
68-
/// <value>The computed height of the item</value>
90+
/// <value>The computed height of the item.</value>
6991
public double Height => this.Area / this.Width;
7092

7193
/// <summary>
72-
/// Gets the value of the item. Equivalent to the Height;
94+
/// Gets the value of the item. Equivalent to the Height.
7395
/// </summary>
7496
/// <value>The value of the item.</value>
7597
public double Value => this.Height;
@@ -100,7 +122,14 @@ public bool Contains(DataPoint p)
100122
/// <returns>The to code.</returns>
101123
public string ToCode()
102124
{
103-
return CodeGenerator.FormatConstructor(this.GetType(), "{0},{1},{2},{3}", this.RangeStart, this.RangeEnd, this.Area, this.Count);
125+
if (!this.Color.IsAutomatic())
126+
{
127+
return CodeGenerator.FormatConstructor(this.GetType(), "{0},{1},{2},{3},{4}", this.RangeStart, this.RangeEnd, this.Area, this.Count, this.Color);
128+
}
129+
else
130+
{
131+
return CodeGenerator.FormatConstructor(this.GetType(), "{0},{1},{2},{3}", this.RangeStart, this.RangeEnd, this.Area, this.Count);
132+
}
104133
}
105134

106135
/// <summary>

Source/OxyPlot/Series/HistogramSeries.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace OxyPlot.Series
1919
public class HistogramSeries : XYAxisSeries
2020
{
2121
/// <summary>
22-
/// The default tracker format string
22+
/// The default tracker format string.
2323
/// </summary>
2424
public new const string DefaultTrackerFormatString = "Start: {5}\nEnd: {6}\nValue: {7}\nArea: {8}\nCount: {9}";
2525

@@ -41,7 +41,7 @@ public class HistogramSeries : XYAxisSeries
4141
/// <summary>
4242
/// The default color mapping.
4343
/// </summary>
44-
private OxyColor defaultColorMapping(HistogramItem item) => ActualFillColor;
44+
private OxyColor defaultColorMapping(HistogramItem item) => this.ActualFillColor;
4545

4646
/// <summary>
4747
/// Initializes a new instance of the <see cref="HistogramSeries" /> class.
@@ -55,7 +55,7 @@ public HistogramSeries()
5555
this.LabelFormatString = null;
5656
this.LabelFontSize = 0;
5757
this.LabelPlacement = LabelPlacement.Outside;
58-
this.ColorMapping = defaultColorMapping;
58+
this.ColorMapping = this.defaultColorMapping;
5959
}
6060

6161
/// <summary>
@@ -138,7 +138,7 @@ public OxyColor ActualFillColor
138138
/// Gets or sets the delegate used to map from <see cref="ItemsSeries.ItemsSource" /> to <see cref="HistogramSeries" />. The default is <c>null</c>.
139139
/// </summary>
140140
/// <value>The mapping.</value>
141-
/// <remarks>Example: series1.Mapping = item => new HistogramItem((double)item.BinStart, (double)item.BinStart + item.BinWidth, (double)item.Count / totalCount, item.Count);</remarks>
141+
/// <remarks>Example: series1.Mapping = item => new HistogramItem((double)item.BinStart, (double)item.BinStart + item.BinWidth, (double)item.Count / totalCount, item.Count).</remarks>
142142
public Func<object, HistogramItem> Mapping { get; set; }
143143

144144
/// <summary>
@@ -213,7 +213,7 @@ public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpo
213213
item.RangeEnd,
214214
item.Value,
215215
item.Area,
216-
item.Count)
216+
item.Count),
217217
};
218218
}
219219
}
@@ -222,7 +222,7 @@ public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpo
222222
// if no HistogramItems contain the point, return null
223223
return null;
224224
}
225-
225+
226226
/// <summary>
227227
/// Renders the legend symbol on the specified rendering context.
228228
/// </summary>
@@ -354,7 +354,7 @@ protected void RenderBins(IRenderContext rc, OxyRect clippingRect, ICollection<H
354354
{
355355
foreach (var item in items)
356356
{
357-
var actualFillColor = ColorMapping(item);
357+
var actualFillColor = this.GetItemFillColor(item);
358358

359359
// transform the data points to screen points
360360
var p1 = this.Transform(item.RangeStart, 0);
@@ -371,6 +371,23 @@ protected void RenderBins(IRenderContext rc, OxyRect clippingRect, ICollection<H
371371
}
372372
}
373373

374+
/// <summary>
375+
/// Gets the fill color of the given <see cref="HistogramItem"/>.
376+
/// </summary>
377+
/// <param name="item">The item.</param>
378+
/// <returns>The fill color of the item.</returns>
379+
protected OxyColor GetItemFillColor(HistogramItem item)
380+
{
381+
if (!item.Color.IsAutomatic())
382+
{
383+
return item.Color;
384+
}
385+
else
386+
{
387+
return this.ColorMapping(item);
388+
}
389+
}
390+
374391
/// <summary>
375392
/// Gets the clipping rectangle, transposed if the X axis is vertically orientated.
376393
/// </summary>
@@ -396,7 +413,6 @@ protected void RenderBins(IRenderContext rc, OxyRect clippingRect, ICollection<H
396413
/// <param name="rc">The render context.</param>
397414
/// <param name="clippingRect">The clipping rectangle.</param>
398415
/// <param name="rect">The column rectangle.</param>
399-
/// <param name="value">The value.</param>
400416
/// <param name="item">The item.</param>
401417
protected void RenderLabel(IRenderContext rc, OxyRect clippingRect, OxyRect rect, HistogramItem item)
402418
{

0 commit comments

Comments
 (0)