Ecco una soluzione basata su vettori. Non l'ho provato, ma concettualmente sembra bene.
Teoria
Ho capito che hai memorizzato la forma come segmenti di linea. Ecco la lettera A rappresentata con tre segmenti di linea.
Ho assunto che i percorsi nel disegno dell'utente siano memorizzati come elenchi di punti.
Possiamo "gonfiare" quei segmenti di linea per consentire un margine di errore quando si verifica la vicinanza : se il percorso disegnato dall'utente è vicino al margine di errore di linee corretto.
Tuttavia, questo da solo non è abbastanza. Dobbiamo anche verificare la copertura : se il disegno dell'utente "copre" gran parte della forma. Questi disegni sono sbagliati, perché anche se rientrano nel margine di errore, mancano alcune parti della lettera:
Se controlliamo entrambe queste cose, possiamo approssimare se il disegno del giocatore è buono.
Implementazione
Controllare la vicinanza significa solo per ogni punto del percorso dell'utente, trovare la distanza tra quella e ogni linea che compone la lettera, prendere il minimo e verificare che sia inferiore al margine di errore.
Il controllo della copertura è più complicato, ma puoi ottenere un'approssimazione molto buona con la matematica vettoriale se per ogni segmento di linea, trovi il percorso disegnato dall'utente più vicino (verde) e proietti le sue parti (verde scuro) su quel segmento di linea (nero), quindi controlla quanto bene coprono i vettori proiettati (blu):
Per proiettare un vettore a
su un altro vettore b
, fare
projection = dotProduct(a, b) / lengthSquared(b) * b
dove dotProduct
calcola il prodotto punto dei due vettori ed lengthSquared
è quello che sembra. In sostanza, questo trova il valore scalare di quanto a
va nella b
direzione e si moltiplica b
per quello per ottenere un vettore nella stessa direzione. (Il tutorial A sul rilevamento delle collisioni del software Metanet ha una buona visualizzazione di questo nell'Appendice A § proiezione .)
La direzione del vettore proiettato potrebbe in realtà non essere importante. Se sommi semplicemente le lunghezze dei vettori proiettati e le confronti con la lunghezza totale del segmento di linea, ciò ti dirà quale frazione di esso è coperta. (Tranne in casi dispari, vedere § Limitazioni di seguito).
Nell'immagine sopra, il percorso coprirebbe circa la metà del segmento. È possibile selezionare qualsiasi valore di tolleranza desiderato.
limitazioni
Lettere curve
I segmenti di linea non sono ideali: molte lettere sono curve! Come si rappresenta una 'P' o una 'O'?
È possibile utilizzare molti segmenti di linea (magari con un margine di errore maggiore).
È inoltre potrebbe iniziare a usare le curve di Bézier , invece di linee per una calzata più stretta, ma nota che trovare il punto più vicino su un Bézier è molto più complessa, come molte altre operazioni di misurazione.
disallineamenti
I margini di tolleranza troppo rilassati per la distanza dalle linee e la copertura della lettera potrebbero avere conseguenze indesiderate.
Ad esempio, il giocatore potrebbe aver provato a disegnare una "H" qui.
Anelli e sovrapposizioni
I loop o le sovrapposizioni nel percorso disegnato dal giocatore potrebbero comportare il conteggio di alcune parti del disegno due volte quando vengono proiettate sul segmento di linea più vicino.
Questo potrebbe essere aggirato eseguendo elaborazioni più elaborate sui vettori proiettati, magari memorizzando esattamente dove sarebbe il vettore proiettato (memorizzare anche la direzione della proiezione e il punto più vicino sul segmento di linea al punto sulla linea disegnata dal giocatore) , quindi rifiutando quelli nuovi che si sovrappongono.
Se il giocatore ha tracciato un singolo percorso ed è stato elaborato a partire dalla fine segnata con il cerchio blu, le parti verdi di quel percorso sarebbero accettate e quelle rosse rifiutate, perché la loro proiezione si sovrapponerebbe con alcune parti elaborate prima.
L'implementazione ha molte sottigliezze tecniche che probabilmente rientrerebbero in una domanda diversa.
Giocatori imprevedibilmente avventurosi
Un giocatore potrebbe pescare qualcosa di strano che ancora passa .
Anche se potresti chiamarlo una caratteristica! :)