Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / signature / ObjectSignatureDiamond.java @ 9c7d220a

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.SQ2;
13
import static org.distorted.objectlib.main.TwistyObject.SQ3;
14
import static org.distorted.objectlib.main.TwistyObject.SQ6;
15

    
16
import org.distorted.library.helpers.QuatHelper;
17
import org.distorted.objectlib.bandaged.FactoryBandagedOctahedron;
18

    
19
import java.util.ArrayList;
20

    
21
///////////////////////////////////////////////////////////////////////////////////////////////////
22

    
23
public class ObjectSignatureDiamond extends ObjectSignature
24
{
25
  private static final float[][] ROT_AXIS =
26
    {
27
      { SQ6/3,  SQ3/3,      0},
28
      {-SQ6/3,  SQ3/3,      0},
29
      {     0, -SQ3/3, -SQ6/3},
30
      {     0, -SQ3/3,  SQ6/3},
31
    };
32

    
33
  private static final float[][] QUATS =
34
    {
35
      { SQ2/2,  0.5f,      0, 0.5f },
36
      {-SQ2/2,  0.5f,      0, 0.5f },
37
      {     0, -0.5f, -SQ2/2, 0.5f },
38
      {     0, -0.5f,  SQ2/2, 0.5f },
39
    };
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42
// Bandaged Diamond objects when read from JSON
43

    
44
  public ObjectSignatureDiamond(int x, long[] signature)
45
    {
46
    super(signature);
47

    
48
    mTmp = new float[4];
49
    mLayer = new int[] {x,x,x,x};
50

    
51
    prepareCubitTouch();
52
    prepareTouchRows();
53
    prepareAllCycles();
54
    }
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57
// Locally created bandaged diamonds 2<=N<=5
58

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

    
65
    prepareCubitTouch();
66

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

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

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

    
83
          if( areNeighbours(xi-xj,yi-yj,zi-zj) )
84
            {
85
            boolean octa = FactoryBandagedOctahedron.isOctahedron(yi);
86
            float xc,yc,zc;
87

    
88
            if( octa )
89
              {
90
              xc = (xi+2*xj)/3;
91
              yc = (yi+2*yj)/3;
92
              zc = (zi+2*zj)/3;
93
              }
94
            else
95
              {
96
              xc = (2*xi+xj)/3;
97
              yc = (2*yi+yj)/3;
98
              zc = (2*zi+zj)/3;
99
              }
100

    
101
            int bitIndex = getIndexOfCubitTouch(xc,yc,zc);
102
            setBit(bitIndex,1);
103
            }
104
          }
105
        }
106
      }
107
    }
108

    
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110

    
111
  private void prepareCubitTouch()
112
    {
113
    float[][][] centers = FactoryBandagedOctahedron.createPositions(mLayer[0]);
114
    float[][] octs = centers[0];
115
    float[][] tets = centers[1];
116

    
117
    ArrayList<float[]> mTouch = new ArrayList<>();
118

    
119
    for(float[] oct : octs)
120
      for(float[] tet : tets)
121
        {
122
        float ox=oct[0];
123
        float oy=oct[1];
124
        float oz=oct[2];
125
        float tx=tet[0];
126
        float ty=tet[1];
127
        float tz=tet[2];
128

    
129
        if( areNeighbours(ox-tx, oy-ty, oz-tz) )
130
          {
131
          float xc=(2*tx+ox)/3;
132
          float yc=(2*ty+oy)/3;
133
          float zc=(2*tz+oz)/3;
134

    
135
          float[] touch = new float[] {xc, yc, zc};
136
          mTouch.add(touch);
137
          }
138
        }
139

    
140
    mNumCubitTouches = mTouch.size();
141
    mCubitTouch = new float[mNumCubitTouches][];
142
    for(int i=0; i<mNumCubitTouches; i++) mCubitTouch[i] = mTouch.remove(0);
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private void prepareTouchRows()
148
    {
149
    mTouchRows = new int[4][mNumCubitTouches];
150
    int num = mLayer[0];
151
    final int N = 10;
152

    
153
    for(int i=0; i<mNumCubitTouches; i++)
154
      {
155
      float[] touch = mCubitTouch[i];
156

    
157
      for(int a=0; a<4; a++)
158
        {
159
        float[] ax = ROT_AXIS[a];
160
        float l = whichLayer(touch,ax,num);
161
        int ll = (int)(N*l);
162
        mTouchRows[a][i] = ( (ll%N)==0 ) ? ll/N : -1;
163
        }
164
      }
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private void prepareAllCycles()
170
    {
171
    ArrayList<float[][]> cycles0 = new ArrayList<>();
172
    ArrayList<float[][]> cycles1 = new ArrayList<>();
173
    ArrayList<float[][]> cycles2 = new ArrayList<>();
174
    ArrayList<float[][]> cycles3 = new ArrayList<>();
175

    
176
    generate3Cycles(cycles0,0);
177
    generate3Cycles(cycles1,1);
178
    generate3Cycles(cycles2,2);
179
    generate3Cycles(cycles3,3);
180

    
181
    mCycles = new int[4][][][];
182

    
183
    int numLayers = mLayer[0];
184
    mCycles[0] = fillUpCycles(cycles0,0,numLayers);
185
    mCycles[1] = fillUpCycles(cycles1,1,numLayers);
186
    mCycles[2] = fillUpCycles(cycles2,2,numLayers);
187
    mCycles[3] = fillUpCycles(cycles3,3,numLayers);
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  private void generate3Cycles(ArrayList<float[][]> cycles, int ax)
193
    {
194
    for(int i=0; i<mNumCubitTouches; i++)
195
      {
196
      int i0 = rotateIndex3(ax,i);
197
      if( i0<=i ) continue;
198
      int i1 = rotateIndex3(ax,i0);
199
      if( i1<=i ) continue;
200

    
201
      float[] f0 = getCubitTouchOfIndex(i);
202
      float[] f1 = getCubitTouchOfIndex(i0);
203
      float[] f2 = getCubitTouchOfIndex(i1);
204

    
205
      float[][] cycle = new float[][] { f0,f1,f2 };
206
      cycles.add(cycle);
207
      }
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  private int[][][] fillUpCycles(ArrayList<float[][]> cyc, int axis, int numLayers)
213
    {
214
    int numCycles = cyc.size();
215
    int[] index = new int[numLayers];
216
    int[] numC = new int[numLayers];
217
    float[] ax = ROT_AXIS[axis];
218

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

    
226
    int[][][] ret = new int[numLayers][][];
227
    for(int i=0; i<numLayers; i++) ret[i] = new int[numC[i]][];
228

    
229
    for(int i=0; i<numCycles; i++)
230
      {
231
      float[][] cycle = cyc.remove(0);
232
      int layer = (int)whichLayer(cycle[0],ax,numLayers);
233

    
234
      int i0 = getIndexOfCubitTouch(cycle[0][0],cycle[0][1],cycle[0][2]);
235
      int i1 = getIndexOfCubitTouch(cycle[1][0],cycle[1][1],cycle[1][2]);
236
      int i2 = getIndexOfCubitTouch(cycle[2][0],cycle[2][1],cycle[2][2]);
237

    
238
      ret[layer][index[layer]] = new int[] {i0,i1,i2};
239
      index[layer]++;
240
      }
241

    
242
    return ret;
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  private float whichLayer(float[] point, float[] ax, int numLayers)
248
    {
249
    float d = point[0]*ax[0] + point[1]*ax[1] + point[2]*ax[2];
250
    float r = (SQ6/2)*d + numLayers*0.5f + 0.001f;
251
    return r>=numLayers ? numLayers-0.001f : r;
252
    }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  private int rotateIndex3(int ax, int index)
257
    {
258
    float[] touch = getCubitTouchOfIndex(index);
259
    QuatHelper.rotateVectorByQuat(mTmp, touch[0], touch[1], touch[2], 1.0f, QUATS[ax]);
260
    return getIndexOfCubitTouch(mTmp[0],mTmp[1],mTmp[2]);
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  private boolean areNeighbours(float dx, float dy, float dz)
266
    {
267
    return dx*dx+dy*dy+dz*dz < SQ6/4 + 0.01f;
268
    }
269
}
(3-3/6)