Project

General

Profile

« Previous | Next » 

Revision 05fa94d9

Added by Leszek Koltunski over 4 years ago

RubikCube: detect if the cube is solved.

In order to do this correctly, we also needed to keep correcting each mQuatScramble quaternions after each quatMultiplication in order to avoid multiplication errors accumulating. This turns out to be easy, because each quaternion representing a legal combination of rotations of a RubikCube must have each of the 4 to its components be equal to one of only 7 possible floats.

View differences:

src/main/java/org/distorted/magic/RubikCube.java
53 53
    private static final Static3D VectY = new Static3D(0,1,0);
54 54
    private static final Static3D VectZ = new Static3D(0,0,1);
55 55

  
56
    private static final float SQ2 = 0.5f*((float)Math.sqrt(2));
57
    private static final float[] LEGAL = { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 };
58

  
56 59
    public static final int VECTX = 0;  //
57 60
    public static final int VECTY = 1;  // don't change this
58 61
    public static final int VECTZ = 2;  //
......
185 188
            }
186 189
      }
187 190

  
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

  
193
    boolean isSolved()
194
      {
195
      Static4D q = mQuatScramble[0][0][0];
196

  
197
      float x = q.get1();
198
      float y = q.get2();
199
      float z = q.get3();
200
      float w = q.get4();
201

  
202
      for(int i = 0; i< mSize; i++)
203
        for(int j = 0; j< mSize; j++)
204
          for(int k = 0; k< mSize; k++)
205
            {
206
            if( i==0 || i==mSize-1 || j==0 || j==mSize-1 || k==0 || k==mSize-1 )
207
              {
208
              q = mQuatScramble[i][j][k];
209

  
210
              if( q.get1()!=x || q.get2()!=y || q.get3()!=z || q.get4()!=w )
211
                {
212
                return false;
213
                }
214
              }
215
            }
216

  
217
      return true;
218
      }
219

  
188 220
///////////////////////////////////////////////////////////////////////////////////////////////////
189 221

  
190 222
    public void apply(Effect effect, int position)
......
498 530

  
499 531
                mRotationAngle[x][y][z].removeAll();
500 532
                mQuatScramble[x][y][z].set(RubikSurfaceView.quatMultiply(quat,mQuatScramble[x][y][z]));
533
                normalizeScrambleQuat(x,y,z);
501 534
                modifyCurrentPosition(x,y,z,quat);
502 535
                }
503 536
              }
......
505 538
      mRotationAngleStatic.set1(0);
506 539
      }
507 540

  
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542
// All legal rotation quats must have all four of their components equal to either
543
// 0, 1, -1, 0.5, -0.5 or +-sqrt(2)/2.
544
//
545
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
546
// correct the value of the 'scramble' quat to what it should be.
547
//
548
// We also have to remember that the group of unit quaternions is a double-cover of rotations
549
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
550

  
551
    private void normalizeScrambleQuat(int i, int j, int k)
552
      {
553
      Static4D quat = mQuatScramble[i][j][k];
554

  
555
      float x = quat.get1();
556
      float y = quat.get2();
557
      float z = quat.get3();
558
      float w = quat.get4();
559
      float diff;
560

  
561
      for(int legal=0; legal<LEGAL.length; legal++)
562
        {
563
        diff = x-LEGAL[legal];
564
        if( diff*diff<0.01f ) x = LEGAL[legal];
565
        diff = y-LEGAL[legal];
566
        if( diff*diff<0.01f ) y = LEGAL[legal];
567
        diff = z-LEGAL[legal];
568
        if( diff*diff<0.01f ) z = LEGAL[legal];
569
        diff = w-LEGAL[legal];
570
        if( diff*diff<0.01f ) w = LEGAL[legal];
571
        }
572

  
573
      if( w<0 )
574
        {
575
        w = -w;
576
        z = -z;
577
        y = -y;
578
        x = -x;
579
        }
580
      else if( w==0 )
581
        {
582
        if( z<0 )
583
          {
584
          z = -z;
585
          y = -y;
586
          x = -x;
587
          }
588
        else if( z==0 )
589
          {
590
          if( y<0 )
591
            {
592
            y = -y;
593
            x = -x;
594
            }
595
          else if( y==0 )
596
            {
597
            if( x<0 )
598
              {
599
              x = -x;
600
              }
601
            }
602
          }
603
        }
604

  
605
      mQuatScramble[i][j][k].set(x,y,z,w);
606
      }
607

  
508 608
///////////////////////////////////////////////////////////////////////////////////////////////////
509 609

  
510 610
    private float getSinkStrength()

Also available in: Unified diff