Aquí hay una solución basada en vectores. No lo he probado, pero parece estar bien conceptualmente.
Teoría
Supongo que has almacenado la forma como segmentos de línea. Aquí está la letra A representada con tres segmentos de línea.
Supuse que las rutas en el dibujo del usuario se almacenan como listas de puntos.
Podemos "inflar" esos segmentos de línea para permitir un margen de error al verificar la proximidad : si la ruta dibujada del usuario está cerca del margen de error de las líneas correctas.
Sin embargo, eso solo no es suficiente. También tenemos que verificar la cobertura : si el dibujo del usuario "cubre" una gran fracción de la forma. Estos dibujos son malos, porque a pesar de que se ajustan al margen de error, les falta parte de la letra:
Si verificamos ambas cosas, podemos aproximarnos si el dibujo del jugador es bueno.
Implementación
Verificar la cercanía solo significa para cada punto de ruta del usuario, encontrar la distancia entre esa y cada línea que forma la letra, tomar la más baja y verificar que sea menor que el margen de error.
Verificar la cobertura es más complicado, pero puede obtener una muy buena aproximación con las matemáticas vectoriales si para cada segmento de línea, encuentra la ruta dibujada por el usuario más cercana (verde) y proyecta sus partes (verde oscuro) en ese segmento de línea (negro), luego verifique qué tan bien lo cubren los vectores proyectados (azul):
Para proyectar un vector a
sobre otro vector b
, haga
projection = dotProduct(a, b) / lengthSquared(b) * b
donde dotProduct
calcula el producto punto de los dos vectores y lengthSquared
es lo que parece. Básicamente, esto encuentra el valor escalar de cuánto a
va en b
la dirección y se multiplica b
por eso para obtener un vector en la misma dirección. (El tutorial de detección de colisión de Metanet Software A tiene una buena visualización de esto en el Apéndice A § proyección ).
La dirección del vector proyectado podría no ser realmente importante. Si solo suma las longitudes de los vectores proyectados y los compara con la longitud total del segmento de línea, eso le indicará qué fracción está cubierta. (Excepto en casos extraños, ver § Limitaciones a continuación).
En la imagen de arriba, la ruta cubriría aproximadamente la mitad del segmento. Puede elegir cualquier valor de tolerancia que desee.
Limitaciones
Letras curvas
Los segmentos de línea son sub ideal: ¡muchas letras son curvas! ¿Cómo se representa una 'P' o una 'O'?
Podría usar muchos segmentos de línea (tal vez con un margen de error mayor).
También podría comenzar a usar curvas de Bézier en lugar de líneas para un ajuste más cercano, pero tenga en cuenta que encontrar el punto más cercano en un Bézier es mucho más complejo, al igual que muchas otras operaciones de medición.
Desajustes
Los márgenes de tolerancia demasiado relajados para la distancia de las líneas y la cobertura de la carta podrían tener consecuencias no deseadas.
Por ejemplo, el jugador podría haber estado tratando de dibujar una 'H' aquí.
Bucles y superposiciones
Los bucles o superposiciones en la ruta dibujada por el jugador pueden hacer que algunas partes del dibujo se cuenten dos veces al proyectarlas en el segmento de línea más cercano.
Esto podría solucionarse haciendo un procesamiento más elegante en los vectores proyectados, tal vez almacenando exactamente dónde estaría el vector proyectado (almacene también la dirección de la proyección y el punto más cercano en el segmento de línea al punto en la línea dibujada por el jugador) , luego rechaza los nuevos que se superponen.
Si el jugador dibujó un solo camino y se procesó comenzando en el extremo marcado con el círculo azul, las partes verdes de ese camino serían aceptadas y las rojas rechazadas, porque su proyección se superpondría con algunas partes procesadas anteriormente.
La implementación tiene muchas sutilezas técnicas que probablemente pertenecerían a una pregunta diferente.
Jugadores aventureros impredecibles
Un jugador puede dibujar algo extraño que todavía pasa .
¡Aunque podrías llamar a eso una característica! :)