using System; using System.Collections.Generic; using System.Windows; using Microsoft.Research.DynamicDataDisplay.Charts.Filters; namespace Microsoft.Research.DynamicDataDisplay.Filters { public sealed class FrequencyFilter : PointsFilterBase { /// Visible region in screen coordinates private Rect screenRect; #region IPointFilter Members public override void SetScreenRect(Rect screenRect) { this.screenRect = screenRect; } // todo probably use LINQ here. public override List Filter(List points) { if (points.Count == 0) return points; List resultPoints = points; List currentChain = new List(); if (points.Count > 2 * screenRect.Width) { resultPoints = new List(); double currentX = Math.Floor(points[0].X); foreach (Point p in points) { if (Math.Floor(p.X) == currentX) { currentChain.Add(p); } else { // Analyse current chain if (currentChain.Count <= 2) { resultPoints.AddRange(currentChain); } else { Point first = MinByX(currentChain); Point last = MaxByX(currentChain); Point min = MinByY(currentChain); Point max = MaxByY(currentChain); resultPoints.Add(first); Point smaller = min.X < max.X ? min : max; Point greater = min.X > max.X ? min : max; if (smaller != resultPoints.GetLast()) { resultPoints.Add(smaller); } if (greater != resultPoints.GetLast()) { resultPoints.Add(greater); } if (last != resultPoints.GetLast()) { resultPoints.Add(last); } } currentChain.Clear(); currentChain.Add(p); currentX = Math.Floor(p.X); } } } resultPoints.AddRange(currentChain); return resultPoints; } #endregion private static Point MinByX(IList points) { Point minPoint = points[0]; foreach (Point p in points) { if (p.X < minPoint.X) { minPoint = p; } } return minPoint; } private static Point MaxByX(IList points) { Point maxPoint = points[0]; foreach (Point p in points) { if (p.X > maxPoint.X) { maxPoint = p; } } return maxPoint; } private static Point MinByY(IList points) { Point minPoint = points[0]; foreach (Point p in points) { if (p.Y < minPoint.Y) { minPoint = p; } } return minPoint; } private static Point MaxByY(IList points) { Point maxPoint = points[0]; foreach (Point p in points) { if (p.Y > maxPoint.Y) { maxPoint = p; } } return maxPoint; } } }