1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using System.Text;
|
---|
5 | using System.Windows.Media.Animation;
|
---|
6 | using System.Windows;
|
---|
7 | using System.Windows.Input;
|
---|
8 | using System.Diagnostics;
|
---|
9 | using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
---|
10 | using System.Windows.Media;
|
---|
11 | using Microsoft.Research.DynamicDataDisplay;
|
---|
12 | using Microsoft.Research.DynamicDataDisplay.Common;
|
---|
13 |
|
---|
14 | namespace Microsoft.Research.DynamicDataDisplay.Charts.Navigation
|
---|
15 | {
|
---|
16 | internal sealed class PhysicalRectAnimation
|
---|
17 | {
|
---|
18 | Vector position = new Vector();
|
---|
19 | Vector velocity = new Vector();
|
---|
20 | public Vector Velocity
|
---|
21 | {
|
---|
22 | get { return velocity; }
|
---|
23 | set { velocity = value; }
|
---|
24 | }
|
---|
25 |
|
---|
26 | Vector acceleration = new Vector();
|
---|
27 | private double mass = 1; // kilogramms
|
---|
28 | public double Mass
|
---|
29 | {
|
---|
30 | get { return mass; }
|
---|
31 | set { mass = value; }
|
---|
32 | }
|
---|
33 |
|
---|
34 | private double frictionCalmCoeff = 0.0;
|
---|
35 | public double FrictionCalmCoeff
|
---|
36 | {
|
---|
37 | get { return frictionCalmCoeff; }
|
---|
38 | set { frictionCalmCoeff = value; }
|
---|
39 | }
|
---|
40 |
|
---|
41 | double frictionMovementCoeff = 0.1;
|
---|
42 | public double FrictionMovementCoeff
|
---|
43 | {
|
---|
44 | get { return frictionMovementCoeff; }
|
---|
45 | set { frictionMovementCoeff = value; }
|
---|
46 | }
|
---|
47 |
|
---|
48 | double springCoeff = 50;
|
---|
49 | public double SpringCoeff
|
---|
50 | {
|
---|
51 | get { return springCoeff; }
|
---|
52 | set { springCoeff = value; }
|
---|
53 | }
|
---|
54 |
|
---|
55 | double liquidFrictionCoeff = 1;
|
---|
56 | public double LiquidFrictionCoeff
|
---|
57 | {
|
---|
58 | get { return liquidFrictionCoeff; }
|
---|
59 | set { liquidFrictionCoeff = value; }
|
---|
60 | }
|
---|
61 |
|
---|
62 | double liquidFrictionQuadraticCoeff = 10;
|
---|
63 | public double LiquidFrictionQuadraticCoeff
|
---|
64 | {
|
---|
65 | get { return liquidFrictionQuadraticCoeff; }
|
---|
66 | set { liquidFrictionQuadraticCoeff = value; }
|
---|
67 | }
|
---|
68 |
|
---|
69 | const double G = 9.81;
|
---|
70 |
|
---|
71 | DataRect from;
|
---|
72 | Viewport2D viewport;
|
---|
73 | Point initialMousePos;
|
---|
74 | CoordinateTransform initialTransform;
|
---|
75 |
|
---|
76 | public PhysicalRectAnimation(Viewport2D viewport, Point initialMousePos)
|
---|
77 | {
|
---|
78 | this.from = viewport.Visible;
|
---|
79 | this.viewport = viewport;
|
---|
80 | this.initialMousePos = initialMousePos;
|
---|
81 |
|
---|
82 | initialTransform = viewport.Transform;
|
---|
83 |
|
---|
84 | position = from.Location.ToVector();
|
---|
85 | }
|
---|
86 |
|
---|
87 | double prevTime;
|
---|
88 |
|
---|
89 | private bool isFinished = false;
|
---|
90 | public bool IsFinished
|
---|
91 | {
|
---|
92 | get { return isFinished; }
|
---|
93 | }
|
---|
94 |
|
---|
95 | private bool useMouse = true;
|
---|
96 | public bool UseMouse
|
---|
97 | {
|
---|
98 | get { return useMouse; }
|
---|
99 | set { useMouse = value; }
|
---|
100 | }
|
---|
101 |
|
---|
102 | public DataRect GetValue(TimeSpan timeSpan)
|
---|
103 | {
|
---|
104 | double time = timeSpan.TotalSeconds;
|
---|
105 |
|
---|
106 | double dtime = time - prevTime;
|
---|
107 |
|
---|
108 | acceleration = GetForces() / mass;
|
---|
109 |
|
---|
110 | velocity += acceleration * dtime;
|
---|
111 | var shift = velocity * dtime;
|
---|
112 |
|
---|
113 | double viewportSize = Math.Sqrt(from.Width * from.Width + from.Height * from.Height);
|
---|
114 | if (!(shift.Length < viewportSize * 0.002 && time > 0.5))
|
---|
115 | {
|
---|
116 | position += shift;
|
---|
117 | }
|
---|
118 | else
|
---|
119 | {
|
---|
120 | isFinished = true;
|
---|
121 | }
|
---|
122 |
|
---|
123 | prevTime = time;
|
---|
124 |
|
---|
125 | Point pos = new Point(position.X, position.Y);
|
---|
126 | DataRect bounds = new DataRect(pos, from.Size);
|
---|
127 |
|
---|
128 | return bounds;
|
---|
129 | }
|
---|
130 |
|
---|
131 | private Vector GetForces()
|
---|
132 | {
|
---|
133 | Vector springForce = new Vector();
|
---|
134 | if (useMouse)
|
---|
135 | {
|
---|
136 | Point mousePos = GetMousePosition();
|
---|
137 | if (!mousePos.IsFinite()) { }
|
---|
138 |
|
---|
139 | Point p1 = initialMousePos.ScreenToData(initialTransform);
|
---|
140 | Point p2 = mousePos.ScreenToData(viewport.Transform);
|
---|
141 |
|
---|
142 | var transform = viewport.Transform;
|
---|
143 |
|
---|
144 | Vector diff = p2 - p1;
|
---|
145 | springForce = -diff * springCoeff;
|
---|
146 | }
|
---|
147 |
|
---|
148 | Vector frictionForce = GetFrictionForce(springForce);
|
---|
149 |
|
---|
150 | Vector liquidFriction = -liquidFrictionCoeff * velocity - liquidFrictionQuadraticCoeff * velocity * velocity.Length;
|
---|
151 |
|
---|
152 | Vector result = springForce + frictionForce + liquidFriction;
|
---|
153 | return result;
|
---|
154 | }
|
---|
155 |
|
---|
156 | private Vector GetFrictionForce(Vector springForce)
|
---|
157 | {
|
---|
158 | double maxCalmFriction = frictionCalmCoeff * mass * G;
|
---|
159 | if (maxCalmFriction >= springForce.Length)
|
---|
160 | return -springForce;
|
---|
161 |
|
---|
162 | if (velocity.Length == 0)
|
---|
163 | return new Vector();
|
---|
164 |
|
---|
165 | return -velocity / velocity.Length * frictionMovementCoeff * mass * G;
|
---|
166 | }
|
---|
167 |
|
---|
168 | private Point GetMousePosition()
|
---|
169 | {
|
---|
170 | return Mouse.GetPosition(viewport.Plotter.ViewportPanel);
|
---|
171 | }
|
---|
172 | }
|
---|
173 | }
|
---|