Kaynağa Gözat

Bresenham: hexagones - vertical vers bas: fonctionne (calcul avec flottants)

unknown 10 yıl önce
ebeveyn
işleme
fa6992ddc4
3 değiştirilmiş dosya ile 87 ekleme ve 84 silme
  1. 10 10
      DMonde.ppr
  2. 1 1
      lib/Case.py
  3. 76 73
      lib/bresenham.py

+ 10 - 10
DMonde.ppr

@@ -204,23 +204,23 @@ DMonde
 5=lib\bresenham.py
 [Selected Project Files]
 Main=
-Selected=DMonde.py
+Selected=lib\bresenham.py
 [DMonde.py]
-TopLine=108
-Caret=28,121
+TopLine=14
+Caret=16,19
 [lib\Plateau.py]
-TopLine=1
-Caret=30,15
+TopLine=7
+Caret=1,39
 BookMark1=9,1512
 [lib\Modes.py]
 TopLine=208
 Caret=13,225
 [lib\Case.py]
-TopLine=71
-Caret=60,76
+TopLine=77
+Caret=22,92
 [lib\Pinceau.py]
-TopLine=47
+TopLine=167
 Caret=23,175
 [lib\bresenham.py]
-TopLine=127
-Caret=39,145
+TopLine=138
+Caret=31,158

+ 1 - 1
lib/Case.py

@@ -88,7 +88,7 @@ class Case(QGraphicsPolygonItem):
         self.setZValue(0)
         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))

+ 76 - 73
lib/bresenham.py

@@ -1,34 +1,43 @@
 """Algorithme de Bresenham"""
 from __future__ import division
+from math import *
+from dmF import *
+ 
+dbg = True
 
 def casesEntre(coord1, coord2, formeCases = "H"):
+    x1, y1 = coord1
+    x2, y2 = coord2
+
+    # 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
+
     if coord1 != coord2:
         if formeCases == "H":
-            retour = _brH(coord1, coord2)
+            retour = _brH(x1, y1, x2, y2)
         else:
-            retour = _brC(coord1, coord2)
+            retour = _brC(x1, y1, x2, y2)
     else:
         retour = [coord1]
+
+    # retourne la liste si les coordonnees ont ete interverties
+    if inversee:
+        retour.reverse()
     return retour
 
-def _brC(coord1, coord2):
+def _brC(x1, y1, x2, y2):
     """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
-        
+        x2, y2 = y2, x2  
+
     # Calcul des ecarts
     dx = x2 - x1
     dy = y2 - y1
@@ -49,43 +58,17 @@ def _brC(coord1, coord2):
             y += pasY
             error -= 1.0
 
-    # retourne la liste si les coordonnees ont ete interverties
-    if inversee:
-        retour.reverse()
     return retour
 
-def _brH(coord1, coord2):
+def _brH(x1, y1, x2, y2):
     """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)
+    if abs(x2 - x1) < (2*(y2-y1) + abs(x2 % 2) - abs(x1 % 1)):
+        if dbg: print "*** V"
+        retour = _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()   
+        if dbg: print "*** H"
+        retour = _brH_h(x1, y1, x2, y2)   
     return retour
         
 def _brH_h(x1, y1, x2, y2):
@@ -97,7 +80,7 @@ def _brH_h(x1, y1, x2, y2):
     # 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)
+    if dbg: print "# de: {}|{} vers {}|{}".format(x1, y1, x2, y2)
     
     # on itere sur les coordonnees de la boite qui contient les coordonnees 1 et 2
     retour = []
@@ -106,7 +89,7 @@ def _brH_h(x1, y1, x2, y2):
     ky = 0
     
     while not x > x2:
-        print "  > {}, {}, {}, {}".format(x, y, pasY * ky, error)
+        if dbg: print "  > {}, {}, {}, {}".format(x, y, pasY * ky, error)
         
         coord = (x, y + (pasY * ky))
         retour.append(coord)
@@ -123,32 +106,52 @@ def _brH_h(x1, y1, x2, y2):
     
 def _brH_v(x1, y1, x2, y2):
     """Algorithme ligne de Bresenham (pour cases hexagonales - secteur vertical)"""
+    #on prend comme unite la demi largeur: u = 0.5773
+    #la demi hauteur d'un hexa vaut donc 0.8860u, ou sqrt(3)/2
+    #[a revoir] une fois cela pose, on muliplie tout par 4dy afin d'eviter nombres flottants et divisions
+
     # 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)
+    dx = 1.5 * (x2 - x1)      #en x, on a 1.5u de centre a centre
+    dy = y2 - y1             #en y, on compte en demi hauteurs
+    if (x1 + x2) % 2 == 1: 
+        if x1 % 2 == 0:
+            dy += 0.5
+        else:
+            dy -= 0.5
+
+    #k est la tangente de l'angle par rapport a la verticale
+    k = dx/(dy*sqrt(3))
+    pas = 0.5*sqrt(3)   #on avance par demi hauteurs
     
-    # 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
+    d = 0.0     #decalage
+    pos = (x1, y1)
+    retour.append(pos)
+    
+    while pos != (x2, y2):
+        d += (k*pas)
+        if d <= 0.5:
+            #on se deplace vers la case en dessous
+            x, y = pos
+            pos = x, y+1
+            retour.append(pos)
+            d += (k*pas)
         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
+            #on se deplace vers la case en dessous a droite
+            x, y = pos
+            if x %2 == 0:
+                pos = x + 1, y 
+            else:
+                pos = x + 1, y + 1            
+            retour.append(pos)
+            d -= 1.5
+        if dbg: print "  > d = {} -> {}".format(d, pos)
+
+    return retour           
+
+# print casesEntre((0,0), (4,5)) 
+# print casesEntre((1,0), (5,5))  
+    
+
+
+