Eu tenho 2 polígonos. Eu sei as coordenadas de vértice de ambos os polígonos. Qual é a melhor maneira de verificar se um está completamente dentro do outro? Por exemplo, o algoritmo deve reconhecer apenas o trapézio preto abaixo como contido:
Eu tenho 2 polígonos. Eu sei as coordenadas de vértice de ambos os polígonos. Qual é a melhor maneira de verificar se um está completamente dentro do outro? Por exemplo, o algoritmo deve reconhecer apenas o trapézio preto abaixo como contido:
Respostas:
Existem muitos trechos de código-fonte para um método que executa um teste para " ponto dentro do polígono ". O princípio vem do teorema da curva de Jordan para polígonos ( http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html ).
A maneira ingênua seria: tendo esse método, chame-o PointInsidePolygon(Point p, Polygon poly)
:
bool isInside = true;
for each (Point p in innerPoly)
{
if (!PointInsidePolygon(p, outerPoly))
{
isInside = false; // at least one point of the innerPoly is outside the outerPoly
break;
}
}
if (!isInside) return false;
// COMPULSORY EDGE INTERSECTION CHECK
for each (innerEdge in innerPoly)
for each (outerEdge in outerPoly)
{
if (EdgesIntersect(innerEdge, outerEdge))
{
isInside = false;
break;
}
}
return isInside;
Teoricamente, ele não deve perder nenhum cenário para seus polígonos, mas não é a solução ideal.
Observações do caso "Edge"
PointInsidePolygon(..)
deve retornar true se o ponto estiver na borda do polígono (está em uma aresta ou é um vértice)
EdgesIntersect(..)
deve retornar false se innerEdge
for um subconjunto (geometricamente) do outerEdge
. Nesse caso, as arestas obviamente se cruzam, mas, para o propósito do algoritmo, precisamos indicar que a interseção não está quebrando a semântica por trás da isInside
variável
Comentários gerais :
sem verificações de interseção de arestas x arestas, conforme indicado nos comentários, a abordagem pode retornar falsos positivos para alguns polígonos côncavos (por exemplo, um quad e um retângulo em forma de V - o retângulo pode ter todos os seus vértices dentro da forma de V, mas interceptá-lo , tendo pelo menos algumas áreas externas).
depois de verificar se pelo menos um dos vértices do polígono interno está dentro do externo e se não houver arestas que se cruzam, significa que a condição procurada é satisfeita.
Tente fazer uma interseção de linha com cada linha vermelha. No pseudocódigo:
// loop over polygons
for (int i = 0; i < m_PolygonCount; i++)
{
bool contained = false;
for (int j = 0; j < m_Polygon[i].GetLineCount(); j++)
{
for (int k = 0; k < m_PolygonContainer.GetLineCount(); k++)
{
// if a line of the container polygon intersects with a line of the polygon
// we know it's not fully contained
if (m_PolygonContainer.GetLine(k).Intersects(m_Polygon[i].GetLine(j)))
{
contained = false;
break;
}
}
// it only takes one intersection to invalidate the polygon
if (!contained) { break; }
}
// here contained is true if the polygon is fully inside the container
// and false if it's not
}
No entanto, como você pode ver, essa solução ficará mais lenta à medida que você adiciona mais polígonos para verificar. Uma solução diferente pode ser:
Essa solução é muito rápida, mas depende da sua implementação (e do que você deseja fazer com o resultado da sua verificação) que solução funciona melhor para você.