1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.ximtec.igesture.algorithm.signature;
29
30 import java.util.BitSet;
31 import java.util.HashMap;
32
33 import org.sigtec.util.Constant;
34
35
36
37
38
39
40
41
42
43 public class Grid {
44
45
46
47
48 private enum Direction {
49 RIGHT, UP
50 }
51
52
53
54
55 private int bitStringLength;
56
57
58
59
60 private int size;
61
62
63
64
65 private BitSet[][] grid;
66
67 private static HashMap<Integer, Grid> gridCache;
68
69 static {
70 gridCache = new HashMap<Integer, Grid>();
71 }
72
73
74
75
76
77
78
79 public Grid(int size) {
80 this.size = computeGridSize(size);
81 bitStringLength = (int)Math.ceil(Math.log(this.size * this.size)
82 / Math.log(2));
83 grid = new BitSet[this.size][this.size];
84 init();
85 }
86
87
88
89
90
91
92
93
94
95 private int getBitPosition(int width, int height) {
96 final double pow = Math.log(width * height) / Math.log(2);
97 return this.bitStringLength - (int)(Math.ceil(pow));
98 }
99
100
101 public int getBitStringLength() {
102 return bitStringLength;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116 private int[] getMirrorPosition(int x, int y, int width, int height,
117 Direction direction) {
118 final int[] coordinate = new int[2];
119
120 if (direction.equals(Direction.UP)) {
121 final int newHeight = 2 * height;
122 coordinate[0] = x;
123 coordinate[1] = newHeight - (y + 1);
124 }
125 else {
126 final int newWidth = 2 * width;
127 coordinate[0] = newWidth - (x + 1);
128 coordinate[1] = y;
129 }
130
131 return coordinate;
132 }
133
134
135
136
137
138
139
140
141
142 public BitSet getSignature(int x, int y) {
143 if (!(x >= 0 && x < size && y >= 0 && y < size)) {
144 throw new RuntimeException("size not allowed");
145 }
146
147 return grid[x][y];
148 }
149
150
151
152
153
154 private void init() {
155 final BitSet bitSet = new BitSet(size);
156 bitSet.clear();
157 grid[0][0] = bitSet;
158 recursive(1, 1, Direction.UP);
159 }
160
161
162
163
164
165
166
167
168 private String prettyPrint(BitSet bitSet) {
169 final StringBuilder sb = new StringBuilder();
170
171 for (int i = 0; i < this.bitStringLength; i++) {
172
173 if (bitSet.get(i)) {
174 sb.append(Constant.ONE);
175 }
176 else {
177 sb.append(Constant.ZERO);
178 }
179
180 }
181
182 return sb.toString();
183 }
184
185
186
187
188
189
190
191
192
193 private void recursive(int x, int y, Direction direction) {
194 if (x >= this.size && y >= this.size) {
195 return;
196 }
197
198 int newX;
199 int newY;
200 Direction newDirection;
201
202 if (direction.equals(Direction.RIGHT)) {
203 newX = x * 2;
204 newY = y;
205 newDirection = Direction.UP;
206 }
207 else {
208 newX = x;
209 newY = y * 2;
210 newDirection = Direction.RIGHT;
211 }
212
213 for (int i = 0; i < x; i++) {
214
215 for (int j = 0; j < y; j++) {
216 final int[] coord = getMirrorPosition(i, j, x, y, direction);
217 final BitSet b = (BitSet)grid[i][j].clone();
218 b.set(getBitPosition(newX, newY));
219 this.setCell(coord[0], coord[1], b);
220 }
221
222 }
223
224 recursive(newX, newY, newDirection);
225 }
226
227
228
229
230
231
232
233
234
235 public void setCell(int x, int y, BitSet bitSet) {
236 if (!(x >= 0 && x < size && y >= 0 && y < size)) {
237 throw new IndexOutOfBoundsException();
238 }
239
240 grid[x][y] = bitSet;
241 }
242
243
244 private static int computeGridSize(int gridSize) {
245 return (int)Math
246 .pow(2, (int)Math.ceil((Math.log(gridSize) / Math.log(2))));
247 }
248
249
250
251
252
253
254
255
256
257
258 public static Grid createInstance(int size) {
259 final int gridSize = computeGridSize(size);
260 Grid result = gridCache.get(gridSize);
261
262 if (result == null) {
263 result = new Grid(gridSize);
264 gridCache.put(gridSize, result);
265 }
266
267 return result;
268 }
269
270
271 @Override
272 public String toString() {
273 final StringBuilder sb = new StringBuilder();
274
275 for (int i = 0; i < size; i++) {
276
277 for (int j = 0; j < size; j++) {
278 sb.append(prettyPrint(grid[i][j]) + Constant.DOUBLE_BLANK);
279 }
280
281 sb.append(Constant.LF_STRING);
282 }
283
284 return sb.toString();
285 }
286
287 }