-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1047 from WildernessLabs/feature/spectrum-view
Histogram
- Loading branch information
Showing
4 changed files
with
219 additions
and
2 deletions.
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
....Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Charts/HistogramChart.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Meadow.Foundation.Graphics.MicroLayout; | ||
|
||
/// <summary> | ||
/// Represents a histogram chart control. | ||
/// </summary> | ||
public class HistogramChart : ChartControl | ||
{ | ||
private List<HistogramChartSeries> _series = new(); | ||
private bool _showXLabels = true; | ||
private int? _maxXAxisValue = null; | ||
private int? _minXAxisValue = null; | ||
|
||
/// <summary> | ||
/// Creates a vertical bar chart instance | ||
/// </summary> | ||
/// <param name="left">The control's left position</param> | ||
/// <param name="top">The control's top position</param> | ||
/// <param name="width">The control's width</param> | ||
/// <param name="height">The control's height</param> | ||
public HistogramChart(int left, int top, int width, int height) | ||
: base(left, top, width, height) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Creates a vertical bar chart instance | ||
/// </summary> | ||
/// <param name="left">The control's left position</param> | ||
/// <param name="top">The control's top position</param> | ||
/// <param name="width">The control's width</param> | ||
/// <param name="height">The control's height</param> | ||
/// <param name="series">A series of data to plot</param> | ||
public HistogramChart(int left, int top, int width, int height, IEnumerable<HistogramChartSeries> series) | ||
: base(left, top, width, height) | ||
{ | ||
Series = series.ToList(); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets a series of float values to plot | ||
/// </summary> | ||
public List<HistogramChartSeries> Series | ||
{ | ||
get => _series; | ||
set => SetInvalidatingProperty(ref _series, value); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the visibility of the X axis labels | ||
/// </summary> | ||
public bool ShowXAxisLabels | ||
{ | ||
get => _showXLabels; | ||
set => SetInvalidatingProperty(ref _showXLabels, value); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets an optional minimum X Axis value | ||
/// </summary> | ||
public int? MinXAxisValue | ||
{ | ||
get => _minXAxisValue; | ||
set => SetInvalidatingProperty(ref _minXAxisValue, value); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets an optional maximum X Axis value | ||
/// </summary> | ||
public int? MaxXAxisValue | ||
{ | ||
get => _maxXAxisValue; | ||
set => SetInvalidatingProperty(ref _maxXAxisValue, value); | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected override void OnDraw(MicroGraphics graphics) | ||
{ | ||
graphics.DrawRectangle(Left, Top, Width, Height, BackgroundColor, true); | ||
|
||
var font = GetAxisFont(); | ||
|
||
ChartAreaTop = Top + (DefaultMargin * 2) - AxisStroke; | ||
ChartAreaBottom = Bottom - DefaultMargin - AxisStroke; | ||
if (ShowXAxisLabels) | ||
{ | ||
ChartAreaBottom -= font.Height; | ||
} | ||
ChartAreaHeight = Height - (DefaultMargin * 3); | ||
|
||
ChartAreaLeft = Left + DefaultMargin; | ||
|
||
ChartAreaWidth = Width - DefaultMargin; | ||
|
||
DrawSeries(graphics, Series, font); | ||
|
||
graphics.DrawRectangle( | ||
ChartAreaLeft, | ||
ChartAreaBottom, | ||
ChartAreaWidth - DefaultMargin, | ||
AxisStroke, | ||
color: AxisColor, | ||
filled: true); | ||
} | ||
|
||
private void DrawSeries(MicroGraphics graphics, List<HistogramChartSeries> seriesList, IFont font) | ||
{ | ||
var barWidth = 3; | ||
var halfWidth = barWidth / 2; | ||
|
||
var count = seriesList.SelectMany(e => e.DataElements).Count(); | ||
if (count == 0) return; | ||
|
||
var minX = MinXAxisValue ?? seriesList.SelectMany(e => e.DataElements).Min(x => x.X); | ||
var maxX = MaxXAxisValue ?? seriesList.SelectMany(e => e.DataElements).Max(x => x.X); | ||
int maxY = seriesList.SelectMany(e => e.DataElements).Max(y => y.Y); | ||
|
||
var heightScale = ChartAreaHeight * 0.9f / maxY; | ||
|
||
for (var s = seriesList.Count - 1; s >= 0; s--) | ||
{ | ||
if (seriesList[s].DataElements.Count() == 0) continue; | ||
|
||
foreach (var pair in seriesList[s].DataElements) | ||
{ | ||
// Normalize the value to the range [0, 1] | ||
double normalizedValue = (Math.Log(pair.X) - Math.Log(minX)) / (Math.Log(maxX) - Math.Log(minX)); | ||
|
||
// Map the normalized value to the display width | ||
int x = (int)(normalizedValue * ChartAreaWidth) + ChartAreaLeft; | ||
|
||
var barHeight = (int)(heightScale * pair.Y); | ||
|
||
graphics.DrawRectangle( | ||
x - halfWidth, | ||
ChartAreaBottom - barHeight, | ||
barWidth, | ||
barHeight, | ||
color: seriesList[s].ForeColor, | ||
filled: true); | ||
} | ||
} | ||
|
||
if (ShowXAxisLabels) | ||
{ | ||
for (var i = 1; i < 100000; i *= 10) | ||
{ | ||
if (i < minX || i > maxX) continue; | ||
|
||
// Normalize the value to the range [0, 1] | ||
double normalizedValue = (Math.Log(i) - Math.Log(minX)) / (Math.Log(maxX) - Math.Log(minX)); | ||
|
||
// Map the normalized value to the display width | ||
int x = (int)(normalizedValue * ChartAreaWidth) + ChartAreaLeft; | ||
|
||
graphics.DrawText( | ||
x + halfWidth, | ||
ChartAreaBottom + DefaultMargin + AxisStroke, | ||
alignmentH: HorizontalAlignment.Center, | ||
color: AxisLabelColor, | ||
text: i.ToString(), | ||
font: font); | ||
} | ||
} | ||
} | ||
|
||
} |
47 changes: 47 additions & 0 deletions
47
...ation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Charts/HistogramChartSeries.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
|
||
namespace Meadow.Foundation.Graphics.MicroLayout; | ||
|
||
/// <summary> | ||
/// Represents a series in a histogram chart. | ||
/// </summary> | ||
public class HistogramChartSeries : INotifyPropertyChanged | ||
{ | ||
private Color _foreColor = Color.White; | ||
private IEnumerable<(int X, int Y)> _elements = Array.Empty<(int X, int Y)>(); | ||
|
||
/// <inheritdoc/> | ||
public event PropertyChangedEventHandler? PropertyChanged; | ||
|
||
/// <summary> | ||
/// Gets or sets the foreground color of the series. | ||
/// </summary> | ||
public Color ForeColor | ||
{ | ||
get => _foreColor; | ||
set | ||
{ | ||
if (value == ForeColor) { return; } | ||
_foreColor = value; | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ForeColor))); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the data elements of the series, where each element is a tuple containing X and Y values. | ||
/// </summary> | ||
public IEnumerable<(int X, int Y)> DataElements | ||
{ | ||
get => _elements; | ||
set | ||
{ | ||
if (value == DataElements) { return; } | ||
_elements = value; | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DataElements))); | ||
} | ||
} | ||
|
||
|
||
} |
2 changes: 1 addition & 1 deletion
2
...Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Charts/LineSeriesPoint.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters