创建围绕中心质量的圆形路径的算法?

发布于 2024-11-19 19:41:32 字数 2028 浏览 1 评论 0原文

我试图简单地使物体围绕中心点运行,例如

Orbiting Objects

绿色和蓝色对象代表在旋转时应与中心点保持距离的对象,基于我传递给方法的角度。

我尝试在 Objective-C 中创建一个函数,但如果没有静态数字,它就无法正常工作。例如(它绕中心旋转,但不是从真正的起点或距对象的距离旋转。)

-(void) rotateGear: (UIImageView*) view heading:(int)heading
{
    // int distanceX = 160 - view.frame.origin.x;
    // int distanceY = 240 - view.frame.origin.y;

    float x = 160 - view.image.size.width / 2 + (50 * cos(heading * (M_PI / 180)));
    float y = 240 - view.image.size.height / 2 + (50 * sin(heading * (M_PI / 180)));
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

我的幻数 160 和 240 是我在其中绘制图像的画布的中心到。 50 是一个静态数字(也是问题所在),它允许函数部分正确地工作——无需保持对象的起始位置或正确的距离。不幸的是,我不知道该放什么。

heading 是一个传入度数的参数,从 0 到 359。它由计时器计算并在此类外部递增。

本质上我希望能够将任何图像放到我的画布上,并且基于图像的起点,它会围绕我的圆心旋转。这意味着,如果我将图像放在 (10,10) 点,到圆心的距离将保持不变,使用 (10,10) 作为一个起点。该物体将围绕中心旋转 360 度,并到达其原始起点。

预期的结果是将例如 (10,10) 传递到该方法中,基于零度,然后返回 (15,25) (不是真实)5 度。

我知道这很简单(这个问题描述完全是多余的),但我会斗鸡眼试图弄清楚我在哪里把事情搞清楚。我不关心你使用什么语言的例子(如果有的话)。我一定能解读你的意思。

失败更新

我已经走得更远了,但我仍然无法得到正确的计算。我的新代码如下所示:

heading 设置为 1 度。

-(void) rotateGear: (UIImageView*) view heading:(int)heading
{
    float y1 = view.frame.origin.y + (view.frame.size.height/2); // 152
    float x1 = view.frame.origin.x + (view.frame.size.width/2); // 140.5

    float radius = sqrtf(powf(160 - x1 ,2.0f) + powf(240 - y1, 2.0f)); // 90.13

    // I know that I need to calculate 90.13 pixels from my center, at 1 degree.      
    float x = 160 + radius * (cos(heading * (M_PI / 180.0f))); // 250.12
    float y = 240 + radius * (sin(heading * (M_PI / 180.0f))); // 241.57

    // The numbers are very skewed.
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

我得到的结果与应有的结果相差甚远。问题在于 x 和 y 的分配。我哪里错了?

I am attempting to simply make objects orbit around a center point, e.g.

Orbiting Objects

The green and blue objects represent objects which should keep their distance to the center point, while rotating, based on an angle which I pass into method.

I have attempted to create a function, in objective-c, but it doesn't work right without a static number. e.g. (It rotates around the center, but not from the true starting point or distance from the object.)

-(void) rotateGear: (UIImageView*) view heading:(int)heading
{
    // int distanceX = 160 - view.frame.origin.x;
    // int distanceY = 240 - view.frame.origin.y;

    float x = 160 - view.image.size.width / 2 + (50 * cos(heading * (M_PI / 180)));
    float y = 240 - view.image.size.height / 2 + (50 * sin(heading * (M_PI / 180)));
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

My magic numbers 160, and 240 are the center of the canvas in which I'm drawing the images onto. 50 is a static number (and the problem), which allows the function to work partially correctly -- without maintaining the starting poisition of the object or correct distance. I don't know what to put here unfortunately.

heading is a parameter that passes in a degree, from 0 to 359. It is calculated by a timer and increments outside of this class.

Essentially what I would like to be able to drop any image onto my canvas, and based on the starting point of the image, it would rotate around the center of my circle. This means, if I were to drop an image at Point (10,10), the distance to the center of the circle would persist, using (10,10) as a starting point. The object would rotate 360 degrees around the center, and reach it's original starting point.

The expected result would be to pass for instance (10,10) into the method, based off of zero degrees, and get back out, (15,25) (not real) at 5 degrees.

I know this is very simple (and this problem description is entirely overkill), but I'm going cross eyed trying to figure out where I'm hosing things up. I don't care about what language examples you use, if any. I'll be able to decipher your meanings.

Failure Update

I've gotten farther, but I still cannot get the right calculation. My new code looks like the following:

heading is set to 1 degree.

-(void) rotateGear: (UIImageView*) view heading:(int)heading
{
    float y1 = view.frame.origin.y + (view.frame.size.height/2); // 152
    float x1 = view.frame.origin.x + (view.frame.size.width/2); // 140.5

    float radius = sqrtf(powf(160 - x1 ,2.0f) + powf(240 - y1, 2.0f)); // 90.13

    // I know that I need to calculate 90.13 pixels from my center, at 1 degree.      
    float x = 160 + radius * (cos(heading * (M_PI / 180.0f))); // 250.12
    float y = 240 + radius * (sin(heading * (M_PI / 180.0f))); // 241.57

    // The numbers are very skewed.
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

I'm getting results that are no where close to where the point should be. The problem is with the assignment of x and y. Where am I going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等风也等你 2024-11-26 19:41:32

您可以很容易地找到该点到中心的距离:

半径 = sqrt((160 - x)^2 + (240 - y)^2)

其中 (x, y) 是对象中心的初始位置。然后只需将 50 替换为半径即可。

http://en.wikipedia.org/wiki/Pythagorean_theorem


然后你就可以算出初始角度使用三角学(tan = 相反/相邻,因此使用中心质量和轨道物体的中心绘制一个直角三角形来可视化它):

角度 = arctan((y - 240) / (x - 160))

如果 x > 160,或:

角度 = arctan((y - 240) / (x - 160)) + 180

如果 x < 160

http://en.wikipedia.org/wiki/Inverse_trigonometric_functions


编辑:请记住,我不实际上不知道任何 Objective-C 但这基本上是我认为你应该做的(你应该能够很容易地将其转换为正确的 Obj-C,这只是为了演示):

// Your object gets created here somewhere

float x1 = view.frame.origin.x + (view.frame.size.width/2); // 140.5
float y1 = view.frame.origin.y + (view.frame.size.height/2); // 152

float radius = sqrtf(powf(160 - x1 ,2.0f) + powf(240 - y1, 2.0f)); // 90.13

// Calculate the initial angle here, as per the first part of my answer
float initialAngle = atan((y1 - 240) / (x1 - 160)) * 180.0f / M_PI;
if(x1 < 160)
    initialAngle += 180;

// Calculate the adjustment we need to add to heading
int adjustment = (int)(initialAngle - heading);

所以我们只执行代码上面一次(当对象被创建时)。我们需要记住半径调整以供稍后使用。然后我们改变 rotateGear 以角度和半径作为输入,而不是 heading (无论如何,这更加灵活):

-(void) rotateGear: (UIImageView*) view radius:(float)radius angle:(int)angle
{
    float x = 160 + radius * (cos(angle * (M_PI / 180.0f)));
    float y = 240 + radius * (sin(angle * (M_PI / 180.0f)));

    // The numbers are very skewed.
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

每次我们想要更新我们所做的位置时像这样的电话:

[objectName rotateGear radius:radius angle:(adjustment + heading)];

顺便说一句,一旦你成功地完成了这个工作,我强烈建议你转换所有的角度,这样你就可以一直使用弧度,这使得它更整洁/更容易遵循!

You can find the distance of the point from the centre pretty easily:

radius = sqrt((160 - x)^2 + (240 - y)^2)

where (x, y) is the initial position of the centre of your object. Then just replace 50 by the radius.

http://en.wikipedia.org/wiki/Pythagorean_theorem


You can then figure out the initial angle using trigonometry (tan = opposite / adjacent, so draw a right-angled triangle using the centre mass and the centre of your orbiting object to visualize this):

angle = arctan((y - 240) / (x - 160))

if x > 160, or:

angle = arctan((y - 240) / (x - 160)) + 180

if x < 160

http://en.wikipedia.org/wiki/Inverse_trigonometric_functions


Edit: bear in mind I don't actually know any Objective-C but this is basically what I think you should do (you should be able to translate this to correct Obj-C pretty easily, this is just for demonstration):

// Your object gets created here somewhere

float x1 = view.frame.origin.x + (view.frame.size.width/2); // 140.5
float y1 = view.frame.origin.y + (view.frame.size.height/2); // 152

float radius = sqrtf(powf(160 - x1 ,2.0f) + powf(240 - y1, 2.0f)); // 90.13

// Calculate the initial angle here, as per the first part of my answer
float initialAngle = atan((y1 - 240) / (x1 - 160)) * 180.0f / M_PI;
if(x1 < 160)
    initialAngle += 180;

// Calculate the adjustment we need to add to heading
int adjustment = (int)(initialAngle - heading);

So we only execute the code above once (when the object gets created). We need to remember radius and adjustment for later. Then we alter rotateGear to take an angle and a radius as inputs instead of heading (this is much more flexible anyway):

-(void) rotateGear: (UIImageView*) view radius:(float)radius angle:(int)angle
{
    float x = 160 + radius * (cos(angle * (M_PI / 180.0f)));
    float y = 240 + radius * (sin(angle * (M_PI / 180.0f)));

    // The numbers are very skewed.
    view.frame = CGRectMake(x, y, view.image.size.width, view.image.size.height);
}

And each time we want to update the position we make a call like this:

[objectName rotateGear radius:radius angle:(adjustment + heading)];

Btw, once you manage to get this working, I'd strongly recommend converting all your angles so you're using radians all the way through, it makes it much neater/easier to follow!

刘备忘录 2024-11-26 19:41:32

基于弧度、半径和中心点的圆上点的 x 和 y 坐标公式:

x = cos(angle) * radius + center_x
y = sin(angle) * radius + center_y

您可以使用 HappyPixel 的公式。

一旦确定了半径和中心点,您只需改变角度即可获得您想要的圆上的所有点。

The formula for x and y coordinates of a point on a circle, based on radians, radius, and center point:

x = cos(angle) * radius + center_x
y = sin(angle) * radius + center_y

You can find the radius with HappyPixel's formula.

Once you figure out the radius and the center point, you can simply vary the angle to get all the points on the circle that you'd want.

救星 2024-11-26 19:41:32

如果我理解正确的话,您需要执行 InitObject(x,y).,然后执行 UpdateObject(angle),其中角度从 0 扫描到 360。(但是使用数学上用弧度代替度数)
因此,您需要跟踪每个对象的角度和半径。:

InitObject(x,y)
    relative_x = x-center.x
    relative_y = y-center.y
    object.radius = sqrt((relative_x)^2, (relative_y)^2)
    object.initial_angle = atan(relative_y,relative_x);

并且

UpdateObject(angle)
    newangle = (object.initial_angle + angle) % (2*PI )
    object.x = cos(newangle) * object.radius + center.x
    object.y = sin(newangle) * object.radius + center.y

If I understand correctly, you want to do InitObject(x,y). followed by UpdateObject(angle) where angle sweeps from 0 to 360. (But use radians instead of degrees for the math)
So you need to track the angle and radius for each object.:

InitObject(x,y)
    relative_x = x-center.x
    relative_y = y-center.y
    object.radius = sqrt((relative_x)^2, (relative_y)^2)
    object.initial_angle = atan(relative_y,relative_x);

And

UpdateObject(angle)
    newangle = (object.initial_angle + angle) % (2*PI )
    object.x = cos(newangle) * object.radius + center.x
    object.y = sin(newangle) * object.radius + center.y
染墨丶若流云 2024-11-26 19:41:32
dx=dropx-centerx; //target-source
dy=-(dropy-centery); //minus = invert screen coords to cartesian coords
radius=sqrt(dy*dy+dx*dx); //faster if your compiler optimizer is bad

if dx=0 then dx=0.000001; //hackpatchfudgenudge*
angle=atan(dy/dx); //set this as start angle for the angle-incrementer

然后使用您拥有的代码就可以了。您似乎每次都在计算当前位置的半径?与角度一样,此操作只能在物体掉落时执行一次,否则半径可能不是恒定的。

*如果您需要 ,而不是处理 dx=0 的 3 个特殊情况起始角度的 1/100 度精度请使用 Google Polar Arctan。

dx=dropx-centerx; //target-source
dy=-(dropy-centery); //minus = invert screen coords to cartesian coords
radius=sqrt(dy*dy+dx*dx); //faster if your compiler optimizer is bad

if dx=0 then dx=0.000001; //hackpatchfudgenudge*
angle=atan(dy/dx); //set this as start angle for the angle-incrementer

Then go with the code you have and you'll be fine. You seem to be calculating radius from current position each time though? This, like the angle, should only be done once, when the object is dropped, or else the radius might not be constant.

*instead of handling 3 special cases for dx=0, if you need < 1/100 degree precision for the start angle go with those instead, google Polar Arctan.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文