2012-02-24 2 views
0

Я использую Python 2.7 и Pygame, но любой ответ на любой язык будет делать.Как найти точку в периметре прямоугольника?

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

Так, например, я хочу найти точку в периметре прямоугольника, следующего за вектором примерно (0.7, 0.7) прямоугольника шириной 2 на 6.

Теперь у меня есть работа; но есть лучший, более элегантный способ: я беру длину более широкого значения между высотой и шириной прямоугольника и используя каждое число между ними и 0 и тестируя это по каждой из четырех сторон прямоугольник и посмотреть, находится ли он в нем.

Это код, я использую исключительно к моей игре, не обобщаются на все: http://pastebin.com/8Ai1iQeL

+0

http://stackoverflow.com/search?q=line+intersection+rectangle –

+0

Спасибо за ссылку, я не использовал эти термины, и кажется, что ваши результаты нашли лучшие результаты, почти лишив мой вопрос. Еще раз спасибо. – TankorSmash

ответ

1

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

Предположим ваш вектор: (x,y), и на данный момент предположим, что обе координаты положительные. Наклон равен y/x, а эквивалентное количество для прямоугольника - h/w, используя систему координат, в которой центр прямоугольника находится в (0,0). Теперь, если y/x > h/w, ваша точка пересечения будет на верхнем краю, поэтому вы знаете, что ее высота равна h/2. Затем вы можете вычислить координаты как (0.5*h*x/y,0.5*h). Если y/x < h/w, точка пересечения находится на правом краю, а координаты - (0.5*w,0.5*w*y/x).

Чтобы использовать это на практике, вы хотите на самом деле провести сравнение между y*w и x*h, чтобы избежать проблем с делением на ноль и избежать относительно дорогого оператора разделения (не то, что действительно имеет большое значение).Кроме того, вы можете найти правильные знаки для компонентов точки пересечения, просто используя знаки x и y. Таким образом, в коде это выглядело бы примерно так:

def intersect_perimeter(x, y, w, h): 
    if abs(y*w) > abs(x*h): 
     return (0.5*h*x/abs(y), 0.5*h*sign(y)) 
    else: 
     return (0.5*w*sign(x), 0.5*w*y/abs(x)) 

(непроверенный). Это не удастся, если x равно нулю и либо y, либо w равно нулю, но в этом случае у вас есть либо нулевой вектор (и проблема не определена), либо прямоугольник нулевой ширины (опять же проблема не определена). Поэтому я бы не стал беспокоиться об ошибках в этом случае.

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

+0

Если вы имеете в виду мое использование функции [sign function] (http://en.wikipedia.org/wiki/Sign_function), нет, это не опечатка. –

+0

Моя ошибка, я предположил, что это была опечатка после того, как я пробовал несколько вещей; math.sign(), math.sgn(), sig() и sign(). Был быстрый поиск и нашел эту страницу с хорошим объяснением того, что вы имели в виду: http://thingspython.wordpress.com/2011/03/12/snippet-sgn-function/ – TankorSmash

1

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

1) Определите, попадет ли вектор в правую или верхнюю части прямоугольника. Сделайте это, построив правый треугольник, гипотенуза которого является диагональю прямоугольника, т. Е. От начала координат до верхнего угла. Если угол A вектора больше, чем этот угол, он попадет в верхнюю часть; иначе он ударит в сторону.

2) Предположим, что он попадает в сторону (решение будет аналогичным, если оно попадает в верхнюю часть). Если ширина треугольника равна w, то вы можете построить правый треугольник, вершины которого являются началом, точкой (w/2, 0) и точкой (w/2, y), где (w/2, y) - точка, которую вы хотите найти. Затем просто используйте law of sines, чтобы получить y.

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

Смежные вопросы