По заданному углу и размерам найти координату по периметру прямоугольника.

StackOverflow https://stackoverflow.com/questions/1026763

  •  06-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

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

Если угол:-atan(d/w) < alfa < atan(d/w) луч пересекает правую сторону прямоугольника.Тогда, поскольку вы знаете, что смещение по оси x от центра прямоугольника к правой стороне равно d/2, смещение dy, деленное на d/2, равно tan(alfa), поэтому

dy = d/2 * tan(альфа)

Вы поступили бы так же, как и с другими тремя угловыми интервалами.

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

alt text

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

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

Ваше здоровье

Другие советы

Это было сделано и проверено для работы с умными часами 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);

Один простой способ сделать это, используя угол в качестве параметра, - просто обрезать значения 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;

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

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

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

# 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 " ... теперь у вас есть две точки. Затем точка, ближайшая к источник - это тот, который первым попадает в прямоугольник).

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

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

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

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

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

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

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top