10. Limitation du zoom
Comme signalé lors de l'implémentation de la fonction zoom, il existe une limite audelà de laquelle l'application réagit bizarrement — on pourrait même dire qu'elle
devient instable. Ce n'est pas très étonnant sachant que, dans MosaiQ, on balaie
plusieurs ordres de grandeur ; si les nombres ont une représentation de taille fixe en
mémoire, il y a forcément des limites aux coordonnées qu'on peut manipuler.
Ce qui serait souhaitable, ce serait de détecter le problème avant qu'il n'arrive et, le
cas échéant, bloquer la fonction zoom. Pour faire cela sans devoir trop réfléchir, on
pourrait suivre une approche empirique : par essais, on évalue le facteur de zoom à
partir duquel on constate que les problèmes surviennent ; puis, à partir de cette
constante, on code un test qui bloque la fonction zoom.
Cette approche empirique n'est pas la meilleure, car la constante obtenue est imprécise
et pourrait même changer d'un environnement d'exécution à l'autre. Heureusement, il
existe une autre approche : elle exige un peu de réflexion, mais elle est plus fiable et
aussi plus simple à implémenter. L'élément principal à comprendre est que la limitation
provient de la classe QGraphicsView : les coordonnées entières sont limitées à la
plage [INT_MIN, INT_MAX], où INT_MIN et INT_MAX sont des constantes dépendant du
système. Ces constantes sont en fait définies au niveau du C++, le langage natif de Qt ;
INT_MAX vaut typiquement 65535 (2 15 −1) ou 2147483647 (2 31 −1). Pour s'assurer qu'il
n'y ait pas de débordement, il suffit de veiller à ce qu'aucune coordonnée vue n'excède
cette valeur INT_MAX. À cette fin, on peut se référer à la taille du plus grand carré —
celle du carré initial, donc — pour obtenir une coordonnée maximale. Partant de ce
principe, il est possible de détecter précisément quand la limite est atteinte et bloquer
le zoom si nécessaire. Voici les quelques lignes à ajouter dans VueMosaiQ (on opère
bien sûr au niveau de la méthode zoom, pour capter aussi bien le zoom à la souris que
le zoom au clavier) :
…
import struct
INT_MAX = 2**(struct.Struct('i').size*8-1) - 1
… class VueMosaiQ(QGraphicsView): … def zoom(self,facteur): if facteur < 0.0:
facteur = -1.0 / facteur else: coordMax =
self.scene().carreMosaiQUnivers.tailleDansVue(self) if coordMax*facteur >=
INT_MAX: QApplication.beep() return …
260
Comme signalé lors de l'implémentation de la fonction zoom, il existe une limite audelà de laquelle l'application réagit bizarrement — on pourrait même dire qu'elle
devient instable. Ce n'est pas très étonnant sachant que, dans MosaiQ, on balaie
plusieurs ordres de grandeur ; si les nombres ont une représentation de taille fixe en
mémoire, il y a forcément des limites aux coordonnées qu'on peut manipuler.
Ce qui serait souhaitable, ce serait de détecter le problème avant qu'il n'arrive et, le
cas échéant, bloquer la fonction zoom. Pour faire cela sans devoir trop réfléchir, on
pourrait suivre une approche empirique : par essais, on évalue le facteur de zoom à
partir duquel on constate que les problèmes surviennent ; puis, à partir de cette
constante, on code un test qui bloque la fonction zoom.
Cette approche empirique n'est pas la meilleure, car la constante obtenue est imprécise
et pourrait même changer d'un environnement d'exécution à l'autre. Heureusement, il
existe une autre approche : elle exige un peu de réflexion, mais elle est plus fiable et
aussi plus simple à implémenter. L'élément principal à comprendre est que la limitation
provient de la classe QGraphicsView : les coordonnées entières sont limitées à la
plage [INT_MIN, INT_MAX], où INT_MIN et INT_MAX sont des constantes dépendant du
système. Ces constantes sont en fait définies au niveau du C++, le langage natif de Qt ;
INT_MAX vaut typiquement 65535 (2 15 −1) ou 2147483647 (2 31 −1). Pour s'assurer qu'il
n'y ait pas de débordement, il suffit de veiller à ce qu'aucune coordonnée vue n'excède
cette valeur INT_MAX. À cette fin, on peut se référer à la taille du plus grand carré —
celle du carré initial, donc — pour obtenir une coordonnée maximale. Partant de ce
principe, il est possible de détecter précisément quand la limite est atteinte et bloquer
le zoom si nécessaire. Voici les quelques lignes à ajouter dans VueMosaiQ (on opère
bien sûr au niveau de la méthode zoom, pour capter aussi bien le zoom à la souris que
le zoom au clavier) :
…
import struct
INT_MAX = 2**(struct.Struct('i').size*8-1) - 1
… class VueMosaiQ(QGraphicsView): … def zoom(self,facteur): if facteur < 0.0:
facteur = -1.0 / facteur else: coordMax =
self.scene().carreMosaiQUnivers.tailleDansVue(self) if coordMax*facteur >=
INT_MAX: QApplication.beep() return …
260
