This repository has been archived by the owner on May 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathzoomview.py
172 lines (121 loc) · 4.76 KB
/
zoomview.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import pygame
from pygame.locals import *
import random
import numpy
fullscreen = object()
class ZoomView(object):
def __init__(self, lines, ws=(800, 600)):
'''Initialises a ZoomView, given a default window sizes and an array of
lines. Each entry in the array of lines should be a 4-element iterable
containing the (x,y)-coords of the start and end of the line.'''
self.set_lines(lines)
self.ws = ws
def set_lines(self, lines):
self.lines = numpy.asarray(lines)
def show(self):
window = pygame.display.set_mode(self.ws)
pygame.key.set_repeat(300, 50)
try:
self.loop(window)
finally:
pygame.display.quit()
def loop(self, window):
self.init_view()
# initialise the view
moving = False
selecting = False
redraw = True
while True:
if redraw:
self.redraw(window)
if selecting:
x, y = og_pos
mx, my = pygame.mouse.get_pos()
pygame.draw.rect(window, (255, 255, 255),
(x, y, mx-x, my-y), 1)
pygame.display.flip()
redraw = False
ev = pygame.event.wait()
if ev.type == MOUSEBUTTONDOWN:
if ev.button == 4 or ev.button == 5:
zf = 0.8
if ev.button == 5:
zf = 1/zf
((xl, yl), (xh, yh)) = self.view
# map pos to doc
(xd, yd) = self.to_doc(ev.pos)
# recentre view on pos, and adjust
xl, yl, xh, yh = xl-xd, yl-yd, xh-xd, yh-yd
xl, yl, xh, yh = zf*xl, zf*yl, zf*xh, zf*yh
# set new view
self.view = ((xl+xd, yl+yd), (xh+xd, yh+yd))
redraw = True
elif ev.button == 1:
og_view = self.view
og_pos = ev.pos
moving = True
elif ev.button == 3:
og_pos = ev.pos
selecting = True
elif ev.type == MOUSEMOTION:
if moving:
dx, dy = ev.pos[0] - og_pos[0], og_pos[1] - ev.pos[1]
((xl, yl), (xh, yh)) = og_view
dvx, dvy = dx / float(self.ws[0]) * (xh-xl), dy / float(self.ws[1]) * (yh-yl)
self.view = ((xl-dvx, yl-dvy), (xh-dvx, yh-dvy))
redraw = moving or selecting
elif ev.type == MOUSEBUTTONUP:
if ev.button == 1:
moving = False
elif ev.button == 3:
pta = self.to_doc(og_pos)
ptb = self.to_doc(ev.pos)
ul = (min(pta[0], ptb[0]), min(pta[1], ptb[1]))
lr = (max(pta[0], ptb[0]), max(pta[1], ptb[1]))
self.handle_select(ul, lr)
selecting = False
redraw = True
elif ev.type == KEYDOWN and ev.key == K_RETURN:
return
elif ev.type == pygame.QUIT:
return
else:
self.handle_event(ev)
def init_view(self):
xs = self.lines[:, [0, 2]]
ys = self.lines[:, [1, 3]]
self.last_view = (0, 0, 0, 0)
self.view = ((numpy.min(xs), numpy.min(ys)), (numpy.max(xs), numpy.max(ys)))
def to_doc(self, pix_pos):
((xl, yl), (xh, yh)) = self.view
# map pos to doc
x, y = pix_pos
xd = xl + x / float(self.ws[0]) * (xh - xl)
yd = yl + (1 - y / float(self.ws[1])) * (yh - yl)
return (xd, yd)
def from_doc(self, doc_pos):
x, y = doc_pos
((xl, yl), (xh, yh)) = self, view
return (self.ws[0] * (x - xl) / float(xh - xl),
self.ws[1] * (1 - (y - yl) / float(yh - yl)))
def redraw(self, window):
random.seed(0)
window.fill((0, 0, 0))
dl = pygame.draw.line
col = (255, 255, 255)
for x in self.line_screen_coords():
dl(window, col, x[:2], x[2:])
def line_screen_coords(self):
'''Using self.view and self.ws, transforms self.lines to in-window
coords.'''
((xl, yl), (xh, yh)) = self.view
xsf = self.ws[0] / float(xh - xl)
ysf = self.ws[1] / float(yh - yl)
scaled_lines = (self.lines - [xl, yl, xl, yl]) * [xsf, ysf, xsf, ysf]
# flip vertically as PyGame has y increasing downwards
scaled_lines[:, [1, 3]] = self.ws[1] - scaled_lines[:, [1, 3]]
return scaled_lines
def handle_select(self, ul, lr):
print ul, lr
def handle_event(self, ev):
return