Commit 2282da383e7b7d10dc27a05ff2768bae1b9797b3

Authored by Pavel Govyadinov
1 parent 6aca1767

added path selection and visualization of the paths. fixed the drawing of the in…

…visible objects interfearing with the drawing of the selected path.... STABLE
GraphCanvas.py
... ... @@ -9,7 +9,7 @@ Created on Mon Aug 5 15:43:59 2019
9 9 """
10 10  
11 11 from vispy import gloo, scene
12   -from vispy.gloo import set_viewport, set_state, clear, set_blend_color
  12 +from vispy.gloo import set_viewport, set_state, clear, set_blend_color, context
13 13 from vispy.util.transforms import perspective, translate, rotate, scale
14 14 import vispy.gloo.gl as glcore
15 15  
... ... @@ -208,6 +208,40 @@ class GraphCanvas(scene.SceneCanvas):
208 208 self.program.bind(self.vbo)
209 209 #self.program_e.bind(self.vbo)
210 210 self.update()
  211 +
  212 + def update_color_buffers(self):
  213 + color = self.G.vertex_properties["RGBA"].get_2d_array(range(4)).T
  214 + self.data['a_bg_color'] = color
  215 + edges = self.G.get_edges()
  216 + for e in range(edges.shape[0]):
  217 + idx = int(4*edges[e][2])
  218 + self.line_data['a_fg_color'][idx] = color[edges[e][0]]
  219 + self.line_data['a_fg_color'][idx+1] = color[edges[e][1]]
  220 + self.line_data['a_fg_color'][idx+2] = color[edges[e][0]]
  221 + self.line_data['a_fg_color'][idx+3] = color[edges[e][1]]
  222 +
  223 +
  224 +
  225 + self.vbo = gloo.VertexBuffer(self.data)
  226 + self.vbo_line = gloo.VertexBuffer(self.line_data)
  227 + self.program.bind(self.vbo)
  228 + self.program_e.bind(self.vbo_line)
  229 +
  230 +
  231 + """
  232 + Function takes a graph and a state and sets all vertices and edges to
  233 + the transparency defined by state
  234 + """
  235 + def make_all_transparent(self, state):
  236 + for v in self.G.vertices():
  237 + temp = self.G.vertex_properties["RGBA"][v]
  238 + temp[3] = state
  239 + self.G.vertex_properties["RGBA"][v] = temp
  240 + for e in self.G.edges():
  241 + temp = self.G.edge_properties["RGBA"][e]
  242 + temp[3] = state
  243 + self.G.edge_properties["RGBA"][e] = temp
  244 + self.update_color_buffers()
211 245  
212 246 """
213 247 Maps a statistic of the vertices based on the size of the canvas to size of
... ... @@ -1121,19 +1155,33 @@ class GraphCanvas(scene.SceneCanvas):
1121 1155 else:
1122 1156 update_view()
1123 1157  
1124   -
1125 1158 """
1126   - Handles the double click event that it responsible for path selection.
1127   - Generates paths our of consecutive paths out of the selected vertices.
  1159 + Gets the path and formats it in terms of vertex-to-vertex
  1160 + instead of source(obj)-to-source(obj)
1128 1161 """
1129   - def on_mouse_double_click(self, event):
1130   -
  1162 + def get_path(self):
  1163 + p = []
  1164 + for s in self.path:
  1165 + for e in s.e_path:
  1166 + temp = (int(e.source()), int(e.target()))
  1167 + if (temp not in p):
  1168 + p.append(temp)
  1169 +
  1170 + return p
  1171 +
  1172 +
  1173 + def update_path(self, event):
1131 1174 #Method to update the vertex buffer of the nodes in the graph view
1132 1175 def update_vbo(self):
1133 1176 self.vbo = gloo.VertexBuffer(self.data)
1134 1177 self.program.bind(self.vbo)
1135 1178 self.update()
1136 1179  
  1180 + def update_vertex_alpha(self, vertex, alpha):
  1181 + temp = self.G.vertex_properties["RGBA"][vertex]
  1182 + temp[3] = alpha
  1183 + self.G.vertex_properties["RGBA"][vertex] = temp
  1184 +
1137 1185 #updates the path structure of the class
1138 1186 #source and target are of type "source" defined in this class.
1139 1187 def add_to_path(self, source, target):
... ... @@ -1141,16 +1189,25 @@ class GraphCanvas(scene.SceneCanvas):
1141 1189 for v in range(1, len(vl)-1):
1142 1190 if (self.G.vertex_properties["selection"][vl[v]] != 1.0):
1143 1191 self.G.vertex_properties["selection"][vl[v]] = 2.0
  1192 + update_vertex_alpha(self, self.G.vertex(vl[v]), 1.0)
1144 1193 self.data['a_selection'][int(vl[v])] = 2.0
1145 1194 source.v_path.append(int(vl[v]))
1146 1195 for e in el:
1147 1196 source.e_path.append(e)
  1197 + temp = self.G.edge_properties["RGBA"][e]
  1198 + temp[3] = 1.0
  1199 + self.G.edge_properties["RGBA"][e] = temp
1148 1200  
1149 1201  
1150 1202 def remove_from_path(self, source):
1151 1203 for v in source.v_path:
1152 1204 self.G.vertex_properties["selection"][self.G.vertex(v)] = 0.0
  1205 + update_vertex_alpha(self,self.G.vertex(v), 0.5)
1153 1206 self.data['a_selection'][v] = 0.0
  1207 + for e in source.e_path:
  1208 + temp = self.G.edge_properties["RGBA"][e]
  1209 + temp[3] = 0.0
  1210 + self.G.edge_properties["RGBA"][e] = temp
1154 1211 source.clear_path()
1155 1212  
1156 1213 if (event.button == 1):
... ... @@ -1164,12 +1221,15 @@ class GraphCanvas(scene.SceneCanvas):
1164 1221 self.pathing = True
1165 1222 self.path.append(path_point(c_id))
1166 1223 self.data['a_selection'][c_id] = 1.0
1167   - update_vbo(self)
  1224 + self.make_all_transparent(0.5)
  1225 + update_vertex_alpha(self, self.G.vertex(c_id), 1.0)
  1226 + self.update_color_buffers()
1168 1227 print("I turned on the first node")
1169 1228 else:
1170 1229 #If the node is selected already, unselect it and remove from path the last occurance in the path
1171 1230 if(self.G.vertex_properties["selection"][self.G.vertex(c_id)] == 1.0):
1172 1231 self.G.vertex_properties["selection"][self.G.vertex(c_id)] = 0.0
  1232 + update_vertex_alpha(self, self.G.vertex(c_id), 1.0)
1173 1233 self.data['a_selection'][c_id] = 0.0
1174 1234 s_id = self.path.index(path_point(c_id))
1175 1235 if(s_id == 0):
... ... @@ -1187,21 +1247,24 @@ class GraphCanvas(scene.SceneCanvas):
1187 1247 if(path_point(c_id) not in self.path):
1188 1248 self.path.append(path_point(c_id))
1189 1249 self.G.vertex_properties["selection"][self.G.vertex(c_id)] = 1.0
  1250 + update_vertex_alpha(self, self.G.vertex(c_id), 1.0)
1190 1251 self.data['a_selection'][c_id] = 1.0
1191 1252 #if the source is not LAST in the path, add it.
1192 1253 elif(self.path[len(self.path)-1] != path_point(c_id)):
1193 1254 self.path.append(path_point(c_id))
1194 1255 self.G.vertex_properties["selection"][self.G.vertex(c_id)] = 1.0
  1256 + update_vertex_alpha(self, self.G.vertex(c_id), 1.0)
1195 1257 self.data['a_selection'][c_id] = 1.0
1196 1258 print("I turned on a node")
1197 1259 if(len(self.path) >= 1):
1198 1260 for i in range(len(self.path)-1):
1199 1261 add_to_path(self, self.path[i], self.path[i+1])
1200   - update_vbo(self)
  1262 + self.update_color_buffers()
1201 1263 #THIS IS WHERE I LEFT IT OFF.
1202 1264 if(np.sum(self.G.vertex_properties["selection"].get_array()) == 0):
1203 1265 self.pathing = False
1204   - update_vbo(self)
  1266 + self.make_all_transparent(1.0)
  1267 + self.update_color_buffers()
1205 1268  
1206 1269  
1207 1270  
... ... @@ -1209,6 +1272,14 @@ class GraphCanvas(scene.SceneCanvas):
1209 1272 # self.G.vertex_properties["selection"][self.G.vertex(c_id)] == False
1210 1273 print("clicked on: ", c_id, " ", self.path)
1211 1274  
  1275 +
  1276 + """
  1277 + Handles the double click event that it responsible for path selection.
  1278 + Generates paths our of consecutive paths out of the selected vertices.
  1279 + """
  1280 + def on_mouse_double_click(self, event):
  1281 + n=1
  1282 +
1212 1283 """
1213 1284 Resets the variables that are used during the pressdown and move events
1214 1285 """
... ...
GraphWidget.py
... ... @@ -142,7 +142,8 @@ class GraphWidget(QtGui.QWidget):
142 142 Pass-through function.
143 143 """
144 144 def on_mouse_double_click(self, event):
145   - self.select.emit(self.canvas.path)
  145 + self.canvas.update_path(event)
  146 + self.select.emit(self.canvas.get_path())
146 147  
147 148 """
148 149 Handles the mouse release event.
... ...
TubeCanvas.py
... ... @@ -11,7 +11,8 @@ Created on Mon Aug 5 15:56:47 2019
11 11 """
12 12  
13 13 from vispy import gloo, scene
14   -from vispy.gloo import set_viewport, set_state, clear, set_blend_color
  14 +from vispy.gloo import set_viewport, set_state, clear, set_blend_color, context
  15 +from vispy.gloo import gl
15 16 from vispy.util.transforms import perspective, translate, rotate, scale
16 17 import vispy.gloo.gl as glcore
17 18 from vispy.util.quaternion import Quaternion
... ... @@ -40,6 +41,7 @@ class TubeDraw(scene.SceneCanvas):
40 41 #unfreeze the drawing area to allow for dynamic drawing and interaction
41 42 self.unfreeze()
42 43 self.edge_dict = {}
  44 + self.select = False
43 45 #generate dummy buffers for the meshes
44 46 self.program = gloo.Program(VERT_SHADER, FRAG_SHADER)
45 47 self.cylinder_data = np.zeros(5*5, dtype=[('a_position', np.float32, 3),
... ... @@ -59,7 +61,7 @@ class TubeDraw(scene.SceneCanvas):
59 61 #set_state(clear_color='white', depth_test=True, blend=True,
60 62 # blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('less'), cull_face='back')
61 63 set_state(clear_color='white', depth_test=True, blend=True,
62   - blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal'))
  64 + blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal'), cull_face='back')
63 65 #set_blend_color(color='black')
64 66 #set_state('translucent')
65 67 self.program['u_LightPos'] = [0., 0., -1000.]
... ... @@ -72,6 +74,7 @@ class TubeDraw(scene.SceneCanvas):
72 74  
73 75 ##### prototype #####
74 76 #Set the visualization matrices
  77 + self.program['u_selection'] = 0.0
75 78 self.program['u_eye'] = self.camera
76 79 self.program['u_up'] = self.up
77 80 self.program['u_target'] = np.asarray([0., 0., 0.], dtype=np.float32)
... ... @@ -143,6 +146,12 @@ class TubeDraw(scene.SceneCanvas):
143 146 def on_draw(self, event):
144 147 clear(color='white', depth=True)
145 148 gloo.set_clear_color('white')
  149 + if self.select:
  150 + set_state(clear_color='white', depth_test=True, blend=True,
  151 + blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('always'), cull_face='back')
  152 + else:
  153 + set_state(clear_color='white', depth_test=True, blend=True,
  154 + blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal'), cull_face='back')
146 155 self.program.draw('triangles', self.triangles)
147 156 self.projection = perspective(90.0, self.physical_size[0]/self.physical_size[1], 1.0, 1000.0)
148 157 self.program['u_projection'] = self.projection
... ... @@ -158,7 +167,7 @@ class TubeDraw(scene.SceneCanvas):
158 167 self.cylinder_data = np.zeros(num_pts*num_sides, dtype=[('a_position', np.float32, 3),
159 168 ('a_normal', np.float32, 3),
160 169 ('a_fg_color', np.float32, 4),
161   - #('a_linewidth', np.float32, 1),
  170 + ('a_selection', np.float32, 1),
162 171 ])
163 172 self.triangle_data = np.random.randint(size=(num_tri, 3), low=0,
164 173 high=(G.num_edges()-1)).astype(np.uint32)
... ... @@ -288,6 +297,7 @@ class TubeDraw(scene.SceneCanvas):
288 297 circle_pts_data = circle_pts.reshape((pts.shape[0]*num_sides, 3))
289 298 self.cylinder_data['a_position'][index:(pts.shape[0]*num_sides+index)] = circle_pts_data
290 299 self.cylinder_data['a_fg_color'][index:(pts.shape[0]*num_sides+index)] = color
  300 + self.cylinder_data['a_selection'][index:(pts.shape[0]*num_sides+index)] = 0.0
291 301 #generate the normals data structure
292 302 pts_normals = circle_pts.copy()
293 303 for p in range(pts.shape[0]):
... ... @@ -299,7 +309,7 @@ class TubeDraw(scene.SceneCanvas):
299 309 pts_normals.reshape((pts.shape[0]*num_sides, 3))
300 310  
301 311 index += pts.shape[0]*num_sides
302   - self.edge_dict[(e.source(), e.target())] = (index-pts.shape[0]*num_sides, index)
  312 + self.edge_dict[(int(e.source()), int(e.target()))] = (index-pts.shape[0]*num_sides, index)
303 313  
304 314 #Add the caps for each of the endpoints.
305 315  
... ... @@ -333,6 +343,37 @@ class TubeDraw(scene.SceneCanvas):
333 343 i+=1
334 344 #create the data.
335 345  
  346 + def select_edges(self, edges):
  347 + #gloo.context.set_current_canvas(gloo.context.get_current_canvas())
  348 + if len(edges) > 0:
  349 + self.select = True
  350 + #gloo.set_depth_func('always')
  351 + #clear(color='white', depth=True)
  352 + #gl.GL_DEPTH_FUNC('always')
  353 + #print(gloo.wrappers.get_gl_configuration())
  354 + self.program['u_selection'] = 1.0
  355 + for e in edges:
  356 + if e in self.edge_dict:
  357 + idx = self.edge_dict[e]
  358 + #print(self.canvas.edge_dict[e])
  359 + elif (e[1], e[0]) in self.edge_dict:
  360 + idx = self.edge_dict[(e[1],e[0])]
  361 + else:
  362 + print("WHAT THE FUCK HAPPENED")
  363 + self.cylinder_data["a_selection"][idx[0]:idx[1]] = 1.0
  364 + self.vbo = gloo.VertexBuffer(self.cylinder_data)
  365 + self.program.bind(self.vbo)
  366 + #self.update()
  367 + else:
  368 + self.program['u_selection'] = 0.0
  369 + self.select = False
  370 + #set_state(clear_color='white', depth_test=True, blend=True,
  371 + # blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal'))
  372 + #gloo.set_depth_func('lequal')
  373 + #clear(color='white', depth=True)
  374 + #print(gloo.wrappers.get_gl_configuration())
  375 + self.update()
  376 + #print(self.canvas.edge_dict[(e[1], e[0])])
336 377 #Handles the mouse wheel event, i.e., zoom
337 378 def on_mouse_wheel(self, event):
338 379 # self.scale[0] = self.scale[0] + self.scale[0]*event.delta[1]*0.05
... ...
TubeWidget.py
... ... @@ -47,7 +47,7 @@ class TubeWidget(QtGui.QWidget):
47 47 if self.down:
48 48 self.sendCameraInfo()
49 49  
50   - #Handles the mouse press event
  50 + #Handles the mouse press events
51 51 def on_mouse_press(self, event):
52 52 self.down = True
53 53 n = 3
... ... @@ -72,6 +72,12 @@ class TubeWidget(QtGui.QWidget):
72 72 """
73 73 @QtCore.pyqtSlot(list)
74 74 def select(self, x):
  75 + self.canvas.select_edges(x)
  76 +# for e in x:
  77 +# if e in self.canvas.edge_dict:
  78 +# print(self.canvas.edge_dict[e])
  79 +# elif (e[1], e[0]) in self.canvas.edge_dict:
  80 +# print(self.canvas.edge_dict[(e[1], e[0])])
75 81 print("got signal", x)
76 82  
77 83 """
... ...
tube_shaders.py
... ... @@ -15,6 +15,7 @@ uniform vec3 u_LightPost;
15 15 uniform mat4 u_model;
16 16 //uniform mat4 u_view;
17 17 uniform mat4 u_projection;
  18 +uniform float u_selection;
18 19  
19 20 uniform vec3 u_eye;
20 21 uniform vec3 u_up;
... ... @@ -25,6 +26,7 @@ uniform vec3 u_target;
25 26 attribute vec3 a_position;
26 27 attribute vec3 a_normal;
27 28 attribute vec4 a_fg_color;
  29 +attribute float a_selection;
28 30  
29 31 // Varyings
30 32 // ------------------------------------
... ... @@ -33,6 +35,7 @@ varying vec4 v_fg_color;
33 35 varying vec3 v_position;
34 36 varying mat4 u_view;
35 37 varying vec3 vt_position;
  38 +varying float v_selection;
36 39  
37 40  
38 41 // Functions
... ... @@ -50,6 +53,7 @@ void main (void) {
50 53 v_position = vec3(MV*vec4(a_position, 1.0));
51 54 vt_position = vec3(a_position);
52 55 v_fg_color = a_fg_color;
  56 + v_selection = a_selection;
53 57 gl_Position = MVP * vec4(a_position, 1.0);
54 58 }
55 59  
... ... @@ -87,6 +91,7 @@ uniform vec3 u_LightPos;
87 91 uniform mat4 u_model;
88 92 //uniform mat4 u_view;
89 93 uniform mat4 u_projection;
  94 +uniform float u_selection;
90 95  
91 96 uniform vec3 u_eye;
92 97 uniform vec3 u_up;
... ... @@ -99,6 +104,7 @@ varying vec4 v_fg_color;
99 104 varying vec3 v_position;
100 105 varying mat4 u_view;
101 106 varying vec3 vt_position;
  107 +varying float v_selection;
102 108  
103 109 float new_alpha();
104 110 float set_view();
... ... @@ -128,6 +134,9 @@ void main()
128 134  
129 135 vec4 color = (ambient_color + diffuse)*v_fg_color;
130 136 float alpha = new_alpha();
  137 + if(u_selection > 0.0)
  138 + alpha = max(alpha*v_selection, 0.00);
  139 + //alpha = max(alpha * v_selection, 0.05);
131 140 //if(alpha == 1.0)
132 141 // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
133 142 // gl_FragColor = vec4(color.rgb, alpha);
... ...