Хорошо, мы попробуем это снова ...
Рассмотрим объединение двух, состоящих из областей, определенных путем рисования линии от каждой вершины в ABCD (черным) до EFGH (красным):
Здесь сложная часть состоит из всех форм, определяемых этими линиями (как серые линии, так и исходные линии, исходящие из прямоугольников ABCD и EFGH.)
Как только вы это выясните, создайте связанный список этих фигур и предположим, что каждая из этих фигур существует в пересечении.
Шаг 1. Перевести иповерните все так, чтобы ABCD имела одну вершину на 0,0, а ее линии параллельны / перпендикулярны осям x и y.
Шаг 1A. Найдите наименьшую вершину значения y в ABCD, а затем вычесть его из всех других вертиков в сцене.Предположим для целей демонстрации, что этой вершиной является C. Вычитая C из каждой вершины сцены, мы эффективно переместим начало координат (0,0) в C, упрощая вращение вокруг C.
for all shapes in linked list {
for all vertices in shape {
vertex -= C;
}
}
Шаг 1B. Повернуть все вокруг начала координат на угол, равный углу между вектором C-> B и осью x, чтобы B попал на ось x:
// see http://en.wikipedia.org/wiki/Atan2
float rotRadians = atan2(B.x, B.y); // assuming ABCD vertices are labelled clockwise
for all shapes in linked list {
for all vertices in shape {
rot(thisVert, rotRadians);
}
}
// ...
// function declaration
void rot(theVertex, theta) {
tempX = theVertex.x;
tempY = theVertex.y;
theVertex.x = cos(theta) * tempX + sin(theta) * tempY;
theVertex.y = cos(theta) * tempY - sin(theta) * tempX;
}
Если вершины ABCD были помечены по часовой стрелке, вершины ABCD теперь должны выглядеть следующим образом:
A = ABCDx , ABCDy
B = ABCDx , 0
C = 0 , 0
D = 0 , ABCDy
(Если они не были помечены по часовой стрелке, то проверка «лежит внутри» на шаге 2 выиграна »это работает, поэтому убедитесь, что вершина, используемая в вызове atan2(...)
, является вершиной против часовой стрелки от самой нижней вершины.)
Шаг 2. Теперь мы можем легко проанализировать, есть ли формалежит внутри прямоугольника ABCD, например, if (thisVert.x >= 0 && thisVert.y >= 0 && thisVert.x <= ABCDx && thisVert.y <= ABCDy)
.Пройдите по связанному списку фигур и убедитесь, что каждая вершина каждой фигуры находится внутри ABCD.Если одна вершина фигуры не лежит внутри ABCD, то эта фигура не является частью пересечения ABCD / EFGH.Отметьте его как не являющийся частью пересечения и перейдите к следующей фигуре.
Шаг 3. Отмените поворот на шаге 1B, затем отмените перевод на шаге 1A.
Шаг 4. Повторите шаги 1-3 с EFGH вместо ABCD, и вы получите набор пересечений.
Если единственным пересечением между двумя наборами является линия,тогда вышеупомянутое ничего не возвратит как пересечение.Если пересечение == NULL, то проверьте, пересекаются ли линии.
Если пересечение все еще равно NULL, то проверьте точки пересечения.