Existe um algoritmo para classificar uma matriz de pontos 2D no sentido horário?
Estou lidando especificamente com o triângulo retângulo no meu caso, então apenas 3 pontos.
No entanto, estou interessado em saber se existe um algoritmo, se não, o que é uma maneira simples de retornar os 3 pontos do meu triângulo no sentido horário?
Edit: Estou tentando calcular os pontos no sentido horário em relação ao centróide do polígono, que é convexo.
Atualização: Esta é a implementação que acabei usando com base na resposta escolhida, não é crítica para o desempenho e acontece apenas de vez em quando, por isso funciona.
ArrayList<PVector> pointList = new ArrayList<PVector>();
pointList.add(A);
pointList.add(B);
pointList.add(C);
Collections.sort( pointList, new TriangleVectorComparator(origin) );
return pointList;
// Comparator
package triangleeditor;
import java.util.Comparator;
import processing.core.PVector;
public class TriangleVectorComparator implements Comparator<PVector> {
private PVector M;
public TriangleVectorComparator(PVector origin) {
M = origin;
}
public int compare(PVector o1, PVector o2) {
double angle1 = Math.atan2(o1.y - M.y, o1.x - M.x);
double angle2 = Math.atan2(o2.y - M.y, o2.x - M.x);
//For counter-clockwise, just reverse the signs of the return values
if(angle1 < angle2) return 1;
else if (angle2 < angle1) return -1;
return 0;
}
}
2d
mathematics
algorithm
onedayitwillmake
fonte
fonte
Respostas:
Sua pergunta não é precisa o suficiente. Uma matriz de pontos é apenas «horário» ou «anti-horário» em relação a um ponto de referência. Caso contrário, qualquer matriz de três pontos sempre pode ser CW ou CCW. Veja a figura a seguir: à esquerda, os pontos são ordenados no sentido horário; à direita, os mesmos pontos são ordenados no sentido anti-horário.
No seu caso, acredito que usar o baricentro dos pontos como ponto de referência é razoável.
Um bom método para um número desconhecido de pontos pode ser o seguinte:
P[0], P[1], ... P[n-1]
ser a lista de pontos para classificara[0], a[1], ... a[n-1]
tal quea[i] = atan2(P[i].y - M.y, P[i].x - M.x);
a
valor, usando,qsort
por exemplo.No entanto, você pode ter certeza de que um bom algoritmo de classificação terá um desempenho ruim com três valores de entrada em comparação com um método ad-hoc. O uso
atan2
ainda é válido, mas não useqsort
.fonte
qsort
aqui é pequeno em comparação comatan2
.Acredito que o que você está realmente perguntando aqui é a ordem de enrolamento do triângulo, que na verdade é bem simples de testar.
Como existem apenas três pontos em seu triângulo, seu triângulo já está no sentido horário ou anti-horário; portanto, tudo o que você precisa fazer é verificar qual desses dois é e reverter a ordem dos índices, se o enrolamento não é o que você quer.
Aqui é a idéia geral, assumindo que os três vértices de um triângulo são a , b e c , e que você tem uma operação simples vetor subtração:
Observe que, dependendo de como você orientou seu eixo + y (para cima ou para baixo), os casos "horário" e "anti-horário" podem ser revertidos da maneira como os rotulei nos comentários neste código de exemplo.
fonte
Você pode dar mais informações? Você deseja a ordem de pontos no sentido anti-horário, mas que ponto deve ser o centro do pedido?
Se você tiver apenas um triângulo (3 pontos) no plano, poderá calcular o determinante a partir da matriz, onde as linhas são coordenadas dos pontos (a terceira coordenada é 1). Se o determinante for> 0, os pontos estão na ordem anti-horário. Caso contrário, você pode trocar, por exemplo, os últimos dois pontos e receberá a ordem no sentido anti-horário.
Se você possui pontos A, B, C, sua matriz se parece com:
O determinante é: xA * yB + xB * yC + xC * yA - yB * xC - yC * xA - yA * xB. Então você pode compará-lo com zero. Se for> 0, retorne os pontos A, B, C, se não for, retorne A, C, B.
Se você definiu pontos e sabe, eles fazem polígono convexo (todos fazem parte do casco convexo) e desejam obter seu pedido, você pode usar Graham Scan ou March of Jarvis (estes são algoritmos para encontrar casco convexo de muitos pontos, mas também deve funcionar aqui :))
fonte