Project

General

Profile

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

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

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