-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathray.py
135 lines (106 loc) · 4.42 KB
/
ray.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
# This file is part of Optosketch. It is released under the GPL v2 licence.
from PyQt4 import QtGui, QtCore, Qt
from PyQt4.QtCore import QPointF
import logging
import numpy as np
import math
default_color = QtGui.QColor('orange')
default_ray_pen = QtGui.QPen(QtGui.QColor('black'))
default_handle_pen = QtGui.QPen(QtGui.QColor('red'))
default_handle_pen.setWidth(3)
default_handle_brush = QtGui.QBrush(QtGui.QColor('red'))
class RayHandleItem(QtGui.QGraphicsPathItem):
"""Widget to show a ray's basepoint and unit vector."""
def __init__(self, basepoint, unit,
pen=default_handle_pen,
brush = default_handle_brush,
radius=4,
*args, **kwargs):
"""basepoint, unit: numpy arrays (1x2)"""
super(RayHandleItem, self).__init__(*args, **kwargs)
self.pen = pen
self.brush = brush
self.basepoint = basepoint
self.radius = radius
self.setPen(self.pen)
self.setBrush(self.brush)
self.path = QtGui.QPainterPath()
self._draw(basepoint, unit)
self.setPath(self.path)
self.setCursor(Qt.Qt.SizeAllCursor)
self.__moving = False
self.__rotating = False
print (self.parentItem())
def _draw(self, basepoint, unit):
center = QtCore.QPointF(basepoint[0], basepoint[1])
self.path.addEllipse(center, self.radius, self.radius)
head = basepoint+30*unit
self.path.moveTo(center)
self.path.lineTo(QtCore.QPointF(head[0], head[1]))
def update(self, basepoint, unit):
"""Update handle position and orientation."""
self.path = QtGui.QPainterPath()
self.basepoint = basepoint
self._draw(basepoint, unit)
self.setPath(self.path)
def mousePressEvent(self, event):
logging.debug('RayHandleItem: mouse press')
pos = event.scenePos()
dist = (self.basepoint[0] - pos.x()) ** 2 + \
(self.basepoint[1] - pos.y()) ** 2
if (dist > (self.radius ** 2)):
self.__rotating = True
else:
self.__moving = True
def mouseReleaseEvent(self, event):
self.__moving = False
self.__rotating = False
def mouseMoveEvent(self, event):
current = event.scenePos()
parent = self.parentItem()
if self.__moving:
parent.backend.set_ray_point(parent, current.x(), current.y())
if self.__rotating:
bpt = self.basepoint
dir_vec = np.asarray((current.x() - bpt[0], current.y() - bpt[1]))
# quantize angle if not too far from handle
norm2 = (dir_vec**2).sum()
if norm2 < 4000:
dir_vec = quantize(dir_vec, np.pi/16)
elif norm2 < 20000:
dir_vec = quantize(dir_vec, np.pi/32)
parent.backend.set_ray_direction(parent, dir_vec)
def quantize(vec, step):
"""Return a vector with same length but quantized angle, with given step
(in radians)"""
angle = math.atan2(vec[1], vec[0])
quantized_angle = round(angle/step)*(1.0*step)
norm = np.sqrt((vec**2).sum())
return np.asarray([np.cos(quantized_angle), np.sin(quantized_angle)])*norm
class RayItem(QtGui.QGraphicsPathItem):
def __init__(self, polyline, basepoint, unit,
color=default_color, backend=None, *args):
"""polyline : numpy array, defining ray as a polyline.
basepoint, unit: point through which the ray passes, and unit vector
along the ray at that point."""
super(RayItem, self).__init__(*args)
self.path = QtGui.QPainterPath()
self._draw_polyline(polyline, color=color)
self.setPath(self.path)
self.handle = RayHandleItem(basepoint, unit, parent=self)
self.backend = backend
def _draw_polyline(self, polyline, color=default_color):
"""Draw polyline in current path"""
pen = QtGui.QPen(color)
pen.setWidth(3)
self.setPen(pen)
self.path.moveTo(QPointF(polyline[0,0], polyline[0,1]))
for k in polyline[1:,]:
# print("point: "+str(k))
self.path.lineTo(QPointF(k[0], k[1]))
def update(self, polyline, basepoint, unit, color=default_color):
"""Change the shape of the ray. """
self.path = QtGui.QPainterPath()
self._draw_polyline(polyline, color=color)
self.setPath(self.path)
self.handle.update(basepoint, unit)