瀏覽代碼

mise en place de l'algo de bresenham

unknown 10 年之前
父節點
當前提交
5ca118edda
共有 10 個文件被更改,包括 266 次插入34 次删除
  1. 17 0
      .project
  2. 8 0
      .pydevproject
  3. 4 0
      .settings/org.eclipse.core.resources.prefs
  4. 19 12
      DMonde.ppr
  5. 11 12
      DMonde.py
  6. 5 5
      lib/Case.py
  7. 3 1
      lib/Modes.py
  8. 11 4
      lib/Pinceau.py
  9. 34 0
      lib/Plateau.py
  10. 154 0
      lib/bresenham.py

+ 17 - 0
.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>DMonde</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>

+ 8 - 0
.pydevproject

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/${PROJECT_DIR_NAME}</path>
+</pydev_pathproperty>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+</pydev_project>

+ 4 - 0
.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+encoding//lib/Combattant.py=utf-8
+encoding//lib/Plateau.py=utf-8
+encoding/DMonde.py=utf-8

+ 19 - 12
DMonde.ppr

@@ -181,6 +181,8 @@ DMonde
 			lib\Terrain.py
 			lib\Terrain.py
 			lib\test.py
 			lib\test.py
 			lib\VueEditionForme.py
 			lib\VueEditionForme.py
+			lib\dmF.py
+			lib\bresenham.py
 		-parties
 		-parties
 			-Partie1
 			-Partie1
 				-journal
 				-journal
@@ -197,23 +199,28 @@ DMonde
 0=DMonde.py
 0=DMonde.py
 1=lib\Plateau.py
 1=lib\Plateau.py
 2=lib\Modes.py
 2=lib\Modes.py
-3=lib\Cache.py
+3=lib\Case.py
 4=lib\Pinceau.py
 4=lib\Pinceau.py
+5=lib\bresenham.py
 [Selected Project Files]
 [Selected Project Files]
 Main=
 Main=
-Selected=lib\Pinceau.py
+Selected=DMonde.py
 [DMonde.py]
 [DMonde.py]
-TopLine=23
-Caret=38,41
+TopLine=108
+Caret=28,121
 [lib\Plateau.py]
 [lib\Plateau.py]
 TopLine=1
 TopLine=1
-Caret=1,1
+Caret=30,15
+BookMark1=9,1512
 [lib\Modes.py]
 [lib\Modes.py]
-TopLine=3
-Caret=37,17
-[lib\Cache.py]
-TopLine=11
-Caret=27,21
+TopLine=208
+Caret=13,225
+[lib\Case.py]
+TopLine=71
+Caret=60,76
 [lib\Pinceau.py]
 [lib\Pinceau.py]
-TopLine=181
-Caret=36,193
+TopLine=47
+Caret=23,175
+[lib\bresenham.py]
+TopLine=127
+Caret=39,145

+ 11 - 12
DMonde.py

@@ -41,7 +41,7 @@ class DMonde(QMainWindow):
         self.plateauConnecte = False
         self.plateauConnecte = False
         self._compteurPj = 0
         self._compteurPj = 0
         self.createWidgets()
         self.createWidgets()
-        
+
     def createWidgets(self):
     def createWidgets(self):
         """construction de l'interface"""
         """construction de l'interface"""
         self.ui = Ui_principal()
         self.ui = Ui_principal()
@@ -114,7 +114,6 @@ class DMonde(QMainWindow):
     def chargerDernierPlateau(self):
     def chargerDernierPlateau(self):
         """charge le dernier plateau sauvegarde"""
         """charge le dernier plateau sauvegarde"""
         infosSvg = afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie))
         infosSvg = afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie))
-        ligne  = 0
         dernier = None
         dernier = None
         for id_svg in infosSvg:
         for id_svg in infosSvg:
             if not dernier or infosSvg[id_svg]["dateSvg"] > infosSvg[dernier]["dateSvg"]:
             if not dernier or infosSvg[id_svg]["dateSvg"] > infosSvg[dernier]["dateSvg"]:
@@ -125,9 +124,9 @@ class DMonde(QMainWindow):
     def sauverPlateau(self):
     def sauverPlateau(self):
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
         if self.plateau.id in afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie)):
         if self.plateau.id in afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie)):
-           idPlateau = self.plateau.id
+            idPlateau = self.plateau.id
         else:   
         else:   
-           idPlateau = str(len(afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie))))
+            idPlateau = str(len(afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie))))
 
 
         enregistrerUnique(self.plateau, "parties\\{}\\svg\\{}.p".format(self.partie, idPlateau))
         enregistrerUnique(self.plateau, "parties\\{}\\svg\\{}.p".format(self.partie, idPlateau))
         infos = {"nom": self.plateau.nom, "chapitre": self.plateau.chapitre, "dateCreation":self.plateau.dateCreation, "dateSvg":self.plateau.dateSvg, \
         infos = {"nom": self.plateau.nom, "chapitre": self.plateau.chapitre, "dateCreation":self.plateau.dateCreation, "dateSvg":self.plateau.dateSvg, \
@@ -145,7 +144,6 @@ class DMonde(QMainWindow):
         """construit/maj le fichier contenant la liste des
         """construit/maj le fichier contenant la liste des
            plateaux sauvegardes et leurs informations"""
            plateaux sauvegardes et leurs informations"""
         #on parcourt les fichiers de sauvegarde
         #on parcourt les fichiers de sauvegarde
-        index = 0   
         f = []
         f = []
         lstFichiersSvg = []
         lstFichiersSvg = []
         for (dirpath, dirnames, filenames) in os.walk("parties\\{}\\svg\\".format(self.partie)):
         for (dirpath, dirnames, filenames) in os.walk("parties\\{}\\svg\\".format(self.partie)):
@@ -231,7 +229,7 @@ class DMonde(QMainWindow):
     def nouveauPj(self):
     def nouveauPj(self):
         self.editionPj = EcranEditionCombattant()
         self.editionPj = EcranEditionCombattant()
         self.editionPj.setAttribute(Qt.WA_DeleteOnClose)
         self.editionPj.setAttribute(Qt.WA_DeleteOnClose)
-        r = self.editionPj.exec_()
+        self.editionPj.exec_()
         pj = self.editionPj.combattant
         pj = self.editionPj.combattant
         self.pjAjouterAListe(pj)
         self.pjAjouterAListe(pj)
         self.pjEnregistrer(self._compteurPj)
         self.pjEnregistrer(self._compteurPj)
@@ -250,12 +248,13 @@ class DMonde(QMainWindow):
         
         
         
         
 if __name__ == "__main__":
 if __name__ == "__main__":
-   app = QApplication(argv)
-   #settrace(trace_calls)
-   dm = DMonde()
-   dm.show()
-   r = app.exec_()
-   exit(r)      
+    app = QApplication(argv)
+    #settrace(trace_calls)
+    dm = DMonde()
+    dm.show()
+    r = app.exec_()
+    exit(r)
+   
 
 
 
 
 
 

+ 5 - 5
lib/Case.py

@@ -89,11 +89,11 @@ class Case(QGraphicsPolygonItem):
         self.setFiltersChildEvents(True)
         self.setFiltersChildEvents(True)
 
 
 ##        #pour afficher les coordonnees des cases:        
 ##        #pour afficher les coordonnees des cases:        
-##        text = QGraphicsSimpleTextItem("{}-{}".format(self.x,self.y), parent=self)
-##        if self.plateau.formeCases == "H":
-##            text.setPos(QPointF(((self.x*0.866)+0.2886)*self.plateau.hCase,  (self.y+k+0.5)*self.plateau.hCase))
-##        else:
-##            text.setPos(QPointF(self.x*self.plateau.hCase,  self.y*self.plateau.hCase))
+        text = QGraphicsSimpleTextItem("{}-{}".format(self.x,self.y), parent=self)
+        if self.plateau.formeCases == "H":
+            text.setPos(QPointF(((self.x*0.866)+0.2886)*self.plateau.hCase,  (self.y+k+0.5)*self.plateau.hCase))
+        else:
+            text.setPos(QPointF(self.x*self.plateau.hCase,  self.y*self.plateau.hCase))
 
 
         self.logoDep = LogoDep(self)
         self.logoDep = LogoDep(self)
         self.logoDep.creer()
         self.logoDep.creer()

+ 3 - 1
lib/Modes.py

@@ -198,6 +198,7 @@ class MajCases(ModeBaseCp):
         self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
         self._sourceCurseur = ":/interface/16/ressource/pinceau_16.png"
         self._focus = True
         self._focus = True
         self._param = None   #parametre avec lequel on mettra a jour la case
         self._param = None   #parametre avec lequel on mettra a jour la case
+        self._caseSurvolee = None
 
 
     def activer(self, param):
     def activer(self, param):
         """active le mode"""
         """active le mode"""
@@ -220,7 +221,8 @@ class MajCases(ModeBaseCp):
         self.plateau.pinceau.demarrer(coord)
         self.plateau.pinceau.demarrer(coord)
 
 
     def survolClic_case(self, coord):
     def survolClic_case(self, coord):
-        self.plateau.pinceau.maj(coord)
+        if coord != self._caseSurvolee:
+            self.plateau.pinceau.maj(coord)
 
 
     def finClicGauche(self, event):
     def finClicGauche(self, event):
         if self.plateau.pinceau.estActif():
         if self.plateau.pinceau.estActif():

+ 11 - 4
lib/Pinceau.py

@@ -3,6 +3,7 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from PyQt4.QtGui import *
 from Terrain import Terrain
 from Terrain import Terrain
 from dmF import *
 from dmF import *
+from bresenham import casesEntre
 
 
 class Pinceau():
 class Pinceau():
     def __init__(self, plateau):
     def __init__(self, plateau):
@@ -134,10 +135,11 @@ class Pinceau():
                 ligne = QLineF(self._origine, self._point2)
                 ligne = QLineF(self._origine, self._point2)
                 self._objetGraphique.setLine(ligne)                                   
                 self._objetGraphique.setLine(ligne)                                   
                 #on liste les cases intersectant la forme
                 #on liste les cases intersectant la forme
-                if self._objetGraphique:
-                    select = self.plateau.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1)
-                else:
-                    select = [coord]
+#                 if self._objetGraphique:
+#                     select = self.plateau.casesSousForme(self._objetGraphique, (self._forme[-1:] == "P"), self._epaisseur - 1)
+#                 else:
+#                     select = [coord]
+                select = self.selectionLigne(self._coordOrigine, coord)
                 for coord in self._selection:
                 for coord in self._selection:
                     if not coord in select:
                     if not coord in select:
                         enMoins.append(coord)
                         enMoins.append(coord)
@@ -167,6 +169,11 @@ class Pinceau():
     def afficherCase(self, coord, actif):
     def afficherCase(self, coord, actif):
         self.plateau.cases[coord].majEstCibleCurseur(actif)
         self.plateau.cases[coord].majEstCibleCurseur(actif)
 
 
+    def selectionLigne(self, coord0, coord1):
+        retour = casesEntre(coord0, coord1, self.plateau.formeCases)
+#         retour = []
+        return retour
+
     def selectionRectangle(self, coord0, coord1, plein = True):
     def selectionRectangle(self, coord0, coord1, plein = True):
         """retourne les cases selectionnees lors de l'utilisation de la forme 'rectP' ou 'rectV'"""
         """retourne les cases selectionnees lors de l'utilisation de la forme 'rectP' ou 'rectV'"""
         retour = []
         retour = []

+ 34 - 0
lib/Plateau.py

@@ -1000,6 +1000,40 @@ class Plateau(QGraphicsScene):
          
          
         return resultat
         return resultat
 
 
+#     def casesEntre(self, coord1, coord2):
+#         """renvoie la liste des cases qui composent le chemin le plus direct
+#             entre les 2 cases en parametre"""
+#         #on determine le secteur et on calcule l'angle du chemin
+#         if coord2[0] != coord1[0]:
+#             if coord2[0] > coord1[0] and coord2[1] <= coord1[1] #0 a 3h
+#                 secteur = 1
+#             elif coord2[0] > coord1[0] and coord2[1] > coord1[1] #3 a 6h
+#                 secteur = 2           
+#             elif coord2[0] < coord1[0] and coord2[1] >= coord1[1] #6 a 9h
+#                 secteur = 3             
+#             elif coord2[0] < coord1[0] and coord2[1] < coord1[1] #9 a 12h
+#                 secteur = 4             
+#             angle = (coord2[1] - coord1[1]) / (coord2[0] - coord1[0])
+#         else:
+#             s = 0
+#             angle = 1
+# 
+#         #on preselectionne les cases concernees
+#         preselect = []
+#         xmin = mini(coord1[0], coord2[0]); xmax = maxi(coord1[0], coord2[0])
+#         ymin = mini(coord1[1], coord2[1]); ymax = maxi(coord1[1], coord2[1])
+#         for coord in self.cases:
+#             if xmin <= coord[0] <= xmax and ymin <= coord[1] <= ymax:
+#                 preselect.append()
+#         
+#         #on progresse de case en case en avancant selon l'angle
+#         coordTest = coord1
+#         while coordTest != coord2:
+#             for coord in preselect: 
+#                 pass
+#         
+
+
     def polygoneAgglo(self, listeCases):
     def polygoneAgglo(self, listeCases):
         """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
         """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
            les cases doivent etre adjacentes (cases hexagonales ou carrees)"""
            les cases doivent etre adjacentes (cases hexagonales ou carrees)"""

+ 154 - 0
lib/bresenham.py

@@ -0,0 +1,154 @@
+"""Algorithme de Bresenham"""
+from __future__ import division
+
+def casesEntre(coord1, coord2, formeCases = "H"):
+    if coord1 != coord2:
+        if formeCases == "H":
+            retour = _brH(coord1, coord2)
+        else:
+            retour = _brC(coord1, coord2)
+    else:
+        retour = [coord1]
+    return retour
+
+def _brC(coord1, coord2):
+    """Algorithme ligne de Bresenham (pour cases carrees)"""
+    x1, y1 = coord1
+    x2, y2 = coord2
+
+    # on verifie si la ligne est plus verticale qu'horizontale
+    estVerticale = abs(y2 - y1) > abs(x2 - x1)
+    if estVerticale:
+        x1, y1 = y1, x1
+        x2, y2 = y2, x2
+               
+    # on inverse les coord si necessaire (si on va de gauche a droite)
+    inversee = False
+    if x1 > x2:
+        x1, x2 = x2, x1
+        y1, y2 = y2, y1
+        inversee = True
+        
+    # Calcul des ecarts
+    dx = x2 - x1
+    dy = y2 - y1
+ 
+    # Calcul de l'erreur  (l'ecart qui doit s'accumuler au fur et a mesure qu'on avance)
+    #2dx est l'unite, de maniere a travailler avec des entiers
+    error = 0.0
+    pasY = 1 if y1 < y2 else -1
+ 
+    # on itere sur les coordonnees de la boite qui contient les coordonnees 1 et 2
+    y = y1
+    retour = []
+    for x in range(x1, x2 + 1):
+        coord = (y, x) if estVerticale else (x, y)
+        retour.append(coord)
+        error += (abs(dy) / dx)
+        if error > 0.5:
+            y += pasY
+            error -= 1.0
+
+    # retourne la liste si les coordonnees ont ete interverties
+    if inversee:
+        retour.reverse()
+    return retour
+
+def _brH(coord1, coord2):
+    """Algorithme ligne de Bresenham (pour cases hexagonales)"""
+    x1, y1 = coord1
+    x2, y2 = coord2
+    if x1%2 == 1: y1 += 0.5
+    if x2%2 == 1: y2 += 0.5
+
+    # on inverse les coord si necessaire (si on va de droite a gauche)
+    inversee = False
+    if x1 > x2:
+        x1, x2 = x2, x1
+        y1, y2 = y2, y1
+        inversee = True
+    
+    #calcul selon secteur
+    if 2*abs(y2 - y1) >= abs(x2 - x1):
+        print "*** V"
+        resultat = _brH_v(x1, y1, x2, y2)
+    else:
+        print "*** H"
+        resultat = _brH_h(x1, y1, x2, y2)   
+
+    print "res: ", resultat
+#     retour = resultat
+    retour = []
+    for x, y in resultat:
+        if x % 2 == 1: y -= 0.5
+        retour.append((x,y))
+
+    # retourne la liste si les coordonnees ont ete inversees
+    if inversee:
+        retour.reverse()   
+    return retour
+        
+def _brH_h(x1, y1, x2, y2):
+    """Algorithme ligne de Bresenham (pour cases hexagonales - secteur horizontal)"""  
+    # Calcul des ecarts
+    dx = x2 - x1
+    dy = y2 - y1
+    
+    # Calcul de l'erreur  (l'ecart qui doit s'accumuler au fur et a mesure qu'on avance)
+    error = 0.0
+    pasY = 1 if y1 < y2 else -1
+    print "# de: {}|{} vers {}|{}".format(x1, y1, x2, y2)
+    
+    # on itere sur les coordonnees de la boite qui contient les coordonnees 1 et 2
+    retour = []
+    x, y = x1, y1
+    #ky: decalage entre cases paires et impaires
+    ky = 0
+    
+    while not x > x2:
+        print "  > {}, {}, {}, {}".format(x, y, pasY * ky, error)
+        
+        coord = (x, y + (pasY * ky))
+        retour.append(coord)
+        
+        x += 1
+        ky = 0.5 if (x - x1) % 2 == 1 else 0
+        
+        error += (0.9087 * (abs(dy) / dx))
+        if error > 0.5 + ky:                   
+            y += pasY
+            error -= 1
+                      
+    return retour
+    
+def _brH_v(x1, y1, x2, y2):
+    """Algorithme ligne de Bresenham (pour cases hexagonales - secteur vertical)"""
+    # Calcul des ecarts
+    dx = x2 - x1
+    dy = y2 - y1
+    signeDy = 1 if dy > 0 else -1
+    
+    error = 0.0
+    pasY = 0.5 if y1 < y2 else -0.5
+    
+    print "# de: {}|{} vers {}|{}".format(x1, y1, x2, y2)
+    
+    # on itere sur les coordonnees de la boite qui contient les coordonnees 1 et 2
+    retour = []
+    x, y = x1, y1
+    while not (signeDy * y) > (signeDy * y2):
+        print "  > {}, {}, {}, {}".format(x, y, pasY, error)
+        if (x%2 == 0 and y == int(y)) or (x%2 == 1 and y != int(y)):
+            coord = (x, y)      #la case existe
+            retour.append(coord)
+            seuil = 0.2886  #a la prochaine position, on sera entre 2 cases
+        else:
+            seuil = 0.5773  #la prochaine position sera une vraie case
+            
+        y += pasY
+        error += (0.5 * (dx / abs(dy)))
+        if error > seuil:                   
+            x += 1
+            error -= 1.1547
+
+    return retour