Browse Source

mise en place de l'algo de bresenham

unknown 10 năm trước cách đây
mục cha
commit
5ca118edda
10 tập tin đã thay đổi với 266 bổ sung34 xóa
  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\test.py
 			lib\VueEditionForme.py
+			lib\dmF.py
+			lib\bresenham.py
 		-parties
 			-Partie1
 				-journal
@@ -197,23 +199,28 @@ DMonde
 0=DMonde.py
 1=lib\Plateau.py
 2=lib\Modes.py
-3=lib\Cache.py
+3=lib\Case.py
 4=lib\Pinceau.py
+5=lib\bresenham.py
 [Selected Project Files]
 Main=
-Selected=lib\Pinceau.py
+Selected=DMonde.py
 [DMonde.py]
-TopLine=23
-Caret=38,41
+TopLine=108
+Caret=28,121
 [lib\Plateau.py]
 TopLine=1
-Caret=1,1
+Caret=30,15
+BookMark1=9,1512
 [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]
-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._compteurPj = 0
         self.createWidgets()
-        
+
     def createWidgets(self):
         """construction de l'interface"""
         self.ui = Ui_principal()
@@ -114,7 +114,6 @@ class DMonde(QMainWindow):
     def chargerDernierPlateau(self):
         """charge le dernier plateau sauvegarde"""
         infosSvg = afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie))
-        ligne  = 0
         dernier = None
         for id_svg in infosSvg:
             if not dernier or infosSvg[id_svg]["dateSvg"] > infosSvg[dernier]["dateSvg"]:
@@ -125,9 +124,9 @@ class DMonde(QMainWindow):
     def sauverPlateau(self):
         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
         if self.plateau.id in afficheSvg("parties\\{}\\svg\\infos_sauvegarde".format(self.partie)):
-           idPlateau = self.plateau.id
+            idPlateau = self.plateau.id
         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))
         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
            plateaux sauvegardes et leurs informations"""
         #on parcourt les fichiers de sauvegarde
-        index = 0   
         f = []
         lstFichiersSvg = []
         for (dirpath, dirnames, filenames) in os.walk("parties\\{}\\svg\\".format(self.partie)):
@@ -231,7 +229,7 @@ class DMonde(QMainWindow):
     def nouveauPj(self):
         self.editionPj = EcranEditionCombattant()
         self.editionPj.setAttribute(Qt.WA_DeleteOnClose)
-        r = self.editionPj.exec_()
+        self.editionPj.exec_()
         pj = self.editionPj.combattant
         self.pjAjouterAListe(pj)
         self.pjEnregistrer(self._compteurPj)
@@ -250,12 +248,13 @@ class DMonde(QMainWindow):
         
         
 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)
 
 ##        #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.creer()

+ 3 - 1
lib/Modes.py

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

+ 11 - 4
lib/Pinceau.py

@@ -3,6 +3,7 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from Terrain import Terrain
 from dmF import *
+from bresenham import casesEntre
 
 class Pinceau():
     def __init__(self, plateau):
@@ -134,10 +135,11 @@ class Pinceau():
                 ligne = QLineF(self._origine, self._point2)
                 self._objetGraphique.setLine(ligne)                                   
                 #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:
                     if not coord in select:
                         enMoins.append(coord)
@@ -167,6 +169,11 @@ class Pinceau():
     def afficherCase(self, coord, 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):
         """retourne les cases selectionnees lors de l'utilisation de la forme 'rectP' ou 'rectV'"""
         retour = []

+ 34 - 0
lib/Plateau.py

@@ -1000,6 +1000,40 @@ class Plateau(QGraphicsScene):
          
         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):
         """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
            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