1 package cz.cuni.amis.pogamut.defcon.communication.worldview.modules.bitmap;
2
3 import java.awt.image.BufferedImage;
4 import java.util.Collections;
5 import java.util.SortedMap;
6 import java.util.TreeMap;
7 import java.util.logging.Logger;
8
9 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
10 import cz.cuni.amis.pogamut.defcon.communication.worldview.AbstractMapSource;
11 import cz.cuni.amis.pogamut.defcon.communication.worldview.modules.grid.flags.BasicFlag;
12 import cz.cuni.amis.pogamut.defcon.utils.Pair;
13
14
15
16
17
18
19
20
21 public class BitmapMapSource extends AbstractMapSource {
22
23 private final BufferedImage[] territories;
24 private final BufferedImage sailable;
25 private final SortedMap<Integer, BufferedImage> ownTerritories =
26 new TreeMap<Integer, BufferedImage>();
27 private final SortedMap<Integer, SortedMap<Integer, BufferedImage>> enemyTerritories =
28 new TreeMap<Integer, SortedMap<Integer, BufferedImage>>();
29
30 private final int LAND_THRESHOLD = 200;
31 private final int SEA_THRESHOLD = 100;
32 private final double X_SPAN = 180d;
33 private final double Y_SPAN = 100d;
34
35 private Logger log;
36
37 public BitmapMapSource(BufferedImage[] territories, int[] ownTerritories,
38 SortedMap<Integer, int[]> enemyIdsAndTerritories,
39 BufferedImage sailable) {
40 this(territories, ownTerritories, enemyIdsAndTerritories, sailable,
41 null);
42 }
43
44 public BitmapMapSource(BufferedImage[] territories, int[] ownTerritories,
45 SortedMap<Integer, int[]> enemyIdsAndTerritories,
46 BufferedImage sailable, Logger log) {
47
48 this.log = log;
49 this.territories = territories;
50 this.sailable = sailable;
51 for (int ownTerritory : ownTerritories) {
52 this.ownTerritories.put(ownTerritory, territories[ownTerritory]);
53 }
54
55 for (int enemyId : enemyIdsAndTerritories.keySet()) {
56 SortedMap<Integer, BufferedImage> enemyTerritoriesList = new TreeMap<Integer, BufferedImage>();
57 this.enemyTerritories.put(enemyId, enemyTerritoriesList);
58 for (int territoryId : enemyIdsAndTerritories.get(enemyId)) {
59 enemyTerritoriesList.put(territoryId, territories[territoryId]);
60
61
62
63
64
65
66 }
67 }
68 }
69
70 public void setTerritorry(int index, BufferedImage bitmap) {
71 territories[index] = bitmap;
72 }
73
74 public BufferedImage getTerritorry(int index) {
75 return territories[index];
76 }
77
78 public SortedMap<Integer, BufferedImage> getOwnTerritories() {
79 return Collections.unmodifiableSortedMap(ownTerritories);
80 }
81
82 private boolean overThresh(BufferedImage image, int x, int y,
83 int overThreshold) {
84
85 return (image.getRGB(x, y) & 0x000000ff) > overThreshold ? true : false;
86 }
87
88 private boolean underThresh(BufferedImage image, int x, int y,
89 int underThreshold) {
90 return !overThresh(image, x, y, underThreshold);
91 }
92
93 private Pair<Integer, Integer> convertToImageCoords(double x, double y,
94 BufferedImage image) {
95 Pair<Integer, Integer> result = new Pair<Integer, Integer>();
96
97 result.first = (int) ((x + X_SPAN) / (2 * X_SPAN) * (image.getWidth() - 1));
98 result.second = image.getHeight() - 1
99 - (int) ((y + Y_SPAN) / (2 * Y_SPAN) * (image.getHeight() - 1));
100
101 return result;
102 }
103
104 @Override
105 public boolean hasFlag(double x, double y, BasicFlag flag) {
106 if (x < -X_SPAN || x > X_SPAN || y < -Y_SPAN || y > Y_SPAN)
107 return false;
108
109 switch (flag) {
110 case SEA: {
111 Pair<Integer, Integer> coords = convertToImageCoords(
112 x,
113 y,
114 sailable);
115 return overThresh(sailable, coords.first, coords.second, 10);
116 }
117 case LAND: {
118 Pair<Integer, Integer> coords = convertToImageCoords(
119 x,
120 y,
121 sailable);
122 return underThresh(sailable, coords.first,
123 coords.second, 5);
124 }
125 case OWN_TERRITORY: {
126
127 Boolean ok = false;
128 for (BufferedImage ownTerritory : getOwnTerritories().values()) {
129
130 Pair<Integer, Integer> coords = convertToImageCoords(
131 x,
132 y,
133 ownTerritory);
134
135 ok = overThresh(ownTerritory, coords.first,
136 coords.second, 10);
137 if (ok)
138 break;
139 }
140
141
142 return ok;
143 }
144 case OWN_PLACEABLE_LAND: {
145
146 Boolean ok = false;
147 for (BufferedImage ownTerritory : getOwnTerritories().values()) {
148
149 Pair<Integer, Integer> coords = convertToImageCoords(
150 x,
151 y,
152 ownTerritory);
153
154 ok = overThresh(ownTerritory, coords.first,
155 coords.second, LAND_THRESHOLD);
156 if (ok)
157 break;
158 }
159
160 return ok;
161 }
162 case OWN_PLACEABLE_SEA: {
163 Boolean ok = false;
164 for (BufferedImage ownTerritory : getOwnTerritories().values()) {
165
166 Pair<Integer, Integer> coords = convertToImageCoords(
167 x,
168 y,
169 ownTerritory);
170
171 ok = overThresh(ownTerritory, coords.first,
172 coords.second, SEA_THRESHOLD) &&
173 underThresh(
174 ownTerritory,
175 coords.first,
176 coords.second,
177 LAND_THRESHOLD);
178 if (ok)
179 break;
180 }
181
182 return ok;
183 }
184 case ENEMY_TERRITORY: {
185
186 Boolean ok = false;
187 for (int i = 0; i < territories.length; ++i) {
188
189 if (ownTerritories.containsKey(i))
190 continue;
191
192 Pair<Integer, Integer> coords = convertToImageCoords(
193 x,
194 y,
195 territories[i]);
196
197 ok = overThresh(
198 territories[i],
199 coords.first,
200 coords.second,
201 10);
202 if (ok)
203 break;
204 }
205 return ok;
206 }
207 case ENEMY_PLACEABLE_SEA: {
208 Boolean ok = false;
209 for (int i = 0; i < territories.length; ++i) {
210
211 if (ownTerritories.containsKey(i))
212 continue;
213
214 Pair<Integer, Integer> coords = convertToImageCoords(
215 x,
216 y,
217 territories[i]);
218
219 ok = overThresh(territories[i], coords.first,
220 coords.second, SEA_THRESHOLD) &&
221 underThresh(
222 territories[i],
223 coords.first,
224 coords.second,
225 LAND_THRESHOLD);
226 if (ok)
227 break;
228 }
229
230 return ok;
231 }
232 case ENEMY_PLACEABLE_LAND: {
233 Boolean ok = false;
234 for (int i = 0; i < territories.length; ++i) {
235
236 if (ownTerritories.containsKey(i))
237 continue;
238
239 Pair<Integer, Integer> coords = convertToImageCoords(
240 x,
241 y,
242 territories[i]);
243
244 ok = overThresh(
245 territories[i],
246 coords.first,
247 coords.second,
248 LAND_THRESHOLD);
249 if (ok)
250 break;
251 }
252
253 return ok;
254 }
255
256 }
257 return false;
258 }
259
260 @Override
261 public boolean hasFlag(Location location, BasicFlag flag) {
262 return hasFlag(location.getX(), location.getY(), flag);
263 }
264
265 @Override
266 public boolean hasEnemyTerritoryFlag(Location location, int enemyId) {
267 return hasEnemyTerritoryFlag(
268 location.getX(),
269 location.getY(),
270 enemyId);
271 }
272
273 @Override
274 public boolean hasEnemyTerritoryFlag(double x, double y, int enemyId) {
275 if (x < -X_SPAN || x > X_SPAN || y < -Y_SPAN || y > Y_SPAN)
276 return false;
277
278 boolean ok = false;
279 for (BufferedImage territory : enemyTerritories.get(enemyId).values()) {
280
281 Pair<Integer, Integer> coords = convertToImageCoords(
282 x,
283 y,
284 territory);
285
286 ok = overThresh(
287 territory,
288 coords.first,
289 coords.second,
290 SEA_THRESHOLD);
291
292 if (ok)
293 break;
294 }
295
296 return ok;
297 }
298
299 @Override
300 public boolean hasEnemyTerritoryFlag(Location location, int enemyId,
301 boolean seaArea) {
302 return hasEnemyTerritoryFlag(
303 location.getX(),
304 location.getY(),
305 enemyId, seaArea);
306 }
307
308 @Override
309 public boolean hasEnemyTerritoryFlag(double x, double y, int enemyId,
310 boolean seaArea) {
311 if (x < -X_SPAN || x > X_SPAN || y < -Y_SPAN || y > Y_SPAN)
312 return false;
313
314
315 boolean ok = false;
316
317 if (!enemyTerritories.containsKey(enemyId)) {
318 if (log != null) {
319 log.info("enemyId: " + enemyId);
320 }
321 return false;
322 }
323
324 if (seaArea) {
325
326 for (BufferedImage territory : enemyTerritories.get(enemyId)
327 .values()) {
328
329 Pair<Integer, Integer> coords = convertToImageCoords(
330 x,
331 y,
332 territory);
333
334
335 ok = overThresh(
336 territory,
337 coords.first,
338 coords.second,
339 SEA_THRESHOLD) && underThresh(
340 territory,
341 coords.first,
342 coords.second,
343 LAND_THRESHOLD);
344
345 if (ok)
346 break;
347 }
348
349 return ok;
350
351 } else {
352
353 for (BufferedImage territory : enemyTerritories.get(enemyId)
354 .values()) {
355
356 Pair<Integer, Integer> coords = convertToImageCoords(
357 x,
358 y,
359 territory);
360
361
362 ok = overThresh(
363 territory,
364 coords.first,
365 coords.second,
366 LAND_THRESHOLD);
367
368 if (ok)
369 break;
370 }
371
372 return ok;
373
374 }
375 }
376
377 }