Зная две точки прямоугольника, как я могу определить две другие? - PullRequest
8 голосов
/ 08 февраля 2010

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

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

Нет гарантии относительно ориентации коробки.

Любая помощь? Кажется, что это должно быть легко, но это действительно пугает меня.

Ответы [ 9 ]

9 голосов
/ 08 февраля 2010

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

если точки (x1, y1) и (x2, y2), и если две точки не являются идеально вертикальными (x1 = x2) или горизонтальными (y1 = y2), то наклон одного края прямоугольник

m1 = (y2-y1) / (x2-x1) 

, а уклон другого края:

m2 = - 1 / m1

Если вам известны длины сторон и средние точки двух противоположных сторон, то угловые точки легко определить, добавив dx, dy к средним точкам: (если L - длина сторон, на которых находятся средние точки)

dx = Sqrt( L^2 / (1 + m2^2) ) / 2

и

dy = m2 * dx

ПРИМЕЧАНИЕ: если точки выровнены по вертикали или горизонтали, этот метод не будет работать, хотя очевидное решение для этих вырожденных случаев намного проще.

5 голосов
/ 08 февраля 2010

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

  • (x1,y1) - координата средней точки на верхней линии
  • (x2,y2) - координата средней точки на нижней линии
  • l1 - длина верхней и нижней линий
  • l2 - длина двух других строк

Сначала мы находим вектор между двумя известными точками. Этот вектор параллелен боковым линиям:

(vx, vy) = (x2 - x1, y2 - y1)

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

vlen = sqrt(vx*vx + vy*vy)

(v1x, v1y) = (vx / vlen, vy / vlen)

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

(u1x, u1y) = (-v1y, v1x)

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

(p1x, p1y) = (x1 - u1x * l1 / 2, y1 - u1y * l1 / 2)

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

(p2x, p2y) = (p1x + u1x * l1, p1y + u1y * l1)

(p3x, p3y) = (p1x + v1x * l2, p1y + v1y * l2)

(p4x, p4y) = (p3x + u1x * l1, p3y + u1y * l1)

2 голосов
/ 03 сентября 2016
  function getFirstPoint(x1,y1,x2,y2,l1,l2)
    distanceV = {x2 - x1, y2 - y1}
    vlen = math.sqrt(distanceV[1]^2 + distanceV[2]^2)
    normalized = {distanceV[1] / vlen, distanceV[2] / vlen}
    rotated = {-normalized[2], normalized[1]}
    p1 = {x1 - rotated[1] * l1 / 2, y1 - rotated[2] * l1 / 2}
    p2 = {p1[1] + rotated[1] * l1, p1[2] + rotated[2] * l1}
    p3 = {p1[1] + normalized[1] * l2, p1[2] + normalized[2] * l2}
    p4 = {p3[1] + rotated[1] * l1, p3[2] + rotated[2] * l1}
    points = { p1 , p2 , p3 , p4}
    return p1
end
0 голосов
/ 24 апреля 2013
/* rcx = center x rectangle, rcy = center y rectangle, rw = width rectangle, rh = height rectangle, rr = rotation in radian from the rectangle (around it's center point) */

function toRectObjectFromCenter(rcx, rcy, rw, rh, rr){
    var a = {
        x: rcx+(Math.sin((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)), 
        y: rcy-(Math.cos((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2))
    };
    var b = {
        x: a.x+Math.cos(rr)*rw,
        y: a.y+Math.sin(rr)*rw
    };
    var c = {
        x: b.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
        y: b.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
    };
    var d = {
        x: a.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
        y: a.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
    };
    return {a:a,b:b,c:c,d:d};
}
0 голосов
/ 08 февраля 2010

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

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

Начиная с верхней центральной точки, двигайтесь относительно (1/2 верхней ширины x sin (угол), 1/2 верхней ширины x cos (угол)) - чтобы получить верхний правый угол.

Продолжить вокруг прямоугольника, используя sin и cos углов и ширины, в зависимости от ситуации

В качестве теста: проверьте, вернулись ли вы к начальной точке

0 голосов
/ 08 февраля 2010

Существует разница между "четырехугольником" и "прямоугольником".

Если у вас есть средняя точка сверху и снизу и длина сторон, остальное просто.

Дано:

(x1, y1) -- (top_middle_x, top_middle_y) -- (x2, y1)

(x1, y2) -- (btm_middle_x, btm_middle_y) -- (x2, y2)

и длина верха / низа вместе с длиной вправо / влево.

x1 = top_middle_x - top / bottom_length / 2; x2 = x1 + top / bottom_length;

y1 = top_middle_y y2 = bottom_middle_y

Очевидно, что это самый простой случай, и предполагается, что линия (tmx, tmy) (bmx, bmy) находится исключительно вдоль оси Y.

Мы назовем эту линию "средней линией".

Следующий трюк состоит в том, чтобы взять среднюю линию и вычислить ее смещение вращения от оси Y.

Теперь мой триг супер ржавый.

dx = tmx - bmx, dy = tmy - bmy.

Итак, тангенс угла равен dy / dx. Арктангенс (dy / dx) - это угол линии.

Отсюда вы можете ориентироваться.

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

Получив ориентацию, вы можете «повернуть» линию обратно к оси Y. Посмотрите 2D графику для математики, это прямо вперед.

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

Виола. Прямоугольник.

Другие вещи, которые вы можете сделать, это «повернуть» линию, которая на половину длины «верхней» линии, на 90 градусов от средней линии. Итак, скажем, у вас есть средняя линия, которая составляет 45 градусов. Вы должны начать эту строку с tmx, tmy и повернуть ее на 135 градусов (90 + 45). Эта точка будет вашим «верхним левым» углом. Поверните это -45 (45 - 90), чтобы получить "верхнюю правую" точку. Затем сделайте что-то похожее с нижними точками.

0 голосов
/ 08 февраля 2010

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

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

                         midpoint
     x,10                 10,10                   x,10
      *--------------------------------------------*
                         width = 30

    mx = midpoint x.
    top left corner = (w/2) - mx  or 15 - 10
    top left corner coords = -5,10

    mx = midpoint x.
    top right corner = (w/2) + mx  or 15 + 10
    top left corner coords = 25,10
0 голосов
/ 08 февраля 2010

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

0 голосов
/ 08 февраля 2010

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

Вы знаете ориентацию и длину длинных сторон, а также их середины, поэтому оттуда легко найти углы.

Реализация оставлена ​​читателю в качестве упражнения.

...