Найти, если точка лежит внутри прямоугольника - PullRequest
3 голосов
/ 14 августа 2010

Как найти, если точка лежит в 2D-прямоугольнике с учетом 4 точек?

Ответы [ 6 ]

8 голосов
/ 14 августа 2010

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

Если прямоугольник состоит из следующих 4 точек:

a  b
c  d

Затем получим «x-axis» и «y-axis» прямоугольника как:

x = Normalize(d-c)
y = Normalize(a-c)

Затем построим матрицу вращения, используя x и y в качестве столбцов:

r = [ x | y ]

ЕслиВы используете трехмерные координаты, нам нужна ось z:

z = CrossProduct(x, y)
r = [ x | y | z ]

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

T = [ r^T | -r^T * c ]
    [ 0^T |     1    ]

Здесь мымы выбрали нижний левый угол c как местное происхождение."R ^ T" является транспонированным.«0 ^ T» представляет собой 2-й или 3-й вектор-строку, заполненный нулями.1 только один.Обратите внимание, что это просто обратная сторона более простого преобразования прямоугольника в мир, которое равно

T^-1 = [ r   | c ]
       [ 0^T | 1 ]

. Мы можем использовать T для преобразования точки в выровненные по оси координаты.Не забудьте дополнить p конечным 1, поскольку T является однородной матрицей.

tp = T * p;  // Don't forget to pad p with a trailing 1 before multiplying.

// Checks that p isn't below or to the left of the rectangle.
for ( int d = 0; d < num_dimensions; ++d ) {
  if ( tp[d] < 0.0 ) {
    return false;
  }
}

// Checks that p isn't to the right of the rectangle
double width = Length(d-c);
if ( tp[0] > width ) {
  return false;
}

// Checks that p isn't above the rectangle.
double height = Length(a-c);
if ( tp[1] > height ) {
  return false;
}

// p must be inside or on the rectangle.
return true

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

if ( fabs(tp[2]) > some_small_positive_number ) {
   return false;  // point is out of the rectangle's plane.
}
2 голосов
/ 14 августа 2010

Я думаю, что это может ответить на ваш вопрос

  • полное раскрытие - я отправился в Дрексель за своим дипломом
0 голосов
/ 16 марта 2018

Общий тест для точки в четырехугольнике достаточно.Квадрат определяется как упорядоченный ряд точек.Ручки как по часовой стрелке, так и против часовой стрелки:

typedef struct {float x; float y} vec2;
bool pointIsInQuad(const vec2 point, const vec2 quad[4])
{
    bool sides[4];
    for (int i = 0; i < 4; i++) {
        sides[i] = ((point.x - quad[i].x)*(quad[(i + 1)%4].y - quad[i].y) - (point.y - quad[i].y)*(quad[(i + 1)%4].x - quad[i].x)) > 0.0f;
    }
    return ((sides[0] == sides[1]) && (sides[0] == sides[2]) && (sides[0] == sides[3]));
}
0 голосов
/ 15 августа 2010

Легко проверить, лежит ли точка в треугольнике, поэтому вы можете разбить прямоугольник на два треугольника и проверить их.См. Например http://www.blackpawn.com/texts/pointinpoly/default.html

0 голосов
/ 14 августа 2010

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

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

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

Если линиякасается луча, но не пересекает его, результат неоднозначен.Поэтому в своих расчетах представьте, что луч бесконечно мал на ɛ больше, чем его координата y, так что для линии невозможно линия коснется луча, не пересекая его.

Учитывая вашу контрольную точку (x, y) и линию (x1, y1, x2, y2), проверить, пересекает ли линия луч, довольно просто.Предположим без ограничения общности, что y1

if y < y2 and y >= y1:
    let x0 = x1 + (y-y1)/(y2-y1) * (x2-x1) // crossing point (x0,y)
    if x0 > x:
        crossing_detected++

http://en.wikipedia.org/wiki/Point_in_polygon

0 голосов
/ 14 августа 2010

Чтобы сделать его специфичным для OpenGl:

Полагаю, ваш 2D-прямоугольник находится в экранных координатах!

сначала:

 gluProject (bli, bla, blorp, ...);

чтобы перейти от 3d к экранным координатам.

Тогда: предложение Ноя.

Стреляйте в себя, только если ваша точка зрения уже 2D;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...