可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
It's been 10 years since I did any math like this... I am programming a game in 2D and moving a player around. As I move the player around I am trying to calculate the point on a circle 200 pixels away from the player position given a positive OR negative angle(degree) between -360 to 360. The screen is 1280x720 with 0,0 being the center point of the screen. The player moves around this entire Cartesian coordinate system. The point I am trying trying to find can be off screen.
I tried the formulas on article Find the point with radius and angle but I don't believe I am understanding what "Angle" is because I am getting weird results when I pass Angle as -360 to 360 into a Cos(angle) or Sin(angle).
So for example I have...
- 1280x720 on a Cartesian plane
- Center Point (the position of player):
- let x = a number between minimum -640 to maximum 640
- let y = a number between minimum -360 to maximum 360
- Radius of Circle around the player: let r always = 200
- Angle: let a = a number given between -360 to 360 (allow negative to point downward or positive to point upward so -10 and 350 would give same answer)
What is the formula to return X on the circle?
What is the formula to return Y on the circle?
回答1:
The simple equations you've linked to give the X and Y coordinates of the point on the circle relative to the center of the circle.
X = r * cosine(angle)
Y = r * sine(angle)
This tells you how far the point is offset from the center of the circle. Since you have the coordinates of the center (Cx, Cy), simply add the calculated offset.
The coordinates of the point on the circle are:
X = Cx + (r * cosine(angle))
Y = Cy + (r * sine(angle))
回答2:
You should post the code you are using. That would help identify the problem exactly.
However, since you mentioned measuring your angle in terms of -360 to 360, you are probably using the incorrect units for your math library. Most implementations of trigonometry functions use radians for their input. And if you use degrees instead...your answers will be weirdly wrong.
x_oncircle = x_origin + 200 * cos (degrees * pi / 180)
y_oncircle = y_origin + 200 * sin (degrees * pi / 180)
Note that you might also run into circumstance where the quadrant is not what you'd expect. This can fixed by carefully selecting where angle zero is, or by manually checking the quadrant you expect and applying your own signs to the result values.
回答3:
I highly suggest using matrices for this type of manipulations. It is the most generic approach, see example below:
// The center point of rotation
var centerPoint = new Point(0, 0);
// Factory method creating the matrix
var matrix = new RotateTransform(angleInDegrees, centerPoint.X, centerPoint.Y).Value;
// The point to rotate
var point = new Point(100, 0);
// Applying the transform that results in a rotated point
Point rotated = Point.Multiply(point, matrix);
- Side note, the convention is to measure the angle counter clockwise starting form (positive) X-axis
回答4:
I am getting weird results when I pass Angle as -360 to 360 into a Cos(angle) or Sin(angle).
I think the reason your attempt did not work is that you were passing angles in degrees. The sin
and cos
trigonometric functions expect angles expressed in radians, so the numbers should be from 0
to 2*M_PI
. For d
degrees you pass M_PI*d/180.0
. M_PI
is a constant defined in math.h
header.
回答5:
I also needed this to form the movement of the hands of a clock in code. I tried several formulas but they didn't work, so this is what I came up with:
- motion - clockwise
- points - every 6 degrees (because 360 degrees divided by 60 minuites is 6 degrees)
- hand length - 65 pixels
- center - x=75,y=75
So the formula would be
x=Cx+(r*cos(d/(180/PI))
y=Cy+(r*sin(d/(180/PI))
where x and y are the points on the circumference of a circle, Cx and Cy are the x,y coordinates of the center, r is the radius, and d is the amount of degrees.
回答6:
Here is the c# implementation. The method will return the circular points which takes radius
, center
and angle interval
as parameter. Angle is passed as Radian.
public static List<PointF> getCircularPoints(double radius, PointF center, double angleInterval)
{
List<PointF> points = new List<PointF>();
for (double interval = angleInterval; interval < 2 * Math.PI; interval += angleInterval)
{
double X = center.X + (radius * Math.Cos(interval));
double Y = center.Y + (radius * Math.Sin(interval));
points.Add(new PointF((float)X, (float)Y));
}
return points;
}
and the calling example:
List<PointF> LEPoints = getCircularPoints(10.0f, new PointF(100.0f, 100.0f), Math.PI / 6.0f);
回答7:
I wanted to share how your contributions above helped me produce an Arduino LCD compass. I hope this is the right etiquette...I just joined stackoverflow so I could thank you fine folks.
While standing on the shoulders of the geometry giants above I was able to produce this sample compass:
Arduino TFT compass with multiple bearings
The code for the function I called repeatedly (for different bearings you see in tiny yellow text) is written in Arduino (kinda like "C")...and is pretty translatable:
void PaintCompassNeedle( int pBearingInDegrees, int pRadius, TSPoint pCentrePt ) {
// ******************************************************************************
// * Formula for finding pointX on the circle based on degrees around the circle:
// * x_oncircle = x_origin + radius * cos (degrees * pi / 180)
// * y_oncircle = y_origin - radius * sin (degrees * pi / 180) //minus explained
// * Thanks to folks at stackoverflow...standing on the shoulders of giants. :)
float bearingInRads = (pBearingInDegrees) * PI / 180;
// Degrees vs Rads...The math folks use Rads in their formulas
// *******************************************************************
// * bearingPt is the point on the circle that we are trying to find
TSPoint bearingPt;
// Find the X on the circle starting with orgin (centre)
bearingPt.x = pCentrePt.x + pRadius * sin(bearingInRads);
// Notice the "minus" R * cos()...because TFT the y is upside down bearingPt.y =
pCentrePt.y - pRadius * cos(bearingInRads);
// * Extra Explanation: The TFT is the graphical display I'm using and it
// * calculates x & y from the top left of screen (portrait mode) as (0,0)
// * ...so by Subtracting from the Y orgin...I flip it vertically
// * Other folks using x,y as increasing to the right and up respectively
// * would keep the plus sign after the pCentrePt.y
// *************************************************************************
// ***************************************************************
// * This part will change for the final product...but leaving
// * it because when call numerous times it shows it working for
// * a number of different quadrants (displaying yellow degrees text)
tft.fillCircle( bearingPt.x, bearingPt.y, 5, RED);
tft.setCursor( bearingPt.x, bearingPt.y );
tft.setTextSize( 1 );
tft.setTextColor( YELLOW );
tft.print( pBearingInDegrees );
TSPoint innerPt;
innerPt.x = pCentrePt.x + pRadius/2 * sin(bearingInRads);
innerPt.y = pCentrePt.y - pRadius/2 * cos(bearingInRads);
tft.drawLine(innerPt.x, innerPt.y, bearingPt.x, bearingPt.y, RED);
}
回答8:
The answer should be exactly opposite.
X = Xc + rSin(angle)
Y = Yc + rCos(angle)
where Xc and Yc are circle's center coordinates and r is the radius.
回答9:
Recommend:
public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3
pivot, Vector3 angles)
{
return Quaternion.Euler(angles) * (point - pivot) + pivot;
}