Anonymous avatar Anonymous committed 9bb0aa9

Basic pygame.draw.arc; TODO width, 24-bit

Comments (0)

Files changed (4)

examples_pygame/draw.py

 __docformat__ = 'restructuredtext'
 __version__ = '$Id$'
 
+import math
 import random
 import sys
 
             return pygame.draw.ellipse(surface, self.color, r, self.width)
         return None
 
+class Arc(Shape):
+    def __init__(self, width):
+        super(Arc, self).__init__(2)
+        self.start_angle = random.random() * (math.pi * 2)
+        self.stop_angle = random.random() * (math.pi * 2)
+        self.d_start_angle = (random.random() - 0.5) * 0.01
+        self.d_stop_angle = (random.random() - 0.5) * 0.01
+        self.width = width
+
+    def update(self, time):
+        super(Arc, self).update(time)
+        self.start_angle += time * self.d_start_angle
+        self.start_angle = self.start_angle % (math.pi * 2)
+        self.stop_angle += time * self.d_stop_angle
+        self.stop_angle = self.stop_angle % (math.pi * 2)
+
+    def draw(self, surface):
+        r = Rect(self.get_points())
+        r.width -= r.left
+        r.height -= r.top
+        r.normalize()
+        if self.width * 2 < r.width and self.width * 2 < r.height:
+            return pygame.draw.arc(surface, self.color, r, 
+                                   0, math.pi/2, self.width)
+        return None
+
 if __name__ == '__main__':
     pygame.init()
 
                     shapes.append(Ellipse(0))
                 elif event.unicode == 'a':
                     shapes.append(AntialiasLine())
+                elif event.unicode == 'q':
+                    shapes.append(Arc(1))
+                elif event.unicode == 'Q':
+                    shapes.append(Arc(4))
                 elif event.unicode == 'c':
                     screen.fill((0, 0, 0))
                     screen.set_clip(screen.get_clip().inflate(-50, -50))
     if len(obj) == 1:
         return _rgba_from_obj(obj[0])
     elif len(obj) == 3:
-        return (obj[0], obj[1], obj[2], 255)
+        return (int(obj[0]), int(obj[1]), int(obj[2]), 255)
     elif len(obj) == 4:
         return obj
     else:
 __version__ = '$Id$'
 
 from copy import copy
+import math
 
 from SDL import *
 
 
     :rtype: `Rect`
     :return: Affected bounding box.
-    '''     
+    '''
+    # Implementation based on XFig rasteriser; u_draw.c, draw_arc() and
+    # curve() functions.
+    # http://www.xfig.org
+
+    if width != 1:
+        raise NotImplementedError, 'TODO'
+
+    color = _get_color(color, surface)
+    rect = _get_rect(rect)
+
+    cx = rect.x + rect.w / 2
+    cy = rect.y + rect.h / 2
+    rx = rect.w / 2
+    ry = rect.h / 2
+    p1 = (cx + math.cos(start_angle) * rx, cy - math.sin(start_angle) * ry)
+    p2 = (cx + math.cos(stop_angle) * rx, cy - math.sin(stop_angle) * ry)
+    direction = 0
+    
+    return _curve(surface, color, p1, p2, direction, rx, ry, cx, cy)
+
+def _curve(surface, color, p1, p2, direction, rx, ry, cx, cy):
+    '''Draw an partial or complete curve.  Based on XFig's curve() function.
+
+    :Parameters:
+        `surface` : `Surface`
+            Surface to draw to
+        `color` : int
+            Mapped stroke color
+        `p1` : (int, int)
+            X, Y coordinates of first point of arc
+        `p2` : (int, int)
+            X, Y coordinates of final point of arc
+        `direction` : int
+            0 for anti-clockwise, 1 for clockwise
+        `rx` : int
+            Ellipse radius in X axis
+        `ry` : int
+            Ellipse radius in Y axis
+        `cx` : int
+            Center of ellipse, X coordinate
+        `cy` : int
+            Center of ellipse, Y coordinate
+    
+    :rtype: pygame.rect.Rect
+    :return: Affected bounding box
+    '''
+    surf = surface._surf
+    if surf.format.BytesPerPixel == 3:
+        raise NotImplementedError, 'TODO, 24-bit'
+
+    pitch = surf.pitch / surf.format.BytesPerPixel
+    pixels = surf.pixels.as_ctypes()
+
+    if rx <= 4 or ry <= 4:
+        # Seems to hang otherwise
+        # XXX still some artifacts with slightly larger rx/ry, but no crash at
+        # least.
+        return pygame.rect.Rect(surf.w, surf.h, -surf.w, -surf.h)
+
+    clip_rect = pygame.rect.Rect(surf.clip_rect)
+
+    rx *= rx
+    ry *= ry
+
+    x, y = p1
+    dfx = 2.0 * ry * (p1[0] - cx)
+    dfy = 2.0 * rx * (p1[1] - cy)
+    dfxx = 2.0 * ry
+    dfyy = 2.0 * rx
+
+    falpha = 0
+    if direction:
+        inc = 1
+        dec = -1
+    else:
+        inc = -1
+        dec = 1
+
+    if p1[0] == p2[0] and p1[1] == p2[1]:
+        test_succeed = margin = 2
+    else:
+        test_succeed = margin = 3
+
+    if clip_rect.collidepoint(int(x), int(y)):
+        pixels[int(y) * pitch + int(x)] = color
+
+    minx, miny = p1
+    maxx, maxy = p1
+
+    while test_succeed:
+        if dfy < 0:
+            deltax = inc
+        else:
+            deltax = dec
+        if dfx < 0:
+            deltay = dec
+        else:
+            deltay = inc
+        fx = falpha + dfx * deltax + ry
+        fy = falpha + dfy * deltay + rx
+        fxy = fx + fy - falpha
+        absfx = abs(fx)
+        absfy = abs(fy)
+        absfxy = abs(fxy)
+
+        if absfxy <= absfx and absfxy <= absfy:
+            falpha = fxy
+        elif absfy <= absfx:
+            deltax = 0
+            falpha = fy
+        else:
+            deltay = 0
+            falpha = fx
+        
+        x += deltax
+        y += deltay
+        dfx += dfxx * deltax
+        dfy += dfyy * deltay
+
+        if clip_rect.collidepoint(int(x), int(y)):
+            pixels[int(y) * pitch + int(x)] = color
+            minx = min(minx, x)
+            miny = min(miny, y)
+            maxx = max(maxx, x)
+            maxy = max(maxy, y)
+        
+        if abs(x - p2[0] < margin) and abs(y - p2[1]) < margin and \
+           (x != p2[0] or y != p2[1]):
+            test_succeed -= 1
+    
+    return pygame.rect.Rect(minx, miny, maxx - minx + 1, maxy - miny + 1)
+
 
 def line(surface, color, start_pos, end_pos, width=1):
     '''Draw a straight line segment.
 
     return SDL_GetRelativeMouseState()
 
-def set_pos(pos):
+def set_pos(x, y):
     '''Set the mouse cursor position.
 
     Set the current mouse position to arguments given. If the mouse cursor is
     a new pygame.MOUSEMOTION event.
     
     :Parameters:
-        `pos` : int, int
-            Tuple of X, Y coordinates.
+        `x` : int
+            X coordinate of mouse cursor
+        `y` : int
+            Y coordinate of mouse cursor
 
     '''
     pygame.display._video_init_check()
 
-    x, y = pos
     SDL_WarpMouse(x, y)
 
 def set_visible(visible):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.