A ideia chave no algoritmo de Graham é a seguinte: a determinação dos pontos extremos pode ser feita de modo eficiente se os pontos p1, p2, ..., pn tiverem sido previamente ordenados polarmente em torno de um ponto interior ao seu fecho convexo. No caso da minha implementação, foi utilizada pseudo-ângulo em quadrado unitário para realizar essa ordenação polar.
O polígono p1, ..., pn possui a propriedade de que existe um ponto interno (o) que vê cada vértice do polígono. Desta forma, a etapa de ordenação reduz o problema de encontrar o fecho convexo de {p1, p2, ..., pn} ao problema de encontrar o fecho convexo de um polígono estrelado. O problema se resume em determinar quais do pontos de C são efetivamente vértices do fecho.
Tendo o polígono estrelado P = p1p2...pn, determinamos o fecho convexo testando se o ângulo interno em cada pi é convexo. Em caso afirmativo, o polígono estrelado é convexo. Caso contrário, removemos de P o ponto pi que viola a condição de convexidade e repetimos o teste para o novo polígono estrelado. O processo continua até que todos os pontos restantes determinem ângulo convexos.
Entretanto, o algoritmo implementado tem algumas alterações: ele não volta à estaca zero cada vez que um ponto pi é retirado do conjunto C.
1. Determina-se o vértice de maior abscissa (suponha que seja p1).
2. O algoritmo examina sucessivamente os vértices p2, p3, ..., até encontrar um pi para o qual o ângulo interno correspondente não seja convexo. Neste ponto, ao invés de recomeçar todo o processo, observamos que a remoção de pi afeta apenas o teste de convexidade do vértice imediatamente anterior.
3. Se o ângulo pi-2pi-1pi+1 continuar sendo convexo, o algoritmo pode continuar, examinando o ângulo em pi+1. Se o ângulo em pi-1 for côncavo, pi-1 é eliminado e o ângulo em seu predecessor reavaliado.
Pseudo-código
Algoritmo de Graham
pn+1 = p1 //feche o ciclo
q1 = p1 //p1 é um ponto do fecho convexo
q2 = p2 //inclua p2 tentativamente
h = 2
para i = 3..n+1
enquanto h > 1 e o ângulo entre qh-1, qh e pi não for convexo
h = h - 1 //remova qh
h = h + 1
qh = pi //inclua pi tentativamente
Ao final, q conterá os h vértices do fecho convexo.
Desta forma, o algoritmo consiste em ordenar polarmente os pontos de C (O(log n)) e aplicar o algoritmo de Graham (O(n)). Portanto, obtemos o fecho convexo em tempo O(n log n). O algoritmo, portanto, é ótimo para FC2D.
Interface do programa que implementa o algoritmo de Graham:
Demonstração:
Obtenha o código aqui (arquivo protegido por senha): https://dl.dropboxusercontent.com/u/21447748/ConvexHull.rar