Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / signature / ObjectSignatureSkewb.java @ 7e8750c9

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.signature;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.SQ3;
13

    
14
import org.distorted.library.helpers.QuatHelper;
15
import org.distorted.objectlib.bandaged.FactoryBandagedSkewb;
16

    
17
import java.util.ArrayList;
18

    
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
public class ObjectSignatureSkewb extends ObjectSignature
22
{
23
  private static final float[][] ROT_AXIS =
24
    {
25
      { SQ3/3, SQ3/3, SQ3/3 },
26
      { SQ3/3, SQ3/3,-SQ3/3 },
27
      { SQ3/3,-SQ3/3, SQ3/3 },
28
      { SQ3/3,-SQ3/3,-SQ3/3 },
29
    };
30

    
31
  private static final float[][] QUATS =
32
    {
33
      { 0.5f, 0.5f, 0.5f, 0.5f },
34
      { 0.5f, 0.5f,-0.5f, 0.5f },
35
      { 0.5f,-0.5f, 0.5f, 0.5f },
36
      { 0.5f,-0.5f,-0.5f, 0.5f },
37
    };
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40
// Bandaged Skewb objects when read from JSON
41

    
42
  public ObjectSignatureSkewb(int x, long[] signature)
43
    {
44
    super(signature);
45

    
46
    mTmp = new float[4];
47
    mLayer = new int[] {x,x,x,x};
48

    
49
    prepareCubitTouch();
50
    prepareTouchRows();
51
    prepareAllCycles();
52
    }
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55
// Locally created bandaged Skewbs 2<=N<=3
56

    
57
  public ObjectSignatureSkewb(int x, float[][] position)
58
    {
59
    mTmp = new float[4];
60
    mLayer = new int[] {x,x,x,x};
61
    mSignature = new long[SIZE];
62

    
63
    prepareCubitTouch();
64

    
65
    for(float[] pos : position)
66
      {
67
      int numCenters = pos.length/3;
68

    
69
      for(int i=0; i<numCenters; i++)
70
        {
71
        float xi = pos[3*i  ];
72
        float yi = pos[3*i+1];
73
        float zi = pos[3*i+2];
74

    
75
        for(int j=i+1; j<numCenters; j++)
76
          {
77
          float xj = pos[3*j  ];
78
          float yj = pos[3*j+1];
79
          float zj = pos[3*j+2];
80

    
81
          if( areNeighbours(xi,yi,zi,xj,yj,zj) )
82
            {
83
            float xc = (xi+xj)/2;
84
            float yc = (yi+yj)/2;
85
            float zc = (zi+zj)/2;
86
            int bitIndex = getIndexOfCubitTouch(xc,yc,zc);
87
            setBit(bitIndex,1);
88
            }
89
          }
90
        }
91
      }
92
    }
93

    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

    
96
  private void prepareCubitTouch()
97
    {
98
    FactoryBandagedSkewb factory = FactoryBandagedSkewb.getInstance();
99
    float[][][] centers = factory.getPositions(mLayer);
100
    int numCubits=0;
101
    int numVariants = centers.length;
102
    for(float[][] center : centers) numCubits += center.length;
103

    
104
    ArrayList<float[]> touch = new ArrayList<>();
105

    
106
    for(int i=0; i<numCubits; i++)
107
      {
108
      float[] first = getPosition(i,centers,numVariants);
109
      float ox = first[0];
110
      float oy = first[1];
111
      float oz = first[2];
112

    
113
      for(int j=i+1; j<numCubits; j++)
114
        {
115
        float[] second = getPosition(j,centers,numVariants);
116
        float tx = second[0];
117
        float ty = second[1];
118
        float tz = second[2];
119

    
120
        if( areNeighbours(ox,oy,oz,tx,ty,tz) )
121
          {
122
          float xc = (tx+ox)/2;
123
          float yc = (ty+oy)/2;
124
          float zc = (tz+oz)/2;
125

    
126
          float[] t = new float[] {xc, yc, zc};
127
          touch.add(t);
128
          }
129
        }
130
      }
131

    
132
    mNumCubitTouches = touch.size();
133
    mCubitTouch = new float[mNumCubitTouches][];
134
    for(int i=0; i<mNumCubitTouches; i++) mCubitTouch[i] = touch.remove(0);
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  private void prepareTouchRows()
140
    {
141
    mTouchRows = new int[4][mNumCubitTouches];
142
    int num = mLayer[0];
143
    final int N = 10;
144

    
145
    for(int i=0; i<mNumCubitTouches; i++)
146
      {
147
      float[] touch = mCubitTouch[i];
148

    
149
      for(int a=0; a<4; a++)
150
        {
151
        float[] ax = ROT_AXIS[a];
152
        float l = whichLayer(touch,ax,num);
153
        int ll = (int)(N*l);
154
        mTouchRows[a][i] = ( (ll%N)==0 ) ? ll/N : -1;
155
        }
156
      }
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
  private void prepareAllCycles()
162
    {
163
    ArrayList<float[][]> cycles0 = new ArrayList<>();
164
    ArrayList<float[][]> cycles1 = new ArrayList<>();
165
    ArrayList<float[][]> cycles2 = new ArrayList<>();
166
    ArrayList<float[][]> cycles3 = new ArrayList<>();
167

    
168
    generate3Cycles(cycles0,0);
169
    generate3Cycles(cycles1,1);
170
    generate3Cycles(cycles2,2);
171
    generate3Cycles(cycles3,3);
172

    
173
    mCycles = new int[4][][][];
174

    
175
    int numLayers = mLayer[0];
176
    mCycles[0] = fillUpCycles(cycles0,0,numLayers);
177
    mCycles[1] = fillUpCycles(cycles1,1,numLayers);
178
    mCycles[2] = fillUpCycles(cycles2,2,numLayers);
179
    mCycles[3] = fillUpCycles(cycles3,3,numLayers);
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  private void generate3Cycles(ArrayList<float[][]> cycles, int ax)
185
    {
186
    for(int i=0; i<mNumCubitTouches; i++)
187
      {
188
      int i0 = rotateIndex3(ax,i);
189
      if( i0<=i ) continue;
190
      int i1 = rotateIndex3(ax,i0);
191
      if( i1<=i ) continue;
192

    
193
      float[] f0 = getCubitTouchOfIndex(i);
194
      float[] f1 = getCubitTouchOfIndex(i0);
195
      float[] f2 = getCubitTouchOfIndex(i1);
196

    
197
      float[][] cycle = new float[][] { f0,f1,f2 };
198
      cycles.add(cycle);
199
      }
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  private int[][][] fillUpCycles(ArrayList<float[][]> cyc, int axis, int numLayers)
205
    {
206
    int numCycles = cyc.size();
207
    int[] index = new int[numLayers];
208
    int[] numC = new int[numLayers];
209
    float[] ax = ROT_AXIS[axis];
210

    
211
    for(int i=0; i<numCycles; i++)
212
      {
213
      float[][] cycle = cyc.get(i);
214
      int layer = (int)whichLayer(cycle[0],ax,numLayers);
215
      numC[layer]++;
216
      }
217

    
218
    int[][][] ret = new int[numLayers][][];
219
    for(int i=0; i<numLayers; i++) ret[i] = new int[numC[i]][];
220

    
221
    for(int i=0; i<numCycles; i++)
222
      {
223
      float[][] cycle = cyc.remove(0);
224
      int layer = (int)whichLayer(cycle[0],ax,numLayers);
225

    
226
      int i0 = getIndexOfCubitTouch(cycle[0][0],cycle[0][1],cycle[0][2]);
227
      int i1 = getIndexOfCubitTouch(cycle[1][0],cycle[1][1],cycle[1][2]);
228
      int i2 = getIndexOfCubitTouch(cycle[2][0],cycle[2][1],cycle[2][2]);
229

    
230
      ret[layer][index[layer]] = new int[] {i0,i1,i2};
231
      index[layer]++;
232
      }
233

    
234
    return ret;
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  private float whichLayer(float[] point, float[] ax, int numLayers)
240
    {
241
    float d = point[0]*ax[0] + point[1]*ax[1] + point[2]*ax[2];
242
    float r = numLayers==2 ? (d/SQ3 + 1.01f) : (d/(0.75f*SQ3) + 1.51f);
243
    return r>=numLayers ? numLayers-0.001f : r;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  private int rotateIndex3(int ax, int index)
249
    {
250
    float[] touch = getCubitTouchOfIndex(index);
251
    QuatHelper.rotateVectorByQuat(mTmp, touch[0], touch[1], touch[2], 1.0f, QUATS[ax]);
252
    return getIndexOfCubitTouch(mTmp[0],mTmp[1],mTmp[2]);
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  private boolean areNeighbours(float x1, float y1, float z1, float x2, float y2, float z2)
258
    {
259
    float dx = x1-x2;
260
    float dy = y1-y2;
261
    float dz = z1-z2;
262

    
263
    if( dx*dx + dy*dy + dz*dz < 2*1.01f )
264
      {
265
      float s = 0.25f*mLayer[0]*mLayer[0];
266
      return (x1==x2 && x1*x1==s) || (y1==y2 && y1*y1==s) || (z1==z2 && z1*z1==s);
267
      }
268

    
269
    return false;
270
    }
271
}
(6-6/6)