Project

General

Profile

« Previous | Next » 

Revision 0d15e934

Added by Leszek Koltunski over 3 years ago

Compute the Quat Group in Java.

View differences:

src/main/java/org/distorted/objectlib/helpers/QuatGroupGenerator.java
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
      for(int angle=1; angle<basicAngles[ax]; angle++)
134
        {
135
        createQuat(rotAxis[ax], 2*PI*angle/basicAngles[ax], quat);
136
        insertQuat(quat,mTable);
137
        }
138

  
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
  public static void showQuats(Static4D[] table)
170
    {
171
    final float MAX_ERR = 0.00001f;
172
    String dbg = "---------------------------------\n";
173

  
174
    for (Static4D quat : table)
175
      {
176
      float x = quat.get0();
177
      float y = quat.get1();
178
      float z = quat.get2();
179
      float w = quat.get3();
180

  
181
      if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
182
      if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
183
      if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
184
      if( w<MAX_ERR && w>-MAX_ERR ) w = 0.0f;
185

  
186
      if( x<0.5f+MAX_ERR && x>0.5f-MAX_ERR ) x = 0.5f;
187
      if( y<0.5f+MAX_ERR && y>0.5f-MAX_ERR ) y = 0.5f;
188
      if( z<0.5f+MAX_ERR && z>0.5f-MAX_ERR ) z = 0.5f;
189
      if( w<0.5f+MAX_ERR && w>0.5f-MAX_ERR ) w = 0.5f;
190

  
191
      if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
192
      if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
193
      if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
194
      if( w<-0.5f+MAX_ERR && w>-0.5f-MAX_ERR ) w = -0.5f;
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
      if( w<1.0f+MAX_ERR && w>1.0f-MAX_ERR ) w = 1.0f;
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
      if( w<-1.0f+MAX_ERR && w>-1.0f-MAX_ERR ) w = -1.0f;
205

  
206
      dbg += ( "("+x+" "+y+" "+z+" "+w+")\n");
207
      }
208

  
209
    android.util.Log.e("D", dbg);
210
    }
211

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

  
214
  public static void showRotations(Static4D[] table)
215
    {
216
    final float MAX_ERR = 0.00001f;
217
    String dbg = "---------------------------------\n";
218

  
219
    for (Static4D quat : table)
220
      {
221
      float cos = quat.get3();
222
      float sin = (float)Math.sqrt(1-cos*cos);
223
      float x = sin==0 ? 0 : quat.get0()/sin;
224
      float y = sin==0 ? 0 : quat.get1()/sin;
225
      float z = sin==0 ? 0 : quat.get2()/sin;
226
      float halfAngle = (float)Math.acos(cos);
227
      int ang = (int) ( (360*halfAngle/Math.PI) + 0.5f);
228

  
229
      if( x<MAX_ERR && x>-MAX_ERR ) x = 0.0f;
230
      if( y<MAX_ERR && y>-MAX_ERR ) y = 0.0f;
231
      if( z<MAX_ERR && z>-MAX_ERR ) z = 0.0f;
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

  
237
      if( x<-0.5f+MAX_ERR && x>-0.5f-MAX_ERR ) x = -0.5f;
238
      if( y<-0.5f+MAX_ERR && y>-0.5f-MAX_ERR ) y = -0.5f;
239
      if( z<-0.5f+MAX_ERR && z>-0.5f-MAX_ERR ) z = -0.5f;
240

  
241
      if( x<1.0f+MAX_ERR && x>1.0f-MAX_ERR ) x = 1.0f;
242
      if( y<1.0f+MAX_ERR && y>1.0f-MAX_ERR ) y = 1.0f;
243
      if( z<1.0f+MAX_ERR && z>1.0f-MAX_ERR ) z = 1.0f;
244

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

  
249
      dbg += ( "("+x+" "+y+" "+z+") "+ang+"\n");
250
      }
251

  
252
    android.util.Log.e("D", dbg);
253
    }
254
  }
src/main/res/raw/compute_quats.c
1
#include <stdio.h>
2
#include <math.h>
3
#include <stdlib.h>
4

  
5
#define TRAJBER
6

  
7
#define SQ2 1.41421356237f
8
#define SQ3 1.73205080757f
9
#define SQ5 2.23606797750f
10
#define PI  3.14159265358f
11
#define NUM_QUATS  200
12

  
13
#ifdef PYRA 
14
int basic[] = { 3,3,3,3 };
15

  
16
float axis[][3] = { { SQ2*SQ3/3,   SQ3/3,          0 } ,
17
                    {-SQ2*SQ3/3,   SQ3/3,          0 } ,
18
                    {         0,  -SQ3/3, -SQ2*SQ3/3 } ,
19
                    {         0,  -SQ3/3,  SQ2*SQ3/3 } };
20
#endif
21

  
22
#ifdef CUBE
23
int basic[] = { 4,4,4 };
24

  
25
float axis[][3] = { { 1,0,0 } , 
26
                    { 0,1,0 } , 
27
                    { 0,0,1 } };
28
#endif
29

  
30
#ifdef DINO
31
int basic[] = { 3,3,3,3 };
32

  
33
float axis[][3] = { {+SQ3/3,+SQ3/3,+SQ3/3} , 
34
                    {+SQ3/3,+SQ3/3,-SQ3/3} , 
35
                    {+SQ3/3,-SQ3/3,+SQ3/3} , 
36
                    {+SQ3/3,-SQ3/3,-SQ3/3} };
37
#endif
38

  
39
#ifdef DIAM
40
int basic[] = { 3,3,3,3 };
41

  
42
float axis[][3] = { {+SQ3*SQ2/3,+SQ3/3,         0} ,
43
                    {-SQ3*SQ2/3,+SQ3/3,         0} ,
44
                    {         0,+SQ3/3,+SQ3*SQ2/3} ,
45
                    {         0,+SQ3/3,-SQ3*SQ2/3} };
46
#endif
47

  
48
#ifdef HELI
49
int basic[] = { 2,2,2,2,2,2 };
50

  
51
float axis[][3] = { {     0, +SQ2/2, -SQ2/2} ,
52
                    {     0, -SQ2/2, -SQ2/2} ,
53
                    {+SQ2/2,      0, -SQ2/2} ,
54
                    {-SQ2/2,      0, -SQ2/2} ,
55
                    {+SQ2/2, -SQ2/2,      0} ,
56
                    {-SQ2/2, -SQ2/2,      0} };
57

  
58
#endif
59

  
60
#ifdef ULTI
61
int basic[] = { 3,3,3,3 };
62

  
63
float axis[][3] = { { 5*SQ5/16 + 11.0f/16,              0.0f   ,    SQ5/8  + 1.0f/4 } ,
64
                    {   SQ5/8  +  1.0f/4 ,  5*SQ5/16 + 11.0f/16,             0.0f   } ,
65
                    {-3*SQ5/16 -  7.0f/16,  3*SQ5/16 +  7.0f/16,  3*SQ5/16 + 7.0f/16} ,
66
                    {             0.0f   ,    SQ5/4  +  1.0f/2 , -5*SQ5/8  -11.0f/8 } };
67

  
68
#endif
69

  
70
#ifdef SQUARE
71
#define COS15 (0.25f*SQ2*(SQ3+1))
72
#define SIN15 (0.25f*SQ2*(SQ3-1))
73

  
74
int basic[] = { 12, 2 };
75

  
76
float axis[][3] = { {     0, 1,     0 } ,
77
                    { COS15, 0, SIN15 } };
78
#endif
79

  
80
#ifdef TRAJBER
81

  
82
int basic[] = { 4,4,4 };
83

  
84
float axis[][3] = { { SQ2/2, 0, SQ2/2 },
85
                    { SQ2/2, 0,-SQ2/2 },
86
                    {     0, 1,     0 } };
87
                     
88
#endif
89

  
90
int inserted=0;
91

  
92
///////////////////////////////////////////////////////////////////
93
// q1*q2
94

  
95
void multiply_quats( float* q1, float* q2, float* output)
96
  {
97
  output[0] = q2[3]*q1[0] - q2[2]*q1[1] + q2[1]*q1[2] + q2[0]*q1[3];
98
  output[1] = q2[3]*q1[1] + q2[2]*q1[0] + q2[1]*q1[3] - q2[0]*q1[2];
99
  output[2] = q2[3]*q1[2] + q2[2]*q1[3] - q2[1]*q1[0] + q2[0]*q1[1];
100
  output[3] = q2[3]*q1[3] - q2[2]*q1[2] - q2[1]*q1[1] - q2[0]*q1[0];
101
  }
102

  
103
///////////////////////////////////////////////////////////////////
104
// sin(A/2)*x, sin(A/2)*y, sin(A/2)*z, cos(A/2)
105

  
106
void create_quat(float* axis, float angle, float* output)
107
  {
108
  float cosAngle = cos(angle/2);
109
  float sinAngle = sin(angle/2);
110

  
111
  output[0] = sinAngle*axis[0];
112
  output[1] = sinAngle*axis[1];
113
  output[2] = sinAngle*axis[2];
114
  output[3] = cosAngle;
115
  }
116

  
117
///////////////////////////////////////////////////////////////////
118
// double cover, so q == -q
119

  
120
int is_the_same(float* q1, float* q2)
121
  {
122
  const float MAX = 0.01f;
123

  
124
  float d0 = q1[0]-q2[0];
125
  float d1 = q1[1]-q2[1];
126
  float d2 = q1[2]-q2[2];
127
  float d3 = q1[3]-q2[3];
128

  
129
  if( d0<MAX && d0>-MAX &&
130
      d1<MAX && d1>-MAX &&
131
      d2<MAX && d2>-MAX &&
132
      d3<MAX && d3>-MAX  ) return 1;
133

  
134
  d0 = q1[0]+q2[0];
135
  d1 = q1[1]+q2[1];
136
  d2 = q1[2]+q2[2];
137
  d3 = q1[3]+q2[3];
138

  
139
  if( d0<MAX && d0>-MAX &&
140
      d1<MAX && d1>-MAX &&
141
      d2<MAX && d2>-MAX &&
142
      d3<MAX && d3>-MAX  ) return 1;
143

  
144
  return 0;
145
  }
146

  
147
///////////////////////////////////////////////////////////////////
148

  
149
int getIndexInTable(float* quat, float* table)
150
  {
151
  for(int i=0; i<inserted; i++)
152
    {
153
    if( is_the_same(quat,table+4*i)==1 ) return i;
154
    }
155

  
156
  return -1;
157
  }
158

  
159
///////////////////////////////////////////////////////////////////
160

  
161
void insert(float* quat, float* table)
162
  {
163
  if( getIndexInTable(quat,table)<0 )
164
    {
165
    if( inserted<NUM_QUATS )
166
      {
167
      table[4*inserted+0] = quat[0];
168
      table[4*inserted+1] = quat[1];
169
      table[4*inserted+2] = quat[2];
170
      table[4*inserted+3] = quat[3];
171

  
172
      inserted++;
173
      }
174
    else printf("Error: inserted=%d\n", inserted);
175
    }
176
  }
177

  
178
///////////////////////////////////////////////////////////////////
179

  
180
void normalize(int index)
181
  {
182
  float* a = axis[index];
183

  
184
  float len = (float)(sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]));
185

  
186
  a[0] /= len;  
187
  a[1] /= len;  
188
  a[2] /= len;  
189
  }
190

  
191
///////////////////////////////////////////////////////////////////
192

  
193
int main(int argc, char** argv)
194
  {
195
  float tmp[4];
196
  float table[4*NUM_QUATS];
197
  int num,NUM_AXIS = sizeof(axis) / sizeof(axis[0]);
198

  
199
  tmp[0] = 0.0f; tmp[1] = 0.0f; tmp[2] = 0.0f; tmp[3] = 1.0f;
200
  insert(tmp,table);
201

  
202
  for(int ax=0; ax<NUM_AXIS; ax++)
203
    {
204
    normalize(ax);
205
    }
206

  
207
  for( int ax=0; ax<NUM_AXIS; ax++)
208
    for(int angle=1; angle<basic[ax]; angle++)
209
      {
210
      create_quat(axis[ax], 2*PI*angle/basic[ax], tmp);
211
      insert(tmp,table); 
212
      }
213

  
214
  do
215
    {
216
    num = inserted;
217

  
218
    for(int i=0; i<num; i++)
219
      for(int j=0; j<num; j++)
220
        {
221
        multiply_quats( table+4*i, table+4*j, tmp);
222
        insert(tmp,table);
223
        }
224
    }
225
  while( num < inserted );
226

  
227
  printf("\n");
228

  
229
  for(int i=0; i<inserted; i++)
230
    {
231
    printf( "%2d %7.4f %7.4f %7.4f %7.4f\n", i, table[4*i], table[4*i+1], table[4*i+2], table[4*i+3] );
232
    }
233

  
234
  printf("\n");
235

  
236
  for(int i=0; i<inserted; i++)
237
    {
238
    printf("{");
239

  
240
    for(int j=0; j<inserted; j++)
241
      {
242
      multiply_quats( table+4*i, table+4*j, tmp);
243
      num = getIndexInTable(tmp,table);
244
      printf("%3d," , num);
245
      }
246
    printf("},\n");
247
    }
248
 
249
return 0;
250
}

Also available in: Unified diff