Como posso saber se um objeto está se movendo no sentido horário ou anti-horário ao redor de um caminho conectado?

19

Digamos que temos uma forma irregular:

shape0

E duas criaturas se movendo ao longo de seu contorno.

Depois, suavizamos completamente a forma puxando os cantos para fora.

Temos isso:

suave

É fácil ver agora que a Orange está se movendo no sentido horário e no sentido anti-horário verde. Como posso saber em que direção eles estão se movendo sem suavizar a forma?

Nova imagem

insira a descrição da imagem aqui

wolfdawn
fonte
Aqui é meus 2 centavos: i.imgur.com/zrBdw.png
Kendall Frey

Respostas:

27

Desenhe uma linha até o infinito e conte quantas vezes você cruza a forma (par ou ímpar), sem contar o segmento em que a criatura está. Depois verifique se a criatura está indo para a esquerda ou direita dessa linha.

exemplo

Neste exemplo, cruzamos a forma duas vezes (até mesmo) e vamos para a esquerda. O resultado é imediato nesta tabela:

   # Crosses | even  | odd
  Direction  |       |
-------------+-------+------
    left     | CCW   |  CW
    right    |  CW   | CCW

No pseudocódigo:

x, y = position of creature
vx, vy = direction of creature movement
crossings = 0
for each x1, y1, x2, y2 in shape segments:
    if (x1 < x and x <= x2) or (x2 < x and x <= x1):
        if y - y1 > (x - x1) * (y2 - y1) / (x2 - x1):
            ++crossings
if (crossings & 1) == (vx < 0):
    return CW
else
    return CCW
sam hocevar
fonte
você inclui a criatura da linha seguindo em frente?
precisa saber é o seguinte
@ Gajoo: não, daí o> em vez de> = na linha 6. Vou adicionar uma observação sobre isso. Mas observe que você pode incluir a linha e reverter o conteúdo da tabela.
Sam Hocevar
1
Eu estava começando a dar uma resposta com base nesse método e a resposta que dei. Fico feliz que tenhamos as duas abordagens representadas aqui. Este é conceitualmente mais simples e muito elegante, mas requer a execução de testes de interseção de segmentos de linha, o que pode ser complicado para ser robusto.
Trevor Powell
@TrevorPowell True. Encontrar a extremidade mais distante pode ser confuso. Eu verifiquei primeiro com base no vértice mais distante da aresta e depois desenhei uma linha do centro da forma e através dos centros das duas arestas (as duas que compartilham o vértice) e ver se uma das linhas cruza outra aresta no caminho para infinito depois de cruzar uma dessas arestas. Funcionou tudo bem
wolfdawn 8/12
5

Depende das informações disponíveis na estrutura de dados da forma, mas uma criatura que se move no sentido horário ao longo do contorno de uma forma sempre terá o interior da forma à direita e uma criatura que se move no sentido anti-horário terá o interior da forma. à esquerda.

Jeff
fonte
Uma solução muito mais simples, e também o meu primeiro pensamento.
usar o seguinte comando
como você sabe qual direção está dentro da forma? Quero dizer, mover-se ao longo de uma borda dentro da forma está à sua esquerda ou à sua direita. como você sabe para que lado é?
precisa saber é o seguinte
Uma solução muito elegante, mas não verdadeira em geral. Imagine uma rosquinha, achatada sobre uma mesa para criar uma forma bidimensional. Você pode caminhar ao longo da borda desta forma, manter o interior da forma à sua esquerda e fazer uma volta no sentido horário ou anti-horário, dependendo de onde você começou.
Marcks Thomas
4
  1. Calcule o ponto central da sua forma.
  2. Escolha a borda mais distante da sua forma do centro.
    • (Escolher a aresta mais distante garante que você não comece a partir de uma parte invertida e côncava da forma, o que resultaria em obter a determinação no sentido horário / anti-horário para trás em toda a forma)
  3. Determine qual direção ao longo dessa borda é no sentido horário
    • (Uma implementação simples disso envolveria a comparação dos ângulos do centro da forma para cada extremidade da aresta selecionada. O sinal da diferença entre os ângulos indicará o seu sentido horário versus anti-horário)
  4. Itere sobre todas as arestas da forma, começando pela aresta que você escolheu na etapa 2, criando uma lista de arestas. Para cada aresta, armazene seus dois vértices no sentido horário.
    • (Se sua forma não estiver mudando com o tempo, você poderá armazenar esta lista de arestas para uso posterior, para não precisar executar as quatro primeiras etapas a cada quadro)
    • (você já pode ter uma lista de arestas. Nesse caso, pode armazenar esta ordem de vértice no sentido horário na mesma lista.)
  5. Para determinar se uma entidade está se movendo no sentido horário ou anti-horário:
    • Determine qual borda a entidade está se movendo.
    • Faça um produto escalar da direção de movimento da entidade em relação ao vetor a partir dos vértices inicial-> final dessa borda, que você determinou na etapa 4.
    • Se o resultado do produto escalar for um valor maior que zero, a entidade estará se movendo no sentido horário. Menos que zero significa no sentido anti-horário.
Trevor Powell
fonte
Resposta muito inteligente
wolfdawn 7/07
Eu tenho uma pequena pergunta? assumindo que os vértices em sua forma são numerados a partir do ponto mais à esquerda do CWW, com base na sua resposta, como posso saber se a mudança de 6-> 7 ou 9-> 10 (com base em zero) está se movendo no sentido horário?
precisa saber é o seguinte
Você começa com a extremidade mais distante e descobre qual o caminho no sentido horário nessa extremidade. Digamos que a aresta A esteja no sentido horário do vértice 'a' a 'b'. Então, se passarmos para a aresta B (que possui os vértices 'b' e 'c'), sabemos que B é no sentido horário de 'b' a 'c'. Da mesma forma, a aresta C será no sentido horário de 'c' a 'd'. Uma vez que conhecemos a direção correta no sentido horário a partir de uma aresta (etapas 1 a 3), continuando nessa direção no sentido horário em torno das bordas da forma, podemos deduzir a direção correta no sentido horário para cada aresta, sem realmente observar onde suas arestas estão localizadas, então concavidade está ok.
Trevor Powell
como você pode saber se a aresta A está no sentido horário de 'a' a 'b' ou se está no sentido horário de 'b' a 'a'? Eu acho que você perdeu essa parte.
Ali1S232 23:00
@ Gajoo Esse é o ponto entre parênteses na etapa 3. Provavelmente não deve ser entre parênteses, pois é realmente a etapa crítica de todo o processo.
Trevor Powell
2

Você precisa saber para que lado o polígono está definido, qual o sentido dos vértices.

Se você não sabe disso, pode resolvê-lo calculando a área do polígono:

float Polygon::area() {
    float result = 0.0f;

    for(int a = 0; a < vertexCount; a ++) {
        int b = (a+1) % vertexCount;
        result += vertices[a].x * vertices[b].y;
        result -= vertices[a].y * vertices[b].x;
    }

    return result * .5f;
}

O sinal do resultado (positivo ou negativo) indica se é no sentido horário ou anti-horário. Você precisa tentar isso para ver qual o caminho que é melhor para você, porque depende do seu sistema de coordenadas.

Se a forma for no sentido horário:

  • Uma criatura que avança em volta da forma está girando no sentido horário , e
  • Uma criatura que gira para trás na forma está girando no sentido anti-horário .

Se a forma estiver no sentido anti-horário:

  • Uma criatura que avança em volta da forma está girando no sentido anti-horário , e
  • Uma criatura que gira para trás na forma está girando no sentido horário .
Chris Burt-Brown
fonte
0

Parece que Trevor já abordou esta questão, mas aqui está a minha solução:

  1. calcular a área que sua forma cobre, significando

    area = 0
    foreach (edge in shape)
        area += edge.begin.x * edge.end.y - edge.begin.y * edge.end.x
  2. usando a área calculada como acima, você pode facilmente saber se a forma em si é no sentido horário ou não. é no sentido horário apenas se a área estiver abaixo de zero.

  3. verifique se os objetos estão se movendo da mesma maneira que os vértices estão em ordem ou na direção oposta.

Ali1S232
fonte
Relacionados: stackoverflow.com/questions/1165647/...
Trevor Powell