Ok so I have searched and searched for a solution to my problem, but non seem to fix it.
I need to make a game with a rotating "cannon", my cannon is a simple rectangle placed in the middle of my panel that I can rotate with my keyboard. It rotates around one edge. I want to shoot out of the edge on the other side. I have found the starting point of where to shoot my bullets by using:
x = a + dia * (float)Math.Cos(angle);
y = b + dia * (float)Math.Sin(angle)
where "a, b" is the center coordinate I rotate it around and "dia" is the diagonal of the rectangle and "angle" is the angle of the one half of my rectangle.
public float rotate = 0.0f;
g.TranslateTransform(a , b);
g.RotateTransform(rotate);
I have a own class for my bullets that I put in a List.
So far so good. But when I rotate my cannon, the bullets don't come out from the tip anymore..they just start appearing far off where I want them to. it's because of this code:
x = (float)((x * Math.Cos(rotate)) - (y * Math.Sin(rotate)));
y = (float)((x * Math.Sin(rotate)) + (y * Math.Cos(rotate)));
that's supposed to update the x, y coordinates of the tip of the cannon.
If I delete it, it just fires from the same spot(no shit).
Can someone please explain to me what code I need to write to update the X, Y so they come out of my rectangle edge? It's driving me crazy..
Edit:
Found my answer staring at the screen in the early mornings. I had no need for any "find new x, y coordinates". I simply made a updater that updated the original angle with the float number it needed to move a little bit each time i rotated it.
hah! so simple, yet so hard to see.
First of all,
x = (float)((x * Math.Cos(rotate)) - (y * Math.Sin(rotate)));
y = (float)((x * Math.Sin(rotate)) + (y * Math.Cos(rotate)));
needs to be something like:
float oldx = x;
float oldy = y;
x = (float)((oldx * Math.Cos(rotate)) - (oldy * Math.Sin(rotate)));
y = (float)((oldx * Math.Sin(rotate)) + (oldy * Math.Cos(rotate)));
your new values need to be based purely off the old values..
If there's any other problem after fixing this, it may be related to how the rectangle is translated on the plane.
Edit: If this were a code review, I'd say the solution I just gave isn't quite the best solution either (it just doesn't suffer from the bug you introduced by using the new value of x to calculate the new value of y). See, Math.Cos and Math.Sin are generally expensive operations compared to multiplication and addition. If you had a bunch of points that need transformed the same way, best to calculate Math.Sin(rotate) and Math.Cos(rotate) once and use those values for every point. This might be a good place to use the Flyweight pattern and define a class where an instance would hold all your points for a given object/context so that operations can be done in aggregate.
Related
I stumbled on a working concept for a fast rotation & orientation system today, based on a two-term quaternion that represents either a rotation about the X axis (1,0,0) in the form w + ix, a rotation about the Y axis (0,1,0) in the form w + jy, or a rotation about the Z axis (0,0,1) in the form w + kz.
They're similar to complex numbers, but a) are half-angled and double-sided like all quaternions (they're simply quaternions with two of three imaginary terms zeroed out), and b) represent rotations about one of three 3D axes specifically.
My problem and question is...I can't find any representation of such a system online and have no idea what to search for. What are these complex numbers called? Who else has done something like this before? Where can I find more information on the path I'm headed down? It seems too good to be true and I want to find the other shoe before it drops on me.
Practical example I worked out (an orientation quaternion from Tait-Bryan angles):
ZQuat Y, YQuat P, XQuat R; // yaw, pitch, roll
float w = Y.W * P.W;
float x = -Y.Z * P.Y;
float y = Y.W * P.Y;
float z = Y.Z * P.W;
Quaternion O; // orientation
O.W = x * R.W + w * R.X;
O.X = y * R.W + z * R.X;
O.Y = z * R.W - y * R.X;
O.Z = w * R.W - x * R.X;
Quaternions in 2D would degenerate to just being a single component being no diferrent than an rotation angle. That's propably why you do not find anything. With quaternions you do f.e. not have the problem of gimbal lock, appearing when two rotation axes align because of rotation order. In normal 2D space you do not have more than a single rotation axis, so it has neither order (how do you sort a single element) and there are no axes to align. The lack of rotation axes in 2D is because you get a rotation axis when being perpendicular to two other axes.
This gives 3 axes for 3D:
X&Y=>Z
X&Z=>Y
Y&Z=>X
But only one for 2D:
X&Y=>Z
I using microsoft visual 2010 with dynamic data display dll
I need to do an circle around a point by angle and radius.
I have been successful but it's wrong, I think so.
First of all, my source code:
I got the prePs from the mouseClick (it's not problem the point is perfect working you can see next in the picture)
// Get the X position of the pointClicked
cx = (double)prePs.X;
// Get the Y position of the pointClicked
cy = double.Parse(this.plotter.Viewport.Transform.DataTransform.ViewportToData(prePs).Y.ToString());
// Get the new X position of the pointClicked by the angel with math calculation
xEndP = (float)(double.Parse(txt_enterRadius.Text.ToString()) * Math.Cos(a * Math.PI / 180F)) + cx;
// Get the new Y position of the pointClicked by the angel with math calculation
yEndP = (float)(double.Parse(txt_enterRadius.Text.ToString()) * Math.Sin(a * Math.PI / 180F)) + cy;
Secondly what I actualy got :
At the middle I got exactly perfect circle, but in the north and south the circle is type of ellipse.
picture:
http://sizmedia.com/my.php?i=hm2zuv5yyenj.png
I would happy to understand :
Why? Is it good? Or I need to change something?
Becuase i thought about it and the Earth is circle and its type of reasonable.
I'm using C#, I have a list of Vector points and would like to try and approximate how close they look like a circle.
Any ideas how to implement this or if someone else has?
Based on the "gestures" tag I guess you not only want to know how close are these points to the smallest-circle (search for "Smallest-circle problem"), but you have to be concerned also about their order and spread:
I would start with the distance from the smallest-circle. If they are too far, you're done, it's not a circle.
If they are close enough to your configured threshold, compute the angle between the vector defined by the circle center, first point and each other point (picture bellow)
Check that each angle is greater than the previous.
Check that difference between any two angles next to each other is not over some configured threshold.
Check that the last point is close enough to the first one.
You will probably think of some other checks eventually, so make it simple to extend.
Another possibility:
Find the centroid
(http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points) of
the points
Determine the distance (radius) of each point from the location of
the centroid
Calculate the distribution and determine if the points
are within acceptable tolerances (e.g. standard deviation < ±0.05 × mean radius or something like that)
Without knowing more about the source of the points, it's hard to suggest the best solution.
These might be of use: http://link.springer.com/article/10.1007%2FBF02276879#page-1 and http://www.dtcenter.org/met/users/docs/write_ups/circle_fit.pdf. Those methods will give you the best fitting circle through the points, but you are still going to need to determine whether your data points are close enough for your purposes.
UPDATE: based on the 'gesture' tag, somebody has already implemented it: http://depts.washington.edu/aimgroup/proj/dollar/
1) Pick any three points from that list, find the center of their appropriate circle
We can do this, using triangle circumcircle construction method, you find the medians of all three sides (two are sufficient) and their intersection is the center of the circle. Something like this:
public PointF findCenter(PointF a, PointF b, PointF c)
{
float k1 = (a.Y - b.Y) / (a.X - b.X) //Two-point slope equation
float k2 = (a.Y - c.Y) / (a.X - c.X) //Same for the (A,C) pair
PointF midAB = new PointF((a.X + b.X) / 2, (a.Y + b.Y) / 2) //Midpoint formula
PointF midAC = new PointF((a.X + c.X) / 2, (a.Y + c.Y) / 2) //Same for the (A,C) pair
k1 = -1*k1; //If two lines are perpendicular, then the product of their slopes is -1.
k2 = -1*k2; //Same for the other slope
float n1 = midAB.Y - k1*midAB.X; //Determining the n element
float n2 = midAC.Y - k2*midAC.Y; //Same for (A,C) pair
//Solve y1=y2 for y1=k1*x1 + n1 and y2=k2*x2 + n2
float x = (n2-n1) / (k1-k2);
float y = k1*x + n1;
return new PointF(x,y);
}
2) Check if the other points are equivalently distanced from this center, if yes, you have a circle, if no, you don't.
P.S. I haven't tested the code, so be prepared to debug. Ask if you need anything else
Take any three points from your point set.
If the points are co-linear then, your point set doesn't all lie on a circle.
Find the circumcircle of the triangle. The diameter is given by: d = (a*b*c)/2*area. The center of the circle is the point of intersection of the perpendicular bisectors of the three sides.
Now for every remaining point in the point set, if the distance from the center is not equal to the radius then the points are not on a circle. You can speed up the calculations by comparing the square of the radius against the square of the distance between the given point and the center.
I'm making an inventory screen for a game I'm working on, and I'd like to be able to draw a series of panels representing each item in the inventory. I want to be able to fit those panels on a circular path.
Here's a mock up I made of what I mean
http://fc02.deviantart.net/fs70/f/2010/280/7/2/khmp_magic_menu_concept_by_magna_alphamon-d30a7em.png
basically I'd like to be able to, give a radius, a center point, and the y co-ordinate to start drawing at, draw this series of panels so they align with the path of the circle like in the image.
Computing the y dimension is easy, its just the startposition y + panel height * panel index, but I'm unsure how to compute the x for a variable radius/center point circle.
Any help would be appreciated.
This is in C#, but something similar in C/C++ will be fine as long as I can convert it
Thanks in advance
EDIT: To calirify, y's position is relative to the top or bottom of the screen and is independent of the circle. If a given y does not map to a point on the circle, then I'll discard that point and not draw the panel.
While ideally I'd like to be able to use any elliptical shape (given two radii), a circle would be good too
Let cx, cy be the coordinates of the center point. Let r be the radius of the circle. Let y be the drawing y-coordinate and x, the x-coordinate. You observe that y = cy + panel height * panel index. By the magic of right triangles, this means that x^2 + y^2 = r^2. Solving for x, we get x = cx + sqrt(r^2 - (y-cy)^2).
EDIT: Converting to code:
#include <math>
float ordinate(float cx, float cy, float r, float y) {
// assumes cx and cy are in the same coordinate system as x and y
// assumes the coordinate origin is in the lower left corner.
return cx + sqrtf(powf(r,2) - powf(y-cy,2));
}
I'm dumb. After seeing Eric's answer, I remembered I can just rearrange and solve the equations of a circle or elipse as necessary.
Thanks
You can use a rotational matrix for this. Here is a simple algorithm that finds the next point {x, y} such that it is rotated theta radians around a circle. You can start with the first item at x=radius and y=radius (wherever really, just a point that you know will contain an item), and then just continue to increment theta as you loop through your items.
Point Rotate(int x, int y, float theta)
int x_p = (x * Math.Cos(theta)) - (y * Math.Sin(theta));
int y_p = (y * Math.Cos(theta)) + (x * Math.Sin(theta));
return new Point(x_p, y_p);
end
On a side note; I always preferred "Bolt1, Bolt2, Bolt3" to "Thunder, Thundara, Thundaga" =P
This piece of code has been taken from a game built with XNA framework. I'd like some explanation of how it works in terms of trig and physics.
ball.velocity = new
Vector2((float)Math.Cos(cannon.rotation),
(float)Math.Sin(cannon.rotation));
ball.rotation is the rotation of a sprite in what i should think, radians.
Why is it that they can use the angle in radians only to find the x position then the same thing to find the y position of a direction of where the hypotenuse is pointing.
Reason why I asked this. I would like to get a feel of how this frameworks does calculations for trig. I am trying to get a sprite to turn in the direction of where the mouse is, that is: x and y is known, i just need the angle.
So there are 2 questions here. explaining that code above and pointing a sprite in the direction of a known point.
Update:
I found out that the point a which the object is at is not (0,0) because xna uses inverse coordinate system. So now the variables I have are these:
point of object.
point of mouse.
Every angle corresponds to a point on the unit circle (the unit circle is the unique circle centered at the origin with radius one; that is, the unit circle is the set of points satisfying x^2 + y^2 = 1). The correspondence is the following: given an angle theta, theta corresponds to the point (cos theta, sin theta). Why does (cos theta, sin theta) live on the unit circle? Because of everyone's favorite identity
cos^2 theta + sin^2 theta = 1.
That is with x = cos theta and y = sin theta, the point (x, y) satisfies x^2 + y^2 = 1 so that (x, y) is on the unit circle.
To reverse this, given a point on the unit circle you can find the angle by using the inverse tangent (perhaps known to you as arctan or atan and sometimes tan-1). Precisely, given (x, y) on the unit circle you can find the angle corresponding to (x, y) by computing theta = arctan(y / x).
Of course, there are some messy details here. The function arctan can't tell the difference between the inputs (x, y) and (-x, -y) because y / x and (-y / -x) have the same sign. Further, arctan can't handle inputs where x = 0. So we typically handle these by defining the function atan2 that will handle these messy details for us
atan2(y, x) = arctan(y / x) if x > 0
= pi + arctan(y / x) if y >= 0, x < 0
= -pi + arctan(y / x) if y < 0, x < 0
= pi / 2 if y > 0, x = 0
= -pi / 2 if y < 0, x = 0
= NaN if y = 0, x = 0
In C#, Math.Atan is the function arctan that I have referred to above, and Math.Atan2 is the function atan2 that I have referred to above.
|
y.-----* P
| /|
| / |
| r/ |
| / a |
|/)___.__
O x
we have:
a = angle in radians
O: origin
P: known point
r: distince between O & P
to calculate x, y:
x = r*cos(a)
y = r*sin(a)
(in your example : r = 1, a = cannon.rotation)
Now, if you have x, y and you want a:
if x!= 0 a = atan(y/x)
otherwise a = sign(y)*Pi/2
for more informations (& prettier graphs): Wikipedia: Polar coordinate system
You can see cos and sin returning the point on a circle.
In that respect see the middle of the canon as the center of the circle. Then given an angle (the angle of the canon) you can get the position on the circle it points to with sin and cos.
If you think of the cannon being centered on the 0,0 position, then this value is also the direction the bullet should travel to.
answer2: if you know x and y and you need to know the angle..you need the atan function which returns the angle formed from the sloping side of the triangle where one point is 0,0, the other point is the x,y point and one point is a point which is at the 90 degree angle
Sadly, this is a good question where SO isn't the best format to answer in.
Instead of explaining in text, I think it would be helpful to learn about parametric equations. You can start by searching "circle parametric equation" in Google.
The way that this concept clicked for me was to experiment with different pieces of code until I understood the relation between sin, cos, circles, and angles. Seeing pictures and images help a lot as well. Before then I would read descriptions but could never firmly grasp the explanations.
What you're asking is difficult to explain if you're not familiar with trig.
The line of code in question calculates a unit vector for the direction of the ball, that I presume will be fired from the cannon. The Cos and Sin part of things extract the X and Y components, respectively, of the cannon's angle. So, where the cannon points, that's the direction the ball shoots.
It's a little misleading because the result is most likely only a direction, not an actual velocity. I would assume there's a line below that one that multiplies that vector by a constant, to give the ball its final movement speed.