Windows 10 IoT Core에서 WinRT C#용 Chart
1. WinRTXamlToolkit.Controls.DataVisualization.UWP를 이용한 Chart.
차트를 드로잉하기 위해서 nuget에 있는 https://www.nuget.org/packages/WinRTXamlToolkit.Controls.DataVisualization.UWP/
Toolkit을 이용하는 방법이 있습니다.
Window 10 iot core 용으로 다운 받을 경우 UWP 버젼으로 다운 받아야 한다. 정상적으로 받았을 경우 xaml 파일과 cs 소스 코드를 이용하여 개발을 수행합니다.
<WinRT_Charting:Chart x:Name="LineChart1" Title="My Chart"> <WinRT_Charting:LineSeries Title="T1" ItemsSource="{Binding Items}" IndependentValueBinding="{Binding Name}" DependentValueBinding="{Binding Value}" IsSelectionEnabled="True"/> <WinRT_Charting:LineSeries Title="T2" ItemsSource="{Binding Items}" IndependentValueBinding="{Binding Name}" DependentValueBinding="{Binding Value}" IsSelectionEnabled="True"/> </WinRT_Charting:Chart> private void updateChart_Click(object sender, RoutedEventArgs e) { try { List<NameValueItem> newitems1 = new List<NameValueItem>(); List<NameValueItem> newitems2 = new List<NameValueItem>();
int num = items1.Count / 250; int con = 0; int value1 = 0; int value2 = 0; string name; for (var i = 0; i < items1.Count; i++) { name = Convert.ToString(newitems1.Count); newitems1.Add(new NameValueItem { Name = name, Value = items1[i].Value }); newitems2.Add(new NameValueItem { Name = name, Value = items2[i].Value }); } ((LineSeries)this.LineChart1.Series[0]).ItemsSource = newitems1; ((LineSeries)this.LineChart1.Series[1]).ItemsSource = newitems2;
newitems1 = null; newitems2 = null; } catch (Exception ex) { status.Text = ex.Message; } } |
Window 10 IoT Core에서 센서값을 차트로 표현결과, 라즈베리 파이에서 그래픽 리소스를 많이 잡아먹는 WinRTXamlToolkit.Controls.DataVisualization를 이용할 경우에는 많은 양의 데이터를 표현은 어렵다는것을 확인하였습니다. 약 1000개의 데이터를 현시할 경우, 약 30초정도 소요됩니다. 아래 그림은 1000개의 데이터를 차트에 표현하여 보았습니다.
실시간으로 데이터 표현이 어렵기 때문에, 데이터를 취득하는 버튼과 데이터 취득 종료버튼을 별도로 이용하여 데이터를 분석하는 모듈로 구성하였습니다.
만약 실시간으로 차트를 표현하고자 한다면, Canvas를 이용하여 직접 Drawing을 수행하면 빠른 현시가 가능합니다.
2. Canvas객체를 이용하 WinRT C# Chart 드로잉
private void DrawChart(Canvas canGraph, List<NameValueItem>[] pList, double axisx_min, double axisx_max, double data_min, double data_max) { canGraph.Children.Clear(); double[] RectWall; RectWall = new double[4]; RectWall[0] = 0; // left RectWall[1] = 0; // top RectWall[2] = canGraph.ActualWidth; // right RectWall[3] = canGraph.ActualHeight; // bottom double[] RectGap; RectGap = new double[4]; RectGap[0] = 30; // left RectGap[1] = 20; // top RectGap[2] = 20; // right RectGap[3] = 20; // bottom double[] RectChart; RectChart = new double[4]; RectChart[0] = RectWall[0] + RectGap[0]; // left RectChart[1] = RectWall[1] + RectGap[1]; // top RectChart[2] = RectWall[2] - RectGap[2]; // right RectChart[3] = RectWall[3] - RectGap[3]; // bottom double fChartWidth = RectChart[2] - RectChart[0]; double fChartHeight = RectChart[3] - RectChart[1]; int xGridNum = 5; int yGridNum = 10; double fGridGapX = fChartWidth / xGridNum; double fGridGapY = fChartHeight / yGridNum; // 차트 그리기. Rectangle pChartRect = new Rectangle(); pChartRect.StrokeThickness = 1; pChartRect.Fill = new SolidColorBrush(Colors.Black); pChartRect.Stroke = new SolidColorBrush(Colors.Yellow); pChartRect.Width = fChartWidth; pChartRect.Height = fChartHeight; Canvas.SetLeft(pChartRect, RectChart[0]); Canvas.SetTop(pChartRect, RectChart[1]); canGraph.Children.Add(pChartRect); // x축 그리기. int iCount = 0; GeometryGroup xaxis_geom = new GeometryGroup(); for (double x = 0; x <= fChartWidth; x += fGridGapX) { LineGeometry xtick = new LineGeometry(); xtick.StartPoint = new Point(x + RectChart[0], RectChart[3] + 5); xtick.EndPoint = new Point(x + RectChart[0], RectChart[1]); xaxis_geom.Children.Add(xtick); TextBlock xlabel = new TextBlock(); int ivalue = (int)axisx_min + (int)(axisx_max - axisx_min) / xGridNum * iCount; xlabel.Text = ivalue.ToString(); xlabel.FontSize = 10; Canvas.SetLeft(xlabel, x + RectChart[0]); Canvas.SetTop(xlabel, RectChart[3] + 5); canGraph.Children.Add(xlabel); iCount = iCount + 1; } Path xaxis_path = new Path(); xaxis_path.StrokeThickness = 1; xaxis_path.Stroke = new SolidColorBrush(Colors.Green); xaxis_path.Data = xaxis_geom; canGraph.Children.Add(xaxis_path); // y축 그리기. iCount = 0; GeometryGroup yxaxis_geom = new GeometryGroup(); for (double y = 0; y <= fChartHeight; y += fGridGapY) { LineGeometry ytick = new LineGeometry(); ytick.StartPoint = new Point(RectChart[0] - 5, RectChart[3] - y); ytick.EndPoint = new Point(RectChart[2], RectChart[3] - y); yxaxis_geom.Children.Add(ytick); TextBlock ylabel = new TextBlock(); int ivalue = (int)data_min + (int)(data_max - data_min) / yGridNum * iCount; ylabel.Text = ivalue.ToString(); ylabel.FontSize = 10; Canvas.SetLeft(ylabel, RectChart[0] - 20); Canvas.SetTop(ylabel, RectChart[3] - y - ylabel.FontSize); canGraph.Children.Add(ylabel); iCount = iCount + 1; } Path yaxis_path = new Path(); yaxis_path.StrokeThickness = 1; yaxis_path.Stroke = new SolidColorBrush(Colors.Green); yaxis_path.Data = yxaxis_geom; canGraph.Children.Add(yaxis_path); // data 그리기. double x1 = 0; double y1 = 0; double x2 = 0; double y2 = 0;
int idim = 0; idim = pList.Length; if (idim > 0) { for (int i = 0; i < idim; i++) { GeometryGroup data_geom = new GeometryGroup(); List<NameValueItem> newitems = pList[i]; double xstep = fChartWidth / newitems.Count; for (int j = 0; j < newitems.Count-1; j++) { LineGeometry vline = new LineGeometry(); x1 = RectChart[0] + xstep * j; y1 = RectChart[3] - fChartHeight * ((newitems[j].Value- data_min) / (data_max - data_min)); if (y1 < RectChart[1]) y1 = RectChart[1]; if (y1 > RectChart[3]) y1 = RectChart[3]; x2 = RectChart[0] + xstep * (j+1); y2 = RectChart[3] - fChartHeight * ((newitems[j+1].Value - data_min) / (data_max - data_min)); if (y2 < RectChart[1]) y2 = RectChart[1]; if (y2 > RectChart[3]) y2 = RectChart[3]; vline.StartPoint = new Point(x1, y1); vline.EndPoint = new Point(x2, y2); data_geom.Children.Add(vline); } Path value_path = new Path(); value_path.StrokeThickness = 1; if (i == 0) value_path.Stroke = new SolidColorBrush(Colors.Red); else if (i == 1) value_path.Stroke = new SolidColorBrush(Colors.Green); else if (i == 2) value_path.Stroke = new SolidColorBrush(Colors.Blue); else value_path.Stroke = new SolidColorBrush(Colors.Yellow); value_path.Data = data_geom; canGraph.Children.Add(value_path); } } } |
위와 같이 직접 Canvas에 직접 차트를 그릴경우에는 약 3000개의 데이터를 현시하는데 있어 2~3초정도 소요됨을 확인하였습니다.
차트를 이용하여 대용량을 현시하고자 할 경우에는 Canvas에 직접 그리는 것을 권고합니다.
Canvas를 이용하여 WinRT용 C# 차트 응용프로그램 실행 화면.
'enuSpace for mars(2017) > Work note(mars)' 카테고리의 다른 글
Windows 10 IoT Core C# Using SQLite (0) | 2016.10.12 |
---|---|
Windows 10 IoT Core Remote Server 사용 Tip (0) | 2016.10.06 |
Windows 10 IoT Core, Raspberry PI, Arduino and enuSpace Platform (0) | 2016.10.05 |
자바스크립트와 엔유스페이스를 이용한 Web Data Visualization (Big data 처리) (0) | 2016.09.20 |
enuSpace for Mars Terrain 객체의 데이터 가시화 작업 (0) | 2016.08.11 |