Classificação da matriz de pontos no sentido horário

16

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;
    }

}
onedayitwillmake
fonte
1
return pode ser return angle1 <angle2? 1: ângulo2> ângulo1? -1: 0;
ademar111190
2
Pode ser expresso de várias maneiras, mas eu costumo evitar operadores ternários aninhados, especialmente quando dou exemplos.
Onedayitwillmake
@onedayitwillmake Você poderia mover o código que acabou usando para uma resposta? Realmente não pertence à questão, mas é muito valioso para futuros leitores.
Anko6 /
@ Anko, acho que você está certo, mas ao mesmo tempo acho que será mais fácil para as pessoas encontrarem dessa maneira. Também ajuda a garantir que eu não retire a resposta do samhocevar na qual a minha é simplesmente baseada.
Onedayitwillmake

Respostas:

19

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 sentido horário ou 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:

  • deixe P[0], P[1], ... P[n-1]ser a lista de pontos para classificar
  • seja M o baricentro de todos os pontos
  • calcular a[0], a[1], ... a[n-1]tal quea[i] = atan2(P[i].y - M.y, P[i].x - M.x);
  • classificar pontos em relação ao seu avalor, usando, qsortpor 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 atan2ainda é válido, mas não use qsort.

sam hocevar
fonte
Isso funcionou perfeitamente :)
onedayitwillmake 6/06
1
Este método tem um nome?
Onedayitwillmake
1
Eu acredito que isso é chamado simplesmente de "ordenação por ângulo polar". É um componente do Graham Scan , por exemplo.
sam hocevar 6/06/11
O desempenho qsortaqui é pequeno em comparação com atan2.
Aviso pequeno: Isso poderá travar e queimar (dependendo da linguagem de programação e das bibliotecas usadas) se algum dos pontos estiver exatamente no baricentro (ou em qualquer outro ponto de orientação que você usar). Você pode excluir esses pontos entre a segunda e a terceira etapa.
Martin Sojka
3

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:

Vector2 AToB = b - a;
Vector2 BToC = c - b;
float crossz = AToB.x * BToC.y - AToB.y * BToC.x;
if ( crossz > 0.0f )
{
  // clockwise
}
else
{
  // counter-clockwise.  Need to reverse the order of our vertices.
}

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.

Trevor Powell
fonte
Preciso passar esses pontos para o Box2D (implementação em java) para criar um polígono. embora não seja o que eu estava perguntando, muito bom insight :)
onedayitwillmake
2

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:

|xA, yA, 1|
|xB, yB, 1|
|xC, yC, 1|

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 :))

zacharmarz
fonte
para concluir o que zacharmarz disse, se você apenas deseja classificar seus pontos no sentido horário em torno de um ponto específico, é possível criar uma matriz a partir de pares de ponto flutuante e ponto em que você armazena todos os pontos com seu ângulo de correspondência de cores a partir desse ponto específico e depois classifica essa matriz.
precisa saber é o seguinte