Project

General

Profile

Download (18 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / ObjectSignature.java @ 8f44228f

1 1d581993 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 a7a40b3c Leszek Koltunski
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8 1d581993 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.helpers;
11
12 882a8142 Leszek Koltunski
import java.util.ArrayList;
13
14 1d581993 Leszek Koltunski
import org.distorted.objectlib.main.ObjectType;
15
16 882a8142 Leszek Koltunski
import static org.distorted.objectlib.scrambling.ScrambleStateBandagedCuboid.MAX_SUPPORTED_SIZE;
17 1d581993 Leszek Koltunski
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 e342c3f7 Leszek Koltunski
public class ObjectSignature implements Comparable<ObjectSignature>
21 1d581993 Leszek Koltunski
{
22 882a8142 Leszek Koltunski
  public static final int SIZE = computeNum();
23
24
  private long[] mSignature;
25 1d581993 Leszek Koltunski
  private int[] mLayer;
26 700dee26 Leszek Koltunski
  private int[][][][] mCycles;
27 1d581993 Leszek Koltunski
  private float[][] mCubitTouch;
28 700dee26 Leszek Koltunski
  private int mNumCubitTouches;
29
  private int[] mNumLeftCyclesPerLayer;
30
  private int[] mNumCentCyclesPerLayer;
31 1f5d92b9 Leszek Koltunski
  private int[] mNumInneCyclesPerLayer;
32 882a8142 Leszek Koltunski
  private String mName=null;
33
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
// a cube of size N has 12*(N-1)^2 possible places two adjacent cubies can be 'glued'; therefore
36
// the signature must contain ceil( 12*(N-1)^2 / 64 ) bytes.
37
38
  private static int computeNum()
39
    {
40
    int max = MAX_SUPPORTED_SIZE-1;
41
    return (int)(0.95f + (3*max*max)/16.0f);
42
    }
43
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45
46
  private void setUpSignature(long[] signature)
47
    {
48
    int size = signature.length;
49
    int diff = SIZE-size;
50
51
    if( diff==0 ) mSignature = signature;
52
    else
53
      {
54
      mSignature = new long[SIZE];
55
56
      for(int i=0; i<size; i++)
57
        {
58
        mSignature[diff+i] = signature[i];
59
        }
60
      }
61
    }
62 1d581993 Leszek Koltunski
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64
// built-in objects
65
66
  public ObjectSignature(ObjectType type)
67
    {
68 882a8142 Leszek Koltunski
    mSignature = new long[SIZE];
69
    mSignature[SIZE-1] = type.ordinal();
70 1d581993 Leszek Koltunski
    }
71
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73
74
  public ObjectSignature(ObjectSignature sig)
75
    {
76 882a8142 Leszek Koltunski
    int len = sig.mSignature.length;
77
    mSignature = new long[len];
78
    for(int i=0; i<len; i++) mSignature[i] = sig.mSignature[i];
79 1d581993 Leszek Koltunski
80
    mLayer      = sig.mLayer;
81 700dee26 Leszek Koltunski
    mCycles     = sig.mCycles;
82 1d581993 Leszek Koltunski
    mCubitTouch = sig.mCubitTouch;
83 882a8142 Leszek Koltunski
    mName       = sig.mName;
84 1d581993 Leszek Koltunski
85 700dee26 Leszek Koltunski
    mNumCubitTouches       = sig.mNumCubitTouches;
86
    mNumCentCyclesPerLayer = sig.mNumCentCyclesPerLayer;
87
    mNumLeftCyclesPerLayer = sig.mNumLeftCyclesPerLayer;
88 0ac2c2e6 Leszek Koltunski
    mNumInneCyclesPerLayer = sig.mNumInneCyclesPerLayer;
89 1d581993 Leszek Koltunski
    }
90
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92
// built-in bandaged 3x3s; objects created from JSON (version1)
93
94
  public ObjectSignature(long signature)
95
    {
96 882a8142 Leszek Koltunski
    mSignature = new long[SIZE];
97
    mSignature[SIZE-1] = signature;
98 1d581993 Leszek Koltunski
    }
99
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101 efeca8ef Leszek Koltunski
// locally created bandaged cuboids created from JSON (version2)
102
103 882a8142 Leszek Koltunski
  public ObjectSignature(String shortName, long[] signature)
104 efeca8ef Leszek Koltunski
    {
105 882a8142 Leszek Koltunski
    setUpSignature(signature);
106 efeca8ef Leszek Koltunski
107
    int x = shortName.charAt(0) - '0';
108
    int y = shortName.charAt(1) - '0';
109
    int z = shortName.charAt(2) - '0';
110
111
    mLayer = new int[] {x,y,z};
112
113
    prepareCubitTouch();
114
    prepareAllCycles();
115
    }
116
117 8f44228f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
118
// BAN*** objects when read from JSON
119
120
  public ObjectSignature(int size, long[] signature)
121
    {
122
    setUpSignature(signature);
123
124
    mLayer = new int[] {size,size,size};
125
126
    prepareCubitTouch();
127
    prepareAllCycles();
128
    }
129
130 efeca8ef Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
131
// other objects created from JSON (version2)
132 1d581993 Leszek Koltunski
133 882a8142 Leszek Koltunski
  public ObjectSignature(long[] signature)
134 1d581993 Leszek Koltunski
    {
135 882a8142 Leszek Koltunski
    setUpSignature(signature);
136 1d581993 Leszek Koltunski
    }
137
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139 539b46ea Leszek Koltunski
// Locally created bandaged cuboids 1<=N,M,K<=7
140 1d581993 Leszek Koltunski
// This is the 'Andreas signature' of a bandaged cube.
141
// https://twistypuzzles.com/forum/viewtopic.php?p=415466#p415466
142
143
  public ObjectSignature(int lenx, int leny, int lenz, float[][] position)
144
    {
145
    mLayer = new int[] {lenx,leny,lenz};
146 882a8142 Leszek Koltunski
    mSignature = new long[SIZE];
147 1d581993 Leszek Koltunski
148
    prepareCubitTouch();
149
    prepareAllCycles();
150
151
    for(float[] pos : position)
152
      {
153
      int numCenters = pos.length/3;
154
155
      for(int i=0; i<numCenters; i++)
156 efeca8ef Leszek Koltunski
        {
157
        float xi = pos[3*i  ];
158
        float yi = pos[3*i+1];
159
        float zi = pos[3*i+2];
160
161 1d581993 Leszek Koltunski
        for(int j=i+1; j<numCenters; j++)
162
          {
163 efeca8ef Leszek Koltunski
          float xj = pos[3*j  ];
164
          float yj = pos[3*j+1];
165
          float zj = pos[3*j+2];
166
167
          if(areNeighbours(xi-xj,yi-yj,zi-zj))
168 1d581993 Leszek Koltunski
            {
169 efeca8ef Leszek Koltunski
            float xc = (xi+xj)/2;
170
            float yc = (yi+yj)/2;
171
            float zc = (zi+zj)/2;
172 1d581993 Leszek Koltunski
173
            int bitIndex = getIndexOfCubitTouch(xc,yc,zc);
174
            setBit(bitIndex,1);
175
            }
176
          }
177 efeca8ef Leszek Koltunski
        }
178 1d581993 Leszek Koltunski
      }
179
    }
180
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
183 882a8142 Leszek Koltunski
  public void setSignature(int signature)
184 1d581993 Leszek Koltunski
    {
185 882a8142 Leszek Koltunski
    for(int i=0; i<SIZE-1; i++) mSignature[i]=0;
186
    mSignature[SIZE-1] = signature;
187 1d581993 Leszek Koltunski
    }
188
189 e342c3f7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191
  public int compareTo(ObjectSignature sig)
192
    {
193 882a8142 Leszek Koltunski
    for(int i=0; i<SIZE; i++)
194 e342c3f7 Leszek Koltunski
      {
195 882a8142 Leszek Koltunski
      long diff = mSignature[i] - sig.mSignature[i];
196
197
           if( diff>0 ) return +1;
198
      else if( diff<0 ) return -1;
199 e342c3f7 Leszek Koltunski
      }
200 882a8142 Leszek Koltunski
201
    return 0;
202 e342c3f7 Leszek Koltunski
    }
203
204 1d581993 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
205
206
  public boolean isEqual(ObjectSignature sig)
207
    {
208 882a8142 Leszek Koltunski
    for(int i=0; i<SIZE; i++)
209
      {
210
      if( mSignature[i] != sig.mSignature[i] ) return false;
211
      }
212 1d581993 Leszek Koltunski
213 882a8142 Leszek Koltunski
    return true;
214 1d581993 Leszek Koltunski
    }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218 882a8142 Leszek Koltunski
  public long[] getArray()
219 1d581993 Leszek Koltunski
    {
220 882a8142 Leszek Koltunski
    return mSignature;
221 1d581993 Leszek Koltunski
    }
222
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224
225 882a8142 Leszek Koltunski
  public String getString()
226 1d581993 Leszek Koltunski
    {
227 882a8142 Leszek Koltunski
    if( mName==null )
228
      {
229
      StringBuilder sb = new StringBuilder();
230 1d581993 Leszek Koltunski
231 882a8142 Leszek Koltunski
      for(int i=0; i<SIZE; i++)
232
        {
233
        String sig = String.format("0x%016X", mSignature[i]);
234
        if( i>0 ) sb.append('_');
235
        sb.append(sig);
236
        }
237 1d581993 Leszek Koltunski
238 882a8142 Leszek Koltunski
      mName = sb.toString();
239
      }
240 efeca8ef Leszek Koltunski
241 882a8142 Leszek Koltunski
    return mName;
242 1d581993 Leszek Koltunski
    }
243
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
246
  public boolean isUnblockedFromLeft(int axis, int layer)
247
    {
248
    if(layer>0)
249
      for(int index=0; index<mNumCubitTouches; index++)
250
        if( getBit(index)!=0 )
251
          {
252
          float[] touch = getCubitTouchOfIndex(index);
253 338e42aa Leszek Koltunski
          if( belongsLeft(touch,axis,layer) ) return false;
254 1d581993 Leszek Koltunski
          }
255
256
    return true;
257
    }
258
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260
261
  public ObjectSignature turn(int axis, int layer, int turn)
262
    {
263
    ObjectSignature ret = new ObjectSignature(this);
264
265 0ac2c2e6 Leszek Koltunski
    // I don't understand it, but Firebase shows mCycles is occasionally null here.
266
    if( mCycles!=null && mCycles[axis]!=null )
267 1d581993 Leszek Koltunski
      {
268 0ac2c2e6 Leszek Koltunski
      int[][] cycles = mCycles[axis][layer];
269
270
      // it can happen that there are no cycles in this layer: 2x1x2 axis 0 layer 0.
271
      if( cycles!=null && cycles.length>0 && cycles[0]!=null )
272
        {
273
        if( cycles[0].length==4 ) for(int[] cyc : cycles) ret.cycle4(turn,cyc);
274
        else                      for(int[] cyc : cycles) ret.cycle2(cyc);
275
        }
276 1d581993 Leszek Koltunski
      }
277
278
    return ret;
279
    }
280
281 338e42aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
282
283
  private boolean belongsLeft(float[] point, int axis, int layer)
284
    {
285
    return 2*point[axis]+mLayer[axis] == 2*layer;
286
    }
287
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289
290 700dee26 Leszek Koltunski
  private void cycle2(int[] cyc)
291 1d581993 Leszek Koltunski
    {
292 700dee26 Leszek Koltunski
    int index0 = cyc[0];
293
    int index1 = cyc[1];
294 1d581993 Leszek Koltunski
295 671a53a2 Leszek Koltunski
    long b0 = getBit(index0);
296
    long b1 = getBit(index1);
297 1d581993 Leszek Koltunski
298 671a53a2 Leszek Koltunski
    setBit(index1,b0);
299
    setBit(index0,b1);
300
    }
301 1d581993 Leszek Koltunski
302 671a53a2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
303 1d581993 Leszek Koltunski
304 700dee26 Leszek Koltunski
  private void cycle4(int turn, int[] cyc)
305 671a53a2 Leszek Koltunski
    {
306 700dee26 Leszek Koltunski
    int index0 = cyc[0];
307
    int index1 = cyc[1];
308
    int index2 = cyc[2];
309
    int index3 = cyc[3];
310 671a53a2 Leszek Koltunski
311
    long b0 = getBit(index0);
312
    long b1 = getBit(index1);
313
    long b2 = getBit(index2);
314
    long b3 = getBit(index3);
315
316
    switch(turn)
317 1d581993 Leszek Koltunski
      {
318 671a53a2 Leszek Koltunski
      case 1: setBit(index0,b3);
319
              setBit(index1,b0);
320
              setBit(index2,b1);
321
              setBit(index3,b2);
322
              break;
323
      case 2: setBit(index0,b2);
324
              setBit(index1,b3);
325
              setBit(index2,b0);
326
              setBit(index3,b1);
327
              break;
328
      case 3: setBit(index0,b1);
329
              setBit(index1,b2);
330
              setBit(index2,b3);
331
              setBit(index3,b0);
332
              break;
333 1d581993 Leszek Koltunski
      }
334
    }
335
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337
338
  private void prepareCubitTouch()
339
    {
340
    int numCenters = mLayer[0]*mLayer[1]*mLayer[2];
341
    if( mLayer[0]>1 && mLayer[1]>1 && mLayer[2]>1 ) numCenters -= (mLayer[0]-2)*(mLayer[1]-2)*(mLayer[2]-2);
342
343
    float[][] centers = new float[numCenters][];
344
    int index = 0;
345
346 1f5d92b9 Leszek Koltunski
    for(int i=0; i<mLayer[0]; i++)
347
      for(int j=0; j<mLayer[1]; j++)
348
        for(int k=0; k<mLayer[2]; k++)
349 1d581993 Leszek Koltunski
          if( (i==0) || (i==mLayer[0]-1) || (j==0) || (j==mLayer[1]-1) || (k==0) || (k==mLayer[2]-1) )
350
            {
351
            centers[index++] = new float[] { i+0.5f*(1-mLayer[0]), j+0.5f*(1-mLayer[1]), k+0.5f*(1-mLayer[2]) };
352
            }
353
354
    ArrayList<float[]> mTouch = new ArrayList<>();
355
356
    for(int i=0; i<numCenters; i++)
357
      for(int j=i+1; j<numCenters; j++)
358
        {
359
        float[] c0 = centers[i];
360
        float[] c1 = centers[j];
361
362
        float x1 = c0[0];
363
        float y1 = c0[1];
364
        float z1 = c0[2];
365
        float x2 = c1[0];
366
        float y2 = c1[1];
367
        float z2 = c1[2];
368
369
        if( areNeighbours(x1-x2,y1-y2,z1-z2) )
370
          {
371 efeca8ef Leszek Koltunski
          float xc = (x1+x2)/2;
372 1d581993 Leszek Koltunski
          float yc = (y1+y2)/2;
373
          float zc = (z1+z2)/2;
374
375
          float[] touch = new float[] {xc,yc,zc};
376
          mTouch.add(touch);
377
          }
378
        }
379
380
    mNumCubitTouches = mTouch.size();
381
    mCubitTouch = new float[mNumCubitTouches][];
382
    for(int i=0; i<mNumCubitTouches; i++) mCubitTouch[i] = mTouch.remove(0);
383 efeca8ef Leszek Koltunski
384
    // now sort the touches so that the order agrees with 'Andreas signature' as defined here:
385
    // https://twistypuzzles.com/forum/viewtopic.php?p=415466#p415466
386
    // i.e. we need to sort by Y first (increasing) then by Z (decreasing) then by X (decreasing)
387
    // i.e. we need to sort by 100Y-10Z-X (increasing)
388
389
    for(int i=0; i<mNumCubitTouches; i++)
390
      {
391
      float[] ci = mCubitTouch[i];
392
      float val_i = 100*ci[1]-10*ci[2]-ci[0];
393
394
      for(int j=i+1; j<mNumCubitTouches; j++)
395
        {
396
        float[] cj = mCubitTouch[j];
397
        float val_j = 100*cj[1]-10*cj[2]-cj[0];
398
399
        if( val_j<val_i )
400
          {
401
          mCubitTouch[i] = cj;
402
          mCubitTouch[j] = ci;
403
          val_i = val_j;
404
          ci = cj;
405
          }
406
        }
407
      }
408 1d581993 Leszek Koltunski
    }
409
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
412
  private void prepareAllCycles()
413
    {
414 700dee26 Leszek Koltunski
    ArrayList<float[][]> cycles0 = new ArrayList<>();
415
    ArrayList<float[][]> cycles1 = new ArrayList<>();
416
    ArrayList<float[][]> cycles2 = new ArrayList<>();
417
418
    mNumLeftCyclesPerLayer = new int[3];
419
    mNumCentCyclesPerLayer = new int[3];
420 1f5d92b9 Leszek Koltunski
    mNumInneCyclesPerLayer = new int[3];
421 700dee26 Leszek Koltunski
422
    if( mLayer[1]==mLayer[2] ) generate4Cycles(cycles0,0);
423
    else                       generate2Cycles(cycles0,0);
424
    if( mLayer[0]==mLayer[2] ) generate4Cycles(cycles1,1);
425
    else                       generate2Cycles(cycles1,1);
426
    if( mLayer[0]==mLayer[1] ) generate4Cycles(cycles2,2);
427
    else                       generate2Cycles(cycles2,2);
428
429
    mCycles = new int[3][][][];
430
431
    mCycles[0] = fillUpCycles(cycles0,0,mLayer[0]);
432
    mCycles[1] = fillUpCycles(cycles1,1,mLayer[1]);
433
    mCycles[2] = fillUpCycles(cycles2,2,mLayer[2]);
434
    }
435
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437
438
  private void generate4Cycles(ArrayList<float[][]> cycles, int axis)
439
    {
440
    for(int i=0; i<mNumCubitTouches; i++)
441
      {
442
      int i0 = rotateIndex(axis,i);
443
      if( i0<=i ) continue;
444
      int i1 = rotateIndex(axis,i0);
445
      if( i1<=i ) continue;
446
      int i2 = rotateIndex(axis,i1);
447
      if( i2<=i ) continue;
448
449
      float[] f0 = getCubitTouchOfIndex(i);
450
      float[] f1 = getCubitTouchOfIndex(i0);
451
      float[] f2 = getCubitTouchOfIndex(i1);
452
      float[] f3 = getCubitTouchOfIndex(i2);
453
454
      int l = (int)(2*f0[axis]+mLayer[axis]);
455
456
      if( l==2 ) mNumLeftCyclesPerLayer[axis]++;
457
      if( l==1 ) mNumCentCyclesPerLayer[axis]++;
458 1f5d92b9 Leszek Koltunski
      if( mLayer[axis]>2 && l==3 ) mNumInneCyclesPerLayer[axis]++;
459 700dee26 Leszek Koltunski
460
      float[][] cycle = new float[][] { f0,f1,f2,f3 };
461
      cycles.add(cycle);
462
      }
463
    }
464
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466
467
  private void generate2Cycles(ArrayList<float[][]> cycles, int axis)
468
    {
469 1d581993 Leszek Koltunski
    for(int i=0; i<mNumCubitTouches; i++)
470 700dee26 Leszek Koltunski
      {
471
      int i0 = rotateIndex2(axis,i);
472
      if( i0<=i ) continue;
473
474
      float[] f0 = getCubitTouchOfIndex(i);
475
      float[] f1 = getCubitTouchOfIndex(i0);
476
477
      int l = (int)(2*f0[axis]+mLayer[axis]);
478
479
      if( l==2 ) mNumLeftCyclesPerLayer[axis]++;
480
      if( l==1 ) mNumCentCyclesPerLayer[axis]++;
481 1f5d92b9 Leszek Koltunski
      if( mLayer[axis]>2 && l==3 ) mNumInneCyclesPerLayer[axis]++;
482 700dee26 Leszek Koltunski
483
      float[][] cycle = new float[][] { f0,f1 };
484
      cycles.add(cycle);
485
      }
486
    }
487
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489
490
  private int[][][] fillUpCycles(ArrayList<float[][]> cyc, int axis, int numLayers)
491
    {
492
    int numCycles = cyc.size();
493
    int[] index = new int[numLayers];
494
495
    int numFirst = mNumCentCyclesPerLayer[axis];
496 1f5d92b9 Leszek Koltunski
    int numNext  = mNumLeftCyclesPerLayer[axis] + mNumInneCyclesPerLayer[axis];
497
    int numLast  = mNumLeftCyclesPerLayer[axis] + numFirst;
498 700dee26 Leszek Koltunski
499
    int[][][] ret = new int[numLayers][][];
500 1f5d92b9 Leszek Koltunski
    ret[          0] = new int[numFirst][];
501
    ret[numLayers-1] = new int[numLast][];
502
503
    for(int i=1; i<numLayers-1; i++) ret[i] = new int[numNext][];
504 700dee26 Leszek Koltunski
505
    for(int i=0; i<numCycles; i++)
506
      {
507
      float[][] cycle = cyc.remove(0);
508
      int layer = (int)(cycle[0][axis]+numLayers*0.5f);
509
510
      if( cycle.length==4 )
511 1d581993 Leszek Koltunski
        {
512 700dee26 Leszek Koltunski
        int i0 = getIndexOfCubitTouch(cycle[0][0],cycle[0][1],cycle[0][2]);
513
        int i1 = getIndexOfCubitTouch(cycle[1][0],cycle[1][1],cycle[1][2]);
514
        int i2 = getIndexOfCubitTouch(cycle[2][0],cycle[2][1],cycle[2][2]);
515
        int i3 = getIndexOfCubitTouch(cycle[3][0],cycle[3][1],cycle[3][2]);
516
        ret[layer][index[layer]] = new int[] {i0,i1,i2,i3};
517
        index[layer]++;
518
        }
519
      else
520
        {
521
        int i0 = getIndexOfCubitTouch(cycle[0][0],cycle[0][1],cycle[0][2]);
522
        int i1 = getIndexOfCubitTouch(cycle[1][0],cycle[1][1],cycle[1][2]);
523
        ret[layer][index[layer]] = new int[] {i0,i1};
524
        index[layer]++;
525 1d581993 Leszek Koltunski
        }
526 700dee26 Leszek Koltunski
      }
527 1d581993 Leszek Koltunski
528 700dee26 Leszek Koltunski
    return ret;
529 1d581993 Leszek Koltunski
    }
530
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532
533
  private int rotateIndex(int axis, int index)
534
    {
535
    float[] touch = getCubitTouchOfIndex(index);
536
537
    switch(axis)
538
      {
539
      case 0: return getIndexOfCubitTouch(+touch[0],+touch[2],-touch[1]);
540
      case 1: return getIndexOfCubitTouch(-touch[2],+touch[1],+touch[0]);
541
      case 2: return getIndexOfCubitTouch(+touch[1],-touch[0],+touch[2]);
542
      }
543
544
    return -1;
545
    }
546
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548
549
  private int rotateIndex2(int axis, int index)
550
    {
551
    float[] touch = getCubitTouchOfIndex(index);
552
553
    switch(axis)
554
      {
555
      case 0: return getIndexOfCubitTouch(+touch[0],-touch[1],-touch[2]);
556
      case 1: return getIndexOfCubitTouch(-touch[0],+touch[1],-touch[2]);
557
      case 2: return getIndexOfCubitTouch(-touch[0],-touch[1],+touch[2]);
558
      }
559
560
    return -1;
561
    }
562
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564
565
  private int getIndexOfCubitTouch(float x, float y, float z)
566
    {
567
    for(int i=0; i<mNumCubitTouches; i++)
568
      {
569
      float[] touch = mCubitTouch[i];
570
      if( touch[0]==x && touch[1]==y && touch[2]==z ) return i;
571
      }
572
573
    return -1;
574
    }
575
576
///////////////////////////////////////////////////////////////////////////////////////////////////
577
578
  private float[] getCubitTouchOfIndex(int index)
579
    {
580
    return mCubitTouch[index];
581
    }
582
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584
585
  private boolean areNeighbours(float dx, float dy, float dz)
586
    {
587
    return dx*dx+dy*dy+dz*dz<1.1f;
588
    }
589
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591
592
  private long getBit(int index)
593
    {
594 882a8142 Leszek Koltunski
    int sigIndex = SIZE-1-(index/64);
595
    return (mSignature[sigIndex]>>(index%64))&0x1;
596 1d581993 Leszek Koltunski
    }
597
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599
600
  private void setBit(int index, long bit)
601
    {
602 882a8142 Leszek Koltunski
    long diff    = (1L<<(index%64));
603
    int sigIndex = SIZE-1-(index/64);
604
    if( bit!=0 ) mSignature[sigIndex] |= diff;
605
    else         mSignature[sigIndex] &=~diff;
606 1d581993 Leszek Koltunski
    }
607
}