View Javadoc

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   * Map source using bitmaps from the Bitmaps/ directory to provide access to map
16   * features.
17   * 
18   * @author Radek 'Black_Hand' Pibil
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  				// if (log != null) {
62  				// log.info("enemyTerritory: "
63  				// + enemyId
64  				// + " " + territoryId);
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 }