In my C# application , i want to restrict the horizontal and vertical scrolling by computing the mouse movement angle difference.
Grater than 60 degree angle need to be tracked as vertical scroll.
I have the initial X,Y positions and current X, Y positions.How can i calculate the angle of mouse movement.
Any help will be appreciated.
This will give you the angle in radians:
int dx = Math.Abs(x2 - x1);
int dy = Math.Abs(y2 - y1);
double angleRadians = Math.Atan2(dy, dx);
double angleDegrees = (angleRadians * 180)/Math.PI;
You will probably want to ignore angles for which dx or dy is less than a certain number (something like 16 would do it).
Related
This is the code that rotates the boat to follow the line. A joint is just a Vector2 on the line. To the left is 0 degrees. And as you can see, when the boat is going from 0 to 360 or vice versa degrees, it glitches out.
float LookAt(Vector2 joint)
{
float deltaY = rect.y - joint.Y; // Calculate Delta y
float deltaX = joint.X - rect.x; // Calculate delta x
float angle = (float)(Math.Atan2(deltaY, deltaX) * 180.0 / Math.PI) + 90; // Find angle
float amountToRotate = angle - rotation;
amountToRotate *= 0.05f;
Console.WriteLine($"Rotation: {rotation} Angle: {angle} Amount: {amountToRotate}");
return rotation + amountToRotate;
}
I'm using an amountToRotate variable because I want the rotation to be a little smooth (doesn't show well on the GIF).
https://gyazo.com/cd907763665ac41a2c8f8e5d246ab292
Any help is much appreciated.
(I'm also doing this in Raylib if that makes any difference).
Because atan2() returns values between -PI and +PI or between -180 and +180 degrees.
So, if your boat is looking at something like 170 deg and the next joint is at 179 deg, then your amountToRotate is +9 deg, which is fine.
But, if your boat is looking at 180 degs and your the joint is at -180 deg, your amountToRotate is suddenly -360 deg (-180 - 180), which is facing right towards the positive x-axis. The you take 5% off of amountToRotate and add it to your current rotation (180 - 360*0.05 = 162) which means, that the boat is turning away from the node.
As a quick solution, you could convert the angle to full 360 degrees:
angle = (angle + 360) % 360;
But you will still get problems in the direction of the positive x-axis. The better solution would be to calculate the angle between two vectors and invert it:
angleTowardsV2FromV1 = -(Math.atan2(v1.y, v1.x) - Math.atan2(v2.y, v2.x))
in your case this would look something like:
angle = (-(Math.atan2(Math.sin(rotation*Math.PI/180), Math.cos(rotation*Math.PI/180)) - Math.atan2(deltaY, deltaX)))*180/Math.PI
And also, if you only take 5% of your angle, the rotation will never get there. I think, it would much wiser to clamp the angle to +-5deg:
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
angle = clamp(angle, -5, +5);
And the just return:
return rotation + angle;
I hope this helps.
public double GetPitchToFace(double Z2, double Z1, double X2, double X1)
{
double Arc;
Arc = Math.Atan2(Z2 - Z1, X2 - X1);
Arc = (Arc >= 0) ? Arc+Math.PI : (2 * Math.PI + Arc);
return Arc;
}
I am attempting to calculate the correct pitch of a player in-game in order to face and travel to a waypoint.
It might be worth noting that the games coordinate system is Right-Handed.
I've confirmed that ATan2 is receiving the correct values yet the return value is incorrect.
It seems to be returning a downward pitch despite the waypoint being above the player. Yet other times it returns the seemingly correct pitch - I suspect this might have something to do when the point / player shift quadrants ?
(Minor side note - the reason I am 2 * Math.PI if Arc is >= 0 is simply the way the game stores and manages player pitch more info can be found here :
Pitch-Ingame
)
Here is an example of the above manually calculated :
Atan2(Z2 - Z1, X2 - X1)
Arc = Atan2(179.7 - 157.9, -3457.1-(-3432.1))
Arc = Atan2(21.7,-25.3)
Arc = 2.4 Radians
Arc = Arc + PI (without adding PI we return 137.51 degrees this is the opposite angle I need so I add PI to flip it to the correct side or add 180 degrees)
Arc = 5.5 Radians
Arc = 315,127 Degrees (this is a downwards trend from the point meaning we still miss the end point)
Here is the really bad plot of the above points
Please keep in mind that the points are plotted such as X,Z not X,Y
I am trying to create a library which allows user to edit shapes on a canvas, primarily moving, resizing, and rotating the shapes.
I have a problem with my rotating code in that the degree of rotation seems to be off by -90 degrees.
This is my code that does the rotation, in the mouseMove event:
var mousePos = e.GetPosition(this.Parent as FrameworkElement);
//gridPos is the center point of the shape object (contained within a grid control for reasons
var gridPos = new Point(Canvas.GetLeft(this) + this.ActualWidth / 2, Canvas.GetTop(this) + this.ActualHeight / 2);
//Get the angle in radians
double radians = Math.Atan2(mousePos.Y - gridPos.Y, mousePos.X - gridPos.X);
//Convert to degrees
double angle = radians * (180 / Math.PI);
//Apply rotation from centre
RenderTransformOrigin = new Point(0.5, 0.5);
//This is applied initially to my shape control object which has the shape as child
RenderTransform = new RotateTransform(degrees);
This is what I'm seeing:
As you can see, the shape immediately rotates about -90. The red marks are drawn at mousePos and gridPos.
If I put some Debug.WriteLine in that, this is what results:
MouseX: 440.14, MouseY: 148
GridX: 443.14, GridY: 197
MouseX - GridX: -3
MouseY - GridY: -49
Radians: -1.631944489444198
Degrees: -93.50353164478446
I can't work out what's wrong with my logic here, although I'm pretty sure Math.Atan2(mousePos.Y - gridPos.Y, mousePos.X - gridPos.X); isn't giving me what I think it is...
Using atan2(y, x) only works if your anchor point is to the _right of the rotation point. Code for each is as follows:
double radians = Math.Atan2(gridPos.Y - mousePos.Y, gridPos.X - mousePos.X); // left
double radians = Math.Atan2(mousePos.X - gridPos.X, gridPos.Y - mousePos.Y); // top
double radians = Math.Atan2(gridPos.X - mousePos.X, mousePos.Y - gridPos.Y); // bottom
double radians = Math.Atan2(mousePos.Y - gridPos.Y, mousePos.X - gridPos.X); // right
Ideally though, what you should be doing is calculating the angle of the point where you initially click down, then calculate the new angle for your mousemove events, setting the rotation to be whatever the difference is between them. That's essentially what each of the 4 lines above is doing, they're just hard-coding the initial mouse down point.
I am currently working on a WinForms app, which at some point has to draw some stuff. Basically, it has to draw an unknown number of circles (f.e 3, 5, 10) in organized in a shape of a circle. Something like this:
I know it looks horrible. So I thought about defining a center of a circle and a radius. Then I just have to go f.e from the top of the big circle and draw a small circle every x-degrees (like for 3 circles it would be 120 degrees, for 4 circles 90 degrees etc.).
My question here is: Is there an algorithm, which would give me the center point of a circle to draw? Like I define my big circle with f.e center X = 50, Y = 50 and a radius R = 10. And then I draw a circle at the top, decide that I want to draw the next one 120 degrees far from the first one and I just need a point (X, Y) which is on the big circle?
Basically, you just need some math to figure out the coordinate of where the angle lands at the end of perimeter of the circle (a distance of the radius of the circle from the center of the circle). Here's psuedocode for this situation.
var center = new Point(0,0);
var radius = 5;
var degrees = 83;
var angle = Math.PI * degrees / 180;
var xPos = center.X + (radius * Math.cos(angle));
var yPos = center.Y + (radius * Math.sin(angle));
var newPosition = new Point(xPos,yPos);
Here, newPosition becomes the center point for the circled you'll be drawing along your imaginary circle. As for gathering the angles, simply use 360 / count * index.
I would like to draw a radar on a pictureBox. Drawing points is no problem but I am struggling with basic maths. Maybe I am too tired.
I have a pictureBox that is 200x200. I have loaded a small, centered image inside the picturebox (4x4) which symbolizes the current player.
I have build a function called
PaintRadar(int meX, int meY, int enemyX, int enemyY)
The parameters could have the following values: meX = 27000, meY = 30000, enemyX = 26000, enemyY = 28000
The desired result is to have the enemies around me and I am always centered in the pictureBox. What do I have to calculate to center meX and meY in the pictureBox?
Thanks
Assume the player is in the middle of the enemies and draw the enemies around the center based on the difference between their positions and the player's position.
Think about it as though the player is the origin. By subtracting the player's position from the enemy's position you are putting the enemy position into a coordinate system with the player at the center. This is essentially what you're radar is.
Example:
// Get differences. d is short for difference (or delta :)).
int dy = enemyY - meY;
int dx = enemyX - meX;
// Then scale the dy and dx values so they fix in the picture box.
dy *= scaleY;
dx *= scaleX;
Then you would draw the enemies at (dx,dy) on the picture box.
Scale should be a formula like this:
scaleY = (1 / maxDetectionDistance) * (heightOfRadarBox / 2);
scaleX = (1 / maxDetectionDistance) * (widthOfRadarBox / 2);
Anything greater than your radar's limit should not be drawn.
// Don't draw if enemy is too far away for radar to pick up.
if (Math.Abs(dy) > maxDetectionDistance || Math.Abs(dx) > maxDetectionDistance)
{
return;
}