View Javadoc

1   package cz.cuni.amis.pogamut.base.utils.math;
2   
3   import java.util.Collection;
4   
5   import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
6   import cz.cuni.amis.pogamut.base3d.worldview.object.IViewable;
7   import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
8   import cz.cuni.amis.utils.IFilter;
9   
10  /**
11   *
12   * @author ik
13   */
14  public class DistanceUtils {
15  	
16      /**
17       * Returns the nearest object to 'target'.
18       * <p><p>
19       * WARNING: O(n) complexity!
20       * 
21       * @param <T>
22       * @param locations
23       * @param target
24       * @return nearest object from collection of objects
25       */
26      public static <T extends ILocated> T getNearest(Collection<T> locations, ILocated target) {
27      	if (locations == null) return null;
28      	if (target == null) return null;
29          T nearest = null;
30          Location targetLoc = target.getLocation();
31          if (targetLoc == null) return null;
32          double minDistance = Double.MAX_VALUE;
33          double d;
34          for(T l : locations) {
35          	if (l.getLocation() == null) continue;
36              d = l.getLocation().getDistance(targetLoc);
37              if(d < minDistance) {
38                  minDistance = d;
39                  nearest = l;
40              }
41          }
42          return nearest;
43      }
44      
45      /**
46       * Returns the nearest object to 'target' that is not further than 'maxDistance'.
47       * <p><p>
48       * WARNING: O(n) complexity!
49       * 
50       * @param <T>
51       * @param locations
52       * @param target
53       * @param maxDistance
54       * @return nearest object from collection of objects that is not further than 'maxDistance'.
55       */
56      public static <T extends ILocated> T getNearest(Collection<T> locations, ILocated target, double maxDistance) {
57      	if (locations == null) return null;
58      	if (target == null) return null;
59          T nearest = null;
60          Location targetLoc = target.getLocation();
61          if (targetLoc == null) return null;
62          double minDistance = Double.MAX_VALUE;
63          double d;
64          for(T l : locations) {
65          	if (l.getLocation() == null) continue;
66              d = l.getLocation().getDistance(targetLoc);
67              if (d > maxDistance) continue;
68              if(d < minDistance) {
69                  minDistance = d;
70                  nearest = l;
71              }
72          }
73          return nearest;
74      }
75      
76      /**
77       * Returns the nearest object to 'target'.
78       * <p><p>
79       * WARNING: O(n) complexity!
80       * 
81       * @param <T>
82       * @param locations
83       * @param target
84       * @return nearest object from collection of objects
85       */
86      public static <T extends ILocated> T getNearestFiltered(Collection<T> locations, ILocated target, IFilter<T> filter) {
87      	if (locations == null) return null;
88      	if (target == null) return null;
89          Location targetLoc = target.getLocation();
90          if (targetLoc == null) return null;
91          T nearest = null;        
92          double minDistance = Double.MAX_VALUE;
93          double d;
94          for(T l : locations) {
95          	if (l.getLocation() == null) continue;
96          	if (!filter.isAccepted(l)) continue;
97              d = l.getLocation().getDistance(targetLoc);
98              if(d < minDistance) {
99                  minDistance = d;
100                 nearest = l;
101             }
102         }
103         return nearest;
104     }
105 
106     /**
107      * Returns the second nearest object to 'target'.
108      * <p><p>
109      * WARNING: O(n) complexity!
110      * 
111      * @param <T>
112      * @param locations
113      * @param target
114      * @return nearest object from collection of objects
115      */
116     public static <T extends ILocated> T getSecondNearest(Collection<T> locations, ILocated target) {
117     	if (locations == null) return null;
118     	if (target == null) return null;
119     	Location targetLoc = target.getLocation();
120         if (targetLoc == null) return null;
121     	T secondNearest = null;
122         T nearest = null;
123         double closestDistance = Double.MAX_VALUE;
124         double secondClosestDistance = Double.MAX_VALUE;
125 
126         for (T l : locations) {
127         	if (l.getLocation() == null) continue;
128             double distance = Location.getDistance(l.getLocation(), targetLoc);
129             if (distance < closestDistance) {
130                 secondClosestDistance = closestDistance;
131                 secondNearest = nearest;
132 
133                 closestDistance = distance;
134                 nearest = l;
135             } else {
136                 if(distance < secondClosestDistance) {
137                     secondClosestDistance = distance;
138                     secondNearest = l;
139                 }
140             }
141         }
142         return secondNearest;
143     }
144     
145     /**
146      * Returns the nearest object to 'target'.
147      * <p><p>
148      * WARNING: O(n) complexity!
149      * 
150      * @param <T>
151      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
152      * @param target
153      * @return nearest object from collection of objects
154      */
155     public static <T extends IViewable> T getNearestVisible(Collection<T> locations, ILocated target) {
156     	if (locations == null) return null;
157     	if (target == null) return null;
158     	Location targetLoc = target.getLocation();
159         if (targetLoc == null) return null;
160     	T nearest = null;
161         double minDistance = Double.MAX_VALUE;
162         double d;
163         for(T l : locations) {
164         	if (!l.isVisible()) continue;
165         	ILocated loc = (ILocated)l;
166         	if (loc.getLocation() == null) continue;
167             d = loc.getLocation().getDistance(targetLoc);
168             if(d < minDistance) {
169                 minDistance = d;
170                 nearest = l;
171             }
172         }
173         return nearest;
174     }
175 
176     /**
177      * Returns the second nearest object to 'target'.
178      * <p><p>
179      * WARNING: O(n) complexity!
180      * 
181      * @param <T>
182      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
183      * @param target
184      * @return nearest object from collection of objects
185      */
186     public static <T extends IViewable> T getSecondNearestVisible(Collection<T> locations, ILocated target) {
187     	if (locations == null) return null;
188     	if (target == null) return null;
189     	Location targetLoc = target.getLocation();
190         if (targetLoc == null) return null;
191     	T secondNearest = null;
192         T nearest = null;
193         double closestDistance = Double.MAX_VALUE;
194         double secondClosestDistance = Double.MAX_VALUE;
195 
196         for (T l : locations) {        
197             if (!l.isVisible()) continue;
198         	ILocated loc = (ILocated)l;
199         	if (loc.getLocation() == null) continue;
200         	double distance = Location.getDistance(loc.getLocation(), targetLoc);
201             if (distance < closestDistance) {
202                 secondClosestDistance = closestDistance;
203                 secondNearest = nearest;
204 
205                 closestDistance = distance;
206                 nearest = l;
207             } else {
208                 if(distance < secondClosestDistance) {
209                     secondClosestDistance = distance;
210                     secondNearest = l;
211                 }
212             }
213         }
214         return secondNearest;
215     }
216     
217     /**
218      * Returns the nearest object to 'target' (ignoring 'z' coordinate).
219      * <p><p>
220      * WARNING: O(n) complexity!
221      * 
222      * @param <T>
223      * @param locations
224      * @param target
225      * @return nearest object from collection of objects
226      */
227     public static <T extends ILocated> T getNearest2D(Collection<T> locations, ILocated target) {
228     	if (locations == null) return null;
229     	if (target == null) return null;
230     	Location targetLoc = target.getLocation();
231         if (targetLoc == null) return null;
232     	T nearest = null;
233         double minDistance = Double.MAX_VALUE;
234         double d;
235         for(T l : locations) {
236         	if (l.getLocation() == null) continue;
237             d = l.getLocation().getDistance2D(targetLoc);
238             if(d < minDistance) {
239                 minDistance = d;
240                 nearest = l;
241             }
242         }
243         return nearest;
244     }
245     
246     /**
247      * Returns the nearest object to 'target' (ignoring 'z' coordinate).
248      * <p><p>
249      * WARNING: O(n) complexity!
250      * 
251      * @param <T>
252      * @param locations
253      * @param target
254      * @return nearest object from collection of objects
255      */
256     public static <T extends ILocated> T getNearestFiltered2D(Collection<T> locations, ILocated target, IFilter<T> filter) {
257     	if (locations == null) return null;
258     	if (target == null) return null;
259     	Location targetLoc = target.getLocation();
260         if (targetLoc == null) return null;
261     	T nearest = null;
262         double minDistance = Double.MAX_VALUE;
263         double d;
264         for(T l : locations) {
265         	if (!filter.isAccepted(l)) continue;
266         	if (l.getLocation() == null) continue;
267             d = l.getLocation().getDistance2D(targetLoc);
268             if(d < minDistance) {
269                 minDistance = d;
270                 nearest = l;
271             }
272         }
273         return nearest;
274     }
275 
276     /**
277      * Returns the second nearest object to 'target' (ignoring 'z' coordinate).
278      * <p><p>
279      * WARNING: O(n) complexity!
280      * 
281      * @param <T>
282      * @param locations
283      * @param target
284      * @return nearest object from collection of objects
285      */
286     public static <T extends ILocated> T getSecondNearest2D(Collection<T> locations, ILocated target) {
287     	if (locations == null) return null;
288     	if (target == null) return null;
289     	Location targetLoc = target.getLocation();
290         if (targetLoc == null) return null;
291     	T secondNearest = null;
292         T nearest = null;
293         double closestDistance = Double.MAX_VALUE;
294         double secondClosestDistance = Double.MAX_VALUE;
295 
296         for (T l : locations) {
297         	if (l.getLocation() == null) continue;
298             double distance = Location.getDistance2D(l.getLocation(), targetLoc);
299             if (distance < closestDistance) {
300                 secondClosestDistance = closestDistance;
301                 secondNearest = nearest;
302 
303                 closestDistance = distance;
304                 nearest = l;
305             } else {
306                 if(distance < secondClosestDistance) {
307                     secondClosestDistance = distance;
308                     secondNearest = l;
309                 }
310             }
311         }
312         return secondNearest;
313     }
314     
315     /**
316      * Returns the nearest object to 'target' (ignoring 'z' coordinate).
317      * <p><p>
318      * WARNING: O(n) complexity!
319      * 
320      * @param <T>
321      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
322      * @param target
323      * @return nearest object from collection of objects
324      */
325     public static <T extends IViewable> T getNearestVisible2D(Collection<T> locations, ILocated target) {
326     	if (locations == null) return null;
327     	if (target == null) return null;
328     	Location targetLoc = target.getLocation();
329         if (targetLoc == null) return null;
330     	T nearest = null;
331         double minDistance = Double.MAX_VALUE;
332         double d;
333         for(T l : locations) {
334         	if (!l.isVisible()) continue;
335         	ILocated loc = (ILocated)l;
336         	if (loc.getLocation() == null) continue;
337             d = loc.getLocation().getDistance2D(targetLoc);
338             if(d < minDistance) {
339                 minDistance = d;
340                 nearest = l;
341             }
342         }
343         return nearest;
344     }
345 
346     /**
347      * Returns the second nearest object to 'target' (ignoring 'z' coordinate).
348      * <p><p>
349      * WARNING: O(n) complexity!
350      * 
351      * @param <T>
352      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
353      * @param target
354      * @return nearest object from collection of objects
355      */
356     public static <T extends IViewable> T getSecondNearestVisible2D(Collection<T> locations, ILocated target) {
357     	if (locations == null) return null;
358     	if (target == null) return null;
359     	Location targetLoc = target.getLocation();
360         if (targetLoc == null) return null;
361     	T secondNearest = null;
362         T nearest = null;
363         double closestDistance = Double.MAX_VALUE;
364         double secondClosestDistance = Double.MAX_VALUE;
365 
366         for (T l : locations) {        
367             if (!l.isVisible()) continue;
368         	ILocated loc = (ILocated)l;
369         	if (loc.getLocation() == null) continue;
370         	double distance = Location.getDistance2D(loc.getLocation(), targetLoc);
371             if (distance < closestDistance) {
372                 secondClosestDistance = closestDistance;
373                 secondNearest = nearest;
374 
375                 closestDistance = distance;
376                 nearest = l;
377             } else {
378                 if(distance < secondClosestDistance) {
379                     secondClosestDistance = distance;
380                     secondNearest = l;
381                 }
382             }
383         }
384         return secondNearest;
385     }
386 
387 }