def _mouse_motion(self, event): """Handler for mouse motion""" if self._button1 or self._button2: dx = event.x - self._event_xy[0] dy = event.y - self._event_xy[1] self._event_xy = (event.x, event.y) if self._button1: if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR rot1 = Quaternion.from_v_theta(self._ax_UD, self._step_UD * dy) rot2 = Quaternion.from_v_theta(ax_LR, self._step_LR * dx) self.rotate(rot1 * rot2) self._draw_cube() if self._button2: factor = 1 - 0.003 * (dx + dy) xlim = self.get_xlim() ylim = self.get_ylim() self.set_xlim(factor * xlim[0], factor * xlim[1]) self.set_ylim(factor * ylim[0], factor * ylim[1]) self.figure.canvas.draw()
def _key_press(self, event): """Handler for key press events""" stickers_to_color = list() if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate(Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 else: direction = 1 # max dir_word = "cw" if direction == 1 else "ccw" if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) # max self.cube.wc.make_move(face=event.key.upper(), layer=d, direction=dir_word) stickers_to_color = self.cube.wc.check_cube() else: self.rotate_face(event.key.upper(), direction) # max self.cube.wc.make_move(face=event.key.upper(), direction=dir_word, layer=0) stickers_to_color = self.cube.wc.check_cube() print(self.cube.wc) print(stickers_to_color) if len(self.stickers_to_color_old) > 0: for i in self.stickers_to_color_old: self._text_annotations[i].set_color("black") for i in stickers_to_color: self._text_annotations[i].set_color("r") self.stickers_to_color_old = stickers_to_color self._draw_cube()
def cube_axes(N=1, **kwargs): """Create an N x N x N rubiks cube kwargs are passed to the PolyView3D instance. """ stickerwidth = 0.9 small = 0.5 * (1. - stickerwidth) d1 = 1 - small d2 = 1 - 2 * small d3 = 1.01 base_sticker = np.array([[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face = np.array( [[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) x, y, z = np.eye(3) rots = [ Quaternion.from_v_theta(x, theta) for theta in (np.pi / 2, -np.pi / 2) ] rots += [ Quaternion.from_v_theta(y, theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] cubie_width = 2. / N translations = np.array( [[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0] for i in range(N) for j in range(N)]) colors = ['blue', 'green', 'white', 'yellow', 'orange', 'red'] factor = np.array([1. / N, 1. / N, 1]) ax = PolyView3D(**kwargs) facecolor = [] polys = [] for t in translations: base_face_trans = factor * base_face + t base_sticker_trans = factor * base_sticker + t for r, c in zip(rots, colors): polys += [r.rotate(base_face_trans), r.rotate(base_sticker_trans)] facecolor += ['k', c] ax.poly3D_batch(polys, facecolor=facecolor) ax.figure.text(0.05, 0.05, ("Drag Mouse or use arrow keys to change perspective.\n" "Hold shift to adjust z-axis rotation"), ha='left', va='bottom') return ax
class Cube(object): """An Axes for displaying a 3D cube""" # fiducial face is perpendicular to z at z=+1 one_face = np.array([[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]]) # Construct six rotators for the cube faces. These will take a single # fiducial face, and rotate it to the appropriate 3D location. x, y, z = np.eye(3) _rots = [ Quaternion.from_v_theta(x, theta) for theta in (np.pi / 2, -np.pi / 2) ] _rots += [ Quaternion.from_v_theta(y, theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] _faces = np.array( [np.dot(one_face, rot.as_rotation_matrix().T) for rot in _rots]) def __init__(self, view=(0, 0, 10), colors=None, alpha=0.8): self.view = view self.current_rotation = Quaternion.from_v_theta((0, 0, 1), 0) if colors is None: colors = ['blue', 'green', 'white', 'yellow', 'orange', 'red'] else: assert len(colors) == 6 self.polys = [ plt.Polygon(self._faces[i, :, :2], facecolor=colors[i], alpha=alpha) for i in range(6) ] def rotate(self, v, theta): new_rot = Quaternion.from_v_theta(v, theta) self.current_rotation = self.current_rotation * new_rot faces_proj = project_points(self._faces, self.current_rotation, self.view) xy = faces_proj[:, :, :2] zorder = -faces_proj[:, :4, 2].mean(-1) for i in range(6): self.polys[i].set_xy(xy[i]) self.polys[i].set_zorder(zorder[i]) def set_view(self, view): self.view = view self.rotate(self.z, 0) def add_to_ax(self, ax): for poly in self.polys: ax.add_patch(poly) ax.set_xlim(-3, 3) ax.set_ylim(-3, 3)
def cube_axes(N=1, **kwargs): """Create an N x N x N rubiks cube kwargs are passed to the PolyView3D instance. """ stickerwidth = 0.9 small = 0.5 * (1. - stickerwidth) d1 = 1 - small d2 = 1 - 2 * small d3 = 1.01 base_sticker = np.array([[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face = np.array([[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) x, y, z = np.eye(3) rots = [Quaternion.from_v_theta(x, theta) for theta in (np.pi / 2, -np.pi / 2)] rots += [Quaternion.from_v_theta(y, theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi)] cubie_width = 2. / N translations = np.array([[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0] for i in range(N) for j in range(N)]) colors = ['blue', 'green', 'white', 'yellow', 'orange', 'red'] factor = np.array([1. / N, 1. / N, 1]) ax = PolyView3D(**kwargs) facecolor = [] polys = [] for t in translations: base_face_trans = factor * base_face + t base_sticker_trans = factor * base_sticker + t for r, c in zip(rots, colors): polys += [r.rotate(base_face_trans), r.rotate(base_sticker_trans)] facecolor += ['k', c] ax.poly3D_batch(polys, facecolor=facecolor) ax.figure.text(0.05, 0.05, ("Drag Mouse or use arrow keys to change perspective.\n" "Hold shift to adjust z-axis rotation"), ha='left', va='bottom') return ax
def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate(Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 else: direction = 1 if np.any(self._digit_flags[:self.cube.N]): for d in solvesolve.arange(self.cube.N)[self._digit_flags[:self.cube.N]]: self.rotate_face(event.key.upper(), direction, layer=d) if direction == 1: self._pycuber_rep((event.key.upper())) elif direction == -1: self._pycuber_rep((event.key.upper()+"'")) else: self.rotate_face(event.key.upper(), direction) if direction == 1: self._pycuber_rep((event.key.upper())) elif direction == -1: self._pycuber_rep((event.key.upper()+"'")) self._draw_cube()
def rotate_event(self, direction, stepsize): if direction == 'right': self.rotate(Quaternion.from_v_theta(self._ax_LR, stepsize * self._step_LR)) elif direction == 'left': self.rotate(Quaternion.from_v_theta(self._ax_LR, -stepsize * self._step_LR)) elif direction == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, stepsize * self._step_UD)) elif direction == 'down': self.rotate(Quaternion.from_v_theta(self._ax_UD, -stepsize * self._step_UD)) self._draw_cube()
def rotate_event(self, direction, stepsize): if direction == 'right': self.rotate( Quaternion.from_v_theta(self._ax_LR, stepsize * self._step_LR)) elif direction == 'left': self.rotate( Quaternion.from_v_theta(self._ax_LR, -stepsize * self._step_LR)) elif direction == 'up': self.rotate( Quaternion.from_v_theta(self._ax_UD, stepsize * self._step_UD)) elif direction == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -stepsize * self._step_UD)) self._draw_cube()
def rotate_face(self, f, n=1, layer=0): """Rotate Face""" if layer < 0 or layer >= self.N: raise ValueError('layer should be between 0 and N-1') try: f_last, n_last, layer_last = self._move_list[-1] except: f_last, n_last, layer_last = None, None, None if (f == f_last) and (layer == layer_last): ntot = (n_last + n) % 4 if abs(ntot - 4) < abs(ntot): ntot = ntot - 4 if np.allclose(ntot, 0): self._move_list = self._move_list[:-1] else: self._move_list[-1] = (f, ntot, layer) else: self._move_list.append((f, n, layer)) v = self.facesdict[f] r = Quaternion.from_v_theta(v, n * np.pi / 2) M = r.as_rotation_matrix() proj = np.dot(self._face_centroids[:, :3], v) cubie_width = 2. / self.N flag = ((proj > 0.9 - (layer + 1) * cubie_width) & (proj < 1.1 - layer * cubie_width)) for x in [self._stickers, self._sticker_centroids, self._faces]: x[flag] = np.dot(x[flag], M.T) self._face_centroids[flag, :3] = np.dot(self._face_centroids[flag, :3], M.T)
def _key_press(self, event): """Handler for key press events""" if not event.key: return elif event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, - 5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate(Quaternion.from_v_theta(self._ax_UD, - 5 * self._step_UD)) elif event.key.upper() in InteractiveCube.FACES: # if self._shift: if event.key in InteractiveCube.FACES: # Upper-case direction = -1 else: # Lower-case direction = 1 N = self.cube.N if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) else: self.rotate_face(event.key.upper(), direction) self._draw_cube()
def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._ax_LR = (0, 0, 1) elif event.key == 'right': self.rotate(Quaternion.from_v_theta(self._ax_LR, 5 * self._step_LR)) elif event.key == 'left': self.rotate(Quaternion.from_v_theta(self._ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate(Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) self._update_projection()
def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._ax_LR = (0, 0, 1) elif event.key == 'right': self.rotate(Quaternion.from_v_theta(self._ax_LR, 5 * self._step_LR)) elif event.key == 'left': self.rotate( Quaternion.from_v_theta(self._ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) self._update_projection()
def _key_press(self, event): """Handler for key press events""" #matplotlib does not detect shift events by itself if event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right' or event.key == 'shift+right': if event.key == 'shift+right': ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'shift+left' or event.key == 'left': if event.key == 'shift+left': ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if event.key in 'LRUDBF': direction = -1 else: direction = 1 sanitizedMove = event.key.upper() + "" if direction == 1 else "'" if np.any(self._digit_flags[:self.cube.N]): for d in np.arange( self.cube.N)[self._digit_flags[:self.cube.N]]: self.rotate_face(event.key.upper(), direction, layer=d) self._pycuber_rep(sanitizedMove) else: self.rotate_face(event.key.upper(), direction) self._pycuber_rep(sanitizedMove) self._moveList.append(sanitizedMove) print(str(self._moveList)) self._printShuffleLabel(self._moveList) self._draw_cube()
def _mouse_motion(self, event): """Handler for mouse motion""" if self._button1 or self._button2: dx = event.x - self._event_xy[0] dy = event.y - self._event_xy[1] self._event_xy = (event.x, event.y) if self._button1: if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR rot1 = Quaternion.from_v_theta(self._ax_UD, self._step_UD * dy) rot2 = Quaternion.from_v_theta(ax_LR, self._step_LR * dx) self.rotate(rot1 * rot2) self._draw_cube() ''' if self._figsave%10==0: plt.savefig("images2/test"+str(self._figsave)+".jpg") abcd = ["test"+str(self._figsave)+".jpg"] # array([0.00834558, 0.00809627, 0.01133022, 0.01168023]) currot = [np.float(ab) for ab in (str(self._current_rot)[7:-2]).replace(" ","").split(",")] abcd.extend(currot) self._figquats.append(abcd) print("Saved ",len(self._figquats)) if len(self._figquats) == 50: print("Saving data to file..") with open('quaternions2.csv', 'w', newline='') as file: writer = csv.writer(file) for quat in self._figquats: writer.writerow(quat) self._figsave += 1 ''' if self._button2: factor = 1 - 0.003 * (dx + dy) xlim = self.get_xlim() ylim = self.get_ylim() self.set_xlim(factor * xlim[0], factor * xlim[1]) self.set_ylim(factor * ylim[0], factor * ylim[1]) self.figure.canvas.draw()
def _key_press(self, event): """Handler for key press events""" if event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': self.rotate(Quaternion.from_v_theta(self._ax_LR, 5 * self._step_LR)) elif event.key == 'left': self.rotate( Quaternion.from_v_theta(self._ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'URF': self.rotate_face(event.key.upper(), 1) self._draw_cube()
def rotate(self, v, theta): new_rot = Quaternion.from_v_theta(v, theta) self.current_rotation = self.current_rotation * new_rot faces_proj = project_points(self._faces, self.current_rotation, self.view) xy = faces_proj[:, :, :2] zorder = -faces_proj[:, :4, 2].mean(-1) for i in range(6): self.polys[i].set_xy(xy[i]) self.polys[i].set_zorder(zorder[i])
def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 #Era -1 else: direction = 1 #Era 1 if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) else: self.rotate_face(event.key.upper(), direction) self.deordering_movs.append( direction * (self.movList.index(event.key.upper()) + 1)) #print("self.deordering_movs") #print(self.deordering_movs) self._draw_cube()
def __init__(self, view=(0, 0, 10), colors=None, alpha=0.8): self.view = view self.current_rotation = Quaternion.from_v_theta((0, 0, 1), 0) if colors is None: colors = ['blue', 'green', 'white', 'yellow', 'orange', 'red'] else: assert len(colors) == 6 self.polys = [plt.Polygon(self._faces[i, :, :2], facecolor=colors[i], alpha=alpha) for i in range(6)]
def __init__(self, view=(0, 0, 10), colors=None, alpha=0.8): self.view = view self.current_rotation = Quaternion.from_v_theta((0, 0, 1), 0) if colors is None: colors = ['blue', 'green', 'white', 'yellow', 'orange', 'red'] else: assert len(colors) == 6 self.polys = [ plt.Polygon(self._faces[i, :, :2], facecolor=colors[i], alpha=alpha) for i in range(6) ]
def _key_press(self, event): """Operador para eventos de pressionar tecla""" if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 else: direction = 1 if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) else: self.rotate_face(event.key.upper(), direction) self._draw_cube()
def __init__(self, view=(0, 0, 10), fig=None, rect=None, **kwargs): if rect is None: rect = [0, 0, 1, 1] if fig is None: fig = plt.gcf() self.view = np.asarray(view) self.start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 # Internal state variable self._button1 = False self._button2 = False self._event_xy = None self._current_rot = self.start_rot self._npts = [1] self._xyzs = [[0, 0, 0]] self._xys = [[0, 0]] self._polys = [] # initialize the axes. We'll set some keywords by default kwargs.update(dict(aspect='equal', xlim=(-2.5, 2.5), ylim=(-2.5, 2.5), frameon=False, xticks=[], yticks=[])) super(PolyView3D, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release)
def __init__(self, view=(0, 0, 10), fig=None, rect=[0, 0, 1, 1], **kwargs): if fig is None: fig = plt.gcf() self.view = np.asarray(view) self.start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 # Internal state variable self._button1 = False self._button2 = False self._event_xy = None self._current_rot = self.start_rot self._npts = [1] self._xyzs = [[0, 0, 0]] self._xys = [[0, 0]] self._polys = [] # initialize the axes. We'll set some keywords by default kwargs.update(dict(aspect='equal', xlim=(-2.5, 2.5), ylim=(-2.5, 2.5), frameon=False, xticks=[], yticks=[])) super(PolyView3D, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release)
class Cube: """Representacao do Cubo Magico""" # define alguns atributos default_plastic_color = 'black' default_face_colors = [ "w", "#00ff80", "#ff007f", "#007fff", "#ff8000", "#ffff00", "#141400", "none" ] base_face = np.array( [[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) stickerwidth = 0.9 stickermargin = 0.5 * (1. - stickerwidth) stickerthickness = 0.001 (d1, d2, d3) = (1 - stickermargin, 1 - 2 * stickermargin, 1 + stickerthickness) base_sticker = np.array([[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face_centroid = np.array([[0, 0, 1]]) base_sticker_centroid = np.array([[0, 0, 1 + stickerthickness]]) # Define a rotacao dos angulos e eixos para os 6 lados do cubo x, y, z = np.eye(3) rots = [ Quaternion.from_v_theta(np.eye(3)[0], theta) for theta in (np.pi / 2, -np.pi / 2) ] rots += [ Quaternion.from_v_theta(np.eye(3)[1], theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] # define os movimentos das faces facesdict = dict(F=z, B=-z, R=x, L=-x, U=y, D=-y) def __init__(self, N=3, plastic_color=None, face_colors=None): self.N = N if plastic_color is None: self.plastic_color = self.default_plastic_color else: self.plastic_color = plastic_color if face_colors is None: self.face_colors = self.default_face_colors else: self.face_colors = face_colors self._move_list = [] self._initialize_arrays() def _initialize_arrays(self): # Inicializa os centroides, faces e adesivos do cubo.Comecamos com uma # base para cada um, e entao transladamos e rotacionamos na posicao. # Define N^2 translacoes para cada face do cubo cubie_width = 2. / self.N translations = np.array( [[[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0]] for i in range(self.N) for j in range(self.N)]) # Cria arrays para os centroides, faces, adesivos e cores face_centroids = [] faces = [] sticker_centroids = [] stickers = [] colors = [] factor = np.array([1. / self.N, 1. / self.N, 1]) for i in range(6): M = self.rots[i].as_rotation_matrix() faces_t = np.dot(factor * self.base_face + translations, M.T) stickers_t = np.dot(factor * self.base_sticker + translations, M.T) face_centroids_t = np.dot(self.base_face_centroid + translations, M.T) sticker_centroids_t = np.dot( self.base_sticker_centroid + translations, M.T) colors_i = i + np.zeros(face_centroids_t.shape[0], dtype=int) # Anexa o id da face a face do centroide para o embaralhamento face_centroids_t = np.hstack( [face_centroids_t.reshape(-1, 3), colors_i[:, None]]) sticker_centroids_t = sticker_centroids_t.reshape((-1, 3)) faces.append(faces_t) face_centroids.append(face_centroids_t) stickers.append(stickers_t) sticker_centroids.append(sticker_centroids_t) colors.append(colors_i) self._face_centroids = np.vstack(face_centroids) self._faces = np.vstack(faces) self._sticker_centroids = np.vstack(sticker_centroids) self._stickers = np.vstack(stickers) self._colors = np.concatenate(colors) self._sort_faces() def _sort_faces(self): # Use o embaralhamento(lexsort) nos centroides para colocar as faces na ordem original ind = np.lexsort(self._face_centroids.T) self._face_centroids = self._face_centroids[ind] self._sticker_centroids = self._sticker_centroids[ind] self._stickers = self._stickers[ind] self._colors = self._colors[ind] self._faces = self._faces[ind] def rotate_face(self, f, n=1, layer=0): """Rotacao da face""" if layer < 0 or layer >= self.N: raise ValueError('camada deve estar entre 0 e N-1') try: f_last, n_last, layer_last = self._move_list[-1] except: f_last, n_last, layer_last = None, None, None if (f == f_last) and (layer == layer_last): ntot = (n_last + n) % 4 if abs(ntot - 4) < abs(ntot): ntot = ntot - 4 if np.allclose(ntot, 0): self._move_list = self._move_list[:-1] else: self._move_list[-1] = (f, ntot, layer) else: self._move_list.append((f, n, layer)) v = self.facesdict[f] r = Quaternion.from_v_theta(v, n * np.pi / 2) M = r.as_rotation_matrix() proj = np.dot(self._face_centroids[:, :3], v) cubie_width = 2. / self.N flag = ((proj > 0.9 - (layer + 1) * cubie_width) & (proj < 1.1 - layer * cubie_width)) for x in [self._stickers, self._sticker_centroids, self._faces]: x[flag] = np.dot(x[flag], M.T) self._face_centroids[flag, :3] = np.dot(self._face_centroids[flag, :3], M.T) def draw_interactive(self): fig = plt.figure(figsize=(5, 5)) fig.add_axes(InteractiveCube(self)) return fig
def __init__(self, cube=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): if cube is None: self.cube = Cube(3) elif isinstance(cube, Cube): self.cube = cube else: self.cube = Cube(cube) self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # disable default key press events callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # add some defaults, and draw axes kwargs.update(dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Internal state variable self._active = False # true when mouse is over axes self._button1 = False # true when button 1 is pressed self._button2 = False # true when button 2 is pressed self._event_xy = None # store xy position of mouse event self._shift = False # shift key pressed self._digit_flags = np.zeros(10, dtype=bool) # digits 0-9 pressed self._current_rot = self._start_rot #current rotation state self._face_polys = None self._sticker_polys = None self._draw_cube() # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) self._initialize_widgets() # write some instructions self.figure.text(0.05, 0.05, "Mouse/arrow keys adjust view\n" "U/D/L/R/B/F keys turn faces\n" "(hold shift for counter-clockwise)", size=10)
def __init__(self, cube=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): if cube is None: self.cube = Cube(3) elif isinstance(cube, Cube): self.cube = cube else: self.cube = Cube(cube) self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # disable default key press events callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # add some defaults, and draw axes kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Internal state variable self._active = False # true when mouse is over axes self._button1 = False # true when button 1 is pressed self._button2 = False # true when button 2 is pressed self._event_xy = None # store xy position of mouse event self._shift = False # shift key pressed self._digit_flags = np.zeros(10, dtype=bool) # digits 0-9 pressed self._current_rot = self._start_rot #current rotation state self._face_polys = None self._sticker_polys = None self._draw_cube() # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) self._initialize_widgets() # write some instructions self.figure.text(0.05, 0.05, "Mouse/arrow keys adjust view\n" "U/D/L/R/B/F keys turn faces\n" "(hold shift for counter-clockwise)", size=10)
def __init__(self, cube=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): if cube is None: self.cube = Cube(3) elif isinstance(cube, Cube): self.cube = cube else: self.cube = Cube(cube) self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # Desabilita eventos de pressionar teclas callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # Adicionar alguns padroes e desenha eixos kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define o movimento cima/baixo do mouse e teclado self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define o movimento de esquerda/direita do mouse e teclado self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Variavel de estado interno self._active = False # Verdade quando o mouse estiver sobre os eixos self._button1 = False # Verdadeiro quando o botão 1 é pressionado self._button2 = False # Verdadeiro quando o botão 2 é pressionado self._event_xy = None # Armazena a posição xy de um evento do mouse self._shift = False # tecla SHIFT pressionada self._digit_flags = np.zeros(10, dtype=bool) # digitos 0-9 pressionados self._current_rot = self._start_rot #Atual estado de rotacao self._face_polys = None self._sticker_polys = None self._draw_cube() # Conecta alguns eventos da GUI self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) self._initialize_widgets() # escrever algumas instrucoes self.figure.text(0.05, 0.05, "Mouse/setas para andar pelo cubo\n" "U/D/L/R/B/F para movimentos\n" "(segure SHIFT para anti-horario)", size=10)
class InteractiveCube(plt.Axes): # Define some attributes base_face = np.array( [[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) stickerwidth = 0.9 stickermargin = 0.5 * (1. - stickerwidth) stickerthickness = 0.001 (d1, d2, d3) = (1 - stickermargin, 1 - 2 * stickermargin, 1 + stickerthickness) base_sticker = np.array([[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face_centroid = np.array([[0, 0, 1]]) base_sticker_centroid = np.array([[0, 0, 1 + stickerthickness]]) # Define rotation angles and axes for the six sides of the cube x, y, z = np.eye(3) rots = [ Quaternion.from_v_theta(x, theta) for theta in (np.pi / 2, -np.pi / 2) ] rots += [ Quaternion.from_v_theta(y, theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] def __init__(self, N, sess=None, inputTensPH=None, outputTens=None, state=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): self._move_list = [] self.N = N self.sess = sess self.inputTensPH = inputTensPH self.outputTens = outputTens self._prevStates = [] self.Environment = Cube(N=3, moveType="qtm") self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # disable default key press events callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # add some defaults, and draw axes kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Internal state variable self._active = False # true when mouse is over axes self._button1 = False # true when button 1 is pressed self._button2 = False # true when button 2 is pressed self._event_xy = None # store xy position of mouse event self._shift = False # shift key pressed self._digit_flags = np.zeros(10, dtype=bool) # digits 0-9 pressed self._current_rot = self._start_rot #current rotation state self._face_polys = None self._sticker_polys = None self.plastic_color = 'black' # WHITE:0 - U, YELLOW:1 - D, BLUE:2 - L, GREEN:3 - R, ORANGE: 4 - B, RED: 5 - F self.face_colors = [ "w", "#ffcf00", "#ff6f00", "#cf0000", "#00008f", "#009f0f", "gray", "none" ] self._initialize_arrays() self._draw_cube() # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) #self._initialize_widgets() # write some instructions """ self.figure.text(0.05, 0.05, "Mouse/arrow keys adjust view\n" "U/D/L/R/B/F keys turn faces\n" "(hold shift for counter-clockwise)", size=10) """ if state is not None: self._colors = np.array([int(x) for x in state.split(",")]) self._draw_cube() def _initialize_arrays(self): # initialize centroids, faces, and stickers. We start with a # base for each one, and then translate & rotate them into position. # Define N^2 translations for each face of the cube cubie_width = 2. / self.N translations = np.array( [[[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0]] for i in range(self.N) for j in range(self.N)]) # Create arrays for centroids, faces, stickers face_centroids = [] faces = [] sticker_centroids = [] stickers = [] colors = [] factor = np.array([1. / self.N, 1. / self.N, 1]) for i in range(6): M = self.rots[i].as_rotation_matrix() faces_t = np.dot(factor * self.base_face + translations, M.T) stickers_t = np.dot(factor * self.base_sticker + translations, M.T) face_centroids_t = np.dot(self.base_face_centroid + translations, M.T) sticker_centroids_t = np.dot( self.base_sticker_centroid + translations, M.T) #colors_i = i + np.zeros(face_centroids_t.shape[0], dtype=int) colors_i = np.arange(i * face_centroids_t.shape[0], (i + 1) * face_centroids_t.shape[0]) # append face ID to the face centroids for lex-sorting face_centroids_t = np.hstack( [face_centroids_t.reshape(-1, 3), colors_i[:, None]]) sticker_centroids_t = sticker_centroids_t.reshape((-1, 3)) faces.append(faces_t) face_centroids.append(face_centroids_t) stickers.append(stickers_t) sticker_centroids.append(sticker_centroids_t) colors.append(colors_i) self._face_centroids = np.vstack(face_centroids) self._faces = np.vstack(faces) self._sticker_centroids = np.vstack(sticker_centroids) self._stickers = np.vstack(stickers) self._colors = np.concatenate(colors) def reset(self): self._colors = self.Environment.solvedState def getState(self): return (self._colors) def _initialize_widgets(self): self._ax_reset = self.figure.add_axes([0.75, 0.05, 0.2, 0.075]) self._btn_reset = widgets.Button(self._ax_reset, 'Reset View') self._btn_reset.on_clicked(self._reset_view) self._ax_solve = self.figure.add_axes([0.55, 0.05, 0.2, 0.075]) self._btn_solve = widgets.Button(self._ax_solve, 'Solve Cube') self._btn_solve.on_clicked(self._solve_cube) def _project(self, pts): return project_points(pts, self._current_rot, self._view, [0, 1, 0]) def _draw_cube(self): stickers = self._project(self._stickers)[:, :, :2] faces = self._project(self._faces)[:, :, :2] face_centroids = self._project(self._face_centroids[:, :3]) sticker_centroids = self._project(self._sticker_centroids[:, :3]) plastic_color = self.plastic_color #self._colors[np.ravel_multi_index((0,1,2),(6,N,N))] = 10 #self._colors[self.Environment.colorsToGet] = 54 colors = np.asarray(self.face_colors)[self._colors / (self.N**2)] face_zorders = -face_centroids[:, 2] sticker_zorders = -sticker_centroids[:, 2] if self._face_polys is None: # initial call: create polygon objects and add to axes self._face_polys = [] self._sticker_polys = [] for i in range(len(colors)): fp = plt.Polygon(faces[i], facecolor=plastic_color, zorder=face_zorders[i]) sp = plt.Polygon(stickers[i], facecolor=colors[i], zorder=sticker_zorders[i]) self._face_polys.append(fp) self._sticker_polys.append(sp) self.add_patch(fp) self.add_patch(sp) else: # subsequent call: update the polygon objects for i in range(len(colors)): self._face_polys[i].set_xy(faces[i]) self._face_polys[i].set_zorder(face_zorders[i]) self._face_polys[i].set_facecolor(plastic_color) self._sticker_polys[i].set_xy(stickers[i]) self._sticker_polys[i].set_zorder(sticker_zorders[i]) self._sticker_polys[i].set_facecolor(colors[i]) self.figure.canvas.draw() def rotate(self, rot): self._current_rot = self._current_rot * rot def rotate_face(self, f, n=1, layer=0): self._move_list.append((f, n, layer)) if not np.allclose(n, 0): self._colors = self.Environment.next_state(self._colors, [f, n], layer=layer) self._draw_cube() def move(self, move, draw=True): self._colors = self.Environment.next_state(self._colors, move) if draw: self._draw_cube() def _reset_view(self, *args): self.set_xlim(self._start_xlim) self.set_ylim(self._start_ylim) self._current_rot = self._start_rot self._draw_cube() def _solve_cube(self, *args): move_list = self._move_list[:] for (face, n, layer) in move_list[::-1]: self.rotate_face(face, -n, layer) self._move_list = [] def _solve_cube_kociemba(self): # WHITE:0 - U, YELLOW:1 - D, BLUE:2 - L, GREEN:3 - R, ORANGE: 4 - B, RED: 5 - F moves = Kociemba.solve(self._colors) #print "Solution length: %i" % (len(moves)) for face, n in moves: self.rotate_face(face, n, 0) def _solve_cube_nnet(self): startTime = time.time() BestFS_solve = search_utils.BestFS_solve([self._colors], self.sess, self.inputTensPH, self.outputTens, self.Environment) isSolved, solveSteps = BestFS_solve.run(numParallel=200, verbose=True) ### Make move moves = solveSteps[0] #print("Cube scrambled %i times. Neural network found solution of length %i (%s)" % (len(self._move_list),len(moves),time.time()-startTime)) for face, n in moves: self.rotate_face(face, n, 0) time.sleep(0.1) def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 else: direction = 1 if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) else: self.rotate_face(event.key.upper(), direction) elif event.key.upper() in 'QWEA': if event.key.upper() == 'Q': self._colors = self.Environment.transpose( self._colors, 0, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'W': self._colors = self.Environment.transpose( self._colors, 2, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'E': self._colors = self.Environment.transpose( self._colors, 4, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'A': self._colors = self.Environment.transpose( self._colors, -1, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'K': self._solve_cube_kociemba() elif event.key.upper() == 'O': self._solve_cube_korf() elif event.key.upper() == 'N': self._solve_cube_nnet() elif event.key.upper() == 'P': self.figure.savefig('cubeSnapshot.eps') self._draw_cube() isSolved = self.Environment.checkSolved(self._colors) if isSolved: print("SOLVED!") self._move_list = [] self._prevStates = [] def _key_release(self, event): """Handler for key release event""" if event.key == 'shift': self._shift = False elif event.key.isdigit(): self._digit_flags[int(event.key)] = 0 def _mouse_press(self, event, event_x=None, event_y=None): """Handler for mouse button press""" if event_x != None and event_y != None: self._event_xy = (event_x, event_y) self._button1 = True else: self._event_xy = (event.x, event.y) if event.button == 1: self._button1 = True elif event.button == 3: self._button2 = True def _mouse_release(self, event): """Handler for mouse button release""" self._event_xy = None if event.button == 1: self._button1 = False elif event.button == 3: self._button2 = False def _mouse_motion(self, event, event_x=None, event_y=None): """Handler for mouse motion""" if self._button1 or self._button2: if event_x != None and event_y != None: dx = event_x - self._event_xy[0] dy = event_y - self._event_xy[1] self._event_xy = (event_x, event_y) else: dx = event.x - self._event_xy[0] dy = event.y - self._event_xy[1] self._event_xy = (event.x, event.y) if self._button1: if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR rot1 = Quaternion.from_v_theta(self._ax_UD, self._step_UD * dy) rot2 = Quaternion.from_v_theta(ax_LR, self._step_LR * dx) self.rotate(rot1 * rot2) self._draw_cube() if self._button2: factor = 1 - 0.003 * (dx + dy) xlim = self.get_xlim() ylim = self.get_ylim() self.set_xlim(factor * xlim[0], factor * xlim[1]) self.set_ylim(factor * ylim[0], factor * ylim[1]) self.figure.canvas.draw()
class Cube: """Rubik's Cube Representation""" # define some attribues default_init_state = np.array([ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5 ]) # move indices moveInds = { \ "U": 0, "U2": 1 , "R": 2, "R2": 3, "F": 4, "F2": 5\ } # move definitions moveDefs = np.array([ \ [ 2, 0, 3, 1, 6, 7, 8, 9, 10, 11, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], \ [ 3, 2, 1, 0, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], \ [ 0, 7, 2, 15, 4, 5, 6, 21, 16, 8, 3, 11, 12, 13, 14, 23, 17, 9, 1, 19, 20, 18, 22, 10], \ [ 0, 21, 2, 23, 4, 5, 6, 18, 17, 16, 15, 11, 12, 13, 14, 10, 9, 8, 7, 19, 20, 1, 22, 3], \ [ 0, 1, 13, 5, 4, 20, 14, 6, 2, 9, 10, 11, 12, 21, 15, 7, 3, 17, 18, 19, 16, 8, 22, 23], \ [ 0, 1, 21, 20, 4, 16, 15, 14, 13, 9, 10, 11, 12, 8, 7, 6, 5, 17, 18, 19, 3, 2, 22, 23], \ ]) # piece definitions pieceDefs = np.array([ \ [ 0, 11, 4], \ [ 2, 5, 6], \ [ 3, 7, 8], \ [ 1, 9, 10], \ [ 20, 14, 13], \ [ 21, 15, 15], \ [ 23, 18, 17], \ ]) default_plastic_color = 'black' default_face_colors = [ "w", "#ffcf00", "#00008f", "#009f0f", "#ff6f00", "#cf0000", "gray", "none" ] base_face = np.array( [[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) face_element_width = 0.9 face_element_margin = 0.5 * (1. - face_element_width) face_element_thickness = 0.001 (d1, d2, d3) = (1 - face_element_margin, 1 - 2 * face_element_margin, 1 + face_element_thickness) base_face_element = np.array( [[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face_centroid = np.array([[0, 0, 1]]) base_face_element_centroid = np.array([[0, 0, 1 + face_element_thickness]]) # apply a move to a state def doMove(self, move): return self.state[self.moveDefs[self.moveInds[m]]] # apply a string sequence of moves to a state def doAlgStr(self, alg): moves = alg.split(" ") for m in moves: if m in self.moveInds: self.state = self.state[self.moveDefs[self.moveInds[m]]] self._printCube() # print state of the cube def _printCube(self): print(" ┌──┬──┐") print(" │ {}│ {}│".format(self.state[0], self.state[1])) print(" ├──┼──┤") print(" │ {}│ {}│".format(self.state[2], self.state[3])) print("┌──┬──┼──┼──┼──┬──┬──┬──┐") print("│ {}│ {}│ {}│ {}│ {}│ {}│ {}│ {}│".format( self.state[4], self.state[5], self.state[6], self.state[7], self.state[8], self.state[9], self.state[10], self.state[11])) print("├──┼──┼──┼──┼──┼──┼──┼──┤") print("│ {}│ {}│ {}│ {}│ {}│ {}│ {}│ {}│".format( self.state[12], self.state[13], self.state[14], self.state[15], self.state[16], self.state[17], self.state[18], self.state[19])) print("└──┴──┼──┼──┼──┴──┴──┴──┘") print(" │ {}│ {}│".format(self.state[20], self.state[21])) print(" ├──┼──┤") print(" │ {}│ {}│".format(self.state[22], self.state[23])) print(" └──┴──┘") # Define rotation angles and axes for the six sides of the cube x, y, z = np.eye(3) rots = [ Quaternion.from_v_theta(np.eye(3)[0], theta) for theta in (np.pi / 2, -np.pi / 2) ] rots += [ Quaternion.from_v_theta(np.eye(3)[1], theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] # define face movements facesdict = dict(F=z, B=-z, R=x, L=-x, U=y, D=-y) def __init__(self, N=2, plastic_color=None, face_colors=None): self.N = N if plastic_color is None: self.plastic_color = self.default_plastic_color else: self.plastic_color = plastic_color if face_colors is None: self.face_colors = self.default_face_colors else: self.face_colors = face_colors self.state = np.array([ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5 ]) #self.state = np.array(['00000', '00001', '00010', '00011', '00100', '00101', '00110', '00111', '01000', '01001', '01010', '01011', '01100', '01101', '01110', '01111', '10000', '10001', '10010', '10011', '10100', '10101', '10110', '10111']) self._move_list = [] self._solution = [] self._initialize_arrays() def _initialize_arrays(self): # initialize centroids, faces, and face elements. We start with a # base for each one, and then translate & rotate them into position. # Define N^2 translations for each face of the cube cubie_width = 2. / self.N translations = np.array( [[[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0]] for i in range(self.N) for j in range(self.N)]) # Create arrays for centroids, faces, face elements, and colors face_centroids = [] faces = [] face_element_centroids = [] face_elements = [] colors = [] factor = np.array([1. / self.N, 1. / self.N, 1]) for i in range(6): M = self.rots[i].as_rotation_matrix() faces_t = np.dot(factor * self.base_face + translations, M.T) face_elements_t = np.dot( factor * self.base_face_element + translations, M.T) face_centroids_t = np.dot(self.base_face_centroid + translations, M.T) face_element_centroids_t = np.dot( self.base_face_element_centroid + translations, M.T) colors_i = i + np.zeros(face_centroids_t.shape[0], dtype=int) # append face ID to the face centroids for lex-sorting face_centroids_t = np.hstack( [face_centroids_t.reshape(-1, 3), colors_i[:, None]]) face_element_centroids_t = face_element_centroids_t.reshape( (-1, 3)) faces.append(faces_t) face_centroids.append(face_centroids_t) face_elements.append(face_elements_t) face_element_centroids.append(face_element_centroids_t) colors.append(colors_i) self._face_centroids = np.vstack(face_centroids) self._faces = np.vstack(faces) self._face_element_centroids = np.vstack(face_element_centroids) self._face_elements = np.vstack(face_elements) self._colors = np.concatenate(colors) self._sort_faces() def _sort_faces(self): # use lexsort on the centroids to put faces in a standard order. ind = np.lexsort(self._face_centroids.T) self._face_centroids = self._face_centroids[ind] self._face_element_centroids = self._face_element_centroids[ind] self._face_elements = self._face_elements[ind] self._colors = self._colors[ind] self._faces = self._faces[ind] def rotate_face(self, f, n=1, layer=0): self.doAlgStr(f) """Rotate Face""" if layer < 0 or layer >= self.N: raise ValueError('layer should be between 0 and N-1') try: f_last, n_last, layer_last = self._move_list[-1] except: f_last, n_last, layer_last = None, None, None if (f == f_last) and (layer == layer_last): ntot = (n_last + n) % 4 if abs(ntot - 4) < abs(ntot): ntot = ntot - 4 if np.allclose(ntot, 0): self._move_list = self._move_list[:-1] else: self._move_list[-1] = (f, ntot, layer) else: self._move_list.append(f) v = self.facesdict[f] r = Quaternion.from_v_theta(v, n * np.pi / 2) M = r.as_rotation_matrix() proj = np.dot(self._face_centroids[:, :3], v) cubie_width = 2. / self.N flag = ((proj > 0.9 - (layer + 1) * cubie_width) & (proj < 1.1 - layer * cubie_width)) for x in [ self._face_elements, self._face_element_centroids, self._faces ]: x[flag] = np.dot(x[flag], M.T) self._face_centroids[flag, :3] = np.dot(self._face_centroids[flag, :3], M.T) def draw_interactive(self): fig = plt.figure(figsize=(5, 5)) fig.add_axes(InteractiveCube(self)) return fig
def __init__(self, cube=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): if cube is None: self.cube = Cube(3) elif isinstance(cube, Cube): self.cube = cube else: self.cube = Cube(cube) self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] self._ax_UD = (1, 0, 0) self._step_UD = 0.01 self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) self._active = False self._button1 = False self._button2 = False self._event_xy = None self._shift = False self._digit_flags = np.zeros(10, dtype=bool) self._current_rot = self._start_rot self._face_polys = None self._sticker_polys = None self._draw_cube() self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) self._initialize_widgets() self.figure.text(0.05, 0.05, "Mouse/arrow keys adjust view\n" "U/D/L/R/B/F keys turn faces\n" "(hold shift for counter-clockwise)", size=10)
def __init__(self, N, sess=None, inputTensPH=None, outputTens=None, state=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): self._move_list = [] self.N = N self.sess = sess self.inputTensPH = inputTensPH self.outputTens = outputTens self._prevStates = [] self.Environment = Cube(N=3, moveType="qtm") self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # disable default key press events callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # add some defaults, and draw axes kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Internal state variable self._active = False # true when mouse is over axes self._button1 = False # true when button 1 is pressed self._button2 = False # true when button 2 is pressed self._event_xy = None # store xy position of mouse event self._shift = False # shift key pressed self._digit_flags = np.zeros(10, dtype=bool) # digits 0-9 pressed self._current_rot = self._start_rot #current rotation state self._face_polys = None self._sticker_polys = None self.plastic_color = 'black' # WHITE:0 - U, YELLOW:1 - D, BLUE:2 - L, GREEN:3 - R, ORANGE: 4 - B, RED: 5 - F self.face_colors = [ "w", "#ffcf00", "#ff6f00", "#cf0000", "#00008f", "#009f0f", "gray", "none" ] self._initialize_arrays() self._draw_cube() # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) #self._initialize_widgets() # write some instructions """ self.figure.text(0.05, 0.05, "Mouse/arrow keys adjust view\n" "U/D/L/R/B/F keys turn faces\n" "(hold shift for counter-clockwise)", size=10) """ if state is not None: self._colors = np.array([int(x) for x in state.split(",")]) self._draw_cube()
def _key_press(self, event): """Handler for key press events""" if event.key == 'shift': self._shift = True elif event.key.isdigit(): self._digit_flags[int(event.key)] = 1 elif event.key == 'right': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, 5 * self._step_LR)) elif event.key == 'left': if self._shift: ax_LR = self._ax_LR_alt else: ax_LR = self._ax_LR self.rotate(Quaternion.from_v_theta(ax_LR, -5 * self._step_LR)) elif event.key == 'up': self.rotate(Quaternion.from_v_theta(self._ax_UD, 5 * self._step_UD)) elif event.key == 'down': self.rotate( Quaternion.from_v_theta(self._ax_UD, -5 * self._step_UD)) elif event.key.upper() in 'LRUDBF': if self._shift: direction = -1 else: direction = 1 if np.any(self._digit_flags[:N]): for d in np.arange(N)[self._digit_flags[:N]]: self.rotate_face(event.key.upper(), direction, layer=d) else: self.rotate_face(event.key.upper(), direction) elif event.key.upper() in 'QWEA': if event.key.upper() == 'Q': self._colors = self.Environment.transpose( self._colors, 0, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'W': self._colors = self.Environment.transpose( self._colors, 2, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'E': self._colors = self.Environment.transpose( self._colors, 4, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'A': self._colors = self.Environment.transpose( self._colors, -1, indexType="position").flatten() self._colors = np.argsort(self._colors) elif event.key.upper() == 'K': self._solve_cube_kociemba() elif event.key.upper() == 'O': self._solve_cube_korf() elif event.key.upper() == 'N': self._solve_cube_nnet() elif event.key.upper() == 'P': self.figure.savefig('cubeSnapshot.eps') self._draw_cube() isSolved = self.Environment.checkSolved(self._colors) if isSolved: print("SOLVED!") self._move_list = [] self._prevStates = []
class Cube: """Magic Cube Representation""" # define some attribues default_plastic_color = 'black' default_face_colors = [ "w", "#ffcf00", "#00008f", "#009f0f", "#ff6f00", "#cf0000", "gray", "none" ] base_face = np.array( [[1, 1, 1], [1, -1, 1], [-1, -1, 1], [-1, 1, 1], [1, 1, 1]], dtype=float) stickerwidth = 0.9 stickermargin = 0.5 * (1. - stickerwidth) stickerthickness = 0.001 (d1, d2, d3) = (1 - stickermargin, 1 - 2 * stickermargin, 1 + stickerthickness) base_sticker = np.array([[d1, d2, d3], [d2, d1, d3], [-d2, d1, d3], [-d1, d2, d3], [-d1, -d2, d3], [-d2, -d1, d3], [d2, -d1, d3], [d1, -d2, d3], [d1, d2, d3]], dtype=float) base_face_centroid = np.array([[0, 0, 1]]) base_sticker_centroid = np.array([[0, 0, 1 + stickerthickness]]) # Define rotation angles and axes for the six sides of the cube x, y, z = np.eye(3) rots = [ Quaternion.from_v_theta(x, theta) for theta in (np.pi / 2, -np.pi / 2) ] rots += [ Quaternion.from_v_theta(y, theta) for theta in (np.pi / 2, -np.pi / 2, np.pi, 2 * np.pi) ] # define face movements facesdict = dict(F=z, B=-z, R=x, L=-x, U=y, D=-y) def __init__(self, N=3, plastic_color=None, face_colors=None): self.N = N if plastic_color is None: self.plastic_color = self.default_plastic_color else: self.plastic_color = plastic_color if face_colors is None: self.face_colors = self.default_face_colors else: self.face_colors = face_colors self._move_list = [] self._initialize_arrays() def _initialize_arrays(self): # initialize centroids, faces, and stickers. We start with a # base for each one, and then translate & rotate them into position. # Define N^2 translations for each face of the cube cubie_width = 2. / self.N translations = np.array( [[[-1 + (i + 0.5) * cubie_width, -1 + (j + 0.5) * cubie_width, 0]] for i in range(self.N) for j in range(self.N)]) # Create arrays for centroids, faces, stickers, and colors face_centroids = [] faces = [] sticker_centroids = [] stickers = [] colors = [] factor = np.array([1. / self.N, 1. / self.N, 1]) for i in range(6): M = self.rots[i].as_rotation_matrix() faces_t = np.dot(factor * self.base_face + translations, M.T) stickers_t = np.dot(factor * self.base_sticker + translations, M.T) face_centroids_t = np.dot(self.base_face_centroid + translations, M.T) sticker_centroids_t = np.dot( self.base_sticker_centroid + translations, M.T) colors_i = i + np.zeros(face_centroids_t.shape[0], dtype=int) # append face ID to the face centroids for lex-sorting face_centroids_t = np.hstack( [face_centroids_t.reshape(-1, 3), colors_i[:, None]]) sticker_centroids_t = sticker_centroids_t.reshape((-1, 3)) faces.append(faces_t) face_centroids.append(face_centroids_t) stickers.append(stickers_t) sticker_centroids.append(sticker_centroids_t) colors.append(colors_i) self._face_centroids = np.vstack(face_centroids) self._faces = np.vstack(faces) self._sticker_centroids = np.vstack(sticker_centroids) self._stickers = np.vstack(stickers) self._colors = np.concatenate(colors) self._sort_faces() def _sort_faces(self): # use lexsort on the centroids to put faces in a standard order. ind = np.lexsort(self._face_centroids.T) self._face_centroids = self._face_centroids[ind] self._sticker_centroids = self._sticker_centroids[ind] self._stickers = self._stickers[ind] self._colors = self._colors[ind] self._faces = self._faces[ind] def rotate_face(self, f, n=1, layer=0): """Rotate Face""" if layer < 0 or layer >= self.N: raise ValueError('layer should be between 0 and N-1') try: f_last, n_last, layer_last = self._move_list[-1] except: f_last, n_last, layer_last = None, None, None if (f == f_last) and (layer == layer_last): ntot = (n_last + n) % 4 if abs(ntot - 4) < abs(ntot): ntot = ntot - 4 if np.allclose(ntot, 0): self._move_list = self._move_list[:-1] else: self._move_list[-1] = (f, ntot, layer) else: self._move_list.append((f, n, layer)) v = self.facesdict[f] r = Quaternion.from_v_theta(v, n * np.pi / 2) M = r.as_rotation_matrix() proj = np.dot(self._face_centroids[:, :3], v) cubie_width = 2. / self.N flag = ((proj > 0.9 - (layer + 1) * cubie_width) & (proj < 1.1 - layer * cubie_width)) for x in [self._stickers, self._sticker_centroids, self._faces]: x[flag] = np.dot(x[flag], M.T) self._face_centroids[flag, :3] = np.dot(self._face_centroids[flag, :3], M.T) def draw_interactive(self): fig = plt.figure(figsize=(5, 5)) fig.add_axes(InteractiveCube(self)) return fig
def __init__(self, cube=None, interactive=True, view=(0, 0, 10), fig=None, rect=[0, 0.16, 1, 0.84], **kwargs): if cube is None: self.cube = Cube(3) elif isinstance(cube, Cube): self.cube = cube else: self.cube = Cube(cube) self._view = view self._start_rot = Quaternion.from_v_theta((1, -1, 0), -np.pi / 6) if fig is None: fig = plt.gcf() # disable default key press events callbacks = fig.canvas.callbacks.callbacks del callbacks['key_press_event'] # add some defaults, and draw axes kwargs.update( dict(aspect=kwargs.get('aspect', 'equal'), xlim=kwargs.get('xlim', (-2.0, 2.0)), ylim=kwargs.get('ylim', (-2.0, 2.0)), frameon=kwargs.get('frameon', False), xticks=kwargs.get('xticks', []), yticks=kwargs.get('yticks', []))) super(InteractiveCube, self).__init__(fig, rect, **kwargs) self.xaxis.set_major_formatter(plt.NullFormatter()) self.yaxis.set_major_formatter(plt.NullFormatter()) self._start_xlim = kwargs['xlim'] self._start_ylim = kwargs['ylim'] # Define movement for up/down arrows or up/down mouse movement self._ax_UD = (1, 0, 0) self._step_UD = 0.01 # Define movement for left/right arrows or left/right mouse movement self._ax_LR = (0, -1, 0) self._step_LR = 0.01 self._ax_LR_alt = (0, 0, 1) # Internal state variable self._active = False # true when mouse is over axes self._button1 = False # true when button 1 is pressed self._button2 = False # true when button 2 is pressed self._event_xy = None # store xy position of mouse event self._shift = False # shift key pressed self._digit_flags = np.zeros(10, dtype=bool) # digits 0-9 pressed self._current_rot = self._start_rot #current rotation state self._face_polys = None self._sticker_polys = None self._draw_cube() # connect some GUI events self.figure.canvas.mpl_connect('button_press_event', self._mouse_press) self.figure.canvas.mpl_connect('button_release_event', self._mouse_release) self.figure.canvas.mpl_connect('motion_notify_event', self._mouse_motion) self.figure.canvas.mpl_connect('key_press_event', self._key_press) self.figure.canvas.mpl_connect('key_release_event', self._key_release) self._initialize_widgets() # write some instructions self.figure.text(0.05, 0.05, "Mouse/flechas ajustan vista\n" " Teclas U/D/L/R/B/F Mueven las caras\n" "L: Vertical Izquierda\n" "R: Vertical Derecha\n" "U: Horizontal Arriba\n" "D: Horizontal Abajo\n" "F: Rotación Adelante\n" "B: Rotación Atras\n" "(shift+tecla para rotar inverso)", size=10) #Definitions for cube solving A* algorithm self.movList = ['L', 'R', 'U', 'D', 'F', 'B'] self.deordering_movs = [] self.prev_movs = [] self.next_movs = [] self.solve_movs = [] self.mov_index = 0 self.prev_index = 0 self.cubo_org = [ 0, 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 ]