diff --git a/Scripts/Editor/PropertyDrawers/SerieDrawer.cs b/Scripts/Editor/PropertyDrawers/SerieDrawer.cs index 51481688..a581026c 100644 --- a/Scripts/Editor/PropertyDrawers/SerieDrawer.cs +++ b/Scripts/Editor/PropertyDrawers/SerieDrawer.cs @@ -31,6 +31,8 @@ namespace XCharts SerializedProperty m_LineArrow = prop.FindPropertyRelative("m_LineArrow"); SerializedProperty m_LineType = prop.FindPropertyRelative("m_LineType"); SerializedProperty m_SampleDist = prop.FindPropertyRelative("m_SampleDist"); + SerializedProperty m_SampleType = prop.FindPropertyRelative("m_SampleType"); + SerializedProperty m_SampleAverage = prop.FindPropertyRelative("m_SampleAverage"); SerializedProperty m_BarWidth = prop.FindPropertyRelative("m_BarWidth"); SerializedProperty m_BarGap = prop.FindPropertyRelative("m_BarGap"); SerializedProperty m_BarCategoryGap = prop.FindPropertyRelative("m_BarCategoryGap"); @@ -98,6 +100,10 @@ namespace XCharts drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; EditorGUI.PropertyField(drawRect, m_SampleDist); drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_SampleType); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(drawRect, m_SampleAverage); + drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; } if (serieType == SerieType.Line || serieType == SerieType.Scatter @@ -361,7 +367,7 @@ namespace XCharts if (serieType == SerieType.Line) { height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_LineArrow")); - height += 2 * EditorGUIUtility.singleLineHeight + 1 * EditorGUIUtility.standardVerticalSpacing; + height += 4 * EditorGUIUtility.singleLineHeight + 3 * EditorGUIUtility.standardVerticalSpacing; } if (serieType == SerieType.Bar) { @@ -371,7 +377,7 @@ namespace XCharts { SerializedProperty m_Data = prop.FindPropertyRelative("m_Data"); int num = m_Data.arraySize + 2; - if (num > 30) num = 14; + if (num > 30) num = 15; if (prop.FindPropertyRelative("m_ShowDataIcon").boolValue) { num *= 5; diff --git a/Scripts/UI/Component/Serie.cs b/Scripts/UI/Component/Serie.cs index 6369554f..6110dc20 100644 --- a/Scripts/UI/Component/Serie.cs +++ b/Scripts/UI/Component/Serie.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using UnityEngine; -using UnityEngine.Serialization; namespace XCharts { @@ -111,6 +110,33 @@ namespace XCharts DashDotDot } + /// + /// 采样类型 + /// + public enum SampleType + { + /// + /// 取峰值。 + /// + Peak, + /// + /// 取过滤点的平均值。 + /// + Average, + /// + /// 取过滤点的最大值。 + /// + Max, + /// + /// 取过滤点的最小值。 + /// + Min, + /// + /// 取过滤点的和。 + /// + Sum + } + /// /// 系列。每个系列通过 type 决定自己的图表类型。 /// @@ -130,6 +156,9 @@ namespace XCharts [SerializeField] private SerieSymbol m_Symbol = new SerieSymbol(); [SerializeField] private LineType m_LineType = LineType.Normal; [SerializeField] private float m_SampleDist = 0; + [SerializeField] private SampleType m_SampleType = SampleType.Average; + [SerializeField] private float m_SampleAverage = 0; + [SerializeField] private LineStyle m_LineStyle = new LineStyle(); [SerializeField] private float m_BarWidth = 0.6f; [SerializeField] private float m_BarGap = 0.3f; // 30% @@ -242,6 +271,16 @@ namespace XCharts /// public float sampleDist { get { return m_SampleDist; } set { m_SampleDist = value < 0 ? 0 : value; } } /// + /// the type of sample. + /// 采样类型。当sampleDist大于0时有效。 + /// + public SampleType sampleType { get { return m_SampleType; } set { m_SampleType = value; } } + /// + /// 设定的采样平均值。当sampleType 为 Peak 时,用于和过滤数据的平均值做对比是取最大值还是最小值。默认为0时会实时计算所有数据的平均值。 + /// + /// + public float sampleAverage { get { return m_SampleAverage; } set { m_SampleAverage = value; } } + /// /// The style of line. /// 线条样式。 /// diff --git a/Scripts/UI/Internal/CoordinateChart_DrawLine.cs b/Scripts/UI/Internal/CoordinateChart_DrawLine.cs index 7f9bef6c..a373d6f9 100644 --- a/Scripts/UI/Internal/CoordinateChart_DrawLine.cs +++ b/Scripts/UI/Internal/CoordinateChart_DrawLine.cs @@ -101,6 +101,8 @@ namespace XCharts if (sampleDist > 0) rate = (int)((maxCount - serie.minShow) / (coordinateWid / sampleDist)); if (rate < 1) rate = 1; var includeLastData = false; + var totalAverage = serie.sampleAverage > 0 ? serie.sampleAverage : + DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate); for (i = serie.minShow; i < maxCount; i += rate) { if (i == maxCount - 1) includeLastData = true; @@ -108,7 +110,7 @@ namespace XCharts { for (int j = 0; j < rate; j++) seriesHig.Add(0); } - float yValue = showData[i].data[1]; + float yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage, i); seriesHig[i] += GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, seriesHig[i], ref np); serie.dataPoints.Add(np); } @@ -186,6 +188,71 @@ namespace XCharts } } + private float DataAverage(ref List showData, SampleType sampleType, int minCount, int maxCount, int rate) + { + var totalAverage = 0f; + if (rate > 1 && sampleType == SampleType.Peak) + { + var total = 0f; + for (int i = minCount; i < maxCount; i++) + { + total += showData[i].data[1]; + } + totalAverage = total / (maxCount - minCount); + } + return totalAverage; + } + + private float SampleValue(ref List showData, SampleType sampleType, int rate, + int minCount, int maxCount, float totalAverage, int index) + { + if (rate <= 1 || index == minCount) return showData[index].data[1]; + switch (sampleType) + { + case SampleType.Sum: + case SampleType.Average: + float total = 0; + for (int i = index; i > index - rate; i--) + { + total += showData[i].data[1]; + } + if (sampleType == SampleType.Average) return total / rate; + else return total; + case SampleType.Max: + float max = float.MinValue; + for (int i = index; i > index - rate; i--) + { + var value = showData[i].data[1]; + if (value > max) max = value; + } + return max; + case SampleType.Min: + float min = float.MaxValue; + for (int i = index; i > index - rate; i--) + { + var value = showData[i].data[1]; + if (value < min) min = value; + } + return min; + case SampleType.Peak: + max = float.MinValue; + min = float.MaxValue; + total = 0; + for (int i = index; i > index - rate; i--) + { + var value = showData[i].data[1]; + total += value; + if (value < min) min = value; + if (value > max) max = value; + } + var average = total / rate; + if (average >= totalAverage) return max; + else return min; + + } + return showData[index].data[1]; + } + private float GetDetailProgress(Serie serie, Axis axis, Vector3 lp, Vector3 np, Vector3 llp, Vector3 nnp, bool fine) {