Получить угол из двух позиций

У меня есть 2 объекта, и когда я двигаю один, я хочу получить угол от другого.

Например:

Object1X = 211.000000, Object1Y = 429.000000
Object2X = 246.500000, Object2Y = 441.500000

Я пробовал следующее и каждую вариацию под солнцем:

double radians = ccpAngle(Object1,Object2);
double degrees = ((radians * 180) / Pi); 

Но я просто получаю 2.949023, где я хочу что-то вроде 45 градусов и т.д.

Ответы

Ответ 1

Помогает ли этот другой ответ?

Как сопоставить atan2() с градусами 0-360

Я написал это следующим образом:

- (CGFloat) pointPairToBearingDegrees:(CGPoint)startingPoint secondPoint:(CGPoint) endingPoint
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
    float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
    float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
    return bearingDegrees;
}

Запуск кода:

CGPoint p1 = CGPointMake(10, 10);
CGPoint p2 = CGPointMake(20,20);

CGFloat f = [self pointPairToBearingDegrees:p1 secondPoint:p2];

И это возвращает 45.

Надеюсь, что это поможет.

Ответ 2

Я изменил решение @tomas для оптимизации. Вероятно (это было для меня), что эта математика будет часто называться.

В моем воплощении вы должны выполнить разницу между двумя точками самостоятельно (или, если вам повезет, (0,0) уже является одним из ваших очков). Вычисляемое значение является направлением точки от (0,0). Да, это достаточно просто, и вы можете сделать это, если захотите. Я предпочитаю более читаемый код.

Я также преобразовал его в вызов функции:

CGFloat CGPointToDegree(CGPoint point) {
  // Provides a directional bearing from (0,0) to the given point.
  // standard cartesian plain coords: X goes up, Y goes right
  // result returns degrees, -180 to 180 ish: 0 degrees = up, -90 = left, 90 = right
  CGFloat bearingRadians = atan2f(point.y, point.x);
  CGFloat bearingDegrees = bearingRadians * (180. / M_PI);
  return bearingDegrees;
}

Если вы не хотите отрицательных значений, вам нужно его самостоятельно преобразовать. Отрицательные значения были хороши для меня - нет необходимости делать ненужные расчеты.

Я использовал это в среде cocos2d, так я называю это: (Математически мы переводим плоскость, чтобы сделать p0 начало координат. Таким образом, вычитая p0 из p1 (p0 - p0= {0,0}). При переводе плоскости углы не изменяются.)

CGPoint p0 = self.position;
CGPoint p1 = other.position;
CGPoint pnormal = ccpSub(p1, p0);
CGFloat angle = CGPointToDegree(pnormal);

ccpSub предоставляется cocos2d, это вычитание кортежа - вы можете сделать это сами, если у вас нет этого доступного

в стороне: обычно это не вежливый стиль, чтобы назвать метод, как указано выше, с схемой именования CG___, которая идентифицирует функцию как часть CoreGraphics - поэтому, если вы хотите переименовать ее в MyConvertCGPointToBearing() или FredLovesWilma() то вы должны это сделать.

Ответ 3

Вот как я делаю это в Swift для тех, кого это интересует, на основе ответа @bshirley выше w/нескольких модификаций, которые помогают соответствовать системе вращения калейзера:

extension CGPoint {
    func angle(to comparisonPoint: CGPoint) -> CGFloat {
        let originX = comparisonPoint.x - self.x
        let originY = comparisonPoint.y - self.y
        let bearingRadians = atan2f(Float(originY), Float(originX))
        var bearingDegrees = CGFloat(bearingRadians).degrees
        while bearingDegrees < 0 {
            bearingDegrees += 360
        }
        return bearingDegrees
    }
}

extension CGFloat {
    var degrees: CGFloat {
        return self * CGFloat(180.0 / M_PI)
    }
}

Это обеспечивает такую ​​систему координат:

        270
180              0
        90

Использование:

point.angle(to: point2)
CGPoint.zero.angle(to: CGPoint(x: 0, y: 1)) // 90

Ответ 4

Между двумя точками нет угла. Если вы хотите знать угол между векторами от начала координат (0,0) до объектов, используйте скалярный (dot) продукт:

theta = arccos ( (veca dot vecb) / ( |veca| * |vecb| )

Математика std lib языка, который вы используете, безусловно, предоставляет функции для косинуса arcus, скалярного произведения и длины.

Ответ 5

Вершина угла - это точка (0,0).

Рассмотрим object1X = x1.... object2Y = y2.

Angle(object1-object2) = 
   90       * (  (1 + sign(x1)) * (1 - sign(y1^2))
               - (1 + sign(x2)) * (1 - sign(y2^2)) )
 + 45       * (  (2 + sign(x1)) * sign(y1)
               - (2 + sign(x2)) * sign(y2)         )
 + 180/pi() * sign(x1*y1) * atan( (abs(x1) - abs(y1)) / (abs(x1) + abs(y1)) )
 - 180/pi() * sign(x2*y2) * atan( (abs(x2) - abs(y2)) / (abs(x2) + abs(y2)) )

Ответ 6

Ответ томаса в Swift 5.1

func angle(between starting: CGPoint, ending: CGPoint) -> CGFloat {
    let center = CGPoint(x: ending.x - starting.x, y: ending.y - starting.y)
    let radians = atan2(center.y, center.x)
    let degrees = radians * 180 / .pi
    return degrees > 0 ? degrees : degrees + degrees
}