"""pinceau utilise pour la selection et la mise a jour des cases du plateau""" class Pinceau(): def __init__(self, plateau): self.plateau = plateau self._forme = "simple" self._epaisseur = 1 self._origine = None self._point2 = None self._selection = [] self._objetGraphique = None self._actif = False def majForme(self, forme): if forme in ["simple", "ligne", "frontiere", "pot", \ "rectV", "rectP", "ecclipseV", "ecclipseP"]: self._forme = forme def majEpaisseur(self, val): if val in range(1, 5): self._epaisseur = val def defOrigine(self, coord): if self.plateau.coordonneesValides(coord): self._origine = self.cases[coord].centreGraphique def defPoint2(self, coord): if self.plateau.coordonneesValides(coord): self._point2 = self.cases[coord].centreGraphique def selection(self): return self._selection def demarrer(self, coord): """commence a peindre a partir de la case choisie comme origine""" if self.plateau.coordonneesValides(coord): self._origine = self.cases[coord].centreGraphique self._point2 = self.cases[coord].centreGraphique self._actif = True def maj(self, coord): """on met a jour la selection en fonction de la case qui vient d'etre ajoutee""" enPlus = [] #cases a ajouter a la selection enMoins = [] #cases a retirer de la selection if self._forme == "simple": #pas de forme: on ajoute les cases survolees a la liste des cases zone = self.plateau.zone(coord, self._epaisseur - 1) for coord in zone: if not coord in self._selection: enPlus.append(coord) elif self._forme == "frontiere": #droite qui selectionne toutes les cases situees au dessus d'elle if self._objetGraphique == None: pinceau = QPen() pinceau.setColor(QColor("black")) self._objetGraphique = QGraphicsLineItem() self._objetGraphique.setPen(pinceau) self.plateau.addItem(self._objetGraphique) self._point2 = self.plateau.cases[coord].centreGraphique ligne = QLineF(self._origine, self._point2) orientation = int((1+int(ligne.angle()/22.5))/2) ligne.setAngle(orientation*45) self._objetGraphique.setLine(ligne) select = self.selectionFrontiere() #on met compare avec l'ancienne selection pour minimiser le nombre de cases a maj for coord in self._selection: if not coord in select: enMoins.append(coord) select.remove(coord) enPlus = select #toutes les coord qui restent dans select sont a ajouter else: if self._forme == "ligne": #segment simple if self._objetGraphique == None: pinceau = QPen() pinceau.setColor(QColor("black")) self._objetGraphique = QGraphicsLineItem() self._objetGraphique.setPen(pinceau) self._objetGraphique.prepareGeometryChange() self.plateau.addItem(self._objetGraphique) self._point2 = self.plateau.cases[coord].centreGraphique ligne = QLineF(self._origine, self._point2) self._objetGraphique.setLine(ligne) elif self._forme == "rectV" or self.modeParam["typeFormeDessin"] == "rectP": #rectangle if self.modeParam["formeDessin"] == None: pinceau = QPen() pinceau.setColor(QColor("black")) self._objetGraphique = QGraphicsRectItem() self._objetGraphique.prepareGeometryChange() self._objetGraphique.setPen(pinceau) self.plateau.addItem(self._objetGraphique) rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \ QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) ) self._objetGraphique.setRect(rect) elif self._forme == "ellipseV" or self.modeParam["typeFormeDessin"] == "ellipseP": #ellipse if self._objetGraphique == None: pinceau = QPen() pinceau.setColor(QColor("black")) self._objetGraphique = QGraphicsEllipseItem() self._objetGraphique.prepareGeometryChange() self._objetGraphique.setPen(pinceau) self.plateau.addItem(self._objetGraphique) rect = QRectF(QPointF(min(self._origine.x(), self._point2.x()), min(self._origine.y(), self._point2.y())), \ QPointF(max(self._origine.x(), self._point2.x()), max(self._origine.y(), self._point2.y())) ) self._objetGraphique.setRect(rect) #on liste les cases intersectant la forme select = self.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1) for coord in self._selection: if not coord in select: enMoins.append(coord) select.remove(coord) enPlus = select for coord in enPlus: self.afficherCase(coord, True) self._selection.append(coord) for coord in enMoins: self.afficherCase(coord, False) self._selection.remove(coord) def annuler(self): self.reinit() def terminer(self): return self._selection def reinit(self): for coord in self_selection: self.afficherCase(coord, False) self._origine = (-1, -1) self._point2 = (-1, -1) self._selection = [] self._actif = False def afficherCase(self, coord, actif): self.plateau.cases[coord].majEstCibleCurseur(actif) def selectionFrontiere(self): """retourne les cases selectionnees lors de l'utilisation de la forme 'frontiere'""" listeCases = [] if self._objetGraphique != None: ligne = self._objetGraphique.line() normale = ligne.normalVector() normale = normale.unitVector() coordOrigine = self.coordonneesAuPoint(self.modeParam["origineFormeDessin"]) dx = normale.p2().x() - normale.p1().x() dy = normale.p2().y() - normale.p1().y() for coord in self.plateau.cases: if dx < 0 and dy == 0: #normale pointe vers la gauche if (coord[0] - coordOrigine[0]) <= 0: listeCases.append(coord) if dx > 0 and dy == 0: #normale pointe vers la droite if (coord[0] - coordOrigine[0]) >= 0: listeCases.append(coord) if dx == 0 and dy < 0: #pointe vers le haut (rappel: axe y vers le bas) if (coord[1] - coordOrigine[1]) <= 0: listeCases.append(coord) elif dx == 0 and dy > 0: #pointe vers le bas if (coord[1] - coordOrigine[1]) >= 0: listeCases.append(coord) if dx > 0 and dy < 0: #pointe vers le haut droite if (coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) >= 0: listeCases.append(coord) elif dx > 0 and dy > 0: #pointe vers le bas droite if -1*(coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) <= 0: listeCases.append(coord) if dx < 0 and dy < 0: #pointe vers le haut gauche if (coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) <= 0: listeCases.append(coord) elif dx < 0 and dy > 0: #pointe vers le bas gauche if -1*(coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) >= 0: listeCases.append(coord) return listeCases def casesSousForme(self, forme, plein = True, epaisseur = 0): """renvoie la liste des cases en collision avec un QGraphicsItem en parametre plein = False: pas le contenu de la forme epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee""" tmp = [] listeCases = [] point1 = None point2 = None #point 1 et 2 if forme.__class__.__name__ == "QGraphicsLineItem": point1 = forme.line().p1() point2 = forme.line().p2() elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem": point1 = forme.rect().topLeft() point2 = forme.rect().bottomRight() else: point1 = forme.boundingRect().topLeft() point2 = forme.boundingRect().bottomRight() #preselection des cases (meilleures perf) if point1 != None and point2 != None and point1 != point2: preSelection = self.preSelectionCollision(point1, point2) else: preSelection = [] for coord in self.cases: preSelection.append(coord) #on liste les cases en collision avec la forme for coord in preSelection: if self.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape): if plein: tmp.append(coord) else: contenu = True for i in range(0,len(self.cases[coord].polygon())): if not forme.contains(self.cases[coord].polygon().at(i)): contenu = False break if contenu == False: tmp.append(coord) #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire if not plein and epaisseur > 0: for coord in tmp: zone = self.zone(coord, epaisseur) for coord2 in zone: if not coord2 in listeCases: listeCases.append(coord2) else: listeCases = tmp #si la liste est vide, on ajoute l'origine de la forme if len(listeCases) == 0: listeCases = [self.coordonneesAuPoint(point1)] return listeCases