1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using System.Text;
|
---|
5 | using System.Windows;
|
---|
6 | using System.Diagnostics;
|
---|
7 |
|
---|
8 | namespace Microsoft.Research.DynamicDataDisplay.ViewportConstraints
|
---|
9 | {
|
---|
10 | /// <summary>
|
---|
11 | /// Represents a restriction in which actual visible rect's proportions depends on
|
---|
12 | /// actual output rect's proportions.
|
---|
13 | /// </summary>
|
---|
14 | public sealed class PhysicalProportionsConstraint : ViewportConstraint
|
---|
15 | {
|
---|
16 | /// <summary>
|
---|
17 | /// Initializes a new instance of the <see cref="PhysicalProportionsConstraint"/> class.
|
---|
18 | /// </summary>
|
---|
19 | public PhysicalProportionsConstraint() { }
|
---|
20 |
|
---|
21 | /// <summary>
|
---|
22 | /// Initializes a new instance of the <see cref="PhysicalProportionsConstraint"/> class with the given proportion ratio.
|
---|
23 | /// </summary>
|
---|
24 | /// <param name="proportionRatio">The proportion ratio.</param>
|
---|
25 | public PhysicalProportionsConstraint(double proportionRatio)
|
---|
26 | {
|
---|
27 | ProportionRatio = proportionRatio;
|
---|
28 | }
|
---|
29 |
|
---|
30 | private double proportionRatio = 1.0;
|
---|
31 | /// <summary>Gets or sets the proportion ratio (width / height). Default value is 1.0.</summary>
|
---|
32 | /// <value>The proportion ratio.</value>
|
---|
33 | public double ProportionRatio
|
---|
34 | {
|
---|
35 | get { return proportionRatio; }
|
---|
36 | set
|
---|
37 | {
|
---|
38 | if (proportionRatio != value)
|
---|
39 | {
|
---|
40 | proportionRatio = value;
|
---|
41 | RaiseChanged();
|
---|
42 | }
|
---|
43 | }
|
---|
44 | }
|
---|
45 |
|
---|
46 | /// <summary>
|
---|
47 | /// Applies the restriction.
|
---|
48 | /// </summary>
|
---|
49 | /// <param name="previousDataRect">Previous data rectangle.</param>
|
---|
50 | /// <param name="proposedDataRect">Proposed data rectangle.</param>
|
---|
51 | /// <param name="viewport">The viewport, to which current restriction is being applied.</param>
|
---|
52 | /// <returns>New changed visible rectangle.</returns>
|
---|
53 | public override DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport)
|
---|
54 | {
|
---|
55 | Rect output = viewport.Output;
|
---|
56 | if (output.Height == 0 || output.Width == 0)
|
---|
57 | return proposedDataRect;
|
---|
58 |
|
---|
59 | double newRatio = proposedDataRect.Width * output.Height /
|
---|
60 | (proposedDataRect.Height * output.Width);
|
---|
61 |
|
---|
62 | // Don't modify rect if new ratio differs only slightly
|
---|
63 | if (Math.Abs(newRatio - proportionRatio) < 1e-3)
|
---|
64 | return proposedDataRect;
|
---|
65 |
|
---|
66 | // Try to keep visible rect's square constant
|
---|
67 | double width = proposedDataRect.Width, height = proposedDataRect.Height;
|
---|
68 | double square = proposedDataRect.Width * proposedDataRect.Height;
|
---|
69 | if (square > 0)
|
---|
70 | {
|
---|
71 | width = Math.Sqrt(proportionRatio * output.Width * square / output.Height);
|
---|
72 | height = Math.Sqrt(output.Height * square / (proportionRatio * output.Width));
|
---|
73 | }
|
---|
74 |
|
---|
75 | // Finally ensure we have correct aspect ratio
|
---|
76 | double delta = (proportionRatio * height * output.Width - width * output.Height) /
|
---|
77 | (output.Height + proportionRatio * output.Width);
|
---|
78 | width += delta;
|
---|
79 | height -= delta;
|
---|
80 |
|
---|
81 | double x0 = (proposedDataRect.XMax + proposedDataRect.XMin) / 2;
|
---|
82 | double y0 = (proposedDataRect.YMax + proposedDataRect.YMin) / 2;
|
---|
83 |
|
---|
84 | return new DataRect
|
---|
85 | {
|
---|
86 | XMin = x0 - width / 2,
|
---|
87 | Width = width,
|
---|
88 | YMin = y0 - height / 2,
|
---|
89 | Height = height
|
---|
90 | };
|
---|
91 | }
|
---|
92 | }
|
---|
93 | }
|
---|