Project

General

Profile

Download (10.3 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / Cubit.java @ 5944e760

1 70b76549 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 70b76549 Leszek Koltunski
22
import android.content.SharedPreferences;
23
24
import org.distorted.library.type.Static3D;
25
import org.distorted.library.type.Static4D;
26 1f9772f3 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
27 70b76549 Leszek Koltunski
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
30
class Cubit
31
  {
32
  private final Static3D mOrigPosition;
33
34
  private RubikObject mParent;
35 0e7bcfb1 Leszek Koltunski
  private Static3D mCurrentPosition;
36 e844c116 Leszek Koltunski
  private int mNumAxis;
37 70b76549 Leszek Koltunski
38 2fcad75d Leszek Koltunski
  int mQuatIndex;
39 66cbdd21 Leszek Koltunski
  float[] mRotationRow;
40 70b76549 Leszek Koltunski
41 470820a7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
42
43
  Cubit(RubikObject parent, Static3D position)
44
    {
45
    float x = position.get0();
46
    float y = position.get1();
47
    float z = position.get2();
48
49
    mParent          = parent;
50
    mOrigPosition    = new Static3D(x,y,z);
51 2fcad75d Leszek Koltunski
    mCurrentPosition = new Static3D(x,y,z);
52
    mQuatIndex       = 0;
53 470820a7 Leszek Koltunski
54
    mNumAxis     = mParent.ROTATION_AXIS.length;
55
    mRotationRow = new float[mNumAxis];
56
    computeRotationRow();
57
    }
58
59 70b76549 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
60
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
61
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the
62 98904e45 Leszek Koltunski
// list QUATS.
63 70b76549 Leszek Koltunski
//
64
// We also have to remember that the group of unit quaternions is a double-cover of rotations
65
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
66 9f4c44fe Leszek Koltunski
67 98904e45 Leszek Koltunski
  private int normalizeScrambleQuat(Static4D quat)
68
    {
69 70b76549 Leszek Koltunski
    float x = quat.get0();
70
    float y = quat.get1();
71
    float z = quat.get2();
72
    float w = quat.get3();
73 98904e45 Leszek Koltunski
    float xd,yd,zd,wd;
74
    float diff, mindiff = Float.MAX_VALUE;
75
    int ret=0;
76
    int num_quats = mParent.QUATS.length;
77
    Static4D qt;
78 70b76549 Leszek Koltunski
79 98904e45 Leszek Koltunski
    for(int q=0; q<num_quats; q++)
80 70b76549 Leszek Koltunski
      {
81 98904e45 Leszek Koltunski
      qt = mParent.QUATS[q];
82 70b76549 Leszek Koltunski
83 98904e45 Leszek Koltunski
      xd = x - qt.get0();
84
      yd = y - qt.get1();
85
      zd = z - qt.get2();
86
      wd = w - qt.get3();
87
88
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
89
90
      if( diff < mindiff )
91 70b76549 Leszek Koltunski
        {
92 98904e45 Leszek Koltunski
        ret = q;
93
        mindiff = diff;
94 70b76549 Leszek Koltunski
        }
95 98904e45 Leszek Koltunski
96
      xd = x + qt.get0();
97
      yd = y + qt.get1();
98
      zd = z + qt.get2();
99
      wd = w + qt.get3();
100
101
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
102
103
      if( diff < mindiff )
104 70b76549 Leszek Koltunski
        {
105 98904e45 Leszek Koltunski
        ret = q;
106
        mindiff = diff;
107 70b76549 Leszek Koltunski
        }
108
      }
109
110 98904e45 Leszek Koltunski
    return ret;
111 70b76549 Leszek Koltunski
    }
112 98904e45 Leszek Koltunski
113 70b76549 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
114
115 94ad5a8f Leszek Koltunski
  private void modifyCurrentPosition(Static4D quat)
116 70b76549 Leszek Koltunski
    {
117 94ad5a8f Leszek Koltunski
    float cubitCenterX = mCurrentPosition.get0();
118
    float cubitCenterY = mCurrentPosition.get1();
119
    float cubitCenterZ = mCurrentPosition.get2();
120 70b76549 Leszek Koltunski
121
    Static4D cubitCenter =  new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
122
    Static4D rotatedCenter = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat);
123
124 49f67f9b Leszek Koltunski
    float rotatedX = rotatedCenter.get0();
125
    float rotatedY = rotatedCenter.get1();
126
    float rotatedZ = rotatedCenter.get2();
127 70b76549 Leszek Koltunski
128 94ad5a8f Leszek Koltunski
    mCurrentPosition.set(rotatedX, rotatedY, rotatedZ);
129
    mParent.clampPos(mCurrentPosition);
130 70b76549 Leszek Koltunski
131 10a2e360 Leszek Koltunski
    computeRotationRow();
132
    }
133
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135 e844c116 Leszek Koltunski
// cast current position on axis; use mStart and mStep to compute the rotation row for each axis.
136 10a2e360 Leszek Koltunski
137
  private void computeRotationRow()
138
    {
139 e844c116 Leszek Koltunski
    float tmp;
140
    Static3D axis;
141
    float x = mCurrentPosition.get0();
142
    float y = mCurrentPosition.get1();
143
    float z = mCurrentPosition.get2();
144
145
    for(int i=0; i<mNumAxis; i++)
146
      {
147
      axis = mParent.ROTATION_AXIS[i];
148
      tmp = x*axis.get0() + y*axis.get1() + z*axis.get2();
149 66cbdd21 Leszek Koltunski
      mRotationRow[i] = (tmp-mParent.mStart)/mParent.mStep;
150 e844c116 Leszek Koltunski
      }
151 70b76549 Leszek Koltunski
    }
152
153 27e6c301 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
154
155
  int computeAssociation()
156
    {
157
    int row, result = 0, accumulativeShift = 0;
158
159
    for(int axis=0; axis<mNumAxis; axis++)
160
      {
161
      row = (int)(mRotationRow[axis]+0.5f);
162
      result += (1<<(row+accumulativeShift));
163 8cccfb10 Leszek Koltunski
      accumulativeShift += RubikObjectList.MAX_OBJECT_SIZE;
164 27e6c301 Leszek Koltunski
      }
165
166
    return result;
167
    }
168
169 70b76549 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
170
171
  void savePreferences(SharedPreferences.Editor editor)
172
    {
173
    String number = mOrigPosition.get0()+"_"+mOrigPosition.get1()+"_"+mOrigPosition.get2();
174 2fcad75d Leszek Koltunski
    editor.putInt("q_"+number, mQuatIndex);
175 70b76549 Leszek Koltunski
    }
176
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179 2fcad75d Leszek Koltunski
  int restorePreferences(SharedPreferences preferences)
180 70b76549 Leszek Koltunski
    {
181
    String number = mOrigPosition.get0()+"_"+mOrigPosition.get1()+"_"+mOrigPosition.get2();
182 2fcad75d Leszek Koltunski
    mQuatIndex = preferences.getInt("q_"+number, 0);
183
    modifyCurrentPosition(mParent.QUATS[mQuatIndex]);
184 70b76549 Leszek Koltunski
185 2fcad75d Leszek Koltunski
    return mQuatIndex;
186 94ad5a8f Leszek Koltunski
    }
187
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
190
// then if it were rotated by quaternion 'quat'.
191
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
192
// middle squares get interchanged. No visible difference!
193
//
194
// So: this is true iff the cubit
195
// a) is a corner or edge and the quaternions are the same
196
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
197
198 2fcad75d Leszek Koltunski
  boolean thereIsNoVisibleDifference(int quatIndex)
199 94ad5a8f Leszek Koltunski
    {
200 2fcad75d Leszek Koltunski
    if ( mQuatIndex == quatIndex ) return true;
201 94ad5a8f Leszek Koltunski
202
    int belongsToHowManyFaces = 0;
203
    int size = mParent.getSize()-1;
204 7437ebb3 Leszek Koltunski
    float row;
205
    final float MAX_ERROR = 0.01f;
206 94ad5a8f Leszek Koltunski
207
    for(int i=0; i<mNumAxis; i++)
208
      {
209 7437ebb3 Leszek Koltunski
      row = mRotationRow[i];
210
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
211
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
212 94ad5a8f Leszek Koltunski
      }
213
214
    switch(belongsToHowManyFaces)
215
      {
216
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
217
      case 1 :                // cubit that lies inside one of the faces
218 5944e760 Leszek Koltunski
               float cubitCenterX = mOrigPosition.get0();
219
               float cubitCenterY = mOrigPosition.get1();
220
               float cubitCenterZ = mOrigPosition.get2();
221 94ad5a8f Leszek Koltunski
222 2fcad75d Leszek Koltunski
               Static4D quat1 = mParent.QUATS[quatIndex];
223
               Static4D quat2 = mParent.QUATS[mQuatIndex];
224
225 94ad5a8f Leszek Koltunski
               Static4D cubitCenter = new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
226 2fcad75d Leszek Koltunski
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
227
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
228 94ad5a8f Leszek Koltunski
229 7437ebb3 Leszek Koltunski
               float row1, row2, row3, row4;
230 94ad5a8f Leszek Koltunski
               float ax,ay,az;
231
               Static3D axis;
232
               float x1 = rotated1.get0();
233
               float y1 = rotated1.get1();
234
               float z1 = rotated1.get2();
235
               float x2 = rotated2.get0();
236
               float y2 = rotated2.get1();
237
               float z2 = rotated2.get2();
238
239
               for(int i=0; i<mNumAxis; i++)
240
                 {
241
                 axis = mParent.ROTATION_AXIS[i];
242
                 ax = axis.get0();
243
                 ay = axis.get1();
244
                 az = axis.get2();
245
246 7437ebb3 Leszek Koltunski
                 row1 = ((x1*ax + y1*ay + z1*az) - mParent.mStart) / mParent.mStep;
247
                 row2 = ((x2*ax + y2*ay + z2*az) - mParent.mStart) / mParent.mStep;
248
                 row3 = row1 - size;
249
                 row4 = row2 - size;
250 94ad5a8f Leszek Koltunski
251 7437ebb3 Leszek Koltunski
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
252
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
253 94ad5a8f Leszek Koltunski
                   {
254
                   return true;
255
                   }
256
                 }
257
               return false;
258 5944e760 Leszek Koltunski
259 94ad5a8f Leszek Koltunski
      default: return false;  // edge or corner
260
      }
261 70b76549 Leszek Koltunski
    }
262
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264
265 98904e45 Leszek Koltunski
  int removeRotationNow(Static4D quat)
266 70b76549 Leszek Koltunski
    {
267 2fcad75d Leszek Koltunski
    Static4D q = RubikSurfaceView.quatMultiply(quat,mParent.QUATS[mQuatIndex]);
268
    mQuatIndex = normalizeScrambleQuat(q);
269 98904e45 Leszek Koltunski
270 001cc0e4 Leszek Koltunski
    modifyCurrentPosition(quat);
271 98904e45 Leszek Koltunski
272 2fcad75d Leszek Koltunski
    return mQuatIndex;
273 70b76549 Leszek Koltunski
    }
274
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
277
  void solve()
278
    {
279 2fcad75d Leszek Koltunski
    mQuatIndex = 0;
280 70b76549 Leszek Koltunski
    mCurrentPosition.set(mOrigPosition);
281 0e7bcfb1 Leszek Koltunski
    computeRotationRow();
282 70b76549 Leszek Koltunski
    }
283
284 9621255f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
285
286
  float getDistSquared(float[] point)
287
    {
288
    float dx = mCurrentPosition.get0() - point[0];
289
    float dy = mCurrentPosition.get1() - point[1];
290
    float dz = mCurrentPosition.get2() - point[2];
291
292
    return dx*dx + dy*dy + dz*dz;
293
    }
294 70b76549 Leszek Koltunski
}