Pergunta

Estou olhando para uma maneira simples e programática de detectar se o usuário desenhou ou não uma forma circular. Estou trabalhando em C, mas estou feliz em trabalhar com pseudo-código. Um pouco de pesquisa no Google traz vários métodos (esperançosamente) de complexos excessivos.

Estou rastreando as coordenadas do mouse como carros alegóricas e criei uma variedade de vetores para rastrear o movimento do mouse ao longo do tempo. Essencialmente, pretendo detectar quando um círculo foi desenhado e, em seguida, desmoga todos os dados de movimento que não estão associados a esse círculo.

Eu tenho uma ideia básica de como isso pode ser realizado:

Acompanhe todos os movimentos usando uma função de pesquisa. Cada vez que a função é pesquisada, a posição atual do mouse é armazenada. Aqui, percorremos os dados históricos da posição e fazemos um 'snap para posicionar' para comparar os dois locais. Se o novo local estiver a uma distância suficientemente próxima a uma posição antiga, removemos todos os dados históricos antes do local antigo.

Embora isso funcione em teoria, é uma bagunça na prática. Alguém tem alguma sugestão? Pontos de bônus se o método sugerido puder detectar se ele foi desenhado no sentido horário ou no sentido anti-horário.

Foi útil?

Solução

Com base na sua função de rastreamento/votação, que empurra os pares de flutuação em uma pilha. Isso deve ser feito em um intervalo de tempo regular.

  1. Faça uma pesquisa baseada em limiar por duas entradas iguais na lista. Agora você tem dois índices em sua pilha; a primeira e a segunda entradas iguais. Considere isso como uma linha.
  2. Obtenha a diferença absoluta nos índices. Em seguida, divida por dois e obtenha as coordenadas deste ponto. (Centro da linha.)
  3. Você tem dois pontos: assim, você pode obter o raio do círculo, obtendo a distância entre os dois pontos divididos por dois.
  4. Divida o número de etapa 2 por 2, agora você tem os quartos.

    Se a linha na etapa 1 for vertical e o primeiro ponto da linha estiver na parte superior: se o primeiro trimestre for deixado do ponto central, o círculo será desenhado no sentido anti-horário. Se o primeiro trimestre estiver certo do ponto central, o círculo foi desenhado no sentido horário. Se o primeiro ponto da linha estiver na parte inferior, reversa (ou seja, CCW => CW e CW => CCW)

    Se a linha na etapa 1 for horizontal e o primeiro ponto da lista estiver à esquerda: se o primeiro trimestre estiver acima do ponto central, o círculo será desenhado no sentido anti-horário. Se o primeiro trimestre estiver abaixo do ponto central, o círculo foi desenhado no sentido horário. Se o primeiro ponto da linha estiver à direita, reverta.

  5. Verifique se era um círculo: itera sobre todos os pares de coordenadas e calcule a distância até o ponto central. Ajuste o limiar das distâncias permitidas da distância calculada e da distância real até o ponto central.

Nas etapas 2 e 4, você pode ajustar esse algoritmo adiante, levando a média de vários índices se o intervalo de tempo for muito baixo (pesquisa rápida). Por exemplo: existem 30 pares na matriz e você médio em pares em 0, 1 e 28, 29 para obter o ponto superior. Faça o mesmo para todos os outros pontos.

Espero que seja fácil o suficiente.

Outras dicas

Você está definitivamente no caminho certo IMHO. Basicamente, você precisa comparar cada ponto do mouse com o ponto anterior do mouse e calcular o ângulo entre eles (como previsto em um círculo unitário onde o primeiro ponto está na origem). Para isso, você pode usar a fórmula:

double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;

if (angle < 0)
    angle += 360;

O que você acaba é com o movimento no sentido horário, o ângulo pedalará em uma direção positiva, enquanto para o movimento do sentido anti -horário o ângulo percorrerá uma direção negativa. Você pode descobrir se o ângulo atual é maior ou menor que o anterior com a seguinte lógica:

if (angle2 > 270 && angle1 < 90)
{
    angle1 += 360
}
else if (angle1 > 270 && angle2 < 90)
{
    angle2 += 360
}

bool isPositive = (angle2-angle1 > 0);

Se você obtiver um certo número de vetores com ângulos que estão aumentando (ispositivo é verdadeiro, digamos, 10 vezes), você pode assumir que um círculo no sentido horário está sendo desenhado; Se a tendência for negativa (ispositiva é falsa 10 vezes), é um círculo no sentido anti -horário. :)

Não tentei isso, mas a ideia veio à mente lendo sua pergunta, então também poderia compartilhá -la com você:

Suponho que o círculo deve ser desenhado em um período de tempo razoável, dada uma "taxa de amostra" constante do mouse que deixaria uma matriz de tamanho conhecido de vetores 2D (pontos). Adicione todos eles e divida pela contagem de vetores 2D para obter uma estimativa do ponto "centro" da matriz. Em seguida, forme vetores deste ponto central para os pontos da matriz e faça produtos de pontos (normalizando pelo comprimento do vetor), certificando-se de que o sinal dos produtos de ponto permaneça idêntico para uma série de pontos significa que todos esses pontos se movem no mesmo Direção, um sinal positivo indicará o movimento no sentido anti-horário, negativo é exatamente o oposto. Se o ângulo acumulado exceder 2 pi, um movimento circular foi desenhado.

Boa sorte.

1 - Escolha qualquer 3 dos pontos

2 - Se os pontos forem colineares +/- 'algum buffer', não é um círculo.

3 - Use o método descrito na Wikipedia para encontrar o círculo circunscrito para um triângulo para encontrar o ponto médio e o raio do seu círculo candidato

O circuncentro de um triângulo pode ser construído desenhando dois dos três bissetores perpendiculares. Para três pontos não colineares, essas duas linhas não podem ser paralelas e o circuncenter é o ponto em que eles cruzam. Qualquer ponto da bissetor é equidistante dos dois pontos que ela corta, da qual se segue que esse ponto, em ambos os bissetores, é equidistante dos três vértices do triângulo. O circunradius é a distância dele para qualquer um dos três vértices.

4 - Verifique a distância para os pontos restantes. Se esses pontos estiverem dentro do 'raio do círculo candidato' +/- 'alguma subsídio de buffer', é um círculo.

5 - Para determinar a direção, basta calcular o ângulo entre o primeiro e o segundo pontos do ponto médio. Um ângulo negativo está certo. Um ângulo positivo é deixado. (Pode ser revertido dependendo do sistema de coordenadas que você está usando)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top