Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 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.objectlib.helpers;
21

    
22
import org.distorted.library.main.QuatHelper;
23
import org.distorted.library.type.Static3D;
24
import org.distorted.library.type.Static4D;
25

    
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

    
28
public class QuatGroupGenerator
29
  {
30
  private static final int MAX_GROUP_SIZE = 256;
31
  private static final double PI = Math.PI;
32
  private static final Static4D[] mTable= new Static4D[MAX_GROUP_SIZE];
33

    
34
  private static int mInserted;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
// sin(A/2)*x, sin(A/2)*y, sin(A/2)*z, cos(A/2)
38

    
39
  private static void createQuat(Static3D axis, double angle, Static4D output)
40
    {
41
    float cosAngle = (float)Math.cos(angle/2);
42
    float sinAngle = (float)Math.sin(angle/2);
43

    
44
    output.set0( sinAngle*axis.get0() );
45
    output.set1( sinAngle*axis.get1() );
46
    output.set2( sinAngle*axis.get2() );
47
    output.set3( cosAngle );
48
    }
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
// double cover, so q == -q
52

    
53
  private static boolean quatTheSame(Static4D q1, Static4D q2)
54
    {
55
    final float MAX_ERROR = 0.01f;
56

    
57
    float q10 = q1.get0();
58
    float q11 = q1.get1();
59
    float q12 = q1.get2();
60
    float q13 = q1.get3();
61

    
62
    float q20 = q2.get0();
63
    float q21 = q2.get1();
64
    float q22 = q2.get2();
65
    float q23 = q2.get3();
66

    
67
    float d0 = q10-q20;
68
    float d1 = q11-q21;
69
    float d2 = q12-q22;
70
    float d3 = q13-q23;
71

    
72
    if( d0<MAX_ERROR && d0>-MAX_ERROR &&
73
        d1<MAX_ERROR && d1>-MAX_ERROR &&
74
        d2<MAX_ERROR && d2>-MAX_ERROR &&
75
        d3<MAX_ERROR && d3>-MAX_ERROR  ) return true;
76

    
77
    d0 = q10+q20;
78
    d1 = q11+q21;
79
    d2 = q12+q22;
80
    d3 = q13+q23;
81

    
82
    if( d0<MAX_ERROR && d0>-MAX_ERROR &&
83
        d1<MAX_ERROR && d1>-MAX_ERROR &&
84
        d2<MAX_ERROR && d2>-MAX_ERROR &&
85
        d3<MAX_ERROR && d3>-MAX_ERROR  ) return true;
86

    
87
    return false;
88
    }
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

    
92
  private static int getIndexInTable(Static4D quat, Static4D[] table)
93
    {
94
    for(int i=0; i<mInserted; i++)
95
      {
96
      if( quatTheSame(quat,table[i]) ) return i;
97
      }
98

    
99
    return -1;
100
    }
101

    
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103

    
104
  private static boolean insertQuat(Static4D quat, Static4D[] table)
105
    {
106
    if( getIndexInTable(quat,table)<0 )
107
      {
108
      if( mInserted<MAX_GROUP_SIZE )
109
        {
110
        table[mInserted] = new Static4D(quat);
111
        mInserted++;
112
        return true;
113
        }
114
      return false;
115
      }
116

    
117
    return true;
118
    }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
// PUBLIC API
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  public static Static4D[] computeGroup(Static3D[] rotAxis, int[][] basicAngles)
125
    {
126
    Static4D quat = new Static4D(0,0,0,1);
127
    int num,numAxis = rotAxis.length;
128
    mInserted = 0;
129

    
130
    insertQuat(quat,mTable);
131

    
132
    for( int ax=0; ax<numAxis; ax++)
133
      {
134
      int numLayers = basicAngles[ax].length;
135

    
136
      for( int layer=0; layer<numLayers; layer++)
137
        {
138
        int numAngles = basicAngles[ax][layer];
139

    
140
        for(int angle=1; angle<numAngles; angle++)
141
          {
142
          createQuat(rotAxis[ax], (2*PI*angle)/numAngles, quat);
143
          insertQuat(quat,mTable);
144
          }
145
        }
146
      }
147

    
148
    do
149
      {
150
      num = mInserted;
151

    
152
      for(int i=0; i<num; i++)
153
        for(int j=0; j<num; j++)
154
          {
155
          quat = QuatHelper.quatMultiply(mTable[i], mTable[j]);
156

    
157
          if( !insertQuat(quat,mTable) )
158
            {
159
            i=num;j=num;
160
            android.util.Log.e("QuatGroupGenerator", "OVERFLOW");
161
            }
162
          }
163
      }
164
    while( num < mInserted );
165

    
166
    Static4D[] table = new Static4D[mInserted];
167

    
168
    for(int i=0; i<mInserted; i++)
169
      {
170
      table[i] = new Static4D(mTable[i]);
171
      }
172

    
173
    return table;
174
    }
175

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

    
178
  private static String printRotation(Static4D quat)
179
    {
180
    final float MAX_ERR = 0.00001f;
181
    float cos = quat.get3();
182
    float sin = (float)Math.sqrt(1-cos*cos);
183
    float x = sin==0 ? 0 : quat.get0()/sin;
184
    float y = sin==0 ? 0 : quat.get1()/sin;
185
    float z = sin==0 ? 0 : quat.get2()/sin;
186
    float halfAngle = (float)Math.acos(cos);
187
    int ang = (int) ( (360*halfAngle/Math.PI) + 0.5f);
188

    
189
    if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
190
    if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
191
    if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
192

    
193
    if( x<0.5f+MAX_ERR && x>0.5f-MAX_ERR ) x = 0.5f;
194
    if( y<0.5f+MAX_ERR && y>0.5f-MAX_ERR ) y = 0.5f;
195
    if( z<0.5f+MAX_ERR && z>0.5f-MAX_ERR ) z = 0.5f;
196

    
197
    if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
198
    if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
199
    if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
200

    
201
    if( x<1.0f+MAX_ERR && x>1.0f-MAX_ERR ) x = 1.0f;
202
    if( y<1.0f+MAX_ERR && y>1.0f-MAX_ERR ) y = 1.0f;
203
    if( z<1.0f+MAX_ERR && z>1.0f-MAX_ERR ) z = 1.0f;
204

    
205
    if( x<-1.0f+MAX_ERR && x>-1.0f-MAX_ERR ) x = -1.0f;
206
    if( y<-1.0f+MAX_ERR && y>-1.0f-MAX_ERR ) y = -1.0f;
207
    if( z<-1.0f+MAX_ERR && z>-1.0f-MAX_ERR ) z = -1.0f;
208

    
209
    return "("+x+" "+y+" "+z+") "+ang;
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

    
214
  private static String printQuat(Static4D quat)
215
    {
216
    final float MAX_ERR = 0.00001f;
217

    
218
    float x = quat.get0();
219
    float y = quat.get1();
220
    float z = quat.get2();
221
    float w = quat.get3();
222

    
223
    if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
224
    if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
225
    if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
226
    if( w<MAX_ERR && w>-MAX_ERR ) w = 0.0f;
227

    
228
    if( x<0.5f+MAX_ERR && x>0.5f-MAX_ERR ) x = 0.5f;
229
    if( y<0.5f+MAX_ERR && y>0.5f-MAX_ERR ) y = 0.5f;
230
    if( z<0.5f+MAX_ERR && z>0.5f-MAX_ERR ) z = 0.5f;
231
    if( w<0.5f+MAX_ERR && w>0.5f-MAX_ERR ) w = 0.5f;
232

    
233
    if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
234
    if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
235
    if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
236
    if( w<-0.5f+MAX_ERR && w>-0.5f-MAX_ERR ) w = -0.5f;
237

    
238
    if( x<1.0f+MAX_ERR && x>1.0f-MAX_ERR ) x = 1.0f;
239
    if( y<1.0f+MAX_ERR && y>1.0f-MAX_ERR ) y = 1.0f;
240
    if( z<1.0f+MAX_ERR && z>1.0f-MAX_ERR ) z = 1.0f;
241
    if( w<1.0f+MAX_ERR && w>1.0f-MAX_ERR ) w = 1.0f;
242

    
243
    if( x<-1.0f+MAX_ERR && x>-1.0f-MAX_ERR ) x = -1.0f;
244
    if( y<-1.0f+MAX_ERR && y>-1.0f-MAX_ERR ) y = -1.0f;
245
    if( z<-1.0f+MAX_ERR && z>-1.0f-MAX_ERR ) z = -1.0f;
246
    if( w<-1.0f+MAX_ERR && w>-1.0f-MAX_ERR ) w = -1.0f;
247

    
248
    return (x+" "+y+" "+z+" "+w);
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  public static void showQuats(Static4D[] table)
254
    {
255
    int len = table.length;
256

    
257
    for (int i=0; i<len; i++)
258
      {
259
      String tmp = printQuat(table[i]);
260
      android.util.Log.e("D", "QUAT"+i+": ("+tmp+")");
261
      }
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  public static void showRotations(Static4D[] table)
267
    {
268
    int len = table.length;
269

    
270
    for (int i=0; i<len; i++)
271
      {
272
      String tmp = printRotation(table[i]);
273
      android.util.Log.e("D", "QUAT"+i+": "+tmp);
274
      }
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  public static void showCubitQuats(Static4D[] table, float[][] pos, int startIndex, int stopIndex)
280
    {
281
    StringBuilder builder = new StringBuilder();
282
    float MAXERR = 0.01f;
283
    float[] tmp = new float[4];
284
    float[] vec = pos[startIndex];
285
    int numQuats = table.length;
286
    float X = vec[0];
287
    float Y = vec[1];
288
    float Z = vec[2];
289

    
290
    for(int cubit=startIndex; cubit<=stopIndex; cubit++)
291
      {
292
      float x = pos[cubit][0];
293
      float y = pos[cubit][1];
294
      float z = pos[cubit][2];
295

    
296
      for(int quat=0; quat<numQuats; quat++)
297
        {
298
        QuatHelper.rotateVectorByQuat(tmp,X,Y,Z,0,table[quat]);
299

    
300
        float dx = tmp[0]-x;
301
        float dy = tmp[1]-y;
302
        float dz = tmp[2]-z;
303

    
304
        if( dx>-MAXERR && dx<MAXERR && dy>-MAXERR && dy<MAXERR && dz>-MAXERR && dz<MAXERR )
305
          {
306
          builder.append(' ');
307
          builder.append(quat);
308
          }
309
        }
310

    
311
      android.util.Log.e("D", "Cubit: "+cubit+" quats: "+builder.toString() );
312
      builder.delete(0, builder.length());
313
      }
314
    }
315
  }
(11-11/11)