1 /* BurrTools
2 *
3 * BurrTools is the legal property of its developers, whose
4 * names are listed in the COPYRIGHT file, which is included
5 * within the source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include <math.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "tablesizes.inc"
27
28 double matrix[NUM_TRANSFORMATIONS_MIRROR][9] = {
29 #include "rotmatrix.inc"
30 };
31
32 /* this matix contains the concatenation of 2 transformations
33 * if you first transform the piece around t1 and then around t2
34 * you can as well transform around transMult[t1][t2]
35 */
36 static unsigned int transMult[NUM_TRANSFORMATIONS_MIRROR][NUM_TRANSFORMATIONS_MIRROR];
37
38 /* this array contains all possible symmetry groups, meaning bitmasks with exactly the bits set
39 * that correspond to transformations tha reorient the piece so that it looks identical
40 */
41 static const unsigned long long symmetries[NUM_SYMMETRY_GROUPS] = {
42 #include "symmetries.inc"
43 };
44
longlong2string(unsigned long long s)45 const char * longlong2string(unsigned long long s) {
46 char hex[17] = "0123456789ABCDEF";
47 static char output[100];
48
49
50 for (int i = 0; i < 12; i++)
51 output[11-i] = hex[(s >> (4*i)) & 0xF];
52
53 output[12] = 0;
54
55 return output;
56 }
57
ssss(unsigned int trans,unsigned long long s)58 unsigned char ssss(unsigned int trans, unsigned long long s) {
59 for (unsigned char t = 0; t < trans; t++)
60 for (unsigned char t2 = 0; t2 < NUM_TRANSFORMATIONS_MIRROR; t2++)
61 if (s & (((unsigned long long)1) << t2)) {
62 unsigned char trrr = transMult[t2][t];
63 if (trrr == trans)
64 return t;
65 }
66
67 return trans;
68 }
69
70
71 /* this function creates the lookup table for the function in the symmetry c-file */
outputMinimumSymmetries(void)72 void outputMinimumSymmetries(void) {
73
74 FILE * out = fopen("transformmini.inc", "w");
75
76 for (int sy = 0; sy < NUM_SYMMETRY_GROUPS; sy++) {
77 fprintf(out, " {");
78 for (int trans = 0; trans < NUM_TRANSFORMATIONS_MIRROR; trans++) {
79 fprintf(out,"%2i", ssss(trans, symmetries[sy]));
80 if (trans < NUM_TRANSFORMATIONS_MIRROR-1)
81 fprintf(out, ",");
82 }
83 if (sy < NUM_SYMMETRY_GROUPS-1)
84 fprintf(out, "},\n");
85 else
86 fprintf(out, "}\n");
87 }
88
89 fclose(out);
90 }
91
92 /* this function creates a table that contains ALL bits for the symmetries
93 * instead of only the ones for the current rotation, that means all bits
94 * are set that where the shape reproduces itself in one of the 48 possible
95 * rotations
96 */
outputCompleteSymmetries(void)97 void outputCompleteSymmetries(void) {
98
99 FILE * fout = fopen("unifiedsym.inc", "w");
100
101 for (int sy = 0; sy < NUM_SYMMETRY_GROUPS; sy++) {
102
103 unsigned long long s = symmetries[sy];
104
105 unsigned long long out = s;
106
107 for (int r = 1; r < NUM_TRANSFORMATIONS_MIRROR; r++) {
108
109 int rinv = 0;
110
111 while (transMult[r][rinv]) {
112 rinv++;
113 }
114
115 // if r + x + rinv one of the symmetries of the initial shape
116 // then x is a symmetriy of the by r rotated shape
117
118 for (int x = 0; x < NUM_TRANSFORMATIONS_MIRROR; x++) {
119 int res = transMult[r][x];
120 res = transMult[res][rinv];
121
122 if ((s >> res) & 1) {
123 out |= (1ll << x);
124 }
125 }
126
127 }
128 fprintf(fout, "0x%012llXLL,\n", out);
129 }
130
131 fclose(fout);
132 }
133
134 /* this function only one bit is set for each possible transformation that results in one possible orientation
135 * of the shape
136 */
outputUniqueSymmetries(void)137 void outputUniqueSymmetries(void) {
138
139 FILE * fout = fopen("uniquesym.inc", "w");
140
141 for (int sy = 0; sy < NUM_SYMMETRY_GROUPS; sy++) {
142
143 unsigned long long s = symmetries[sy];
144 unsigned long long ttt = 0;
145 unsigned long long out = 0;
146
147 for (int r = 0; r < NUM_TRANSFORMATIONS_MIRROR; r++)
148 {
149 if (!((ttt >> r) & 1))
150 {
151 out |= 1ll << r;
152
153 for (int r2 = 0; r2 < NUM_TRANSFORMATIONS_MIRROR; r2++)
154 {
155 if ((s >> r2) & 1)
156 ttt |= 1ll << transMult[r2][r];
157 }
158 }
159 }
160 fprintf(fout, "0x%012llXLL,\n", out);
161 }
162
163 fclose(fout);
164 }
165
166 /* this function creates a decision tree for symmetry creation trying to optimize for the
167 * lowest number of checks (6-7 should be possible, if we can subdivide each time#
168 * with nearly equal subparts
169 */
makeSymmetryTree(unsigned long long taken,unsigned long long val,FILE * out)170 void makeSymmetryTree(unsigned long long taken, unsigned long long val, FILE * out) {
171
172 /* greedy implementation: find the subdivision that is most equal */
173 int best_div = -100;
174 int best_bit = 0;
175 int b1, b2;
176
177 for (int t = 0; t < NUM_TRANSFORMATIONS_MIRROR; t++)
178 if (!(taken & (((unsigned long long)1) << t))) {
179 b1 = 0;
180 b2 = 0;
181 int lastfound = 0;
182 for (int s = 0; s < NUM_SYMMETRY_GROUPS; s++) {
183 if ((symmetries[s] & taken) == val) {
184 b1++;
185 lastfound = s;
186 }
187 if ((symmetries[s] & (taken | (((unsigned long long)1) << t))) == val)
188 b2++;
189 }
190
191 if (b1 == 1) {
192 fprintf(out, "return (symmetries_t)%i; //%s\n", lastfound, longlong2string(symmetries[lastfound]));
193 return;
194 }
195
196 if ((b2 > 0) && (b1-b2>0) && (abs(b1/2 - best_div) > abs(b1/2 - b2))) {
197 best_div = b2;
198 best_bit = t;
199 }
200 }
201
202 fprintf(out, "v = pp->getGridType()->getVoxel(pp);\nv->transform(%i);\nres=pp->identicalInBB(v);\ndelete v;\nif (res) {\n", best_bit);
203
204 makeSymmetryTree(taken | ((unsigned long long)1 << best_bit), val | ((unsigned long long)1 << best_bit), out);
205
206 fprintf(out, "} else {\n");
207
208 makeSymmetryTree(taken | ((unsigned long long)1 << best_bit), val, out);
209
210 fprintf(out, "}\n");
211
212 }
213
mmult(double * m,double * matrix)214 void mmult(double * m, double * matrix) {
215
216 double n[9];
217
218 for (int x = 0; x < 3; x++)
219 for (int y = 0; y < 3; y++) {
220 n[y*3+x] = 0;
221 for (int c = 0; c < 3; c++) {
222 n[y*3+x] += m[c*3+x]*matrix[y*3+c];
223 }
224 }
225
226 for (int i = 0; i < 9; i++)
227 m[i] = n[i];
228 }
229
mmult(double * m,int num)230 void mmult(double * m, int num) {
231
232
233 mmult(m, matrix[num]);
234 }
235
mequal(double * m,int num)236 bool mequal(double *m, int num) {
237
238 for (int i = 0; i < 9; i++)
239 if (fabs(m[i]-matrix[num][i]) > 0.00001)
240 return false;
241
242 return true;
243 }
244
245
multTranformationsMatrix(void)246 void multTranformationsMatrix(void) {
247
248 FILE * out = fopen("transmult.inc", "w");
249
250 for (int tr1 = 0; tr1 < NUM_TRANSFORMATIONS_MIRROR; tr1++) {
251 fprintf(out, "{");
252
253
254 for (int tr2 = 0; tr2 < NUM_TRANSFORMATIONS_MIRROR; tr2++) {
255
256 double m[9];
257 m[0] = m[4] = m[8] = 1;
258 m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0;
259
260 mmult(m, tr1);
261 mmult(m, tr2);
262
263 bool found = false;
264
265 for (int t = 0; t < NUM_TRANSFORMATIONS_MIRROR; t++) {
266
267 if (mequal(m, t)) {
268 if (tr2 < NUM_TRANSFORMATIONS_MIRROR-1)
269 fprintf(out, "%3i,", t);
270 else
271 fprintf(out, "%3i", t);
272 transMult[tr1][tr2] = t;
273 found = true;
274 break;
275 }
276 }
277
278 if (!found) {
279 if (tr2 < NUM_TRANSFORMATIONS_MIRROR-1)
280 fprintf(out, "TND,");
281 else
282 fprintf(out, "TND");
283 transMult[tr1][tr2] = (unsigned int)-1;
284 }
285
286 }
287 if (tr1 < NUM_TRANSFORMATIONS_MIRROR-1)
288 fprintf(out, "},\n");
289 else
290 fprintf(out, "}\n");
291 }
292 fclose(out);
293 }
294
main(int,char **)295 int main(int /*argv*/, char** /*args[]*/) {
296
297 multTranformationsMatrix();
298 outputMinimumSymmetries();
299 outputCompleteSymmetries();
300 outputUniqueSymmetries();
301
302 FILE * out = fopen("symcalc.inc", "w");
303 fprintf(out, "voxel_c * v;\nbool res;\n");
304 makeSymmetryTree(0, 0, out);
305 fclose(out);
306 }
307
308