Initial Commit
This commit is contained in:
16
Charts/Filters/EmptyFilter.cs
Normal file
16
Charts/Filters/EmptyFilter.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Filters
|
||||
{
|
||||
public sealed class EmptyFilter : PointsFilterBase
|
||||
{
|
||||
public override List<Point> Filter(List<Point> points)
|
||||
{
|
||||
return points;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Charts/Filters/FrequencyFilter.cs
Normal file
136
Charts/Filters/FrequencyFilter.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
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
|
||||
{
|
||||
|
||||
/// <summary>Visible region in screen coordinates</summary>
|
||||
private Rect screenRect;
|
||||
|
||||
#region IPointFilter Members
|
||||
|
||||
public override void SetScreenRect(Rect screenRect)
|
||||
{
|
||||
this.screenRect = screenRect;
|
||||
}
|
||||
|
||||
// todo probably use LINQ here.
|
||||
public override List<Point> Filter(List<Point> points)
|
||||
{
|
||||
if (points.Count == 0) return points;
|
||||
|
||||
List<Point> resultPoints = points;
|
||||
List<Point> currentChain = new List<Point>();
|
||||
|
||||
if (points.Count > 2 * screenRect.Width)
|
||||
{
|
||||
resultPoints = new List<Point>();
|
||||
|
||||
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<Point> points)
|
||||
{
|
||||
Point minPoint = points[0];
|
||||
foreach (Point p in points)
|
||||
{
|
||||
if (p.X < minPoint.X)
|
||||
{
|
||||
minPoint = p;
|
||||
}
|
||||
}
|
||||
return minPoint;
|
||||
}
|
||||
|
||||
private static Point MaxByX(IList<Point> points)
|
||||
{
|
||||
Point maxPoint = points[0];
|
||||
foreach (Point p in points)
|
||||
{
|
||||
if (p.X > maxPoint.X)
|
||||
{
|
||||
maxPoint = p;
|
||||
}
|
||||
}
|
||||
return maxPoint;
|
||||
}
|
||||
|
||||
private static Point MinByY(IList<Point> points)
|
||||
{
|
||||
Point minPoint = points[0];
|
||||
foreach (Point p in points)
|
||||
{
|
||||
if (p.Y < minPoint.Y)
|
||||
{
|
||||
minPoint = p;
|
||||
}
|
||||
}
|
||||
return minPoint;
|
||||
}
|
||||
|
||||
private static Point MaxByY(IList<Point> points)
|
||||
{
|
||||
Point maxPoint = points[0];
|
||||
foreach (Point p in points)
|
||||
{
|
||||
if (p.Y > maxPoint.Y)
|
||||
{
|
||||
maxPoint = p;
|
||||
}
|
||||
}
|
||||
return maxPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
Charts/Filters/FrequencyFilter2.cs
Normal file
90
Charts/Filters/FrequencyFilter2.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Research.DynamicDataDisplay.Charts.Filters;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Filters
|
||||
{
|
||||
public class FrequencyFilter2 : PointsFilterBase
|
||||
{
|
||||
private Rect screenRect;
|
||||
public override void SetScreenRect(Rect screenRect)
|
||||
{
|
||||
this.screenRect = screenRect;
|
||||
}
|
||||
|
||||
public override List<Point> Filter(List<Point> points)
|
||||
{
|
||||
List<Point> result = new List<Point>();
|
||||
|
||||
using (var enumerator = points.GetEnumerator())
|
||||
{
|
||||
double currentX = Double.NegativeInfinity;
|
||||
|
||||
double minX = 0, maxX = 0, minY = 0, maxY = 0;
|
||||
|
||||
Point left = new Point(), right = new Point(), top = new Point(), bottom = new Point();
|
||||
|
||||
bool isFirstPoint = true;
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
Point currPoint = enumerator.Current;
|
||||
double x = currPoint.X;
|
||||
double y = currPoint.Y;
|
||||
double xInt = Math.Floor(x);
|
||||
if (xInt == currentX)
|
||||
{
|
||||
if (x > maxX)
|
||||
{
|
||||
maxX = x;
|
||||
right = currPoint;
|
||||
}
|
||||
|
||||
if (y > maxY)
|
||||
{
|
||||
maxY = y;
|
||||
top = currPoint;
|
||||
}
|
||||
else if (y < minY)
|
||||
{
|
||||
minY = y;
|
||||
bottom = currPoint;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isFirstPoint)
|
||||
{
|
||||
result.Add(left);
|
||||
|
||||
Point leftY = top.X < bottom.X ? top : bottom;
|
||||
Point rightY = top.X > bottom.X ? top : bottom;
|
||||
|
||||
if (top != bottom)
|
||||
{
|
||||
result.Add(leftY);
|
||||
result.Add(rightY);
|
||||
}
|
||||
else if (top != left)
|
||||
result.Add(top);
|
||||
|
||||
if (right != rightY)
|
||||
result.Add(right);
|
||||
}
|
||||
|
||||
currentX = xInt;
|
||||
left = right = top = bottom = currPoint;
|
||||
minX = maxX = x;
|
||||
minY = maxY = y;
|
||||
}
|
||||
|
||||
isFirstPoint = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Charts/Filters/IPointsFilter.cs
Normal file
23
Charts/Filters/IPointsFilter.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Filters
|
||||
{
|
||||
/// <summary>Provides algorithm for filtering point lists in screen coordinates</summary>
|
||||
public interface IPointsFilter
|
||||
{
|
||||
|
||||
/// <summary>Performs filtering</summary>
|
||||
/// <param name="points">List of source points</param>
|
||||
/// <returns>List of filtered points</returns>
|
||||
List<Point> Filter(List<Point> points);
|
||||
|
||||
/// <summary>Sets visible rectangle in screen coordinates</summary>
|
||||
/// <param name="rect">Screen rectangle</param>
|
||||
/// <remarks>Should be invoked before first call to <see cref="Filter"/></remarks>
|
||||
void SetScreenRect(Rect screenRect);
|
||||
|
||||
event EventHandler Changed;
|
||||
}
|
||||
}
|
||||
74
Charts/Filters/InclinationFilter.cs
Normal file
74
Charts/Filters/InclinationFilter.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using Microsoft.Research.DynamicDataDisplay.Charts.Filters;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Filters
|
||||
{
|
||||
[Obsolete("Works incorrectly", true)]
|
||||
public sealed class InclinationFilter : PointsFilterBase
|
||||
{
|
||||
private double criticalAngle = 179;
|
||||
public double CriticalAngle
|
||||
{
|
||||
get { return criticalAngle; }
|
||||
set
|
||||
{
|
||||
if (criticalAngle != value)
|
||||
{
|
||||
criticalAngle = value;
|
||||
RaiseChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region IPointFilter Members
|
||||
|
||||
public override List<Point> Filter(List<Point> points)
|
||||
{
|
||||
if (points.Count == 0)
|
||||
return points;
|
||||
|
||||
List<Point> res = new List<Point> { points[0] };
|
||||
|
||||
int i = 1;
|
||||
while (i < points.Count)
|
||||
{
|
||||
bool added = false;
|
||||
int j = i;
|
||||
while (!added && (j < points.Count - 1))
|
||||
{
|
||||
Point x1 = res[res.Count - 1];
|
||||
Point x2 = points[j];
|
||||
Point x3 = points[j + 1];
|
||||
|
||||
double a = (x1 - x2).Length;
|
||||
double b = (x2 - x3).Length;
|
||||
double c = (x1 - x3).Length;
|
||||
|
||||
double angle13 = Math.Acos((a * a + b * b - c * c) / (2 * a * b));
|
||||
double degrees = 180 / Math.PI * angle13;
|
||||
if (degrees < criticalAngle)
|
||||
{
|
||||
res.Add(x2);
|
||||
added = true;
|
||||
i = j + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
// reached the end of resultPoints
|
||||
if (!added)
|
||||
{
|
||||
res.Add(points.GetLast());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
26
Charts/Filters/PointsFilterBase.cs
Normal file
26
Charts/Filters/PointsFilterBase.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Research.DynamicDataDisplay.Filters;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Filters
|
||||
{
|
||||
public abstract class PointsFilterBase : IPointsFilter
|
||||
{
|
||||
#region IPointsFilter Members
|
||||
|
||||
public abstract List<Point> Filter(List<Point> points);
|
||||
|
||||
public virtual void SetScreenRect(Rect screenRect) { }
|
||||
|
||||
protected void RaiseChanged()
|
||||
{
|
||||
Changed.Raise(this);
|
||||
}
|
||||
public event EventHandler Changed;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user