I have a slider for rotating the line. When the slider is slide I want to rotate the line. The slider value is set as an angle. When the page initial loading the line shape is placed as horizontal. The slider value is binded from getting the angle. I have used the below code to calculate the angle between two points.
const double Rad2Deg = 180.0 / Math.PI;
private double Angle(Point start, Point end)
{
return Math.Atan2(start.Y - end.Y, end.X - start.X) * Rad2Deg;
}
Now I want to calculate the two points using angle. Please give me a suggestion.
Let's say we have a line beginning in a point (0,0) and ending in point (x,y). And we want to rotate it to the angle a.
So, the (x,y) point will translate into (x', y') point, where
x' = x*cos(a)-y*sin(a)
y' = x*sin(a)+y*cos(a)
And the whole line will be from (0,0) to (x', y')
Related
I have a ship and I want the Ship to follow the mouse, it does that fine and dandy. When forward and backwards are pressed it goes towards and away from the mouse perfectly, but I can not figure out how to make the left and right buttons make the ship circle around the mouse in a clockwise/counterclockwise direction.
I have tried to take the ships location, and the mouse's location, creating a slope, and then getting the perpendicular to that slope, but that doesn't work either.
How can I achieve this? I do not think it needs code, more of an equation, but if there is code, please tell me.
You need the parametric form for the equation of a circle. Since you want it centered about the mouse's current location, you need an offset translation. Try something like:
float radius = 10f;
float shipX;
float shipY;
float angle = current_angle; // update this to animate
shipX = mouseX + ( radius * Math.Sin(angle));
shipY = mouseY + ( radius * Math.Cos(angle));
I am implementing landscape mode augmented reality app. The little circle to the top left is the compass which shows where north is. Previously I used it in portrait mode. And it absolutely worked fine. but when I shifted to there are two problems. One problem is existing already in portrait mode also.
When the trueheading changes from 1 to 359 or 359 to 1, the compass doesnt know to take the shortest angle directly but it rotates all the full circle and goes to the final heading. Like when the trueheading is 1 degree and I turn the device a little north to make the trueheading 358, it doesnt directly go from 1-0-359-358, it takes a full path from 1-2-5-200-300-358 i.e an almost full circle.
This is because I am animating the rotation using storyboard double animation. So how do I fix this ?
And the second problem is, as you can easily understand, the reference axis for trueheading is the device's top part, when the device's top part is headed towards north, the N letter in the circle is always in the green area. I.e 0 degree with respect to the grid in which it is placed. But I want it to take the reference line for measuring the angle by which to turn to be the line joining device's top and bottom part.
How do I achieve this ? How can I set the double animation's reference line 90degree to the original ??
There seems to be a bug here because I cannot add the code. But here is the text file which contains the code that I want to show you.
Code sample explained above
For your point 1, what you want to do is to detect cases when you're about to rotate of an angle greater than 180°, and then take the shorter path.
var rotation = newAngle - oldAngle;
if (Math.Abs(rotation) > 180)
{
// Rotating of more than 180, which means it exists a shorter path
newAngle += rotation > 0 ? -360 : 360;
}
// Start the animation to rotate to newAngle
If the old angle is 1 and the new angle is 359, the rotation will be 358. It's positive, so the code will subtract 360 to 359, and therefore rotate from 1 to -1.
If the old angle is 359 and the new angle is 1, the rotation will be -358. It's negative, so the code will add 360 to 1, and therefore rotate from 359 to 361.
Note: in the second case, after the rotation, the angle will be 361. Then you'll have exactly the same problem is you try to rotate to 2° or 3°, and the algorithm will correct the angle to 362, 363, and so on. At some point, if the compass keeps rotating in the same direction, the angle will reach 540 and the algorithm will stop working properly. To prevent this kind of issue, you need to detect when your animation has stopped (there's an event for that), then adjust the angle so it stays in the 0-359 range:
if (angle > 359)
{
angle += (angle / 360) * -360;
}
else if (angle < 0)
{
angle += ((angle / 360) - 1) * -360;
}
Since you're changing the angle by multiples of 360, there will be no visual impact to this adjustment.
I'm writing a little test project. I have an object (with a position and bounding box) at an origin, and when something happens (say a mouse click/touch on phone), I want a line to be drawn from the origin object to the point.
Using a texture, I realise I'm going to have to use the rotation here, but have no idea how to work out how much to rotate the texture by. Any help would be appreciated.
So far, I have:
Vector2 Origin
Vector2 TouchPoint
and that's about it.
Thanks all!
Theres a simple formula for calculating an angle based on the X and Y coordinates:
float angle = Math.Atan2(TouchPoint.Y - Origin.Y, TouchPoint.X - Origin.X);
You can use this angle in an overload of the SpriteBatch.Draw() that accept an angle for the rotation.
See this for reference:
http://msdn.microsoft.com/en-us/library/ff433992.aspx
You may want to convert between degrees and radians:
float rad = deg * Math.PI/180;
float deg = rad * 180/Math.PI;
I have a program in C# (Windows Forms) which draws some rectangles on a picturebox. They can be drawn at an angle too (rotated).
I know each of the rectangles' start point (upper-left corner), their size(width+height) and their angle. Because of the rotation, the start point is not necessarely the upper-left corner, but that does not matter here.
Then when I click the picturebox, I need to check in which rectangle (if any) I have clicked.
So I need some way of checking if a point is in a rectangle, but I also need to take into account the rotation of each rectangle.
Does anybody know of a way to do this in C#?
Is it possible to apply the same rotation applied to the rectangle to the point in reverse?
For example, Rectangle A is rotated 45 degrees clockwise from its origin (upper left corner), you would then just rotate point B around the same origin 45 degrees COUNTER clockwise, then check to see if it falls within Rectangle A pre-rotation
You could keep a second, undisplayed image where you draw duplicates of the rectangles, each uniquely colored. When the user clicks on the picturebox, find the color of the corresponding pixel in the 2nd image, which will identify which rectangle was clicked.
Edit: After looking back, I'm using MonoGame and the OP is using Windows Forms. The following is for MonoGame.
I've been messing this for a while now and have found a couple answers, just none of them actually worked. Here is a C# function that does exactly as OP describes, if not for OP then other people Googling like I was.
It was a headache to figure this out. A lot of the typical guesswork.
bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation)
{
Matrix rotMat = Matrix.CreateRotationZ(-rotation);
Vector2 Localpoint = P - (rect.Location).ToVector2();
Localpoint = Vector2.Transform(Localpoint, rotMat);
Localpoint += (rect.Location).ToVector2();
if (rect.Contains(Localpoint)) { return true; }
return false;
}
And here it is in a single line of code. Probably faster to use.
bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation)
{
return rect.Contains(Vector2.Transform(P - (rect.Location).ToVector2(), Matrix.CreateRotationZ(-rotation)) + (rect.Location).ToVector2());
}
I know this was already answered but I had to do something similar a while ago. I created an extension method for the System.Windows.Point class that helped do exactly what Neil suggested:
public static double GetAngle(this Point pt)
{
return Math.Atan2(pt.X, -pt.Y) * 180 / Math.PI;
}
public static Point SetAngle(this Point pt, double angle)
{
var rads = angle * (Math.PI / 180);
var dist = Math.Sqrt(pt.X * pt.X + pt.Y * pt.Y);
pt.X = Math.Sin(rads) * dist;
pt.Y = -(Math.Cos(rads) * dist);
return pt;
}
This would allow me to work with the angles of points around 0, 0. So if you know the center of the rect that you are testing you would offset the point by the negative of this value (for example: pt.X -= 32; pt.Y -= 32) And then you would apply the negative rotation of the rectangle (as suggested by Neil: pt.SetAngle(-45);)...
Now if the point is within 64, 64 you know you hit the rectangle. More specifically I was checking a pixel of a rotated image to make sure I hit a pixel of a specific color.
Would the rectangles be allowed to overlap?
If so, would you want all the rectangles in a point, or just the one in the top layer?
If you know the coordinates of the corners of the rectangle, this is an fast, elegant solution that merely involves a couple of dot and scalar products: https://math.stackexchange.com/a/190373/178768
See the rectangle edges as a list of vectors linking a corner to the next, sorting corners clockwise. If the point is in the square, it must be to the right with respect to all of the edge vectors.
This can be solved by vector products, but it boils down to the following:
Iterate over rectangle corners:
the point to be checked is P=[px,py]
the current corner is C=[cx,cy] and the next corner is N=[nx,ny]
if px*ny+cx*py+nx*cy<py*nx+cy*px+ny*cx, the point is outside the square.
this would actually work for every convex polygon.
Background:
I was recently playing around with GDI+ to draw a "Disc" displaying a sweeping color change through 360 degrees. (I dug up some HSL to RGB code to loop through HSL(1,1,1) -> HSL(360,1,1))
Regarding the disc, I first drew a full solid circle using the above, and then a second circle in Grey over the center to give the following
So this is all fine... but I realised that GDI+ is insulating us from a lot of the tricky match that's going on here by way of the FillPie method. Also, FillPie requires you to supply a bounding rectangle for the pie as opposed to a Radius Length. It also does a full segment fill and doesnt allow you to specify a part of that segment only.
Question:
Can anyone point me in the direction of some Math functions or give any explanation on what forumla I would need to calculate the area & plot points of the following "Green Filled Area" given:
Point `c` - an x,y co-ordinate
Angle `A` - an angle from horizontal
Angle `B - an angle from horizontal where `B` - `A` == the sweep angle
Length `r` - a distance from `c`
Length `r2` - a distance from `c` where `r2` - `r` == the `height` of the segment to be filled.
Links to Math sources are fine but I've had a quick google & look at Wolfram Math and could find what I was looking for. Also, if there was some way to generate a sequence of bounding (x,y) co-or's that could be passed as a Point[] to Graphics.FillPolygon, that'd be cool too.
The area is the difference of the outer and inner disc parts. The area of a disc part is proportional to the angle sweep:
area = (b-a)*((r+r2)^2-r^2)/2
a and b must be expressed in radians.
For b-a = 2*Pi, area = Pi*(r+r2)^2 - Pi*r^2 is the difference of the areas of the outer and inner discs.
You can generate points on the inner / outer circle using
x = cx + r * cos(t) / x = cx + (r+r2) * cos(t)
y = cy + r * sin(t) / y = cy + (r+r2) * sin(t)
Where t varies from a to b.
Hope this helps. The second part provides a method for calculating the area of a sector of a circle
http://www.wikihow.com/Calculate-the-Area-of-a-Circle
The area of a segment of a circle is simply the angle of the arc (in radians) times the radius. So the area of the green circle is obviously:
(B-A) * r2
You need to draw lines (this pseudo code):
for aa from A to B
set color to required color // you could use aa in an equation with HSL to get something like your sample
x1=r*cos(aa)+x
y1=r*sin(aa)+y
x2=r1*cos(aa)+x
y2=r1*sin(aa)+y
draw line between (x1,y1) and (x2,y2)
for a small-enough increment in the angles, and small-enough radii, this should be OK.
The points you're looking for are (x1,y1) and (x2,y2) for each angle aa