ImageCube is a program written by Lars Vandenbergh to show images of Rubik’s cube where you define what stickers to show.

I wrote a version of ImageCube that can also be used as a model of the Rubik’s Cube. I decided to give away the code, because *that’s how cool I am*. If you’re only into cubing and not into programming at all, you should just check out what I did with it at the algorithm database or my Rubik’s cube site.

And now for the source. If you have any comments, feel free to leave them here.

<?
/*
Cube object
Copyright (C) 2007 Michiel van der Blonk - <a href="mailto:blonkm@gmail.com">blonkm@gmail.com</a> - All Rights Reserved
Based on C++ code by JoÃ«l van Noort
This software is licensed as per the MIT License below:
MIT License: <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
Â * To generate the imagecube sticker codes, this program first simulates the
Â * cube, using aÂ string that represents the cube state. Every elementarty move
Â * (UDLRFB) is then executed as five 4-cycles of stickers. Example: the
Â * sticker permutations corresponding with the move U are:
Â *
Â *Â U: (53, 51, 45, 47) (50, 52, 48, 46) (2, 38, 29, 11)
Â *Â Â Â Â (1, 37, 28, 10,) (0, 36, 27, 9)
Â */
// just for debugging
class Debug
{
Â function out($s)
Â {
Â Â echo '<div class="debug">';
Â Â print_r($s);
Â Â echo '</div>';
Â }
}
// post, get
class Page
{
Â function get($s)
Â {
Â Â if (isset($_GET[$s]))
Â Â Â return $_GET[$s];
Â Â if (isset($_POST[$s]))
Â Â Â return $_POST[$s];
Â }
}
// handy functions
class Util
{
Â //swaps two elements in an array
Â functionÂ swap(&$var, $a, $b){
Â Â $temp = $var[$a];
Â Â $var[$a] = $var[$b];
Â Â $var[$b] = $temp;
Â }
}
// model of a Rubik's cube
class Cube
{
Â var $stickers;
Â var $mode;
Â // constructor
Â function Cube()
Â {
Â Â // initialize stickers
Â Â $this->stickers = "rrrrrrrrrgggggggggwwwwwwwwwooooooooobbbbbbbbbyyyyyyyyy";
Â }
Â //this function uses swap function 3 times to make a 4-cycles of stickers:
Â function execute_permutation($a, $b, $c, $d){
Â Â Util::swap($this->stickers, $a, $b);
Â Â Util::swap($this->stickers, $a, $c);
Â Â Util::swap($this->stickers, $a, $d);
Â }
Â // perform a move and update stickers member variable
Â // for multiple moves in the string $token the moves are done one by one
Â function move($token)
Â {
Â Â $moveTransforms = array('u'=>'UEEE', 'd'=>'DE', 'f'=>'FS', 'b'=>'BSSS', 'l'=>'LM', 'r'=>'RMMM', 'x'=>'rLLL', 'y'=>'uDDD', 'z'=>'fBBB');
Â Â // recursive calls to walk through the translated lowercase moves
Â Â if (strlen($token) > 1)
Â Â Â foreach (str_split($token) as $ch)
Â Â Â Â $this->move($ch);
Â Â switch($token)
Â Â {
Â Â Â case 'U':
Â Â Â Â //one of the elementary move functions. Uses the execute_permutation function
Â Â Â Â //five times to make five 4-cycles of stickers:
Â Â Â Â $this->execute_permutation(53, 51, 45, 47); // top layer
Â Â Â Â $this->execute_permutation(50, 52, 48, 46);
Â Â Â Â $this->execute_permutation(2, 38, 29, 11);
Â Â Â Â $this->execute_permutation(1, 37, 28, 10);
Â Â Â Â $this->execute_permutation(0, 36, 27, 9);
Â Â Â Â break;
Â Â Â case 'D':
Â Â Â Â $this->execute_permutation(20, 26, 24, 18);
Â Â Â Â $this->execute_permutation(23, 25, 21, 19);
Â Â Â Â $this->execute_permutation(8, 17, 35, 44);
Â Â Â Â $this->execute_permutation(7, 16, 34, 43);
Â Â Â Â $this->execute_permutation(6, 15, 33, 42);
Â Â Â Â break;
Â Â Â case 'F':
Â Â Â Â $this->execute_permutation(2, 8, 6, 0);
Â Â Â Â $this->execute_permutation(5, 7, 3, 1);
Â Â Â Â $this->execute_permutation(9, 20, 44, 51);
Â Â Â Â $this->execute_permutation(12, 19, 41, 52);
Â Â Â Â $this->execute_permutation(15, 18, 38, 53);
Â Â Â Â break;
Â Â Â case 'B':
Â Â Â Â $this->execute_permutation(29, 35, 33, 27);
Â Â Â Â $this->execute_permutation(32, 34, 30, 28);
Â Â Â Â $this->execute_permutation(47, 36, 24, 17);
Â Â Â Â $this->execute_permutation(46, 39, 25, 14);
Â Â Â Â $this->execute_permutation(45, 42, 26, 11);
Â Â Â Â break;
Â Â Â case 'R':
Â Â Â Â $this->execute_permutation(11, 17, 15, 9);
Â Â Â Â $this->execute_permutation(14, 16, 12, 10);
Â Â Â Â $this->execute_permutation(2, 47, 33, 20);
Â Â Â Â $this->execute_permutation(5, 50, 30, 23);
Â Â Â Â $this->execute_permutation(8, 53, 27, 26);
Â Â Â Â break;
Â Â Â case 'L':
Â Â Â Â $this->execute_permutation(38, 44, 42, 36);
Â Â Â Â $this->execute_permutation(41, 43, 39, 37);
Â Â Â Â $this->execute_permutation(0, 18, 35, 45);
Â Â Â Â $this->execute_permutation(3, 21, 32, 48);
Â Â Â Â $this->execute_permutation(6, 24, 29, 51);
Â Â Â Â break;
Â Â Â case 'M':
Â Â Â Â $this->execute_permutation(4, 22, 31, 49 );
Â Â Â Â $this->execute_permutation(1, 19, 34, 46 );
Â Â Â Â $this->execute_permutation(7, 25, 28, 52 );
Â Â Â Â break;
Â Â Â case 'E':
Â Â Â Â $this->execute_permutation(4, 13, 31, 40);
Â Â Â Â $this->execute_permutation(5, 14, 32, 41);
Â Â Â Â $this->execute_permutation(3, 12, 30, 39);
Â Â Â Â break;
Â Â Â case 'S':
Â Â Â Â $this->execute_permutation(49, 13, 22, 40);
Â Â Â Â $this->execute_permutation(50, 16, 21, 37);
Â Â Â Â $this->execute_permutation(48, 10, 23, 43);
Â Â Â Â break;
Â Â Â case '':
Â Â Â Â break;
Â Â Â default:
Â Â Â Â // u,d,f,b,l,r,x,y,z
Â Â Â Â $this->move($moveTransforms[$token]);
Â Â }
Â }
Â // clean from certain tokens
Â // note: only cleans up space, minus, quote
Â function clean($input)
Â {
Â Â if ($input=='')
Â Â Â return $input;
Â Â $tokens = " ()-\\'";
Â Â $input_clean = '';
Â Â $prevCh = '';
Â Â // delete magic quotes
Â Â $input = str_replace("\\\\", '', $input);
Â Â foreach (str_split($input) as $ch)
Â Â {
Â Â Â if (!strpos($tokens, $ch))
Â Â Â Â Â Â $input_clean .= $ch;
Â Â Â // only add prime when right after a move token, e.g. R'
Â Â Â // so skip R2' (becomes R2)
Â Â Â if ($ch=='\\'' && $prevCh!='2')
Â Â Â Â $input_clean .= $ch;
Â Â Â $prevCh = $ch;
Â Â }
Â Â return $input_clean;
Â }
Â // normalize algorithm
Â // e.g. R2L'FD' becomes R2L3F1D3
Â function normalize($input_clean){
Â Â $temp = str_replace('\\'', '3', $input_clean);
Â Â foreach (str_split($temp) as $ch)
Â Â {
Â Â Â // when both ch and prev are moves, insert a 1 between them
Â Â Â // RL becomes R1L
Â Â Â if (preg_match("/\\D/", $prevCh) && preg_match("/\\D/", $ch))
Â Â Â Â $alg_normal .= '1';
Â Â Â $alg_normal .= $ch;
Â Â Â $prevCh = $ch;
Â Â }
Â Â if (preg_match("/\\D/", $ch))
Â Â Â $alg_normal .= '1';
Â Â return $alg_normal;
Â }
Â // reverse moves
Â // used to show an algorithm that solves a cube
Â functionÂ inverse($alg_normal){
Â Â // split into separate moves
Â Â $moves = str_split($alg_normal, 2);
Â Â // reverse those
Â Â $moves_inverse = array_reverse($moves);
Â Â // back to string
Â Â $alg_inverse = implode("", $moves_inverse);
Â Â // inverse quantifiers
Â Â $alg_inverse = str_replace('1', '#', $alg_inverse); // temp ch for 3
Â Â $alg_inverse = str_replace('3', '1', $alg_inverse);
Â Â $alg_inverse = str_replace('#', '3', $alg_inverse);
Â Â return $alg_inverse;
Â }
Â // several predefined sticker modes
Â function setMode($mode='')
Â {
Â Â if ($mode!='')
Â Â Â $this->mode = $mode;
Â Â switch (strtoupper($this->mode))
Â Â {
Â Â Â case "F2L":
Â Â Â Â $this->stickers =Â "xxxrrrrrrxxxggggggwwwwwwwwwxxxooooooxxxbbbbbbxxxxyxxxx";
Â Â Â Â break;
Â Â Â case "SHORTCUT":
Â Â Â Â $this->stickers = "xxxxrrxrrxxxggxggxxwwwwwxwxxxxxoxxoxxxxxbxxbxxxxxyxxxx";
Â Â Â Â break;
Â Â Â case "OLL":
Â Â Â Â $this->stickers = "xxxrrrrrrxxxggggggwwwwwwwwwxxxooooooxxxbbbbbbyyyyyyyyy";
Â Â Â Â break;
Â Â Â case "PLL":
Â Â Â Â $this->stickers = "rrrrrrrrrgggggggggwwwwwwwwwooooooooobbbbbbbbbyyyyyyyyy";
Â Â Â Â break;
Â Â }
Â }
Â // execute an algorithm
Â functionÂ execute($alg, $mode='')
Â {
Â Â // prepare with a certain mode if given
Â Â if ($preset!='')
Â Â Â $this->setMode($mode);
Â Â // walk through all moves in a normalized alg
Â Â for ($i=0; $i < strlen($alg); $i+=2)
Â Â {
Â Â Â // define operation (move) and quantifier
Â Â Â $op = $alg[$i];
Â Â Â $q = $alg[$i+1];
Â Â Â // move a face n times
Â Â Â foreach (range(1, $q) as $value)
Â Â Â Â $this->move($op);
Â Â }
Â Â return $this->stickers;
Â }
Â // applet sticker for RubikPlayer are
Â // the same as the stickers member variable
Â function toAppletStickers()
Â {
Â Â return $this->stickers;
Â }
Â // return only visible faces for imagecube
Â // i.e. U, F, R
Â function toImageCubeStickers()
Â {
Â Â // split into 9 faces
Â Â $faces = str_split($this->stickers, 9);
Â Â // create string for up, right, front
Â Â $upFace = $faces[5];
Â Â $frontFace = $faces[0];
Â Â $rightFace = $faces[1];
Â Â $imageStickers = $upFace . $frontFace . $rightFace;
Â Â return $imageStickers ;
Â }
Â // perform an algorithm given
Â // done in the steps
Â // 1. clean up
Â // 2. normalize (add quantifiers)
Â // 3. optionally inverse
Â // 4. execute
Â function performAlg($input, $inverse = false)
Â {
Â Â Â $input_clean = "";
Â Â Â $alg_normal = "";
Â Â Â $alg_inverse = "";
Â Â // clean input leaves only the moves
Â Â $alg = $this->clean($input);
Â Â // process to get normalized alg (e.g. R2F1L3)
Â Â $alg = $this->normalize($alg);
Â Â // process inverse of alg
Â Â if ($inverse)
Â Â Â $alg = $this->inverse($alg);
Â Â // perform inverse on the stickers
Â Â $this->stickers = $this->execute($alg);
Â }
}
?>