InputSimulator smooth linear mouse movement between 2 points - c#

I'm struggling to figure out why the below function is only ever moving my mouse from 0, 0 screen coords, to my final destination, even though Cursor.Position is returning the correct screen coords. If anybody could enlighten me i'd be most grateful.
public void MoveAndClick(int x, int y, int steps)
{
Point start = Cursor.Position;
PointF iterPoint = start;
PointF slope = new PointF(x - start.X, y - start.Y);
slope.X = slope.X / steps;
slope.Y = slope.Y / steps;
for(int i=0; i<steps; i++)
{
iterPoint = new PointF(iterPoint.X + slope.X, iterPoint.Y + slope.Y);
inputSim.Mouse.MoveMouseTo(iterPoint.X, iterPoint.Y);
Thread.Sleep(10);
}
inputSim.Mouse.MoveMouseTo(x, y);
inputSim.Mouse.RightButtonDown();
inputSim.Mouse.RightButtonUp();
}
Taken from https://stackoverflow.com/a/913703/2014393

DOH! Always stop working when you're sleepy and go to bed.
The InputSimulator library requires that you translate coordinates like so:
int startX = 65535 * Cursor.Position.X / Screen.PrimaryScreen.Bounds.Width;
int startY = 65535 * Cursor.Position.Y / Screen.PrimaryScreen.Bounds.Height;
I was converting the end coordinates but completely forgot to translate the starting coordinates, derp.

FlaUI allows for the mouse to move smoothly. Here is the Mouse class in FlaUI for reference.

Related

Coordinate system of panels in c#?

I'm very new to c# and running into a problem while trying to program and visualize the Mandelbrotset.
I have created a 400 by 400 panel and want to use this to graph the set. I want my graph to go from -2 to 2 on both axes so I'm using a scale of 0.01. When looking at my code, I think the paint method should work; the coordinates are converted in the correct way it seems. The problem is that the graph is not fully shown on the panel while running. (0,0) is somewhere in the lower right corner, removing much of the coordinates in that corner.
Below is the function used to draw the graph on the panel. Did I make a mistake in coding the coordinates this way? Or am I misunderstanding how coordinates work in a panel?
for (int xco =0; xco<400; xco++)
{
for (int yco=0; yco<400; yco++)
{
double x = (xco - 200) * scale;
double y = (yco - 200) * scale;
int mandel = 0;
double fx = x, fy = y;
double distance = 0;
while ((mandel<max) && (distance<2))
{
double fx1 = fx;
fx = fx * fx - fy * fy + x;
fy = 2 * fx1 * fy + y;
distance = Math.Sqrt(fx * fx + fy * fy);
mandel++;
}
if (mandel%2==1)
pea.Graphics.FillRectangle(Brushes.White, xco, yco, xco + 1, yco + 1);
else
pea.Graphics.FillRectangle(Brushes.Black, xco, yco, xco + 1, yco + 1);
}
}

How do I implement a "rotate-algorithm" in Emgu CV?

I'm currently working on implementing an algorithm in EmguCV in C#, meaning that I don't want to use the build in rotate function that comes with EmguCV.
I've already found the algorithm that I want to implement, but I'm kinda stuck as how to implement it. The main problem is, that I don't know how the specify the X and Y values of my Matrix to be able to do the intended calculations.
Rotation Algorithm:
http://i.stack.imgur.com/hQMxF.jpg
Right now my Code looks like this:
static void Main(string[] args) {
Mat image = CvInvoke.Imread("C:\\Users\\Leon\\Desktop\\a.jpg", LoadImageType.Grayscale);
int height = image.Height;
int width = image.Width;
//Convert to Matrix
Matrix<Byte> matrix = new Matrix<Byte>(image.Rows, image.Cols, image.NumberOfChannels);
image.CopyTo(matrix);
Matrix<Byte> newMatrix = new Matrix<Byte>(image.Rows, image.Cols, image.NumberOfChannels);
image.CopyTo(newMatrix);
for (int i = 0; i < matrix.Rows-1; i++)
{
for (int j = 0; j < matrix.Cols-1; j++)
{
}
}
CvInvoke.Imshow("abc", matrix);
CvInvoke.WaitKey(0);
}
But as I said, I'm in doubt of as how to implement the algorithm. My plan was to rotate the pixels in "matrix" and store them in "newMatrix" but I do not know how to specify the X and Y values of my matrix.
Maybe someone can help me out here.
EDIT:
There has been suggested that this answer here: "How can I get and set pixel values of an EmguCV Mat image?" will be an answer to my question. But it is not. I know that I can do Math.Cos and Math.Sin but I do not know how to specify X and Y in my Matrix. I don't have problems accessing the Data in my Matrix.
If you're trying to rotate a point (x,y) about some point (cx,cy) given the matrix in the attached image:
class Program {
/**
* #param x coordinate of point want to rotate
* #param y coordinate of point want to rotate
* #param cx x coordinate of point you want to rotate about
* #param cy y coordinate of point you want to rotate about
* #return the result of rotation {x,y}
*/
static double[] rotate(double x, double y, double cx, double cy, double angle) {
double cos_a = Math.Cos(angle);
double sin_a = Math.Sin(angle);
// move to origin
x -= cx;
y -= cy;
// rotate and then move back
return new double[] {
x*cos_a - y*sin_a + cx,
x*sin_a + y*cos_a + cy
};
}
static void Main(string[] args) {
double x = 1;
double y = 0;
double a = Math.PI / 2;
double[] r = rotate(x, y, 0, 0, a);
Console.WriteLine("new x = " + r[0]);
Console.WriteLine("new y = " + r[1]);
}
}

Move PictureBox using Timer

My goal is to move a picturebox back and forth. My issue is how to do this.
I have written the following:
int x = enemy.Location.X;
int y = enemy.Location.Y;
enemy.Location = new Point(x+-1, y);
This moves the picturebox off-screen, left. After moving left, I'd like it to move right, so that it moves back and forth - in a continuous loop.
The noob that I am, I tried:
if (x < 40)
enemy.Location = new Point(x - -100, y);
else if (x > 400)
enemy.Location = new Point(x - 5, y);
This proves unsuccessful - the box doesn't seem to move on reaching pixel 40.
Is there a simple solution that you can prod me towards, or have I dug an early grave for myself?!
I should specify: I am writing in C# per college assignment requirements.
Cheers.
When moving left, when the x location reaches 0, change direction and move right.
When moving right, you need to use the width of the screen minus the width of your picturebox.
System.Windows.SystemParameters.PrimaryScreenWidth
edit:
Or better yet, use the width of your form minus the width of the picturebox. Then it will still work if its not maximized.
Setup a variable that toggles between negative and positive values to make it go left and right. You toggle the direction by multiplying by -1. Then you simply add that variable to the current X value like this:
private int direction = -1; // this can be values other than 1 to make it jump farther each move
private void timer1_Tick(object sender, EventArgs e)
{
int x = enemy.Location.X + direction;
if (x <= 0)
{
direction = -1 * direction;
x = 0;
}
else if (x >= this.ClientRectangle.Width - enemy.Width)
{
direction = -1 * direction;
x = this.ClientRectangle.Width - enemy.Width;
}
enemy.Location = new Point(x, enemy.Location.Y);
}

Trouble drawing 3d-style effect

I've been racking my brain trying to figure out how to animate an effect. This is related to a question I asked on math.stackexchange.com.
https://math.stackexchange.com/questions/91120/equal-division-of-rectangles-to-make-total/
As a side note, I didn't implement the drawing algorithm that was defined on the question above -- instead using my own in order to change the perspective to make it look more condensed.
I've been able to draw a stationary 3d style effect, but I am having trouble wrapping my brain around the logic to make the lines below look like they are coming towards you.
My code is as follows,
List<double> sizes = new List<double>();
private void Form1_Load(object sender, EventArgs e)
{
for (int y = 1; y < 10; y++)
{
double s = ((240 / 2) / y) / 4;
sizes.Add(s);
}
sizes.Add(0);
}
int offset = 0;
private void button1_Click(object sender, EventArgs e)
{
Bitmap b = new Bitmap(320, 480);
Graphics g = Graphics.FromImage(b);
Color firstColor = Color.DarkGray;
Color secondColor = Color.Gray;
Color c = firstColor;
int yOffset = 0;
for(int i = 0; i < sizes.Count; i++)
{
c = (i % 2 == 0) ? firstColor : secondColor;
int y = (int)Math.Round(b.Height - yOffset - sizes[i]);
int height = (int)Math.Round(sizes[i]);
g.FillRectangle(new SolidBrush(c), new Rectangle(0, y + offset, b.Width, height + offset));
yOffset += (int)sizes[i];
}
this.BackgroundImage = b;
offset+=1;
}
Each button click should cause the rectangles to resize and move closer. However, my rectangles aren't growing as they should. My logic draws fine, but simply doesn't work as far as moving goes.
So my question is:
Is there an existing algorithm for this effect that I am not aware of, or is this something pretty simple that I'm over thinking? Any help in correcting my logic or pointing me in the right direction would be very appreciated.
Interesting...
(video of the answer here: http://youtu.be/estq62yz7v0)
I would do it like that:
First, drop all RECTANGLE drawing and draw your effect line by line. Like so:
for (int y=start;y<end;y++)
{
color = DetermineColorFor(y-start);
DrawLine(left, y, right, y, color);
}
This is of course pseudo-code not to be troubled with GDI+ or something.
Everything is clear here, except on how to code DetermineColorFor() method. That method will have to return color of the line at specified PROJECTED height.
Now, on the picture, you have:
you point of view (X) - didn't know how to draw an eye
red line (that's your screen - projection plane)
your background (alternating stripes at the bottom)
and few projecting lines that should help you devise the DetermineColorFor() method
Hint - use triangle similarity to go from screen coordinates to 'bar' coordinates.
Next hint - when you are in 'bar' coordinates, use modulo operator to determine color.
I'll add more hints if needed, but it would be great if you solved this on your own.
I was somehow inspired by the question, and have created a code for the solution. Here it is:
int _offset = 0;
double period = 20.0;
private void timer1_Tick(object sender, EventArgs e)
{
for (int y = Height / 3; y < Height; y++)
{
using (Graphics g = CreateGraphics())
{
Pen p = new Pen(GetColorFor(y - Height / 3));
g.DrawLine(p, 0, y, Width, y);
p.Dispose();
}
}
_offset++;
}
private Color GetColorFor(int y)
{
double d = 10.0;
double h = 20.0;
double z = 0.0;
if (y != 0)
{
z = d * h / (double)y + _offset;
}
double l = 128 + 127 * Math.Sin(z * 2.0 * Math.PI / period);
return Color.FromArgb((int)l, (int)l, (int)l);
}
Experiment with:
d - distance from the eye to the projection screen
h - height of the eye from the 'bar'
period - stripe width on the 'bar'
I had a timer on the form and event properly hooked. Timer duration was 20ms.
Considering that you're talking here about 2D rendering, as much as I understodd, to me it seems that you're gonna to reenvent the wheel. Cause what you need, IMHO; is use Matrix Transformations already available in GDI+ for 2D rendering.
Example of aplying it in GDI+ : GDI+ and MatrixTranformations
For this they use System.Drawing.Drawing2D.Matrix class, which is inside Graphics.
The best ever 2D rendering framework I ever used is Piccolo2D framework which I used with great success in big real production project. Definitely use this for your 2D rendering projects, but first you need to study it little bit.
Hope this helps.

C# smooth object movement

I have all the necessary code to move and click the mouse via C# code, but I don't want to just set the mouse position to X and Y; that will look jerky. Instead, I want to have a smooth transition from point X1, Y1 to point X2, Y2 over Z seconds. Similar to keyframing.
I'm looking for a method similar to this:
public void TransitionMouse(int x, int y, double durationInSecs)
It will just smoothly move the mouse from its current position to x and y in durationInSecs seconds. I have a function called:
public void MoveMouse(int x, int y)
That moves the mouse to x, y immediately.
EDIT
Thanks for the help guys! Here's the finished, and tested, code:
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public void TransitionMouseTo(double x, double y, double durationSecs)
{
double frames = durationSecs*100;
PointF vector = new PointF();
PointF mousePos = Cursor.Position;
vector.X = (float)((x - mousePos.X) / frames);
vector.Y = (float)((y - mousePos.Y) / frames);
for (int i = 0; i < frames; i++)
{
SetCursorPos((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y));
Thread.Sleep((int)((durationSecs / frames) * 1000.0));
}
}
You could do this in several ways. One option would be to calculate the vector required to move the mouse every frame and apply it over the time period to the mouse position.
So, if we are at position 5,5 and want to move to 20,30 over 10 frames, our vector would be the following:
val = (target - start) / frames;
x = (20 - 5) / 10;
y = (30 - 5) / 10;
Vector = 1.5,2.5
Then, in your TransitionMouse method, you apply the vector to the mouse position slowly over whatever duration you wish, using the Thread.Sleep method to control the speed. The code might look like this:
public void TransitionMouseTo(int x, int y, int durationSecs)
{
int frames = 10;
PointF vector = new PointF();
vector.X = (x - Cursor.Position.X) / frames;
vector.Y = (y - Cursor.Position.Y) / frames;
for (int i = 0; i < frames; i++)
{
Point pos = Cursor.Position;
pos.X += vector.X;
pos.Y += vector.Y;
Cursor.Position = pos;
Thread.Sleep((durationSecs / frames) * 1000);
}
}
Another way of doing it would be to use Bresenhams algorithm to calculate all the points the mouse cursor will move through and then loop through each point and apply it to the cursor again using Thread.Sleep to keep the timing correct.
Steve
really depend on your definition of smooth, however most algorithm of "smooth" motion use spline to interpolate between 2 or more data points.
this could help
http://geekswithblogs.net/JuanDoNeblo/archive/2007/10/25/Data-Interpolation-with-SPLINE-in-Csharp.aspx

Categories