Aqui está uma solução baseada em vetor. Eu não tentei, mas parece bem conceitualmente.
Teoria
Acho que você armazenou a forma como segmentos de linha. Aqui está a letra A representada com três segmentos de linha.
Eu assumi que os caminhos no desenho do usuário são armazenados como listas de pontos.
Podemos "inflar" esses segmentos de linha para permitir uma margem de erro ao verificar a proximidade : se o caminho desenhado pelo usuário está próximo da margem de erro correta das linhas.
No entanto, isso por si só não é suficiente. Também precisamos verificar a cobertura : se o desenho do usuário "cobre" uma grande fração da forma. Esses desenhos são ruins, porque, mesmo que se encaixem na margem de erro, estão faltando parte da carta:
Se verificarmos as duas coisas, podemos aproximar se o desenho do jogador é bom.
Implementação
Verificar a proximidade significa apenas para cada ponto do caminho do usuário, encontrar a distância entre essa e todas as linhas que compõem a letra, obter a menor e verificar se é menor que a margem de erro.
Verificar a cobertura é mais complicado, mas é possível obter uma aproximação muito boa com a matemática vetorial se, para cada segmento de linha, você encontrar o caminho mais próximo desenhado pelo usuário (verde) e projetar suas partes (verde escuro) nesse segmento de linha (preto), em seguida, verifique se os vetores projetados (em azul) a cobrem:
Para projetar um vetor a
em outro vetor b
, faça
projection = dotProduct(a, b) / lengthSquared(b) * b
onde dotProduct
calcula o produto escalar dos dois vetores e lengthSquared
é o que parece. Essencialmente, isso encontra o valor escalar de quanto a
vai na b
direção e multiplica- b
o para obter um vetor na mesma direção. (O tutorial de detecção de colisão A da Metanet Software tem uma boa visualização disso na projeção do Apêndice A § ).
A direção do vetor projetado pode não ser realmente importante. Se você somar os comprimentos dos vetores projetados e compará-los com o comprimento total do segmento de linha, isso indicará qual fração é coberta. (Exceto em casos ímpares, consulte § Limitações abaixo).
Na imagem acima, o caminho abrangeria cerca da metade do segmento. Você pode escolher qualquer valor de tolerância que desejar.
Limitações
Letras curvas
Os segmentos de linha são sub-ideais: muitas letras são curvas! Como você representa um 'P' ou um 'O'?
Você pode usar muitos segmentos de linha (talvez com uma margem de erro maior).
Você também pode começar a usar curvas de Bézier em vez de linhas para um ajuste mais próximo, mas observe que encontrar o ponto mais próximo em um Bézier é muito mais complexo - assim como muitas outras operações de medição.
Incompatibilidades
Margens de tolerância excessivamente relaxadas quanto à distância das linhas e cobertura da carta podem ter conseqüências não intencionais.
Por exemplo, o jogador pode estar tentando desenhar um 'H' aqui.
Loops e sobreposições
Loops ou sobreposições no caminho desenhado pelo jogador podem resultar em algumas partes do desenho sendo contadas duas vezes ao projetá-las no segmento de linha mais próximo.
Isso poderia ser contornado através do processamento mais sofisticado dos vetores projetados, talvez armazenando exatamente onde o vetor projetado seria (armazene também a direção da projeção e o ponto mais próximo do segmento de linha ao ponto da linha desenhada pelo jogador) , rejeitando os novos que se sobrepõem.
Se o jogador desenhasse um único caminho e este fosse processado a partir do final marcado com o círculo azul, as partes verdes desse caminho seriam aceitas e as vermelhas rejeitadas, porque sua projeção se sobrepunha a algumas partes processadas anteriormente.
A implementação possui muitas sutilezas técnicas que provavelmente pertenceriam a uma pergunta diferente.
Jogadores imprevisivelmente aventureiros
Um jogador pode desenhar algo estranho que ainda passa .
Embora você possa chamar isso de recurso! :)