using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics;
namespace Microsoft.Research.DynamicDataDisplay.ViewportConstraints
{
///
/// Represents a restriction in which actual visible rect's proportions depends on
/// actual output rect's proportions.
///
public sealed class PhysicalProportionsConstraint : ViewportConstraint
{
///
/// Initializes a new instance of the class.
///
public PhysicalProportionsConstraint() { }
///
/// Initializes a new instance of the class with the given proportion ratio.
///
/// The proportion ratio.
public PhysicalProportionsConstraint(double proportionRatio)
{
ProportionRatio = proportionRatio;
}
private double proportionRatio = 1.0;
/// Gets or sets the proportion ratio (width / height). Default value is 1.0.
/// The proportion ratio.
public double ProportionRatio
{
get { return proportionRatio; }
set
{
if (proportionRatio != value)
{
proportionRatio = value;
RaiseChanged();
}
}
}
///
/// Applies the restriction.
///
/// Previous data rectangle.
/// Proposed data rectangle.
/// The viewport, to which current restriction is being applied.
/// New changed visible rectangle.
public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
{
Rect output = viewport.Output;
if (output.Height == 0 || output.Width == 0)
return proposedDataRect;
double newRatio = proposedDataRect.Width * output.Height /
(proposedDataRect.Height * output.Width);
// Don't modify rect if new ratio differs only slightly
if (Math.Abs(newRatio - proportionRatio) < 1e-3)
return proposedDataRect;
// Try to keep visible rect's square constant
double width = proposedDataRect.Width, height = proposedDataRect.Height;
double square = proposedDataRect.Width * proposedDataRect.Height;
if (square > 0)
{
width = Math.Sqrt(proportionRatio * output.Width * square / output.Height);
height = Math.Sqrt(output.Height * square / (proportionRatio * output.Width));
}
// Finally ensure we have correct aspect ratio
double delta = (proportionRatio * height * output.Width - width * output.Height) /
(output.Height + proportionRatio * output.Width);
width += delta;
height -= delta;
double x0 = (proposedDataRect.XMax + proposedDataRect.XMin) / 2;
double y0 = (proposedDataRect.YMax + proposedDataRect.YMin) / 2;
return new DataRect
{
XMin = x0 - width / 2,
Width = width,
YMin = y0 - height / 2,
Height = height
};
}
}
}