Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / QuatGroupGenerator.java @ c0266cb1

1 0d15e934 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 0d15e934 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.helpers;
11
12
import org.distorted.library.main.QuatHelper;
13
import org.distorted.library.type.Static3D;
14
import org.distorted.library.type.Static4D;
15 ee28f820 Leszek Koltunski
import org.distorted.objectlib.main.ObjectControl;
16 0d15e934 Leszek Koltunski
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18
19
public class QuatGroupGenerator
20
  {
21
  private static final int MAX_GROUP_SIZE = 256;
22
  private static final double PI = Math.PI;
23
  private static final Static4D[] mTable= new Static4D[MAX_GROUP_SIZE];
24
25
  private static int mInserted;
26
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// sin(A/2)*x, sin(A/2)*y, sin(A/2)*z, cos(A/2)
29
30
  private static void createQuat(Static3D axis, double angle, Static4D output)
31
    {
32
    float cosAngle = (float)Math.cos(angle/2);
33
    float sinAngle = (float)Math.sin(angle/2);
34
35
    output.set0( sinAngle*axis.get0() );
36
    output.set1( sinAngle*axis.get1() );
37
    output.set2( sinAngle*axis.get2() );
38
    output.set3( cosAngle );
39
    }
40
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42
// double cover, so q == -q
43
44
  private static boolean quatTheSame(Static4D q1, Static4D q2)
45
    {
46
    final float MAX_ERROR = 0.01f;
47
48
    float q10 = q1.get0();
49
    float q11 = q1.get1();
50
    float q12 = q1.get2();
51
    float q13 = q1.get3();
52
53
    float q20 = q2.get0();
54
    float q21 = q2.get1();
55
    float q22 = q2.get2();
56
    float q23 = q2.get3();
57
58
    float d0 = q10-q20;
59
    float d1 = q11-q21;
60
    float d2 = q12-q22;
61
    float d3 = q13-q23;
62
63
    if( d0<MAX_ERROR && d0>-MAX_ERROR &&
64
        d1<MAX_ERROR && d1>-MAX_ERROR &&
65
        d2<MAX_ERROR && d2>-MAX_ERROR &&
66
        d3<MAX_ERROR && d3>-MAX_ERROR  ) return true;
67
68
    d0 = q10+q20;
69
    d1 = q11+q21;
70
    d2 = q12+q22;
71
    d3 = q13+q23;
72
73
    if( d0<MAX_ERROR && d0>-MAX_ERROR &&
74
        d1<MAX_ERROR && d1>-MAX_ERROR &&
75
        d2<MAX_ERROR && d2>-MAX_ERROR &&
76
        d3<MAX_ERROR && d3>-MAX_ERROR  ) return true;
77
78
    return false;
79
    }
80
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
83
  private static int getIndexInTable(Static4D quat, Static4D[] table)
84
    {
85
    for(int i=0; i<mInserted; i++)
86
      {
87
      if( quatTheSame(quat,table[i]) ) return i;
88
      }
89
90
    return -1;
91
    }
92
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94
95
  private static boolean insertQuat(Static4D quat, Static4D[] table)
96
    {
97
    if( getIndexInTable(quat,table)<0 )
98
      {
99
      if( mInserted<MAX_GROUP_SIZE )
100
        {
101
        table[mInserted] = new Static4D(quat);
102
        mInserted++;
103
        return true;
104
        }
105
      return false;
106
      }
107
108
    return true;
109
    }
110
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112
// PUBLIC API
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
115 beee90ab Leszek Koltunski
  public static Static4D[] computeGroup(Static3D[] rotAxis, int[][] basicAngles)
116 0d15e934 Leszek Koltunski
    {
117
    Static4D quat = new Static4D(0,0,0,1);
118
    int num,numAxis = rotAxis.length;
119
    mInserted = 0;
120
121
    insertQuat(quat,mTable);
122
123
    for( int ax=0; ax<numAxis; ax++)
124 beee90ab Leszek Koltunski
      {
125
      int numLayers = basicAngles[ax].length;
126
127
      for( int layer=0; layer<numLayers; layer++)
128 0d15e934 Leszek Koltunski
        {
129 beee90ab Leszek Koltunski
        int numAngles = basicAngles[ax][layer];
130
131
        for(int angle=1; angle<numAngles; angle++)
132
          {
133
          createQuat(rotAxis[ax], (2*PI*angle)/numAngles, quat);
134
          insertQuat(quat,mTable);
135
          }
136 0d15e934 Leszek Koltunski
        }
137 beee90ab Leszek Koltunski
      }
138 0d15e934 Leszek Koltunski
139
    do
140
      {
141
      num = mInserted;
142
143
      for(int i=0; i<num; i++)
144
        for(int j=0; j<num; j++)
145
          {
146
          quat = QuatHelper.quatMultiply(mTable[i], mTable[j]);
147
148
          if( !insertQuat(quat,mTable) )
149
            {
150
            i=num;j=num;
151
            android.util.Log.e("QuatGroupGenerator", "OVERFLOW");
152
            }
153
          }
154
      }
155
    while( num < mInserted );
156
157
    Static4D[] table = new Static4D[mInserted];
158
159
    for(int i=0; i<mInserted; i++)
160
      {
161
      table[i] = new Static4D(mTable[i]);
162
      }
163
164
    return table;
165
    }
166
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168
169 f335f6f3 Leszek Koltunski
  private static String printRotation(Static4D quat)
170 0d15e934 Leszek Koltunski
    {
171
    final float MAX_ERR = 0.00001f;
172 f335f6f3 Leszek Koltunski
    float cos = quat.get3();
173
    float sin = (float)Math.sqrt(1-cos*cos);
174
    float x = sin==0 ? 0 : quat.get0()/sin;
175
    float y = sin==0 ? 0 : quat.get1()/sin;
176
    float z = sin==0 ? 0 : quat.get2()/sin;
177
    float halfAngle = (float)Math.acos(cos);
178
    int ang = (int) ( (360*halfAngle/Math.PI) + 0.5f);
179
180
    if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
181
    if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
182
    if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
183
184
    if( x<0.5f+MAX_ERR && x>0.5f-MAX_ERR ) x = 0.5f;
185
    if( y<0.5f+MAX_ERR && y>0.5f-MAX_ERR ) y = 0.5f;
186
    if( z<0.5f+MAX_ERR && z>0.5f-MAX_ERR ) z = 0.5f;
187
188
    if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
189
    if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
190
    if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
191
192
    if( x<1.0f+MAX_ERR && x>1.0f-MAX_ERR ) x = 1.0f;
193
    if( y<1.0f+MAX_ERR && y>1.0f-MAX_ERR ) y = 1.0f;
194
    if( z<1.0f+MAX_ERR && z>1.0f-MAX_ERR ) z = 1.0f;
195
196
    if( x<-1.0f+MAX_ERR && x>-1.0f-MAX_ERR ) x = -1.0f;
197
    if( y<-1.0f+MAX_ERR && y>-1.0f-MAX_ERR ) y = -1.0f;
198
    if( z<-1.0f+MAX_ERR && z>-1.0f-MAX_ERR ) z = -1.0f;
199
200
    return "("+x+" "+y+" "+z+") "+ang;
201
    }
202
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
205
  private static String printQuat(Static4D quat)
206
    {
207
    final float MAX_ERR = 0.00001f;
208
209
    float x = quat.get0();
210
    float y = quat.get1();
211
    float z = quat.get2();
212
    float w = quat.get3();
213
214
    if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
215
    if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
216
    if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
217
    if( w<MAX_ERR && w>-MAX_ERR ) w = 0.0f;
218
219
    if( x<0.5f+MAX_ERR && x>0.5f-MAX_ERR ) x = 0.5f;
220
    if( y<0.5f+MAX_ERR && y>0.5f-MAX_ERR ) y = 0.5f;
221
    if( z<0.5f+MAX_ERR && z>0.5f-MAX_ERR ) z = 0.5f;
222
    if( w<0.5f+MAX_ERR && w>0.5f-MAX_ERR ) w = 0.5f;
223
224
    if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
225
    if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
226
    if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
227
    if( w<-0.5f+MAX_ERR && w>-0.5f-MAX_ERR ) w = -0.5f;
228
229
    if( x<1.0f+MAX_ERR && x>1.0f-MAX_ERR ) x = 1.0f;
230
    if( y<1.0f+MAX_ERR && y>1.0f-MAX_ERR ) y = 1.0f;
231
    if( z<1.0f+MAX_ERR && z>1.0f-MAX_ERR ) z = 1.0f;
232
    if( w<1.0f+MAX_ERR && w>1.0f-MAX_ERR ) w = 1.0f;
233
234
    if( x<-1.0f+MAX_ERR && x>-1.0f-MAX_ERR ) x = -1.0f;
235
    if( y<-1.0f+MAX_ERR && y>-1.0f-MAX_ERR ) y = -1.0f;
236
    if( z<-1.0f+MAX_ERR && z>-1.0f-MAX_ERR ) z = -1.0f;
237
    if( w<-1.0f+MAX_ERR && w>-1.0f-MAX_ERR ) w = -1.0f;
238
239
    return (x+" "+y+" "+z+" "+w);
240
    }
241 0d15e934 Leszek Koltunski
242 f335f6f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
243
244
  public static void showQuats(Static4D[] table)
245
    {
246
    int len = table.length;
247
248
    for (int i=0; i<len; i++)
249 0d15e934 Leszek Koltunski
      {
250 f335f6f3 Leszek Koltunski
      String tmp = printQuat(table[i]);
251
      android.util.Log.e("D", "QUAT"+i+": ("+tmp+")");
252 0d15e934 Leszek Koltunski
      }
253
    }
254
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256
257
  public static void showRotations(Static4D[] table)
258
    {
259 f335f6f3 Leszek Koltunski
    int len = table.length;
260 0d15e934 Leszek Koltunski
261 f335f6f3 Leszek Koltunski
    for (int i=0; i<len; i++)
262 0d15e934 Leszek Koltunski
      {
263 f335f6f3 Leszek Koltunski
      String tmp = printRotation(table[i]);
264
      android.util.Log.e("D", "QUAT"+i+": "+tmp);
265 0d15e934 Leszek Koltunski
      }
266
    }
267 e7587264 Leszek Koltunski
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269
270
  public static void showCubitQuats(Static4D[] table, float[][] pos, int startIndex, int stopIndex)
271
    {
272
    StringBuilder builder = new StringBuilder();
273
    float MAXERR = 0.01f;
274
    float[] tmp = new float[4];
275
    float[] vec = pos[startIndex];
276
    int numQuats = table.length;
277
    float X = vec[0];
278
    float Y = vec[1];
279
    float Z = vec[2];
280
281
    for(int cubit=startIndex; cubit<=stopIndex; cubit++)
282
      {
283
      float x = pos[cubit][0];
284
      float y = pos[cubit][1];
285
      float z = pos[cubit][2];
286
287
      for(int quat=0; quat<numQuats; quat++)
288
        {
289
        QuatHelper.rotateVectorByQuat(tmp,X,Y,Z,0,table[quat]);
290
291
        float dx = tmp[0]-x;
292
        float dy = tmp[1]-y;
293
        float dz = tmp[2]-z;
294
295
        if( dx>-MAXERR && dx<MAXERR && dy>-MAXERR && dy<MAXERR && dz>-MAXERR && dz<MAXERR )
296
          {
297
          builder.append(' ');
298
          builder.append(quat);
299
          }
300
        }
301
302 51683301 Leszek Koltunski
      android.util.Log.e("D", "Cubit: "+cubit+" quats: "+builder );
303 e7587264 Leszek Koltunski
      builder.delete(0, builder.length());
304
      }
305
    }
306 0d15e934 Leszek Koltunski
  }