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