174 lines
3.9 KiB
C#
174 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Diagnostics;
|
|
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
|
using System.Windows.Media;
|
|
using Microsoft.Research.DynamicDataDisplay;
|
|
using Microsoft.Research.DynamicDataDisplay.Common;
|
|
|
|
namespace Microsoft.Research.DynamicDataDisplay.Charts.Navigation
|
|
{
|
|
internal sealed class PhysicalRectAnimation
|
|
{
|
|
Vector position = new Vector();
|
|
Vector velocity = new Vector();
|
|
public Vector Velocity
|
|
{
|
|
get { return velocity; }
|
|
set { velocity = value; }
|
|
}
|
|
|
|
Vector acceleration = new Vector();
|
|
private double mass = 1; // kilogramms
|
|
public double Mass
|
|
{
|
|
get { return mass; }
|
|
set { mass = value; }
|
|
}
|
|
|
|
private double frictionCalmCoeff = 0.0;
|
|
public double FrictionCalmCoeff
|
|
{
|
|
get { return frictionCalmCoeff; }
|
|
set { frictionCalmCoeff = value; }
|
|
}
|
|
|
|
double frictionMovementCoeff = 0.1;
|
|
public double FrictionMovementCoeff
|
|
{
|
|
get { return frictionMovementCoeff; }
|
|
set { frictionMovementCoeff = value; }
|
|
}
|
|
|
|
double springCoeff = 50;
|
|
public double SpringCoeff
|
|
{
|
|
get { return springCoeff; }
|
|
set { springCoeff = value; }
|
|
}
|
|
|
|
double liquidFrictionCoeff = 1;
|
|
public double LiquidFrictionCoeff
|
|
{
|
|
get { return liquidFrictionCoeff; }
|
|
set { liquidFrictionCoeff = value; }
|
|
}
|
|
|
|
double liquidFrictionQuadraticCoeff = 10;
|
|
public double LiquidFrictionQuadraticCoeff
|
|
{
|
|
get { return liquidFrictionQuadraticCoeff; }
|
|
set { liquidFrictionQuadraticCoeff = value; }
|
|
}
|
|
|
|
const double G = 9.81;
|
|
|
|
DataRect from;
|
|
Viewport2D viewport;
|
|
Point initialMousePos;
|
|
CoordinateTransform initialTransform;
|
|
|
|
public PhysicalRectAnimation(Viewport2D viewport, Point initialMousePos)
|
|
{
|
|
this.from = viewport.Visible;
|
|
this.viewport = viewport;
|
|
this.initialMousePos = initialMousePos;
|
|
|
|
initialTransform = viewport.Transform;
|
|
|
|
position = from.Location.ToVector();
|
|
}
|
|
|
|
double prevTime;
|
|
|
|
private bool isFinished = false;
|
|
public bool IsFinished
|
|
{
|
|
get { return isFinished; }
|
|
}
|
|
|
|
private bool useMouse = true;
|
|
public bool UseMouse
|
|
{
|
|
get { return useMouse; }
|
|
set { useMouse = value; }
|
|
}
|
|
|
|
public DataRect GetValue(TimeSpan timeSpan)
|
|
{
|
|
double time = timeSpan.TotalSeconds;
|
|
|
|
double dtime = time - prevTime;
|
|
|
|
acceleration = GetForces() / mass;
|
|
|
|
velocity += acceleration * dtime;
|
|
var shift = velocity * dtime;
|
|
|
|
double viewportSize = Math.Sqrt(from.Width * from.Width + from.Height * from.Height);
|
|
if (!(shift.Length < viewportSize * 0.002 && time > 0.5))
|
|
{
|
|
position += shift;
|
|
}
|
|
else
|
|
{
|
|
isFinished = true;
|
|
}
|
|
|
|
prevTime = time;
|
|
|
|
Point pos = new Point(position.X, position.Y);
|
|
DataRect bounds = new DataRect(pos, from.Size);
|
|
|
|
return bounds;
|
|
}
|
|
|
|
private Vector GetForces()
|
|
{
|
|
Vector springForce = new Vector();
|
|
if (useMouse)
|
|
{
|
|
Point mousePos = GetMousePosition();
|
|
if (!mousePos.IsFinite()) { }
|
|
|
|
Point p1 = initialMousePos.ScreenToData(initialTransform);
|
|
Point p2 = mousePos.ScreenToData(viewport.Transform);
|
|
|
|
var transform = viewport.Transform;
|
|
|
|
Vector diff = p2 - p1;
|
|
springForce = -diff * springCoeff;
|
|
}
|
|
|
|
Vector frictionForce = GetFrictionForce(springForce);
|
|
|
|
Vector liquidFriction = -liquidFrictionCoeff * velocity - liquidFrictionQuadraticCoeff * velocity * velocity.Length;
|
|
|
|
Vector result = springForce + frictionForce + liquidFriction;
|
|
return result;
|
|
}
|
|
|
|
private Vector GetFrictionForce(Vector springForce)
|
|
{
|
|
double maxCalmFriction = frictionCalmCoeff * mass * G;
|
|
if (maxCalmFriction >= springForce.Length)
|
|
return -springForce;
|
|
|
|
if (velocity.Length == 0)
|
|
return new Vector();
|
|
|
|
return -velocity / velocity.Length * frictionMovementCoeff * mass * G;
|
|
}
|
|
|
|
private Point GetMousePosition()
|
|
{
|
|
return Mouse.GetPosition(viewport.Plotter.ViewportPanel);
|
|
}
|
|
}
|
|
}
|