1 package cz.cuni.amis.pogamut.ut2004.storyworld.place;
2
3 import java.util.Arrays;
4 import java.util.Collection;
5 import java.util.Comparator;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Random;
12 import java.util.Set;
13
14 import javax.vecmath.Point3d;
15
16 import com.thoughtworks.xstream.annotations.XStreamAlias;
17 import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
18 import com.thoughtworks.xstream.annotations.XStreamOmitField;
19
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
21 import cz.cuni.amis.pogamut.ut2004.storyworld.perception.SPLocation;
22 import cz.cuni.amis.utils.collections.MyCollections;
23 import cz.cuni.amis.utils.token.Token;
24 import cz.cuni.amis.utils.token.Tokens;
25
26
27
28
29
30
31
32
33
34
35
36 @XStreamAlias("place")
37 public class SPStoryPlace {
38
39 @XStreamOmitField
40 private static Random random = new Random(System.currentTimeMillis());
41
42 @XStreamOmitField
43 private SPStoryPlace insidePlace = null;
44
45 @XStreamAlias("inside")
46 @XStreamAsAttribute
47 protected String insidePlaceName;
48
49 @XStreamOmitField
50 private Set<SPStoryPlace> higherPlaces = null;
51
52 @XStreamOmitField
53 private Set<SPStoryPlace> containsPlaces = new HashSet<SPStoryPlace>();
54
55 @XStreamOmitField
56 private Set<SPStoryPlace> containsAllPlaces = null;
57
58 @XStreamOmitField
59 private Set<NavPoint> virtualPlaces = null;
60
61 @XStreamOmitField
62 private SPLocation center = null;
63
64 @XStreamOmitField
65 private NavPoint centerNavPoint = null;
66
67 @XStreamAlias("name")
68 @XStreamAsAttribute
69 private String nameString;
70
71 @XStreamOmitField
72 private Token name = null;
73
74 @XStreamOmitField
75 private List<NavPoint> navPointsList = null;
76
77 public SPStoryPlace(String name, SPStoryPlace inside) {
78 this.nameString = name;
79 this.name = Tokens.get(name);
80 setInsidePlace(inside);
81
82 }
83
84 public SPStoryPlace(String name) {
85 this.nameString = name;
86 this.name = Tokens.get(name);
87 }
88
89
90
91
92 private SPStoryPlace readResolve() {
93 insidePlace = null;
94 higherPlaces = null;
95 containsPlaces = new HashSet<SPStoryPlace>();
96 containsAllPlaces = null;
97 virtualPlaces = null;
98 name = null;
99 getName();
100 return this;
101 }
102
103
104
105
106
107
108
109
110
111 protected void setInsidePlace(SPStoryPlace place) {
112 if (insidePlace != null) throw new RuntimeException("insidePlace already set for the " + this);
113 this.insidePlace = place;
114 if (this.insidePlace != null) {
115 this.insidePlaceName = place.getName().getToken();
116 this.insidePlace.getContainsPlaces().add(this);
117 }
118 }
119
120 @Override
121 public int hashCode() {
122 return name.hashCode();
123 }
124
125 @Override
126 public boolean equals(Object obj) {
127 if (obj == null) return false;
128 if (!(obj instanceof SPStoryPlace)) return false;
129 SPStoryPlace place = (SPStoryPlace)obj;
130 return name.equals(place.getName());
131 }
132
133 public Token getName() {
134 if (name == null) name = Tokens.get(nameString);
135 return name;
136 }
137
138
139
140
141
142
143 public SPStoryPlace getInsidePlace() {
144 return insidePlace;
145 }
146
147
148
149
150
151 public String getInsidePlaceName() {
152 return insidePlaceName;
153 }
154
155
156
157
158
159
160
161
162
163
164
165 public Set<SPStoryPlace> getHigherPlaces() {
166 if (higherPlaces == null) {
167 higherPlaces = new HashSet<SPStoryPlace>();
168 SPStoryPlace current = insidePlace;
169 while (current != null) {
170 higherPlaces.add(current);
171 current = current.getInsidePlace();
172 }
173 }
174 return higherPlaces;
175 }
176
177
178
179
180
181 public Set<SPStoryPlace> getContainsPlaces() {
182 return containsPlaces;
183 }
184
185
186
187
188
189
190
191
192
193 public Set<SPStoryPlace> getContainsAllPlaces() {
194 if (containsAllPlaces == null) {
195 containsAllPlaces = new HashSet<SPStoryPlace>();
196 for (SPStoryPlace place : containsPlaces) {
197 containsAllPlaces.addAll(place.getContainsAllPlaces());
198 }
199 }
200 return containsAllPlaces;
201 }
202
203
204
205
206
207
208
209
210
211
212
213 public Set<NavPoint> getNavPoints() {
214 if (virtualPlaces == null) {
215 virtualPlaces = new HashSet<NavPoint>();
216 for (SPStoryPlace place : getContainsPlaces()) {
217 virtualPlaces.addAll(place.getNavPoints());
218 }
219 }
220 return virtualPlaces;
221 }
222
223
224
225
226
227
228
229
230
231
232 public List<NavPoint> getNavPointsList() {
233 if (navPointsList == null) {
234 navPointsList = MyCollections.asList(getNavPoints());
235 }
236 return navPointsList;
237 }
238
239 public SPLocation getCenter() {
240 if (center == null) {
241 double x = 0, y = 0, z = 0;
242 for (NavPoint navPoint : getNavPoints()) {
243 x += navPoint.getLocation().x;
244 y += navPoint.getLocation().y;
245 z += navPoint.getLocation().z;
246 }
247 center = new SPLocation(x / getNavPoints().size(), y / getNavPoints().size(), z / getNavPoints().size());
248 }
249 return center;
250 }
251
252 public NavPoint getCenterNavPoint() {
253 if (centerNavPoint == null) {
254 centerNavPoint = getNearestNavPoint(getCenter());
255 }
256 return centerNavPoint;
257 }
258
259 public NavPoint getRandomNavPoint() {
260 if (getNavPointsList().size() == 0) return null;
261 return getNavPointsList().get(random.nextInt(getNavPointsList().size()));
262 }
263
264 public NavPoint getNearestNavPoint(SPLocation location) {
265
266 Point3d loc = location.asPoint3d();
267 double nearestDistance = Double.MAX_VALUE;
268 NavPoint nearest = null;
269 for (NavPoint navPoint : getNavPoints()) {
270 double distance = loc.distance(navPoint.getLocation().getPoint3d());
271 if (distance < nearestDistance) {
272 nearestDistance = distance;
273 nearest = navPoint;
274 }
275 }
276 return nearest;
277 }
278
279 public NavPoint getFurthestNavPoint(SPLocation location) {
280
281 Point3d loc = location.asPoint3d();
282 double furthestDistance = Double.MAX_VALUE;
283 NavPoint furthest = null;
284 for (NavPoint navPoint : getNavPoints()) {
285 double distance = loc.distance(navPoint.getLocation().getPoint3d());
286 if (distance > furthestDistance) {
287 furthestDistance = distance;
288 furthest = navPoint;
289 }
290 }
291 return furthest;
292 }
293
294 public Map<NavPoint, Double> getNavPointDistances(SPLocation location) {
295 Map<NavPoint, Double> distances = new HashMap<NavPoint, Double>();
296 for (NavPoint navPoint : getNavPoints()) {
297 distances.put(navPoint, navPoint.getLocation().getPoint3d().distance(location.asPoint3d()));
298 }
299 return distances;
300 }
301
302 public Map<Double, NavPoint> getNavPointDistancesSwapped(SPLocation location) {
303 Map<Double, NavPoint> distances = new HashMap<Double, NavPoint>();
304 for (NavPoint navPoint : getNavPoints()) {
305 distances.put(navPoint.getLocation().getPoint3d().distance(location.asPoint3d()), navPoint);
306 }
307 return distances;
308 }
309
310
311
312
313
314 public NavPoint getRandomNavPoint(SPLocation location, double distance) {
315 if (distance >= 1) {
316 return getFurthestNavPoint(location);
317 }
318 Map<Double, NavPoint> distances = getNavPointDistancesSwapped(location);
319
320 if (distance <= 0) {
321 Collection<NavPoint> navPoints = distances.values();
322 int num = random.nextInt(navPoints.size());
323 Iterator<NavPoint> np = navPoints.iterator();
324 for (int i = 0; i < num-1; ++i) {
325 np.next();
326 }
327 return np.next();
328 }
329
330 Double[] keys = distances.keySet().toArray(new Double[distances.keySet().size()]);
331 Arrays.sort(keys, new Comparator<Double>() {
332
333 @Override
334 public int compare(Double o1, Double o2) {
335 return Double.compare(o1, o2);
336 }
337
338 });
339 int randomInt = Double.valueOf(Math.round((1-distance)*keys.length)).intValue();
340 int index = 0;
341 if (randomInt > 1) {
342 index = keys.length - 1 - random.nextInt(randomInt);
343 } else {
344 index = keys.length - 1;
345 }
346 if (index < 0) {
347 System.out.println("huh");
348 }
349 NavPoint navPoint = distances.get(keys[index]);
350 return navPoint;
351 }
352
353
354
355
356
357
358 @Override
359 public String toString() {
360 return name.getToken();
361 }
362
363 public boolean contains(SPStoryPlace place) {
364 if (place == this) return true;
365 return getContainsAllPlaces().contains(place);
366 }
367
368 }