// // The Rubix cube program // Copyright c Brian P. Vogl // October 3 - 6, 2018 // Revised JS version // Started June 14 2018 var CD = [ //new int[6][9]; Color of each square [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ], // Green face [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ], // Yellow face [ 3, 3, 3, 3, 3, 3, 3, 3, 3 ], // Red face [ 4, 4, 4, 4, 4, 4, 4, 4, 4 ], // Blue face [ 5, 5, 5, 5, 5, 5, 5, 5, 5 ], // White face [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] ]; // Orange face var AP = [ //new int[12][6][2]; Rotation Rules [[4,6], [3,6], [3,0], [4,2], [3,2], [3,8]], [[4,7], [3,7], [3,3], [4,1], [3,1], [3,5]], [[4,8], [3,8], [3,6], [4,0], [3,0], [3,2]], [[2,6], [5,0], [1,0], [5,2], [2,0], [4,0]], [[2,7], [5,3], [1,3], [5,1], [2,3], [4,3]], [[2,8], [5,6], [1,6], [5,0], [2,6], [4,6]], [[1,6], [0,6], [0,8], [1,2], [0,2], [0,0]], [[1,7], [0,7], [0,5], [1,1], [0,1], [0,3]], [[1,8], [0,8], [0,2], [1,0], [0,0], [0,6]], [[5,6], [2,8], [4,8], [2,2], [5,8], [1,8]], [[5,7], [2,5], [4,5], [2,1], [5,5], [1,5]], [[5,8], [2,2], [4,2], [2,0], [5,2], [1,2]] ]; // Polygon vertices, (X,Y) polygon number (0-2) and index into CD array. var QP = [ //new int[5][54]; [139,473,475, 93,185,427,521, 47,139,231,381,473,475,567, 2, 93,185,276, // X 427,521, 48,139,230,381,473,475,567, 2, 94,184,276,427,474,521, 48,230, 381,428,520,567, 2, 94,184,276,382,474,566, 48,230,428,520, 94,184,474 ], [ -8,-10,-10, 8, 8, 6, 6, 24, 24, 24, 22, 20, 20, 22, 40, 40, 40, 40, // Y 36, 36, 56, 56, 56, 52, 50, 50, 52, 70, 72, 72, 70, 66, 80, 66, 86, 86, 82, 96, 96, 82,100,102,102,100,112,112,112,116,116,128,128,132,132,144 ], [0,2,1,0,0,2,1,0,0,0,2,2,1,1,1,0,0,2,2,1,1,0,2,2,2,1,1, // Polygon type 1,1,2,2,2,0,1,1,2,2,0,0,1,1,1,2,2,0,0,0,1,2,0,0,1,2,0 ], [0,5,4,0,0,5,4,0,0,0,5,5,4,4,1,0,0,2,5,4,1,0,2,5,5,4,4, // X index into CD 1,1,2,2,5,3,4,1,2,5,3,3,4,1,1,2,2,3,3,3,1,2,3,3,1,2,3 ], [0,8,6,3,1,7,7,6,4,2,6,5,3,8,8,7,5,6,4,4,7,8,7,3,2,0,5, // Y index into CD 5,6,8,3,1,2,1,4,4,0,5,1,2,2,3,5,0,8,4,0,1,1,7,3,0,2,6 ] ]; var RP = [ //new int[4][42]; Points (X1,Y1)-(X2,Y2) lines [ 1, 1,139,277,277,139, 1,139,231, 93,185, 47, 93,231, // X1 47,185,139, 1,139, 1,139,336,474,612,612,474,336,336, 474,566,428,520,382,428,566,382,520,474,336,474,336,474 ], [ 39,129,177,129, 39, -9, 39, 87, 23, 71, 7, 55, 7, 55, // Y1 23, 71, 87, 69,117, 99,147,127,175,127, 37,-11, 37,127, 79,143, 95,159,111,159,111,143, 95, 79, 67, 19, 97, 49 ], [ 1,139,277,277,139, 1,139,277, 93, 93, 47, 47,231,231, // X2 185,185,139,139,277,139,277,474,612,612,474,336,336,474, 612,428,428,382,382,566,566,520,520,474,474,612,474,612 ], [129,177,129, 39, -9, 39, 87, 39, 71,161, 55,145, 55,145, // Y2 71,161,177,117, 69,147, 99,175,127, 37,-11, 37,127, 79, 127, 95, 5,111, 21,111, 21, 95, 5,-11, 19, 67, 49, 97 ] ]; var PP = [ 0,2,8,6,1,5,7,3 ]; var canvas = document.getElementById("thecanvas"); canvas.style.backgroundColor = "white"; var ctx; if(ctx = canvas.getContext('2d')) { canvas.oncontextmenu = function (event) { event.preventDefault(); MousePos(event); }; do_display(ctx); document.addEventListener("click", MousePos); } function leftofline(rp, xc, yc) { // Returns true if point is left of or below the RP line if(RP[2][rp] == RP[0][rp]) return ( xc < RP[0][rp] ); var m = ((RP[3][rp] - RP[1][rp]) / (RP[2][rp] - RP[0][rp])); var b = RP[1][rp] - parseInt(RP[0][rp] * m); return ( yc < ( m * xc + b )); } function incenter(rp1, rp2, rp3, rp4, xc, yc) { // Returns true if point is in the center of the box bounded by the 4 RP lines. return( leftofline(rp1, xc, yc) && !leftofline(rp2, xc, yc) && leftofline(rp3, xc, yc) && !leftofline(rp4, xc, yc)); } function MousePos(event) { // Determine which face and which button was pressed over it var bbox = canvas.getBoundingClientRect(); var xs = event.clientX - 20 - bbox.left; var ys = event.clientY / 2 - 35 - bbox.top; var buttstate = event.which > 1 ? 1 : 0; var fc = -1; if(incenter( 6, 5, 7, 4, xs, ys)) fc = 0; // GREEN Face if(incenter( 1, 6,16, 0, xs, ys)) fc = 1; // YELLOW Face if(incenter( 2, 7, 3,16, xs, ys)) fc = 2; // RED Face if(incenter(21,27,22,28, xs, ys)) fc = 3; // BLUE Face if(incenter(28,24,23,37, xs, ys)) fc = 4; // WHITE Face if(incenter(27,25,37,26, xs, ys)) fc = 5; // ORANGE Face if(fc >= 0) { if(buttstate == 0) { rotateDn(fc); } if(buttstate == 1) { rotateUp(fc); } do_display(); } } function rotateUp(fc) // An upper button was desired { var TCD = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; var n, t, p, tmp; for(n=0; n<=1; n++) // Translate the face of the cube { tmp = CD[fc][PP[n*4]]; for(t=0; t<=2; t++) CD[fc][PP[n*4+t]] = CD[fc][PP[n*4+t+1]]; CD[fc][PP[n*4+3]] = tmp; } // Translate the sides of the cube for(p=0; p<12; p++) TCD[p] = CD[AP[p][fc][0]][AP[p][fc][1]]; for(n=0; n<=2; n++) { tmp = TCD[n]; for(t=0; t<=2; t++) TCD[n+t*3] = TCD[n+(t+1)*3]; TCD[n+9] = tmp; } for(p=0; p<12; p++) CD[AP[p][fc][0]][AP[p][fc][1]] = TCD[p]; } function rotateDn(fc) // A lower button was desired { var TCD = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; var n, t, p, tmp; for(n=1; n>=0; n--) // Translate the face of the cube { tmp = CD[fc][PP[n*4+3]]; for(t=2; t>=0; t--) CD[fc][PP[n*4+t+1]] = CD[fc][PP[n*4+t]]; CD[fc][PP[n*4]] = tmp; } // Translate the sides of the cube for(p=0; p<12; p++) TCD[p] = CD[AP[p][fc][0]][AP[p][fc][1]]; for(n=2; n>=0; n--) { tmp = TCD[n+9]; for(t=2; t>=0; t--) TCD[n+(t+1)*3] = TCD[n+t*3]; TCD[n] = tmp; } for(p=0; p<12; p++) CD[AP[p][fc][0]][AP[p][fc][1]] = TCD[p]; } function do_display() { var k, Xo, Yo; ctx.beginPath(); ctx.lineWidth=3; ctx.strokeStyle = '#000000'; var polyX = [ 0, 0, 0, 0, 0 ]; var polyY = [ 0, 0, 0, 0, 0 ]; for(k=0; k < 42; k++) // Draw the cube grid first { ctx.moveTo(RP[0][k]+20, (RP[1][k]+35)*2); ctx.lineTo(RP[2][k]+20, (RP[3][k]+35)*2); } ctx.stroke(); ctx.lineWidth=1; for(var k=0; k<54; k++) { Xo = QP[0][k]+20; // Determine the offset of the polygons Yo = QP[1][k]+35; polyX[0] = Xo; polyY[0] = 2*Yo; polyX[4] = Xo; polyY[4] = 2*Yo; switch(QP[2][k]) { // Select the polygon to draw case 0: polyX[1] = Xo-45; polyY[1] = 2*(Yo+15); polyX[2] = Xo; polyY[2] = 2*(Yo+30); polyX[3] = Xo+45; polyY[3] = 2*(Yo+15); break; case 1: polyX[1] = Xo; polyY[1] = 2*(Yo+28); polyX[2] = Xo+44; polyY[2] = 2*(Yo+44); polyX[3] = Xo+44; polyY[3] = 2*(Yo+16); break; case 2: polyX[1] = Xo-44; polyY[1] = 2*(Yo+16); polyX[2] = Xo-44; polyY[2] = 2*(Yo+44); polyX[3] = Xo; polyY[3] = 2*(Yo+28); break; } ctx.beginPath(); ctx.moveTo(polyX[0], polyY[0]); ctx.lineTo(polyX[1], polyY[1]); ctx.lineTo(polyX[2], polyY[2]); ctx.lineTo(polyX[3], polyY[3]); ctx.closePath(); switch(CD[QP[3][k]][QP[4][k]]) { // Select the color to appear on the face of the polygon case 1 : ctx.fillStyle = 'green'; break; case 2 : ctx.fillStyle = 'yellow'; break; case 3 : ctx.fillStyle = 'red'; break; case 4 : ctx.fillStyle = 'blue'; break; case 5 : ctx.fillStyle = 'white'; break; case 6 : ctx.fillStyle = 'orange'; break; } // Finally draw the polygon. ctx.fill(); ctx.stroke(); } }