[pypy-svn] r14123 - pypy/dist/pypy/translator/tool/pygame
niemeyer at codespeak.net
niemeyer at codespeak.net
Sun Jul 3 12:34:27 CEST 2005
Author: niemeyer
Date: Sun Jul 3 12:34:26 2005
New Revision: 14123
Modified:
pypy/dist/pypy/translator/tool/pygame/drawgraph.py
Log:
- Implementing caching of bezier curve/arrow head/limit points on edges.
- Implementing detection of visible nodes and edges, and now
acting on those rather than on every node and edge whenever
rendering and detecting objects under the cursor.
Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py
==============================================================================
--- pypy/dist/pypy/translator/tool/pygame/drawgraph.py (original)
+++ pypy/dist/pypy/translator/tool/pygame/drawgraph.py Sun Jul 3 12:34:26 2005
@@ -116,56 +116,77 @@
rest = rest[3:]
self.style, self.color = rest
self.highlight = False
+ self.cachedbezierpoints = None
+ self.cachedarrowhead = None
+ self.cachedlimits = None
def sethighlight(self, which):
self.highlight = bool(which)
- def bezierpoints(self, resolution=8):
- result = []
- pts = self.points
- for i in range(0, len(pts)-3, 3):
- result += beziercurve(pts[i], pts[i+1],
- pts[i+2], pts[i+3], resolution)
+ def limits(self):
+ result = self.cachedlimits
+ if result is None:
+ points = self.bezierpoints()
+ xs = [point[0] for point in points]
+ ys = [point[1] for point in points]
+ self.cachedlimits = result = (min(xs), max(ys), max(xs), min(ys))
+ return result
+
+ def bezierpoints(self):
+ result = self.cachedbezierpoints
+ if result is None:
+ result = []
+ pts = self.points
+ for i in range(0, len(pts)-3, 3):
+ result += beziercurve(pts[i], pts[i+1], pts[i+2], pts[i+3])
+ self.cachedbezierpoints = result
return result
def arrowhead(self):
- bottom_up = self.points[0][1] > self.points[-1][1]
- if (self.tail.y > self.head.y) != bottom_up: # reversed edge
- head = 0
- dir = 1
- else:
- head = -1
- dir = -1
- n = 1
- while True:
- try:
- x0, y0 = self.points[head]
- x1, y1 = self.points[head+n*dir]
- except IndexError:
- return []
- vx = x0-x1
- vy = y0-y1
- try:
- f = 0.12 / math.sqrt(vx*vx + vy*vy)
- vx *= f
- vy *= f
- return [(x0 + 0.9*vx, y0 + 0.9*vy),
- (x0 + 0.4*vy, y0 - 0.4*vx),
- (x0 - 0.4*vy, y0 + 0.4*vx)]
- except (ZeroDivisionError, ValueError):
- n += 1
+ result = self.cachedarrowhead
+ if result is None:
+ bottom_up = self.points[0][1] > self.points[-1][1]
+ if (self.tail.y > self.head.y) != bottom_up: # reversed edge
+ head = 0
+ dir = 1
+ else:
+ head = -1
+ dir = -1
+ n = 1
+ while True:
+ try:
+ x0, y0 = self.points[head]
+ x1, y1 = self.points[head+n*dir]
+ except IndexError:
+ result = []
+ break
+ vx = x0-x1
+ vy = y0-y1
+ try:
+ f = 0.12 / math.sqrt(vx*vx + vy*vy)
+ vx *= f
+ vy *= f
+ result = [(x0 + 0.9*vx, y0 + 0.9*vy),
+ (x0 + 0.4*vy, y0 - 0.4*vx),
+ (x0 - 0.4*vy, y0 + 0.4*vx)]
+ break
+ except (ZeroDivisionError, ValueError):
+ n += 1
+ self.cachedarrowhead = result
+ return result
def beziercurve((x0,y0), (x1,y1), (x2,y2), (x3,y3), resolution=8):
result = []
f = 1.0/(resolution-1)
+ append = result.append
for i in range(resolution):
t = f*i
t0 = (1-t)*(1-t)*(1-t)
t1 = t *(1-t)*(1-t) * 3.0
t2 = t * t *(1-t) * 3.0
t3 = t * t * t
- result.append((x0*t0 + x1*t1 + x2*t2 + x3*t3,
- y0*t0 + y1*t1 + y2*t2 + y3*t3))
+ append((x0*t0 + x1*t1 + x2*t2 + x3*t3,
+ y0*t0 + y1*t1 + y2*t2 + y3*t3))
return result
def segmentdistance((x0,y0), (x1,y1), (x,y)):
@@ -173,16 +194,16 @@
vx = x1-x0
vy = y1-y0
try:
- l = math.sqrt(vx*vx+vy*vy)
+ l = math.hypot(vx, vy)
vx /= l
vy /= l
dlong = vx*(x-x0) + vy*(y-y0)
except (ZeroDivisionError, ValueError):
dlong = -1
if dlong < 0.0:
- return math.sqrt((x-x0)*(x-x0) + (y-y0)*(y-y0))
+ return math.hypot(x-x0, y-y0)
elif dlong > l:
- return math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1))
+ return math.hypot(x-x1, y-y1)
else:
return abs(vy*(x-x0) - vx*(y-y0))
@@ -209,6 +230,8 @@
self.textzones = []
self.highlightwords = graphlayout.links
self.highlight_word = None
+ self.visiblenodes = []
+ self.visibleedges = []
def wordcolor(self, word):
if word == self.highlight_word:
@@ -298,8 +321,26 @@
coordinates may sometimes become longs and cause OverflowErrors
within pygame.
"""
- return (x1 < self.width-self.ofsx and x2 > -self.ofsx and
- y1 < self.height-self.ofsy and y2 > -self.ofsy)
+ w, h = self.screen.get_size()
+ return x1 < w and x2 > 0 and y1 < h and y2 > 0
+
+ def computevisible(self):
+ del self.visiblenodes[:]
+ del self.visibleedges[:]
+ w, h = self.screen.get_size()
+ for node in self.graphlayout.nodes.values():
+ x, y = self.map(node.x, node.y)
+ nw2 = int(node.w * self.scale)//2
+ nh2 = int(node.h * self.scale)//2
+ if x-nw2 < w and x+nw2 > 0 and y-nh2 < h and y+nh2 > 0:
+ self.visiblenodes.append(node)
+ for edge in self.graphlayout.edges:
+ x1, y1, x2, y2 = edge.limits()
+ x1, y1 = self.map(x1, y1)
+ if x1 < w and y1 < h:
+ x2, y2 = self.map(x2, y2)
+ if x2 > 0 and y2 > 0:
+ self.visibleedges.append(edge)
def map(self, x, y):
return (int(x*self.scale) - (self.ofsx - self.margin),
@@ -382,6 +423,14 @@
def cmd():
pygame.draw.rect(self.screen, fgcolor, rect, 1)
commands.append(cmd)
+ elif node.shape == 'ellipse':
+ rect = (x-1, y-1, boxwidth+2, boxheight+2)
+ def cmd():
+ pygame.draw.ellipse(self.screen, bgcolor, rect, 0)
+ bkgndcommands.append(cmd)
+ def cmd():
+ pygame.draw.ellipse(self.screen, fgcolor, rect, 1)
+ commands.append(cmd)
elif node.shape == 'octagon':
step = 1-math.sqrt(2)/2
points = [(int(x+boxwidth*fx), int(y+boxheight*fy))
@@ -400,14 +449,15 @@
def draw_commands(self):
nodebkgndcmd = []
nodecmd = []
- for node in self.graphlayout.nodes.values():
+ for node in self.visiblenodes:
cmd1, cmd2 = self.draw_node_commands(node)
nodebkgndcmd += cmd1
nodecmd += cmd2
edgebodycmd = []
edgeheadcmd = []
- for edge in self.graphlayout.edges:
+ for edge in self.visibleedges:
+
fgcolor = getcolor(edge.color, (0,0,0))
if edge.highlight:
fgcolor = highlight_color(fgcolor)
@@ -435,6 +485,8 @@
return edgebodycmd + nodebkgndcmd + edgeheadcmd + nodecmd
def render(self):
+ self.computevisible()
+
bbox = self.getboundingbox()
self.screen.fill((224, 255, 224), bbox)
@@ -478,7 +530,7 @@
def node_at_position(self, (x, y)):
"""Return the Node under the cursor."""
x, y = self.revmap(x, y)
- for node in self.graphlayout.nodes.itervalues():
+ for node in self.visiblenodes:
if 2.0*abs(x-node.x) <= node.w and 2.0*abs(y-node.y) <= node.h:
return node
return None
@@ -489,7 +541,7 @@
distmax /= self.scale
xy = self.revmap(x, y)
closest_edge = None
- for edge in self.graphlayout.edges:
+ for edge in self.visibleedges:
pts = edge.bezierpoints()
for i in range(1, len(pts)):
d = segmentdistance(pts[i-1], pts[i], xy)
More information about the Pypy-commit
mailing list