Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lucas.philippe.etu/philippe-iihm
1 result
Show changes
Commits on Source (3)
No preview for this file type
......@@ -3,3 +3,4 @@ import os
DATA_DIR = os.path.dirname(os.path.abspath(__file__))
LAYOUT_FILE = os.path.join(DATA_DIR, 'layout.json')
MOTS_FILE = os.path.join(DATA_DIR, 'mots.txt')
......@@ -14,8 +14,8 @@
{ "symbol": "i", "x" : 7, "y" : 1, "width": 1 },
{ "symbol": "o", "x" : 8, "y" : 1, "width": 1 },
{ "symbol": "p", "x" : 9, "y" : 1, "width": 1 },
{ "symbol": "q", "x" : 1, "y" : 2, "width": 1 },
{ "symbol": "s", "x" : 0, "y" : 2, "width": 1 },
{ "symbol": "q", "x" : 0, "y" : 2, "width": 1 },
{ "symbol": "s", "x" : 1, "y" : 2, "width": 1 },
{ "symbol": "d", "x" : 2, "y" : 2, "width": 1 },
{ "symbol": "f", "x" : 3, "y" : 2, "width": 1 },
{ "symbol": "g", "x" : 4, "y" : 2, "width": 1 },
......@@ -24,16 +24,15 @@
{ "symbol": "k", "x" : 7, "y" : 2, "width": 1 },
{ "symbol": "l", "x" : 8, "y" : 2, "width": 1 },
{ "symbol": "m", "x" : 9, "y" : 2, "width": 1 },
{ "symbol": "q", "x" : 1, "y" : 2, "width": 1 },
{ "symbol": "⇧", "x" : 0, "y" : 3, "width": 2 },
{ "symbol": "⇧", "x" : 0, "y" : 3, "width": 2 },
{ "symbol": "w", "x" : 2, "y" : 3, "width": 1 },
{ "symbol": "x", "x" : 3, "y" : 3, "width": 1 },
{ "symbol": "c", "x" : 4, "y" : 3, "width": 1 },
{ "symbol": "v", "x" : 5, "y" : 3, "width": 1 },
{ "symbol": "b", "x" : 6, "y" : 3, "width": 1 },
{ "symbol": "n", "x" : 7, "y" : 3, "width": 1 },
{ "symbol": "⇦", "x" : 8, "y" : 3, "width": 2 },
{ "symbol": "", "x" : 8, "y" : 3, "width": 2 },
{ "symbol": " ", "x" : 0, "y" : 4, "width": 8 },
{ "symbol": "↵", "x" : 8, "y" : 4, "width": 2 }
{ "symbol": "", "x" : 8, "y" : 4, "width": 2 }
]
}
\ No newline at end of file
This diff is collapsed.
......@@ -4,6 +4,12 @@ class Key:
def __init__(self, x, y, keyWidth, keyHeight, keySpacing, width, symbol):
self.x = x * (keyWidth + keySpacing)
self.y = y * (keyHeight + keySpacing)
self.position = QPoint(self.x, self.y)
self.symbol = symbol
self.rect = QRect(self.x, self.y, width * (keyWidth + keySpacing) - keySpacing, keyHeight)
self.rect = QRect(self.x, self.y, (width * (keyWidth + keySpacing) - keySpacing), keyHeight)
def isOver(self, point):
adjustedRect = self.rect.adjusted(5, 5, -5, -5)
return adjustedRect.contains(point)
def getCenter(self):
return self.rect.center()
class Mot:
def __init__(self, word: str, stroke: list, distance: int):
self.word = word
self.stroke = stroke
self.distance = distance
class Dictionnaire:
def __init__(self):
self.words = dict()
for letter in list(map(chr, range(97, 123))):
self.words[letter] = []
def addWord(self, word: str, stroke: list, distance: int):
# get first letter of word
letter = word[0]
self.words[letter].append(Mot(word, stroke, distance))
import numpy as np
def find_distance(s, t):
len_s, len_t = len(s), len(t)
DTW = np.zeros((len_s + 1, len_t + 1))
DTW[1:, 0] = np.inf
DTW[0, 1:] = np.inf
for i in range(1, len_s + 1):
for j in range(1, len_t + 1):
cost = abs(s[i - 1][1] - t[j - 1][1]) + abs(s[i - 1][0] - t[j - 1][0])
min_val = min(DTW[i - 1, j], DTW[i, j - 1], DTW[i - 1, j - 1])
DTW[i, j] = cost + min_val
return DTW[len_s, len_t]
class DwtAlgo:
def __init__(self, nb_of_words, dictionary):
self.nb_of_words = nb_of_words
self.dictionary = dictionary
def compare_to_dictionary(self, s, first_letter):
min_distances = [np.inf] * self.nb_of_words
best_words = [None] * self.nb_of_words
for template in self.dictionary.words[first_letter]:
distance = find_distance(s, template.stroke)
for i in range(3):
if distance < min_distances[i]:
min_distances[i+1:] = min_distances[i:-1]
min_distances[i] = distance
best_words[i+1:] = best_words[i:-1]
best_words[i] = template.word
break
return best_words
import math
def interpolate(a, b, d):
ax, ay = a
bx, by = b
ab_dist = math.sqrt((bx - ax) ** 2 + (by - ay) ** 2)
ratio = d / ab_dist
return ax + ratio * (bx - ax), ay + ratio * (by - ay)
def resample(stroke, d):
if not stroke:
return []
resampled = [stroke[0]]
remaining_distance = d
for i in range(1, len(stroke)):
current_point = stroke[i - 1]
next_point = stroke[i]
distance = math.sqrt((next_point[0] - current_point[0]) ** 2 + (next_point[1] - current_point[1]) ** 2)
if (distance >= remaining_distance):
new_point = interpolate(current_point, next_point, remaining_distance)
resampled.append(new_point)
stroke.insert(i, new_point)
remaining_distance = d
else:
remaining_distance -= distance
return resampled
from PyQt5.QtWidgets import QWidget, QLineEdit, QVBoxLayout
from src.widgets.KeyboardWidget import KeyboardWidget
# from PySide6.QtCore import Slot # This line might not be necessary unless you're using it elsewhere
class EditeurWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Editeur')
# Création des widgets
line_edit = QLineEdit(self)
# Define line_edit as an attribute of the class
self.line_edit = QLineEdit(self)
keyboard_widget = KeyboardWidget()
# Création du layout et ajout des widgets
layout = QVBoxLayout()
layout.addWidget(line_edit)
layout.addWidget(self.line_edit) # Use self.line_edit here
layout.addWidget(keyboard_widget)
self.setLayout(layout)
\ No newline at end of file
self.setLayout(layout)
# Connexion du signal
keyboard_widget.newletter.connect(self.addCharacter)
def addCharacter(self, character):
currentText = self.line_edit.text() # This should work now
# Add a space only if "character" is more than one letter (meaning it's a word)
if len(character) > 1:
newText = currentText + character + ' '
else:
newText = currentText + character
self.line_edit.setText(newText)
import json
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import Qt, QSize, QPoint, pyqtSignal
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtWidgets import QWidget
from documents.FileDefinition import LAYOUT_FILE
from documents.FileDefinition import LAYOUT_FILE, MOTS_FILE
from src.model.Key import Key
from src.module.Dictionnaire import Dictionnaire
from src.module.Dwt_algo import DwtAlgo
from src.module.Reconnaisseur import resample
DEFAULT_COLOR = QColor("white")
OVER_COLOR = QColor("gray")
PEN_COLOR = QColor(0, 0, 255, 128)
PEN_COLOR2 = QColor(255, 0, 0, 255)
PEN_WIDTH = 5
WordSelectorHeight = 0
distanceStroke = 50
class KeyboardWidget(QWidget):
newletter = pyqtSignal(str)
def __init__(self):
super().__init__()
self.dwt = None
self.letter_selected = None
self.keys = []
self.keyWidth = None
self.keyHeight = None
......@@ -17,9 +35,27 @@ class KeyboardWidget(QWidget):
self.keyboardWidth = 0
self.keyboardHeight = 0
self.trace = []
self.resampledTrace = []
self.nbReco = 0
self.mousePos = QPoint(0,0)
self.pressedKey = None
self.wordSelectors = []
# Initialiser le clavier
self.loadLayoutJson()
self.setMouseTracking(True)
# Initialiser le dictionnaire
self.dictionnaire = Dictionnaire()
self.initDictionnaire()
# Initialiser le wordSelector
self.initWordSelector()
self.update()
def loadLayoutJson(self):
......@@ -29,6 +65,7 @@ class KeyboardWidget(QWidget):
# Accéder aux paramètres
self.nbReco = layout_clavier['nbReco']
self.keyWidth = layout_clavier['keyWidth']
self.keyHeight = layout_clavier['keyHeight']
self.keySpacing = layout_clavier['keySpacing']
......@@ -37,8 +74,29 @@ class KeyboardWidget(QWidget):
for keyData in layout_clavier['keys']:
self.keys.append(self.createKey(keyData))
# Créer les touches de selection de mot
# word_selector_key_width = 10 / self.nbReco
word_selector_key_width = 2.5
print(word_selector_key_width)
for i in range(self.nbReco):
key = Key(i * word_selector_key_width, 0, self.keyWidth, self.keyHeight, self.keySpacing, word_selector_key_width, '')
self.wordSelectors.append(key)
self.keys.insert(0, key)
def initWordSelector(self):
self.dwt = DwtAlgo(self.nbReco, self.dictionnaire)
def initDictionnaire(self):
with open(MOTS_FILE, "r") as file:
lines = file.readlines()
for line in lines:
word = line.strip()
self.wordToStroke(word, distanceStroke)
def createKey(self, keyData):
key = Key(keyData['x'], keyData['y'], self.keyWidth, self.keyHeight, self.keySpacing, keyData['width'], keyData['symbol'])
key = Key(keyData['x'], keyData['y'] + WordSelectorHeight, self.keyWidth, self.keyHeight, self.keySpacing, keyData['width'], keyData['symbol'])
bottomRightPoint = key.rect.bottomRight()
currentHeight = bottomRightPoint.y() + self.keySpacing
currentWidth = bottomRightPoint.x() + self.keySpacing
......@@ -51,12 +109,117 @@ class KeyboardWidget(QWidget):
return key
def paintEvent(self, event):
self.sizeHint()
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# Dessiner les touches du clavier
for key in self.keys:
painter.drawRect(key.rect)
painter.drawText(key.rect, Qt.AlignCenter, key.symbol)
if key.isOver(self.mousePos):
self.paintKey(painter, key, OVER_COLOR)
else:
self.paintKey(painter, key, DEFAULT_COLOR)
# Dessiner le tracé courant
pen = QPen(PEN_COLOR, PEN_WIDTH, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
pen2 = QPen(PEN_COLOR2, PEN_WIDTH, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
# Dessiner la ligne entre les points
for i in range(len(self.trace) - 1):
painter.setPen(pen)
painter.drawLine(self.trace[i][0], self.trace[i][1], self.trace[i + 1][0], self.trace[i + 1][1])
# Dessiner les points du tracé resample
for i in range(len(self.resampledTrace) - 1):
painter.setPen(pen2)
painter.drawPoint(self.resampledTrace[i][0], self.resampledTrace[i][1])
def sizeHint(self):
return QSize(self.keyboardWidth, self.keyboardHeight)
def mouseMoveEvent(self, event):
self.mousePos = event.pos()
self.update()
def mousePressEvent(self, event):
position = event.pos()
self.trace.append((position.x(), position.y()))
for key in self.keys:
if key.isOver(self.mousePos):
self.pressedKey = key
self.letter_selected = key.symbol
return
def mouseReleaseEvent(self, event):
position = event.pos()
self.resampledTrace.append((position.x(), position.y()))
for key in self.keys:
if key.isOver(self.mousePos):
if key == self.pressedKey:
self.newletter.emit(key.symbol)
if len(key.symbol) > 1:
for key_selector in self.wordSelectors:
key_selector.symbol = ''
self.clearTrace()
return
elif len(key.symbol) == 0:
self.clearTrace()
return
break
else:
break
# Nouvelle section: Imprimer les lettres sélectionnées par le tracé ré-échantillonné
print("Lettres sélectionnées par le tracé ré-échantillonné :")
selected_symbols = set() # Utiliser un ensemble pour éviter les duplicatas
for point in self.resampledTrace:
for key in self.keys:
if key.isOver(QPoint(*point)):
if key.symbol not in selected_symbols: # Pour éviter de réimprimer les mêmes symboles
print(key.symbol, end=' ')
selected_symbols.add(key.symbol)
print() # Pour le retour à la ligne après l'impression des symboles
best_words = self.dwt.compare_to_dictionary(self.resampledTrace, self.letter_selected)
for i in range(len(best_words)):
self.wordSelectors[i].symbol = best_words[i]
self.clearTrace()
def paintKey(self, painter, key, color):
painter.setBrush(color)
painter.drawRect(key.rect)
painter.drawText(key.rect, Qt.AlignCenter, key.symbol)
def clearTrace(self):
self.trace = []
self.resampledTrace = []
self.update()
self.pressedKey = None
def mouseMoveEvent(self, event):
self.mousePos = event.pos()
if self.pressedKey is not None:
point = (self.mousePos.x(), self.mousePos.y())
self.trace.append(point)
self.resampledTrace = resample(self.trace, distanceStroke)
self.update()
def wordToStroke(self, word: str, d: int):
strokes = []
for letter in word:
for key in self.keys:
if key.symbol == letter:
point = key.getCenter()
strokes.append((point.x(), point.y()))
break
# Ajouter le mot au dictionnaire
resampledTrace = resample(strokes, d)
self.dictionnaire.addWord(word, resampledTrace, d)