Prechádzať zdrojové kódy

mise en place de l'algo de bresenham

unknown 10 rokov pred
rodič
commit
5ca118edda
10 zmenil súbory, kde vykonal 266 pridanie a 34 odobranie
  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