Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / Cubit.java @ 3717a94e

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
package org.distorted.objects;
21

    
22
import android.content.SharedPreferences;
23

    
24
import org.distorted.library.type.Static3D;
25
import org.distorted.library.type.Static4D;
26
import org.distorted.main.RubikSurfaceView;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

    
30
class Cubit
31
  {
32
  private final Static3D mOrigPosition;
33

    
34
  private RubikObject mParent;
35
  private Static3D mCurrentPosition;
36
  private int mNumAxis;
37

    
38
  int mQuatIndex;
39
  float[] mRotationRow;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
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
    mCurrentPosition = new Static3D(x,y,z);
52
    mQuatIndex       = 0;
53

    
54
    mNumAxis     = mParent.ROTATION_AXIS.length;
55
    mRotationRow = new float[mNumAxis];
56
    computeRotationRow();
57
    }
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
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
// list QUATS.
63
//
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

    
67
  private int normalizeScrambleQuat(Static4D quat)
68
    {
69
    float x = quat.get0();
70
    float y = quat.get1();
71
    float z = quat.get2();
72
    float w = quat.get3();
73
    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

    
79
    for(int q=0; q<num_quats; q++)
80
      {
81
      qt = mParent.QUATS[q];
82

    
83
      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
        {
92
        ret = q;
93
        mindiff = diff;
94
        }
95

    
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
        {
105
        ret = q;
106
        mindiff = diff;
107
        }
108
      }
109

    
110
    return ret;
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

    
115
  private void modifyCurrentPosition(Static4D quat)
116
    {
117
    float cubitCenterX = mCurrentPosition.get0();
118
    float cubitCenterY = mCurrentPosition.get1();
119
    float cubitCenterZ = mCurrentPosition.get2();
120

    
121
    Static4D cubitCenter =  new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
122
    Static4D rotatedCenter = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat);
123

    
124
    float rotatedX = rotatedCenter.get0();
125
    float rotatedY = rotatedCenter.get1();
126
    float rotatedZ = rotatedCenter.get2();
127

    
128
    mCurrentPosition.set(rotatedX, rotatedY, rotatedZ);
129
    mParent.clampPos(mCurrentPosition);
130

    
131
    computeRotationRow();
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135
// cast current position on axis; use mStart and mStep to compute the rotation row for each axis.
136

    
137
  private void computeRotationRow()
138
    {
139
    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
      mRotationRow[i] = (tmp-mParent.mStart)/mParent.mStep;
150
      }
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  Static3D getOrigPosition()
156
    {
157
    return mOrigPosition;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  int computeAssociation()
163
    {
164
    int row, result = 0, accumulativeShift = 0;
165

    
166
    for(int axis=0; axis<mNumAxis; axis++)
167
      {
168
      row = (int)(mRotationRow[axis]+0.5f);
169
      result += (1<<(row+accumulativeShift));
170
      accumulativeShift += RubikObjectList.MAX_OBJECT_SIZE;
171
      }
172

    
173
    return result;
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  void savePreferences(SharedPreferences.Editor editor)
179
    {
180
    String number = mOrigPosition.get0()+"_"+mOrigPosition.get1()+"_"+mOrigPosition.get2();
181
    editor.putInt("q_"+number, mQuatIndex);
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  int restorePreferences(SharedPreferences preferences)
187
    {
188
    String number = mOrigPosition.get0()+"_"+mOrigPosition.get1()+"_"+mOrigPosition.get2();
189
    mQuatIndex = preferences.getInt("q_"+number, 0);
190
    modifyCurrentPosition(mParent.QUATS[mQuatIndex]);
191

    
192
    return mQuatIndex;
193
    }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

    
197
  int removeRotationNow(Static4D quat)
198
    {
199
    Static4D q = RubikSurfaceView.quatMultiply(quat,mParent.QUATS[mQuatIndex]);
200
    mQuatIndex = normalizeScrambleQuat(q);
201

    
202
    modifyCurrentPosition(quat);
203

    
204
    return mQuatIndex;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  void solve()
210
    {
211
    mQuatIndex = 0;
212
    mCurrentPosition.set(mOrigPosition);
213
    computeRotationRow();
214
    }
215

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

    
218
  float getDistSquared(float[] point)
219
    {
220
    float dx = mCurrentPosition.get0() - point[0];
221
    float dy = mCurrentPosition.get1() - point[1];
222
    float dz = mCurrentPosition.get2() - point[2];
223

    
224
    return dx*dx + dy*dy + dz*dz;
225
    }
226
}
(1-1/14)