172 lines
4.0 KiB
C#
172 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Specialized;
|
|
|
|
namespace Microsoft.Research.DynamicDataDisplay.ViewportRestrictions
|
|
{
|
|
public class DataHeightRestriction : ViewportRestriction, ISupportAttachToViewport
|
|
{
|
|
private double yEnlargeCoeff = 1.1;
|
|
public double YEnlargeCoeff
|
|
{
|
|
get { return yEnlargeCoeff; }
|
|
set
|
|
{
|
|
if (yEnlargeCoeff != value)
|
|
{
|
|
yEnlargeCoeff = value;
|
|
RaiseChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
public override DataRect Apply(DataRect oldDataRect, DataRect newDataRect, Viewport2D viewport)
|
|
{
|
|
DataRect overallBounds = DataRect.Empty;
|
|
|
|
foreach (var chart in viewport.ContentBoundsHosts)
|
|
{
|
|
var plotterElement = chart as IPlotterElement;
|
|
var visual = viewport.Plotter.VisualBindings[plotterElement];
|
|
var points = (ReadOnlyCollection<Point>)PointsGraphBase.GetVisiblePoints(visual);
|
|
if (points != null)
|
|
{
|
|
|
|
// searching for indices of chart's visible points which are near left and right borders of newDataRect
|
|
double startX = newDataRect.XMin;
|
|
double endX = newDataRect.XMax;
|
|
|
|
if (points[0].X > endX || points[points.Count - 1].X < startX)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int startIndex = -1;
|
|
|
|
// we assume that points are sorted by x values ascending
|
|
if (startX <= points[0].X)
|
|
{
|
|
startIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
for (int i = 1; i < points.Count - 1; i++)
|
|
{
|
|
if (points[i].X <= startX && startX < points[i + 1].X)
|
|
{
|
|
startIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int endIndex = points.Count;
|
|
|
|
if (points[points.Count - 1].X < endX)
|
|
{
|
|
endIndex = points.Count;
|
|
}
|
|
else
|
|
{
|
|
for (int i = points.Count - 1; i >= 1; i--)
|
|
{
|
|
if (points[i - 1].X <= endX && endX < points[i].X)
|
|
{
|
|
endIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rect bounds = Rect.Empty;
|
|
for (int i = startIndex; i < endIndex; i++)
|
|
{
|
|
bounds.Union(points[i]);
|
|
}
|
|
if (startIndex > 0)
|
|
{
|
|
Point pt = GetInterpolatedPoint(startX, points[startIndex], points[startIndex - 1]);
|
|
bounds.Union(pt);
|
|
}
|
|
if (endIndex < points.Count - 1)
|
|
{
|
|
Point pt = GetInterpolatedPoint(endX, points[endIndex], points[endIndex + 1]);
|
|
bounds.Union(pt);
|
|
}
|
|
|
|
overallBounds.Union(bounds);
|
|
}
|
|
}
|
|
|
|
if (!overallBounds.IsEmpty)
|
|
{
|
|
double y = overallBounds.YMin;
|
|
double height = overallBounds.Height;
|
|
|
|
if (height == 0)
|
|
{
|
|
height = newDataRect.Height;
|
|
y -= height / 2;
|
|
}
|
|
|
|
newDataRect = new DataRect(newDataRect.XMin, y, newDataRect.Width, height);
|
|
newDataRect = DataRectExtensions.ZoomY(newDataRect, newDataRect.GetCenter(), yEnlargeCoeff);
|
|
}
|
|
|
|
return newDataRect;
|
|
}
|
|
|
|
private static Point GetInterpolatedPoint(double x, Point p1, Point p2)
|
|
{
|
|
double xRatio = (x - p1.X) / (p2.X - p1.X);
|
|
double y = (1 - xRatio) * p1.Y + xRatio * p2.Y;
|
|
|
|
return new Point(x, y);
|
|
}
|
|
|
|
#region ISupportAttach Members
|
|
|
|
void ISupportAttachToViewport.Attach(Viewport2D viewport)
|
|
{
|
|
((INotifyCollectionChanged)viewport.ContentBoundsHosts).CollectionChanged += OnContentBoundsHostsChanged;
|
|
|
|
foreach (var item in viewport.ContentBoundsHosts)
|
|
{
|
|
PointsGraphBase chart = item as PointsGraphBase;
|
|
if (chart != null)
|
|
{
|
|
chart.ProvideVisiblePoints = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnContentBoundsHostsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if (e.NewItems != null)
|
|
{
|
|
foreach (var item in e.NewItems)
|
|
{
|
|
PointsGraphBase chart = item as PointsGraphBase;
|
|
if (chart != null)
|
|
{
|
|
chart.ProvideVisiblePoints = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// todo probably set ProvideVisiblePoints to false on OldItems
|
|
}
|
|
|
|
void ISupportAttachToViewport.Detach(Viewport2D viewport)
|
|
{
|
|
((INotifyCollectionChanged)viewport.ContentBoundsHosts).CollectionChanged -= OnContentBoundsHostsChanged;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|