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;
}
}
}