Ho 2 poligoni. Conosco le coordinate del vertice di entrambi i poligoni. Qual è il modo migliore per verificare se uno è completamente dentro l'altro? Ad esempio, l'algoritmo dovrebbe riconoscere solo il trapezio nero di seguito come contenuto:
Ho 2 poligoni. Conosco le coordinate del vertice di entrambi i poligoni. Qual è il modo migliore per verificare se uno è completamente dentro l'altro? Ad esempio, l'algoritmo dovrebbe riconoscere solo il trapezio nero di seguito come contenuto:
Risposte:
Esistono tonnellate di frammenti di origine per un metodo che esegue un test per " punto all'interno del poligono ". Il principio deriva dal teorema della curva della Giordania per i poligoni ( http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html ).
Il modo ingenuo sarebbe: avendo quel metodo, chiamalo 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, non dovrebbe mancare nessuno scenario per i tuoi poligoni, ma non è la soluzione ottimale.
Osservazioni sul caso "Edge"
PointInsidePolygon(..)
deve restituire true se il punto si trova sul bordo del poligono (o si trova su un bordo o è un vertice)
EdgesIntersect(..)
deve restituire false se innerEdge
è un sottoinsieme (dal punto di vista geometrico) di outerEdge
. In questo caso, i bordi ovviamente si intersecano, ma ai fini dell'algoritmo, dobbiamo indicare che l'intersezione non sta infrangendo la semantica dietro la isInside
variabile
Remakrs generali :
senza i controlli di intersezione tra spigolo e spigolo, come sottolineato nei commenti, l'approccio potrebbe restituire falsi positivi per alcuni poligoni concavi (ad esempio un quadratino a V e un rettangolo - il rettangolo potrebbe avere tutti i suoi vertici all'interno della forma a V, ma intersecarlo , avendo quindi almeno alcune aree all'esterno).
dopo che uno controlla che almeno uno dei vertici del poligono interno sia all'interno di quello esterno, e se non ci sono bordi intersecanti, significa che la condizione desiderata è soddisfatta.
Prova a fare un'intersezione di linea con ogni linea rossa. In pseudocodice:
// 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
}
Tuttavia, come puoi vedere, questa soluzione diventerà più lenta man mano che aggiungi più poligoni da controllare. Una soluzione diversa potrebbe essere:
Questa soluzione è molto veloce, ma dipende dalla tua implementazione (e da cosa vuoi fare con il risultato del tuo controllo) quale soluzione funziona meglio per te.