Алгоритм создания круговой траектории вокруг центра масс? - PullRequest
3 голосов
/ 12 июля 2011

Я пытаюсь просто заставить объекты вращаться вокруг центральной точки, например,

Orbiting Objects

Зеленый и синий объекты представляют объекты, которые должны держать свое расстояниево время поворота к центральной точке на основе угла, который я передаю в метод.

Я попытался создать функцию в target-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);
}

Я получаю результаты, которые находятся далеко не там, где должна быть точка.Проблема с назначением х и у.Куда я иду не так?

Ответы [ 4 ]

1 голос
/ 12 июля 2011

Формула для координат x и y точки на окружности, основанная на радианах, радиусе и центральной точке:

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

Радиус можно найти с помощью HappyPixel 'формула s.

Как только вы определите радиус и центральную точку, вы можете просто изменить angle, чтобы получить все точки на окружности, которые вам нужны.

1 голос
/ 12 июля 2011

Вы можете легко найти расстояние от центра до точки:

радиус = sqrt ((160 - х) ^ 2 + (240 - у) ^ 2)

где (x, y) - начальная позиция центра вашего объекта. Тогда просто замените 50 на радиус.

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


Затем вы можете определить начальный угол, используя тригонометрию (tan = противоположный / соседний, поэтому нарисуйте прямоугольный треугольник, используя центральную массу и центр вашего орбитального объекта, чтобы визуализировать это):

угол = арктан ((у - 240) / (х - 160))

если х> 160 или:

угол = арктан ((у - 240) / (х - 160)) + 180

если х <160 </p>

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);

Таким образом, мы выполняем код выше только один раз (когда объект создается). Нам нужно запомнить radius и adjustment на потом. Затем мы изменим 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)];

Кстати, как только вам удастся заставить это работать, я настоятельно рекомендую преобразовать все ваши углы, чтобы вы использовали радианы на всем протяжении, это делает его намного более аккуратным / более легким для отслеживания!

0 голосов
/ 16 августа 2011
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

Тогда иди с кодом, который у тебя есть, и все будет хорошо. Кажется, вы каждый раз рассчитываете радиус от текущей позиции? Это, как и угол, должно выполняться только один раз, когда объект падает, иначе радиус может быть не постоянным.

* вместо обработки 3 особых случаев для dx = 0, если вам нужна точность <1/100 градусов для начального угла, используйте вместо этого Google Polar Arctan. </em>

0 голосов
/ 12 июля 2011

Если я правильно понимаю, вы хотите сделать 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
...