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