Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the velocity of the mouse in C#

How can i find the instantaneous vertical speed of the mouse at the exact moment that the mouse is released? i have the users dragging over a custom control and when they release i need to know this information so i can continue the object they were dragging using the vertical component of the velocity...

so for instance, if they were dragging at an angle, use trig to determine the vertical speed and then use that..

i cant just do distance over time, because the mouse can be moved at irregular speeds and this will not represent the correct velocity at all.

I was thinking that there might be a specific interval between the triggers of MouseMove that i could use, but im not sure.

like image 791
caesay Avatar asked Jan 30 '11 05:01

caesay


3 Answers

How can i find the instantaneous vertical speed of the mouse at the exact moment that the mouse is released?

You can't. As Zeno made clear centuries ago, speed is only meaningful over a period of time. If I had to do it, I'd probably use a weighted moving average, so (for example) I computed the distance/time for each of the last 5 mouse movement messages, but their importance "decayed" over time. For example, I might multiply the most recent by 1, the next one back by .8, the next one back by .6, and so on. This way if (for example) they happen to slow down (or speed up) the movement just as they release the button, you still get a reasonable approximation of what they were doing just prior to that.

like image 66
Jerry Coffin Avatar answered Sep 18 '22 02:09

Jerry Coffin


Consider pinvoking GetMouseMovePointsEx(). It can give you move history for up to 64 points. Each point has a time stamp, allowing you to accurately calculate speed. It gets you much more accuracy since the time stamp is not affected by any delays you may get from having the mouse move messages buffered in the message queue. And you can get points in native mouse units instead of pixels. Visit pinvoke.net for the declarations.

like image 25
Hans Passant Avatar answered Sep 21 '22 02:09

Hans Passant


What I would do is sample the mouse movement constantly and keep track of -say- the last 10 positions. Then when the mouse button is released you would have an array of measurements that would allow you to estimate the mouse velocity when the mouse is released.

I wrote a quick winform app to play with this idea. This computes the velocity for every mouse move. You need to play with the queue length.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace MouseVelocity
{
    public partial class Form1 : Form
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        Queue timePoints;

        public Form1()
        {
            sw.Start();
            timePoints = new Queue(100);
            InitializeComponent();
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            addPoint(e);
        }

        private void addPoint(MouseEventArgs e)
        {
            timePoints.Enqueue(new TimePoint(new Point(e.X, e.Y), sw.ElapsedMilliseconds));
            if (timePoints.Count == 40) timePoints.Dequeue();
            object[] array = timePoints.ToArray();
            TimePoint tip = (TimePoint)array[array.Length - 1];
            TimePoint end = (TimePoint)array[0];
            long deltaX = tip.point.X - end.point.X;
            long deltaY = tip.point.Y - end.point.Y;

            long distance = deltaX * deltaX + deltaY * deltaY;

            long deltaT = tip.time - end.time;
            double velocity_modulo = Math.Sqrt(distance) / deltaT;
            double velocity_X = deltaX / (double)deltaT;
            double velocity_Y = deltaY / (double)deltaT;
            label1.Text = string.Format("|V| = {0}; Vx = {1}; Vy = {2}", velocity_modulo, velocity_X, velocity_Y);
        }

    }
    public class TimePoint
    {
        public Point point;
        public long time;

        public TimePoint(Point pt, long ms)
        {
            point = pt;
            time = ms;
        }
    }
}
like image 27
Marco Avatar answered Sep 18 '22 02:09

Marco