Учитывая угол и размеры, найдите координату по периметру прямоугольника - PullRequest
2 голосов
/ 22 июня 2009

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

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

Если бы кто-нибудь мог дать мне пример прямоугольника 100х150, это было бы здорово.

РЕДАКТИРОВАТЬ: чтобы уточнить, вращая вокруг, я имею в виду перемещение по периметру (или на орбите) формы.

Ответы [ 6 ]

4 голосов
/ 22 июня 2009

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

Если угол равен: -atan (d / w)

dy = d / 2 * tan (alfa)

Вы бы справились с этим аналогично с другими тремя угловыми интервалами.

Хорошо, здесь идет. У вас есть прямоугольник с шириной w и глубиной d. В середине у вас есть центральная точка, ср. Я предполагаю, что вы хотите рассчитать P, для различных значений угла альфа.

alt text

Я разделил прямоугольник на четыре области или угловые интервалы (от 1 до 4). Интервал, который я упомянул выше, является первым справа. Я надеюсь, что это имеет смысл для вас.

Сначала вам нужно вычислить угловые интервалы, они полностью определяются w и d. В зависимости от того, какое значение имеет альфа, вычислите P соответственно, т. Е. Если «луч» из CP в P пересекает верхняя, нижняя, правая или левая стороны прямоугольника.

Приветствия

1 голос
/ 21 марта 2016

Это было сделано и проверено для работы с умными часами Pebble, но изменено на псевдокод:

struct GPoint {
  int x;
  int y;
}

// Return point on rectangle edge.  Rectangle is centered on (0,0) and has a width of w and height of h
GPoint getPointOnRect(int angle, int w, int h) {
  var sine = sin(angle), cosine = cos(angle);   // Calculate once and store, to make quicker and cleaner
  var dy = sin>0 ? h/2 : h/-2;                  // Distance to top or bottom edge (from center)
  var dx = cos>0 ? w/2 : w/-2;                  // Distance to left or right edge (from center)
  if(abs(dx*sine) < abs(dy*cosine)) {           // if (distance to vertical line) < (distance to horizontal line)
    dy = (dx * sine) / cosine;                  // calculate distance to vertical line
  } else {                                      // else: (distance to top or bottom edge) < (distance to left or right edge)
    dx = (dy * cosine) / sine;                  // move to top or bottom line
  }
  return GPoint(dx, dy);                        // Return point on rectangle edge
}


Use:
rectangle_width  = 100;
rectangle_height = 150;
rectangle_center_x = 300;
rectangle_center_y = 300;
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height);
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height);
point.x += rectangle_center_x;
point.y += rectangle_center_y;
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);
0 голосов
/ 22 июня 2009

Использовать матрицу 2D преобразования . Многие языки (например, Java) поддерживают это изначально (ищите AffineTransformation); в противном случае, запишите процедуру, чтобы сделать ротацию самостоятельно, один раз, отладить ее и использовать ее навсегда. Мне нужно, чтобы пять из них были написаны на разных языках.

Как только вы сможете просто повернуть, найдите место на прямоугольнике, выполнив пересечение линия-линия . Найдите центр орбитальной иконки, пересекая две линии:

  1. Луч от вашего центра вращения под желаемым углом
  2. Одна из четырех сторон, ограниченная тем, какой угол вы хотите (четыре квадранта).
0 голосов
/ 22 июня 2009

Один простой способ сделать это с использованием угла в качестве параметра - просто обрезать значения X и Y, используя границы прямоугольника. Другими словами, рассчитайте положение, как будто значок будет вращаться вокруг круговой или эллиптической траектории, затем примените это:

(Предполагается, что выровненный по оси прямоугольник с центром в (0,0), с длиной оси X для оси X и длиной оси Y для оси Y):

if (X > XAxis/2)    
         X = XAxis/2;

if (X < 0 - XAxis/2)
         X = 0 - XAxis/2;

if (Y > YAxis/2)    
         Y = YAxis/2;

if (Y < 0 - YAxis/2)    
         Y = 0 - YAxis/2;

Проблема этого подхода состоит в том, что угол не будет полностью точным, а скорость по периметру прямоугольника не будет постоянной. Моделирование эллипса, который изгибает прямоугольник в его углах, может минимизировать эффект, но если вы ищете плавную "орбиту" с постоянной скоростью, этот метод не будет адекватным.

0 голосов
/ 22 июня 2009

Нарисуйте эскиз на листе бумаги с прямоугольником и центром вращения. Сначала переведите прямоугольник в центр в начале координат вашей системы координат (запомните параметры перевода, вам нужно будет перевернуть перевод позже). Поверните прямоугольник так, чтобы его стороны были параллельны осям координат (по той же причине).

Теперь у вас есть треугольник с известным углом в начале координат, противоположная сторона имеет известную длину (половину длины одной стороны прямоугольника), и теперь вы можете:

- решить треугольник

- отменить вращение

- отменить перевод

0 голосов
/ 22 июня 2009

Если вы думаете, что имеете в виду вращаться, как Земля вращается вокруг Солнца (не самовращение ... так что ваш вопрос о том, как скользить по краям прямоугольника?)

Если это так, вы можете попробовать:

# pseudo coode
for i = 0 to 499
  if i < 100:  x++
  else if i < 250: y--
  else if i < 350: x--
  else y++

  drawTheIcon(x, y)

Обновление: (см. Комментарий ниже)

чтобы использовать угол, одна строка будет

y / x = tan(th)       # th is the angle

остальные строки просты, так как они просто горизонтальные или вертикальные. так, например, это х = 50, и вы можете поместить это в строку выше, чтобы получить у. сделайте это для пересечения горизонтальной линии и вертикальной линии (например, угол равен 60 градусам, и он снимает "NorthEast" ... теперь у вас есть две точки. Тогда точка, ближайшая к началу координат, это та, которая попадает сначала прямоугольник).

...