0% found this document useful (0 votes)
41 views

Pdf

The document is a project report for a Rubik's Cube simulator developed in Python, aimed at providing an interactive 3D visualization and educational tool for users to learn solving techniques. It outlines the project's objectives, system analysis, hardware and software requirements, and the technologies used, including Pygame and PyOpenGL for rendering. The simulator addresses limitations of traditional learning methods by offering real-time interaction and guided tutorials, enhancing user engagement and understanding of the Rubik's Cube mechanics.

Uploaded by

Chala Jemal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views

Pdf

The document is a project report for a Rubik's Cube simulator developed in Python, aimed at providing an interactive 3D visualization and educational tool for users to learn solving techniques. It outlines the project's objectives, system analysis, hardware and software requirements, and the technologies used, including Pygame and PyOpenGL for rendering. The simulator addresses limitations of traditional learning methods by offering real-time interaction and guided tutorials, enhancing user engagement and understanding of the Rubik's Cube mechanics.

Uploaded by

Chala Jemal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Report

of
Project II(506)

Bachelor of Computer Applications


(Batch 2022 - 2025)

Submitted By:

Name : Y o n a s A s h a g r i e

Roll No: 132290

Submitted
To

Gourav Kalra(Assistant Professor)

M.M. Institute of Computer Technology & Business Management


Maharishi Markandeshwar (Deemed to be University), Mullana (Ambala)
(NAAC accredited Grade ‘A++’ University)

November 29
TABLE OF CONTENTS
1
INTRODUCTION 6
b) Introduction of project 6
Key Features: 7
c) Problem Definition 7
d) Limitations of Existing System 7
e) Objective of the Project 8
SYSTEM ANALYSIS 8
a) Feasibility Study 8
Technical Feasibility 8
Economic Feasibility 9
Legal and Regulatory Feasibility 9
Operational Feasibility 9
b) Hardware and Software Requirements 9
Software Requirements: 9
Hardware Requirements: 10
DEVELOPMENT ENVIRONMENT 10
a) Introduction to Technologies Used 10
● Python: 10
● Pygame: 10
● PyOpenGL: 11
● Numpy: 11
● Quaternion Mathematics: 11
● Visual Studio Code (VS Code): 11
● Additional Libraries: 11
SYSTEM DESIGN 11
a) Modular Description 11
IMPLEMENTATION AND TESTING 12
a) Implementation and screenshots: 12
//Save file as cube_interactive.py 12
//Save file as projection.py 32
b) Testing 41
Key Testing Focus Areas 42
INTRODUCTION

The Rubik's Cube simulator is a Python-based application designed to visualize and interact
with a 3D representation of a Rubik's Cube. Using the powerful matplotlib library, the
simulator provides users with the ability to manipulate the cube's faces and observe the
resulting changes in real time. The implementation leverages quaternion mathematics to
facilitate smooth and accurate rotations, ensuring a realistic user experience.

This simulator not only serves as an educational tool for understanding the mechanics of the
Rubik's Cube but also offers a platform for further exploration into algorithms for solving the
cube. The program's modular design allows for easy enhancements, making it suitable for
both
casual users and advanced programmers interested in algorithm development or graphical
programming.

Key Features:

● Interactive 3D visualization of a Rubik's Cube


● Mouse and keyboard controls for rotation and face manipulation
● Utilization of quaternion rotation for smooth 3D transformations

By offering a comprehensive environment for exploring the Rubik's Cube, this simulator
contributes to a deeper understanding of both the puzzle itself and the underlying
programming techniques used to create it.

b) Problem Definition

The Rubik's Cube, a popular 3D puzzle, often frustrates individuals who struggle with its
mechanics and solving techniques. Traditional resources, such as books and videos,
frequently lack the interactivity needed to engage learners effectively.

This project aims to address this gap by developing an interactive Rubik's Cube simulator
that includes:

● 3D Representation: A dynamic model allowing users to manipulate the cube in


real time.
● Step-by-Step Guides: Clear instructions to help users learn various solving techniques.
● Algorithm Demonstrations: Visualizations of algorithms to enhance
understanding of the cube's structure.

By facilitating hands-on learning, this tool will make the Rubik's Cube more approachable for
beginners, promoting deeper engagement with essential problem-solving techniques in
mathematics and computer science.

c) Limitations of Existing System

The current methods for learning to solve the Rubik's Cube exhibit several limitations that
hinder effective understanding and engagement among users:

1. Lack of Interactivity: Traditional resources, such as books and videos, primarily


offer static information without enabling users to practice in real-time, severely
limiting hands-on learning opportunities that are essential for mastering the puzzle.
2. Limited Accessibility: Many instructional materials require prior knowledge or
experience, making it challenging for complete beginners to start their journey
without appropriate guidance or foundational knowledge.
3. Inconsistent Quality: The quality and comprehensibility of available tutorials can
vary significantly, leading to confusion and frustration among learners who may
struggle to find reliable resources.
4. Insufficient Visualizations: Most current resources fail to adequately illustrate the
three-dimensional aspects of the Rubik's Cube, making it difficult for users to grasp
the spatial relationships and movements involved in solving the puzzle.
5. No Feedback Mechanism: Existing systems lack an immediate feedback or
correction mechanism, which is crucial for mastering problem-solving techniques.
Without this support, learners may not recognize or correct their mistakes effectively.

d) Objective of the Project

The primary objective of this project is to develop an interactive Rubik's Cube simulator that
enhances the learning experience for users aspiring to master the puzzle. Key objectives
include:

1. Interactive Learning: To create a user-friendly platform for users to manipulate


a virtual Rubik's Cube, fostering better understanding and retention of solving
techniques.
2. Visual Feedback: To integrate real-time visual feedback that illustrates user
actions, helping learners recognize and correct mistakes.
3. Guided Tutorials: To offer structured tutorials tailored to various skill levels,
making it easier for beginners and advanced users to refine their strategies.
4. Accessibility: To ensure the simulator is available across multiple devices,
enabling users to learn anytime, anywhere.
5. Engagement: To incorporate gamification elements that make learning
enjoyable and motivating, encouraging regular practice

SYSTEM ANALYSIS

a) Feasibility Study

The feasibility study for the Rubik’s Cube simulator project includes assessments across
technical, economic, legal, and operational aspects to ensure a successful launch.

Technical Feasibility
● Technology Stack: The simulator will be developed in Python, leveraging libraries
for 3D graphics and user interaction to achieve smooth rotations and realistic cube
transformations.
● Integration: Will assess compatibility with educational and gaming platforms,
enabling potential integration for broader reach.
● Security and Compliance: Implements secure handling of user inputs and data
privacy features.

Economic Feasibility

● Budget:
○ Development Costs: Estimated at $5,000 for design, $10,000 for coding, and
$3,000 for testing.
○ Operational Costs: Maintenance, updates, and support will require approximately
$2,000 per year.
○ Marketing Costs: Promotion and user acquisition estimated at $2,000.
● Funding: Potential revenue through educational partnerships, advertising,
and in-app purchases.

Legal and Regulatory Feasibility

● Privacy Policies: Adheres to data protection policies to ensure user security.


● Legal Risks: Prioritizes compliance with intellectual property laws to avoid legal issues.

Operational Feasibility

● Project Management: 10 days for design, 10 days for front-end, and 24 days
for back-end development.
● Team: A team of 2 developers and a project manager.
● Maintenance: One developer for ongoing support.
● User Experience: Ensures a responsive, engaging user interface for both
desktop and mobile.

b) Hardware and Software Requirements

The hardware and software requirements for developing a Rubik’s Cube simulator are
outlined below. These requirements may vary based on the system’s complexity and
interactive features.

Software Requirements:

1. Operating System: Compatible with Windows, Linux, and macOS for


broad accessibility.
2. Programming Languages/Technologies: Developed primarily in Python, utilizing
libraries like Pygame for 3D rendering, Numpy for mathematical operations, and
PyOpenGL for real-time cube transformations.
3. Database: An SQLite or MongoDB database can be used if user data or progress
tracking is required.
4. Algorithms: Quaternion and 3D transformation algorithms for simulating realistic
cube rotations and solving mechanics.
5. Integrated Development Environment (IDE): Tools like Visual Studio Code or
PyCharm for efficient coding and debugging.
6. Version Control: Git for version tracking and collaborative development.
7. Testing Tools: Testing frameworks like Pytest for unit tests and Pylint for code
quality analysis.

Hardware Requirements:

1. Processor: An Intel Core i5 or higher for handling 3D rendering and


complex transformations.
2. Memory (RAM): Minimum 8GB RAM for smooth performance with
graphic simulations and transformations.
3. Storage: Sufficient storage space (minimum 500MB) for application files,
libraries, and possible database management.
4. Graphics Support: A graphics card compatible with OpenGL for optimized
3D visualization.
5. Network: Internet connectivity for any online resources, updates, or cloud storage
if applicable.

DEVELOPMENT ENVIRONMENT

a) Introduction to Technologies Used

The Rubik’s Cube simulator project leverages a variety of tools and technologies to create a
realistic and interactive experience, primarily using Python-based libraries and graphical
tools. The following highlights each technology's role.

● Python:
Python is a versatile programming language, ideal for this project due to its simplicity,
extensive library support, and strong computational capabilities. As the foundation for
the Rubik’s Cube simulator, Python efficiently handles the complex operations
involved in 3D transformations, making it suitable for implementing realistic
movement and rotation calculations.
● Pygame:
Pygame, a popular Python library for multimedia applications, is central to rendering
the Rubik’s Cube in a 3D space. Pygame's core functionalities—like handling
real-time graphics, user inputs, and animations—allow the simulator to deliver a
smooth and
responsive experience. With Pygame, users can interact with the cube, simulating
real-time moves that mimic physical rotation.
● PyOpenGL:
PyOpenGL, which binds the OpenGL library to Python, allows high-performance 3D
rendering by tapping into the GPU’s processing power. It enhances visual quality and
ensures smooth rotations for the cube's transformations. The support for OpenGL’s
complex 3D transformation, lighting, and depth processing features brings a realistic,
high-quality display that feels immersive.
● Numpy:
Numpy, a mathematical library in Python, is employed to handle 3D coordinates and
transformations. It simplifies complex matrix and vector operations, which are
essential to achieving realistic cube rotations. Numpy’s efficient handling of
multidimensional data also optimizes the computational aspects of the simulator,
providing accuracy and speed to rotation and transformation calculations.
● Quaternion Mathematics:
Quaternion mathematics is used to handle smooth and accurate 3D rotations,
avoiding common issues such as gimbal lock that arise with traditional rotation
methods. This approach ensures that every turn or twist of the Rubik's Cube feels
intuitive and smooth, providing a stable rotation system crucial for realistic
simulations.
● Visual Studio Code (VS Code):
Visual Studio Code (VS Code) is the integrated development environment (IDE) for
the project, supporting essential tools like Git version control, syntax highlighting, and
debugging. VS Code enhances productivity, allowing easy testing and debugging,
which is crucial for a project that requires fine-tuning graphics and functionality.
● Git:
Git is the version control system used to manage and track code changes throughout
development. It enables version history and safe experimentation with features,
which are valuable for ensuring project stability and supporting collaboration if the
project scales to a larger team.
● Additional Libraries:
Libraries like Matplotlib and JSON enhance the project by supporting data
visualization (tracking rotation data) and configuration management, providing
flexibility for user settings or future enhancements.

SYSTEM DESIGN

a) Modular Description

The Rubik’s Cube simulator is organized into several modules:

● Main Application: Manages initialization and controls overall functionality.


● 3D Graphics: Handles cube rendering using Pygame and PyOpenGL
for smooth, realistic visuals.
● Rotation and Transformation: Implements quaternion-based 3D
rotations, ensuring accuracy.
● User Interface: Provides interactive elements like navigation, move
history, and feedback.
● User Input: Processes keyboard and mouse actions to perform cube rotations.
● Settings and Configuration: Manages user preferences for display and controls.
● Data Management: Stores cube states, move history, and progress data.

IMPLEMENTATION AND TESTING

a) Implementation and screenshots:

//Save file as cube_interactive.py

import numpy as np

import matplotlib.pyplot as plt

from matplotlib import

widgets

from projection import Quaternion, project_points

"""

Sticker representation

Each face is represented by a length [5, 3] array:

[v1, v2, v3, v4, v1]

Each sticker is represented by a length [9, 3] array:

[v1a, v1b, v2a, v2b, v3a, v3b, v4a, v4b, v1a]


In both cases, the first point is repeated to close the polygon.

Each face also has a centroid, with the face number

appended at the end in order to sort correctly using lexsort.

The centroid is equal to sum_i[vi].

Colors are accounted for using color indices and a look-up table.

With all faces in an NxNxN cube, then, we have three arrays:

centroids.shape = (6 * N *

N, 4) faces.shape = (6 * N *

N, 5, 3)

stickers.shape = (6 * N * N, 9,

3) colors.shape = (6 * N * N,)

The canonical order is found by doing

ind = np.lexsort(centroids.T)

After any rotation, this can be used to quickly restore the

cube to canonical position.

"""
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(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=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 -

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(s

elf)) return fig

class

InteractiveCube(plt.Axes):

def init (self, cube=None,

interactive=True,

view=(0, 0, 10),

fig=None, rect=[0, 0.16, 1, 0.84],

**kwa

r gs): 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_even

t ',

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 _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.cube._stickers)[:, :,

:2] faces = self._project(self.cube._faces)[:, :,

:2]

face_centroids = self._project(self.cube._face_centroids[:, :3])

sticker_centroids = self._project(self.cube._sticker_centroids[:, :3])

plastic_color = self.cube.plastic_color

colors = np.asarray(self.cube.face_colors)[self.cube._colors]

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(f

p)

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, face, turns=1, layer=0,

steps=5): if not np.allclose(turns, 0):

for i in range(steps):

self.cube.rotate_face(face, turns * 1. /

steps,

layer=la

yer)

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.cube._move_list[:] for

(face, n, layer) in

move_list[::-1]:
self.rotate_face(face, -n, layer, steps=3)

self.cube._move_list = []
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._shif

t: 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)


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 _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):

"""Handler for mouse button

press""" 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): """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._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()

if name == '

main ': import sy


N = int(sys.argv[1]) except:

N=3

c = Cube(N)

# do a 3-corner swap

#c.rotate_face('R')

#c.rotate_face('D')

#c.rotate_face('R',

-1) #c.rotate_face('U'

, -1)

#c.rotate_face('R'

#c.rotate_face('D'

, -1)

#c.rotate_face('R'

, -1)

#c.rotate_face('U'

c.draw_interactive()

plt.show()

You might also like