View Javadoc

1   package cz.cuni.amis.pogamut.base.utils.math;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.Comparator;
7   import java.util.LinkedList;
8   import java.util.List;
9   
10  import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
11  import cz.cuni.amis.pogamut.base3d.worldview.object.IViewable;
12  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
13  import cz.cuni.amis.utils.IFilter;
14  import cz.cuni.amis.utils.Tuple2;
15  
16  /**
17   * DistanceUtils consists of usual routines for selecting "X" from some "collections of Xes" that are in some "distance" relation to the "target",
18   * e.g., "get nearest weapon from collection of available weapons to my position".
19   * <p><p>
20   * Note that you may always use custom metric via {@link IGetDistance} interface.
21   * <p><p>
22   * Note that you may always use some custom filters via {@link IDistanceFilter} interface.
23   * 
24   * @author Jimmy
25   * @author ik
26   */
27  public class DistanceUtils {
28  	
29  	// --------------
30  	// =====================
31  	// RELATIONs
32  	// =====================
33  	// --------------
34  	
35  	/**
36  	 * Relation-ship estimator between two {@link ILocated} objects and their distance (or whatever required).
37  	 * @author Jimmy
38  	 *
39  	 * @param <T>
40  	 */
41  	public static interface IBetterRelation<T> {
42  		
43  		public boolean isBetterRelation(ILocated target, T examinedObject, double examinedObjectToTargetDistance, T currentBestCandidate, double currentBestObjectToTargetDistance);
44  		
45  	}
46  	
47  	/**
48  	 * Prefer "closer" objects to "target"
49  	 * @author Jimmy
50  	 *
51  	 * @param <T>
52  	 */
53  	public static class RelationCloser<T> implements IBetterRelation<T> {
54  		
55  		@Override
56  		public boolean isBetterRelation(ILocated target, T examinedObject, double examinedObjetToTargetDistance, T currentBestCandidate, double currentBestObjectToTargetDistance) {
57  			return examinedObjetToTargetDistance < currentBestObjectToTargetDistance;
58  		}
59  		
60  	}
61  	
62  	@SuppressWarnings("rawtypes")
63  	public static final RelationCloser relationCloser = new RelationCloser();
64  	
65  	/**
66  	 * Prefer "further" objects to "target"
67  	 * @author Jimmy
68  	 *
69  	 * @param <T>
70  	 */
71  	public static class RelationFurther<T> implements IBetterRelation<T> {
72  		
73  		@Override
74  		public boolean isBetterRelation(ILocated target, T examinedObject, double examinedObjetToTargetDistance, T currentBestCandidate, double currentBestObjectToTargetDistance) {
75  			return examinedObjetToTargetDistance > currentBestObjectToTargetDistance;
76  		}
77  		
78  	}
79  	
80  	@SuppressWarnings("rawtypes")
81  	public static final RelationFurther relationFurther = new RelationFurther();
82  	
83  	// --------------
84  	// =====================
85  	// METRICS
86  	// =====================
87  	// --------------
88  	
89  	/**
90  	 * Distance estimator between object of types T and some {@link Location} target.
91  	 * @author Jimmy
92  	 *
93  	 * @param <T>
94  	 */
95  	public static interface IGetDistance<T> {
96  		
97  		public double getDistance(T object, ILocated target);
98  		
99  	}
100 	
101 	/**
102 	 * Simple implementation of {@link IGetDistance} that uses {@link Location#getDistance(Location)} method.
103 	 * @author Jimmy
104 	 *
105 	 * @param <T>
106 	 */
107 	public static class GetLocatedDistance3D<T extends ILocated> implements IGetDistance<T> {
108 
109 		/**
110 		 * Uses {@link Location#getDistance(Location)} method.
111 		 */
112 		@Override
113 		public double getDistance(T object, ILocated target) {
114 			if (object.getLocation() == null) return Double.MAX_VALUE;
115 			return object.getLocation().getDistance(target.getLocation());
116 		}
117 		
118 	}
119 	
120 	/**
121 	 * See {@link GetLocatedDistance3D}.
122 	 */
123 	public static final GetLocatedDistance3D<ILocated> getLocatedDistance3D = new GetLocatedDistance3D<ILocated>();
124 	
125 	/**
126 	 * Simple implementation of {@link IGetDistance} that uses {@link Location#getDistance2D(Location)} method.
127 	 * @author Jimmy
128 	 *
129 	 * @param <T>
130 	 */
131 	public static class GetLocatedDistance2D<T extends ILocated> implements IGetDistance<T> {
132 
133 		/**
134 		 * Uses {@link Location#getDistance(Location)} method.
135 		 */
136 		@Override
137 		public double getDistance(T object, ILocated target) {
138 			if (object.getLocation() == null) return Double.MAX_VALUE;
139 			return object.getLocation().getDistance2D(target.getLocation());
140 		}
141 		
142 	}
143 	
144 	/**
145 	 * See {@link GetLocatedDistance2D}.
146 	 */
147 	public static final GetLocatedDistance2D<ILocated> getLocatedDistance2D = new GetLocatedDistance2D<ILocated>();
148 	
149 	// --------------
150 	// =====================
151 	// FILTERS
152 	// =====================
153 	// --------------
154 	
155 	/**
156 	 * Filter that allows to check whether "object" is accepted with respect to "distanceToTarget" for given "target".
157 	 * @author Jimmy
158 	 *
159 	 * @param <T>
160 	 */
161 	public static interface IDistanceFilter<T> {
162 		
163 		/**
164 		 * @param object
165 		 * @param target
166 		 * @param distanceToTarget
167 		 * @return TRUE == can be result, FALSE == filter out
168 		 */
169 		public boolean isAccepted(T object, ILocated target, double distanceToTarget);
170 		
171 	}
172 	
173 	
174 	/**
175 	 * Filter that accepts all "objects" (does not filter anything out).
176 	 * @author Jimmy
177 	 *
178 	 * @param <T>
179 	 */
180 	public static final class AcceptAllDistanceFilter<T> implements IDistanceFilter<T> {
181 
182 		@Override
183 		public boolean isAccepted(T object, ILocated target, double distanceToTarget) {
184 			return true;
185 		}
186 		
187 	}
188 	
189 	/**
190 	 * See {@link AcceptAllDistanceFilter}.
191 	 */
192 	@SuppressWarnings("unchecked")
193 	public static final AcceptAllDistanceFilter acceptAllDistanceFilter = new AcceptAllDistanceFilter();
194 	
195 	/**
196 	 * Contains single filter, {@link #acceptAllDistanceFilter}, i.e., this will ACCEPTS-ALL-ITEMS.
197 	 */
198 	public static final IDistanceFilter[] NO_FILTER = new IDistanceFilter[]{ acceptAllDistanceFilter };
199 	
200 	/**
201 	 * Filter that accepts all "objects" that are within range of min/max distance (inclusive).
202 	 * @author Jimmy
203 	 *
204 	 * @param <T>
205 	 */
206 	public static class RangeDistanceFilter<T> implements IDistanceFilter<T> {
207 
208 		private double minDistance;
209 		private double maxDistance;
210 
211 		public RangeDistanceFilter(double minDistance, double maxDistance) {
212 			this.minDistance = minDistance;
213 			this.maxDistance = maxDistance;
214 		}
215 		
216 		@Override
217 		public boolean isAccepted(T object, ILocated target, double distanceToTarget) {
218 			return minDistance <= distanceToTarget && distanceToTarget <= maxDistance;
219 		}
220 		
221 	}
222 	
223 	/**
224 	 * Accepts only VISIBLE ({@link IViewable#isVisible()} == TRUE) objects.
225 	 * @author Jimmy
226 	 *
227 	 * @param <T>
228 	 */
229 	public static class VisibleFilter<T extends IViewable> implements IDistanceFilter<T> {
230 
231 		@Override
232 		public boolean isAccepted(T object, ILocated target, double distanceToTarget) {
233 			return object.isVisible();
234 		}
235 		
236 	}
237 	
238 	/**
239 	 * See {@link VisibleFilter}.
240 	 */
241 	public static final VisibleFilter<IViewable> visibleFilter = new VisibleFilter<IViewable>();
242 	
243 	/**
244 	 * Adapter that wraps {@link IFilter} making it into {@link IDistanceFilter}.
245 	 * 
246 	 * @author Jimmy
247 	 *
248 	 * @param <T>
249 	 */
250 	public static class FilterAdapter<T> implements IDistanceFilter<T> {
251 		
252 		private IFilter<T> filter;
253 
254 		public FilterAdapter(IFilter<T> filter) {
255 			this.filter = filter;
256 		}
257 
258 		@Override
259 		public boolean isAccepted(T object, ILocated target, double distanceToTarget) {
260 			return filter.isAccepted(object);
261 		}
262 		
263 	}
264 	
265 	// --------------
266 	// =====================
267 	// getNearest()
268 	// =====================
269 	// --------------
270 	
271 	/**
272      * Returns "in-best-distance-relation-to-'target'" object. 
273      * <p><p>
274      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
275      * <p><p>
276      * Relation checking is provided via {@link IBetterRelation#isBetterRelation(Object, ILocated, double, double)}.
277      * <p><p>
278      * Only 'locations' that passes ALL 'filters' may get into the result.
279      * 
280      * WARNING: O(n) complexity!
281      * 
282      * @param <T>
283      * @param locations
284      * @param target
285      * @param getDistance distance-computer between 'locations' and 'target'.
286      * @param betterRelation assessing 
287      * @param filters if null or empty, is ignored
288      * @return nearest object from collection of objects
289      */
290     public static <T> T getInBestRelation(Collection<T> locations, ILocated target, IGetDistance getDistance, IBetterRelation betterRelation, IDistanceFilter... filters) {
291     	if (filters == null || (filters.length == 1 && filters[0] == acceptAllDistanceFilter)) {
292     		return getInBestRelation(locations, target, getDistance, betterRelation);
293     	}
294     	if (filters == null) return null;
295     	if (locations == null) return null;
296     	if (target == null) return null;
297     	if (target.getLocation() == null) return null;
298     	if (getDistance == null) return null;
299     	if (betterRelation == null) return null;
300         
301         T nearest = null;        
302         double minDistance = Double.MAX_VALUE;
303         double distance;
304         
305         for(T location : locations) {        	
306         	distance = getDistance.getDistance(location, target);
307         	
308         	boolean accepted = true;
309         	for (IDistanceFilter filter : filters) {
310         		if (filter == null) continue;
311         		if (filter.isAccepted(location, target, distance)) continue;
312         		accepted = false;
313         		break;
314         	}
315         	
316         	if (accepted) {
317 	        	if (betterRelation.isBetterRelation(target, location, distance, nearest, minDistance)) {
318 	                minDistance = distance;
319 	                nearest = location;
320 	            }
321         	}
322         }
323         
324         return nearest;
325     }
326     
327     /**
328      * Returns "in-best-distance-relation-to-'target'" object. 
329      * <p><p>
330      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
331      * <p><p>
332      * Relation checking is provided via {@link IBetterRelation#isBetterRelation(Object, ILocated, double, double)}.
333      * 
334      * WARNING: O(n) complexity!
335      * 
336      * @param <T>
337      * @param locations
338      * @param target
339      * @param getDistance distance computer between 'locations' and 'target'.
340      * @param betterRelation
341      * @return nearest object from collection of objects
342      */
343     public static <T> T getInBestRelation(Collection<T> locations, ILocated target, IGetDistance getDistance, IBetterRelation betterRelation) {
344     	if (locations == null) return null;
345     	if (target == null) return null;
346     	if (target.getLocation() == null) return null;
347     	if (getDistance == null) return null;
348     	if (betterRelation == null) return null;
349         
350         T best = null;        
351         double bestDistance = Double.MAX_VALUE;
352         double distance;
353         
354         for(T location : locations) {        	
355         	distance = getDistance.getDistance(location, target);
356         	
357         	if (betterRelation.isBetterRelation(target, location, distance, best, bestDistance)) {
358         		bestDistance = distance;
359 	            best = location;
360 	        }
361         }
362         
363         return best;
364     }
365     
366     /**
367      * Returns "in-nth-best-distance-relation-to-'target'" object from 'location'. This means is will not get the 1st best, 2nd best but n-th best, i.e.,
368      * if we would sort all 'locations' according to 'betterRelation', this returns n-th element. 
369      * <p><p>
370      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
371      * <p><p>
372      * Relation checking is provided via {@link IBetterRelation#isBetterRelation(Object, ILocated, double, double)}.
373      * <p><p>
374      * Only 'locations' that passes ALL 'filters' may get into the result.
375      * 
376      * WARNING: O(locations.size * N) ~ O(n^2) complexity!
377      * 
378      * @param <T>
379      * @param nthBest if &lt;= 0, returns the 1-BEST
380      * @param locations if locations.size() &lt; 'nthBest', returns the "worst" from 'locations'
381      * @param target
382      * @param getDistance distance computer between 'locations' and 'target'.
383      * @param filters if insufficient (&lt; nthBest) locations gets to the result, the "worst" is returned, or null in case of all locations are filtered out
384      * @return "in-nth-best-distance-relation-to-'target'" object from 'location'
385      */
386     public static <T> T getInNthBestRelation(int nthBest, Collection<T> locations, ILocated target, IGetDistance getDistance, IBetterRelation betterRelation, IDistanceFilter... filters) {
387     	if (nthBest < 1) return getInBestRelation(locations, target, getDistance, betterRelation, filters);
388     	if (filters == null) return null;
389     	if (locations == null) return null;
390     	if (target == null) return null;
391     	if (target.getLocation() == null) return null;
392     	if (getDistance == null) return null;
393     	if (betterRelation == null) return null;
394         
395     	List<Tuple2<T, Double>> best = new ArrayList<Tuple2<T, Double>>();
396     	
397         double distance;
398         
399         for(T location : locations) {        	
400         	distance = getDistance.getDistance(location, target);
401         	
402         	boolean accepted = true;
403         	for (IDistanceFilter filter : filters) {
404         		if (filter == null) continue;
405         		if (filter.isAccepted(location, target, distance)) continue;
406         		accepted = false;
407         		break;
408         	}
409         	
410         	if (accepted) {
411 	        	int i = 0;
412 	        	for (; i < best.size(); ++i) {
413 	        		Tuple2<T, Double> candidate = best.get(i);
414 	        		if (betterRelation.isBetterRelation(target, location, distance, candidate.getFirst(), candidate.getSecond())) {
415 	        			break;
416 	        		}
417 	        	}
418 	        	if (i < nthBest) {
419 	        		if (i < best.size()) {
420 	        			best.add(i, new Tuple2<T, Double>(location, distance));
421 	        		} else {
422 	        			best.add(new Tuple2<T, Double>(location, distance));
423 	        		}
424 	        	}        	
425         	}
426         }
427         
428         return best.size() == 0 ? null : best.get(best.size()-1).getFirst();
429     }
430     
431     /**
432      * Returns "in-nth-best-distance-relation-to-'target'" object from 'locations'. This means is will not get the 1st best, 2nd best but n-th best, i.e.,
433      * if we would sort all 'locations' according to 'betterRelation', this returns n-th element. 
434      * <p><p>
435      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
436      * <p><p>
437      * Relation checking is provided via {@link IBetterRelation#isBetterRelation(Object, ILocated, double, double)}.
438      * 
439      * WARNING: O(locations.size * N) ~ O(n^2) complexity!
440      * 
441      * @param <T>
442      * @param nthBest if &lt;= 0, returns the 1-BEST
443      * @param locations if locations.size() &lt; 'nthBest', returns the "worst" from 'locations'
444      * @param target
445      * @param getDistance distance computer between 'locations' and 'target'.
446      * @return nth-nearest object from 'locations'
447      */
448     public static <T> T getInNthBestRelation(int nthBest, Collection<T> locations, ILocated target, IGetDistance getDistance, IBetterRelation betterRelation) {
449     	if (nthBest < 1) return getInBestRelation(locations, target, getDistance, betterRelation);
450     	if (locations == null) return null;
451     	if (target == null) return null;
452     	if (target.getLocation() == null) return null;
453     	if (getDistance == null) return null;
454     	if (betterRelation == null) return null;
455         
456     	List<Tuple2<T, Double>> best = new ArrayList<Tuple2<T, Double>>();
457     	
458         double distance;
459         
460         for(T location : locations) {        	
461         	distance = getDistance.getDistance(location, target);
462         	
463         	int i = 0;
464         	for (; i < best.size(); ++i) {
465         		Tuple2<T, Double> candidate = best.get(i);
466         		if (betterRelation.isBetterRelation(target, location, distance, candidate.getFirst(), candidate.getSecond())) {
467         			break;
468         		}
469         	}
470         	if (i < nthBest) {
471         		if (i < best.size()) {
472         			best.add(i, new Tuple2<T, Double>(location, distance));
473         		} else {
474         			best.add(new Tuple2<T, Double>(location, distance));
475         		}
476         	}        	
477         }
478         
479         return best.size() == 0 ? null : best.get(best.size()-1).getFirst();
480     }
481     
482     /**
483      * Returns the nearest object from 'location' to 'target' that is accepted by all 'filters'.
484      * <p><p> 
485      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
486      * <p><p>
487      * WARNING: O(n) complexity!
488      * 
489      * @param <T>
490      * @param locations
491      * @param target
492      * @param getDistance distance computer between 'locations' and 'target'.
493      * @param filters filters to be used (that can filter out unsuitable results)
494      * @return nearest object from 'locations'
495      */
496     public static <T> T getNearest(Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
497     	return 
498     		getInBestRelation(
499     				locations, 
500     				target, 
501     				getDistance, 
502     				relationCloser,
503     				filters
504     		);
505     }
506     
507     /**
508      * Returns the n-th nearest object from 'locations' to 'target' that is accepted by all 'filters'.
509      * <p><p> 
510      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
511      * <p><p>
512      * WARNING: O(n) complexity!
513      * 
514      * @param <T>
515      * @param nthNearest if &lt;= 0, returns the nearest
516      * @param locations
517      * @param target
518      * @param getDistance distance computer between 'locations' and 'target'.
519      * @param filters filters to be used (that can filter out unsuitable results)
520      * @return nth-nearest object from 'locations'
521      */
522     public static <T> T getNthNearest(int nthNearest, Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
523     	return 
524     		getInNthBestRelation(
525     				nthNearest,
526     				locations, 
527     				target, 
528     				getDistance, 
529     				relationCloser,
530     				filters
531     		);
532     }
533     
534     /**
535      * Returns the farthest object from 'locations' to 'target' that is accepted by all 'filters'.
536      * <p><p> 
537      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
538      * <p><p>
539      * WARNING: O(n) complexity!
540      * 
541      * @param <T>
542      * @param locations
543      * @param target
544      * @param getDistance distance computer between 'locations' and 'target'.
545      * @param filters filters to be used (that can filter out unsuitable results)
546      * @return nearest object from 'location'
547      */
548     public static <T> T getFarthest(Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
549     	return 
550     		getInBestRelation(
551     				locations, 
552     				target, 
553     				getDistance, 
554     				relationFurther,
555     				filters
556     		);
557     }
558     
559     /**
560      * Returns the n-th farthest object from 'locations' to 'target' that is accepted by all 'filters'.
561      * <p><p> 
562      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
563      * <p><p>
564      * WARNING: O(n) complexity!
565      * 
566      * @param <T>
567      * @param nthFarthest if &lt;= 0, returns the farthest
568      * @param locations
569      * @param target
570      * @param getDistance distance computer between 'locations' and 'target'.
571      * @param filters filters to be used (that can filter out unsuitable results)
572      * @return nearest object from 'locations'
573      */
574     public static <T> T getNthFarthest(int nthFarthest, Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
575     	return 
576     		getInNthBestRelation(
577     				nthFarthest,
578     				locations, 
579     				target, 
580     				getDistance, 
581     				relationFurther,
582     				filters
583     		);
584     }
585 	
586 	/**
587      * Returns the nearest object from 'locations' to 'target'. 
588      * <p><p>
589      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
590      * <p><p>
591      * WARNING: O(n) complexity!
592      * 
593      * @param <T>
594      * @param locations
595      * @param target
596      * @param getDistance distance computer between 'locations' and 'target'.
597      * @return nearest object from 'locations'
598      */
599     public static <T> T getNearest(Collection<T> locations, ILocated target, IGetDistance getDistance) {
600     	return 
601     		getInBestRelation(
602     			locations, 
603     			target,
604     			getDistance,
605     			relationCloser
606     		);    	
607     }
608     
609     /**
610      * Returns the n-th nearest object from 'locations' to 'target'. 
611      * <p><p>
612      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
613      * <p><p>
614      * WARNING: O(n) complexity!
615      * 
616      * @param <T>
617      * @param nthNearest if &lt;= 0, returns the nearest
618      * @param locations
619      * @param target
620      * @param getDistance distance computer between 'locations' and 'target'.
621      * @return nth-nearest object from 'locations'
622      */
623     public static <T> T getNthNearest(int nthNearest, Collection<T> locations, ILocated target, IGetDistance getDistance) {
624     	return 
625     		getInNthBestRelation(
626     			nthNearest,
627     			locations, 
628     			target,
629     			getDistance,
630     			relationCloser
631     		);    	
632     } 
633     
634     /**
635      * Returns the farthest object to 'target'. 
636      * <p><p>
637      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
638      * <p><p>
639      * WARNING: O(n) complexity!
640      * 
641      * @param <T>
642      * @param locations
643      * @param target
644      * @param getDistance distance computer between 'locations' and 'target'.
645      * @return farthest object from 'locations'
646      */
647     public static <T> T getFarthest(Collection<T> locations, ILocated target, IGetDistance getDistance) {
648     	return 
649     		getInBestRelation(
650     			locations, 
651     			target,
652     			getDistance,
653     			relationFurther
654     		);    	
655     }
656     
657     /**
658      * Returns the n-th farthest object from 'locations' to 'target'. 
659      * <p><p>
660      * Distance is obtained via provided {@link IGetDistance#getDistance(Object, Location)}.
661      * <p><p>
662      * WARNING: O(n) complexity!
663      * 
664      * @param <T>
665      * @param nthFarthest if &lt;= 0, returns the farthest
666      * @param locations
667      * @param target
668      * @param getDistance distance computer between 'locations' and 'target'.
669      * @return nth-farthest object from 'locations'
670      */
671     public static <T> T getNthFarthest(int nthFarthest, Collection<T> locations, ILocated target, IGetDistance getDistance) {
672     	return 
673     		getInNthBestRelation(
674     			nthFarthest,
675     			locations, 
676     			target,
677     			getDistance,
678     			relationFurther
679     		);    	
680     }
681     
682     /**
683      * Returns the nearest object from 'locations' to 'target' that is accepted by all 'filters'.
684      * <p><p>
685      * WARNING: O(n) complexity!
686      * 
687      * @param <T>
688      * @param locations
689      * @param target
690      * @param filters
691      * @return nearest object from 'locations'
692      */
693     public static <T extends ILocated> T getNearest(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
694     	return getNearest(locations, target, getLocatedDistance3D, filters);
695     }
696     
697     /**
698      * Returns the nearest object from 'locations' to 'target' that is accepted by all 'filters'.
699      * <p><p>
700      * WARNING: O(n) complexity!
701      * 
702      * @param <T>
703      * @param nthNearest if &lt;= 0, returns the nearest
704      * @param locations
705      * @param target
706      * @param filters
707      * @return nearest object from 'locations'
708      */
709     public static <T extends ILocated> T getNthNearest(int nthNearest, Collection<T> locations, ILocated target, IDistanceFilter... filters) {
710     	return getNthNearest(nthNearest, locations, target, getLocatedDistance3D, filters);
711     }
712     
713     /**
714      * Returns the farthest object from 'locations' to 'target' that is accepted by all 'filters'.
715      * <p><p>
716      * WARNING: O(n) complexity!
717      * 
718      * @param <T>
719      * @param locations
720      * @param target
721      * @param filters
722      * @return farthest object from 'locations'
723      */
724     public static <T extends ILocated> T getFarthest(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
725     	return getFarthest(locations, target, getLocatedDistance3D, filters);
726     }
727     
728     /**
729      * Returns the nth-farthest object from 'locations' to 'target' that is accepted by all 'filters'.
730      * <p><p>
731      * WARNING: O(n) complexity!
732      * 
733      * @param <T>
734      * @param nthFarthest if &lt;= 0, returns the farthest
735      * @param locations
736      * @param target
737      * @param filters
738      * @return nth-farthest object from 'locations'
739      */
740     public static <T extends ILocated> T getNthFarthest(int nthFarthest, Collection<T> locations, ILocated target, IDistanceFilter... filters) {
741     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance3D, filters);
742     }
743 	
744     /**
745      * Returns the nearest object from 'locations' to 'target'.
746      * <p><p>
747      * WARNING: O(n) complexity!
748      * 
749      * @param <T>
750      * @param locations
751      * @param target
752      * @return nearest object from 'locations'
753      */
754     public static <T extends ILocated> T getNearest(Collection<T> locations, ILocated target) {
755     	return getNearest(locations, target, getLocatedDistance3D);
756     }
757     
758     /**
759      * Returns the nth-nearest object from 'locations' to 'target'.
760      * <p><p>
761      * WARNING: O(n) complexity!
762      * 
763      * @param <T>
764      * @param nthNearest if &lt;= 0, returns the nearest
765      * @param locations
766      * @param target
767      * @return nth-nearest object from 'locations'
768      */
769     public static <T extends ILocated> T getNthNearest(int nthNearest, Collection<T> locations, ILocated target) {
770     	return getNthNearest(nthNearest, locations, target, getLocatedDistance3D);
771     }
772     
773     /**
774      * Returns the farthest object from 'locations' to 'target'.
775      * <p><p>
776      * WARNING: O(n) complexity!
777      * 
778      * @param <T>
779      * @param locations
780      * @param target
781      * @return farthest object from 'locations'
782      */
783     public static <T extends ILocated> T getFarthest(Collection<T> locations, ILocated target) {
784     	return getFarthest(locations, target, getLocatedDistance3D);
785     }
786     
787     /**
788      * Returns the nth-farthest object from 'locations' to 'target'.
789      * <p><p>
790      * WARNING: O(n) complexity!
791      * 
792      * @param <T>
793      * @param nthFarthest if &lt;= 0, returns the farthest
794      * @param locations
795      * @param target
796      * @return nth-farthest object from 'locations'
797      */
798     public static <T extends ILocated> T getNthFarthest(int nthFarthest, Collection<T> locations, ILocated target) {
799     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance3D);
800     }
801     
802     /**
803      * Returns the nearest object from 'locations' to 'target' that is not further than 'maxDistance'.
804      * <p><p>
805      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
806      * <p><p>
807      * WARNING: O(n) complexity!
808      * 
809      * @param <T>
810      * @param locations
811      * @param target
812      * @param maxDistance
813      * @return nearest object from 'locations' that is not further than 'maxDistance'
814      */
815     public static <T extends ILocated> T getNearest(Collection<T> locations, ILocated target, double maxDistance) {
816     	return getNearest(locations, target, new RangeDistanceFilter<T>(0, maxDistance));
817     }
818     
819     /**
820      * Returns the nth-nearest object from 'locations' to 'target' that is not further than 'maxDistance'.
821      * <p><p>
822      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
823      * <p><p>
824      * WARNING: O(n) complexity!
825      * 
826      * @param <T>
827      * @param nthNearest if &lt;= 0, returns the nearest
828      * @param locations
829      * @param target
830      * @param maxDistance
831      * @return nth-nearest object from 'locations' that is not further than 'maxDistance'
832      */
833     public static <T extends ILocated> T getNthNearest(int nthNearest, Collection<T> locations, ILocated target, double maxDistance) {
834     	return getNthNearest(nthNearest, locations, target, new RangeDistanceFilter<T>(0, maxDistance));
835     }
836     
837     /**
838      * Returns the farthest object from 'locations' to 'target' that is not further than 'maxDistance'.
839      * <p><p>
840      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
841      * <p><p>
842      * WARNING: O(n) complexity!
843      * 
844      * @param <T>
845      * @param locations
846      * @param target
847      * @param maxDistance
848      * @return farthest object from 'locations' that is not further than 'maxDistance'
849      */
850     public static <T extends ILocated> T getFarthest(Collection<T> locations, ILocated target, double maxDistance) {
851     	return getFarthest(locations, target, new RangeDistanceFilter<T>(0, maxDistance));
852     }
853     
854     /**
855      * Returns the nth-farthest object from 'locations' to 'target' that is not further than 'maxDistance'.
856      * <p><p>
857      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
858      * <p><p>
859      * WARNING: O(n) complexity!
860      * 
861      * @param <T>
862      * @param nthFarthest if &lt;= 0, returns the farthest
863      * @param locations
864      * @param target
865      * @param maxDistance
866      * @return nth-farthest object from 'locations' that is not further than 'maxDistance'
867      */
868     public static <T extends ILocated> T getNthFarthest(int nthFarthest, Collection<T> locations, ILocated target, double maxDistance) {
869     	return getNthFarthest(nthFarthest, locations, target, new RangeDistanceFilter<T>(0, maxDistance));
870     }
871     
872     /**
873      * Returns the nearest object from 'location' to 'target' that is accepted by 'filter'.
874      * <p><p>
875      * WARNING: O(n) complexity!
876      * 
877      * @param <T>
878      * @param locations
879      * @param target
880      * @param filter if null behave as if ALL locations are accepted
881      * @return nearest object from 'locations' accepted by 'filter'
882      */
883     public static <T extends ILocated> T getNearestFiltered(Collection<T> locations, ILocated target, IFilter filter) {
884     	if (filter == null) {
885     		return getNearest(locations, target);
886     	}
887     	return getNearest(locations, target, new FilterAdapter<T>(filter));
888     }
889     
890     /**
891      * Returns the nth-nearest object from 'locations' to 'target' that is accepted by 'filter'.
892      * <p><p>
893      * WARNING: O(n) complexity!
894      * 
895      * @param <T>
896      * @param nthNearest if &lt;= 0, returns the nearest
897      * @param locations
898      * @param target
899      * @param filter if null behave as if ALL locations are accepted
900      * @return nth-nearest object from 'locations' accepted by 'filter'
901      */
902     public static <T extends ILocated> T getNthNearestFiltered(int nthNearest, Collection<T> locations, ILocated target, IFilter filter) {
903     	if (filter == null) {
904     		return getNthNearest(nthNearest, locations, target);
905     	}
906     	return getNthNearest(nthNearest, locations, target, new FilterAdapter<T>(filter));
907     }
908     
909     /**
910      * Returns the farthest object from 'locations' to 'target' that is accepted by 'filter'.
911      * <p><p>
912      * WARNING: O(n) complexity!
913      * 
914      * @param <T>
915      * @param locations
916      * @param target
917      * @param filter if null behave as if ALL locations are accepted
918      * @return farthest object from 'locations' accepted by 'filter'
919      */
920     public static <T extends ILocated> T getFarthestFiltered(Collection<T> locations, ILocated target, IFilter filter) {
921     	if (filter == null) {
922     		return getFarthest(locations, target);
923     	}
924     	return getFarthest(locations, target, new FilterAdapter<T>(filter));
925     }
926     
927     /**
928      * Returns the nth-farthest object from 'locations' to 'target' that is accepted by 'filter'.
929      * <p><p>
930      * WARNING: O(n) complexity!
931      * 
932      * @param <T>
933      * @param nthFarthest if &lt;= 0, returns the farthest
934      * @param locations
935      * @param target
936      * @param filter if null behave as if ALL locations are accepted
937      * @return nth-farthest object from 'locations' accepted by 'filter'
938      */
939     public static <T extends ILocated> T getNthFarthestFiltered(int nthFarthest, Collection<T> locations, ILocated target, IFilter filter) {
940     	if (filter == null) {
941     		return getNthFarthest(nthFarthest, locations, target);
942     	}
943     	return getNthFarthest(nthFarthest, locations, target, new FilterAdapter<T>(filter));
944     }
945     
946     /**
947      * Returns the nearest object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
948      * <p><p>
949      * WARNING: O(n) complexity!
950      * 
951      * @param <T>
952      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
953      * @param target
954      * @return nearest visible object from 'locations'
955      */
956     public static <T extends IViewable> T getNearestVisible(Collection<T> locations, ILocated target) {
957     	return getNearest(locations, target, getLocatedDistance3D, visibleFilter);
958     }
959     
960     /**
961      * Returns the nth-nearest object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
962      * <p><p>
963      * WARNING: O(n) complexity!
964      * 
965      * @param <T>
966      * @param ntNearest if &lt;= 0, returns the nearest
967      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
968      * @param target
969      * @return nth-nearest visible object from 'locations'
970      */
971     public static <T extends IViewable> T getNthNearestVisible(int nthNearest, Collection<T> locations, ILocated target) {
972     	return getNthNearest(nthNearest, locations, target, getLocatedDistance3D, visibleFilter);
973     }
974     
975     /**
976      * Returns the farthest object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
977      * <p><p>
978      * WARNING: O(n) complexity!
979      * 
980      * @param <T>
981      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
982      * @param target
983      * @return farthest visible object from 'locations'
984      */
985     public static <T extends IViewable> T getFarthestVisible(Collection<T> locations, ILocated target) {
986     	return getFarthest(locations, target, getLocatedDistance3D, visibleFilter);
987     }
988     
989     /**
990      * Returns the nth-farthest object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
991      * <p><p>
992      * WARNING: O(n) complexity!
993      * 
994      * @param <T>
995      * @param ntFarthest if &lt;= 0, returns the farthest
996      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
997      * @param target
998      * @return nth-farthest visible object from 'locations'
999      */
1000     public static <T extends IViewable> T getNthFarthestVisible(int nthFarthest, Collection<T> locations, ILocated target) {
1001     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance3D, visibleFilter);
1002     }
1003     
1004 	// --------------
1005 	// =====================
1006 	// getDistanceSorted()
1007 	// =====================
1008 	// --------------
1009 
1010     private static class DistancesComparator implements Comparator<Tuple2<Object, Double>> {
1011 
1012 		@Override
1013 		public int compare(Tuple2<Object, Double> o1, Tuple2<Object, Double> o2) {
1014 			double result = o1.getSecond() - o2.getSecond();
1015 			if (result < 0) return -1;
1016 			if (result > 0) return 1;
1017 			return 0;
1018 		}
1019     	
1020     }
1021     
1022     private static final DistancesComparator distancesComparator = new DistancesComparator();
1023 
1024     /**
1025      * Returns "locations" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1026      * <p><p>
1027      * Distance is provided by {@link IGetDistance#getDistance(Object, Location)}.
1028      * <p><p>
1029      * WARNING: 2*O(n) + O(n*log n) complexity!
1030      * 
1031      * @param <T>
1032      * @param locations
1033      * @param target
1034      * @param getDistance
1035      * @return
1036      */
1037     public static <T> List<T> getDistanceSorted(Collection<T> locations, ILocated target, IGetDistance getDistance) {
1038     	if (locations == null) return null;
1039     	if (target == null) return null;
1040     	if (target.getLocation() == null) return null;
1041     	if (getDistance == null) return null;
1042     	
1043     	List<Tuple2<T, Double>> distances = new ArrayList<Tuple2<T, Double>>(locations.size());
1044     	
1045     	for (T location : locations) {
1046     		double distance = getDistance.getDistance(location, target);
1047     		distances.add(new Tuple2<T, Double>(location, distance));
1048     	}
1049     	
1050     	Collections.sort((List)distances, (Comparator)distancesComparator);
1051     	
1052     	List<T> result = new ArrayList<T>(distances.size());
1053     	
1054     	for (Tuple2<T, Double> location : distances) {
1055     		result.add(location.getFirst());
1056     	}
1057     	
1058     	return result;
1059     }
1060     
1061     /**
1062      * Returns "locations" accepted by all "filters" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1063      * <p><p>
1064      * Distance is provided by {@link IGetDistance#getDistance(Object, Location)}.
1065      * <p><p>
1066      * WARNING: 2*O(n) + O(n*log n) complexity!
1067      * 
1068      * @param <T>
1069      * @param locations
1070      * @param target
1071      * @param getDistance
1072      * @return
1073      */
1074     public static <T> List<T> getDistanceSorted(Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
1075     	if (filters == null || filters.length == 0 || (filters.length == 1 && filters[0] instanceof AcceptAllDistanceFilter)) {
1076     		return getDistanceSorted(locations, target, getDistance);
1077     	}
1078     	if (locations == null) return null;
1079     	if (target == null) return null;
1080     	if (getDistance == null) return null;
1081     	Location targetLoc = target.getLocation();
1082     	if (targetLoc == null) return null;
1083     	
1084     	List<Tuple2<T, Double>> distances = new ArrayList<Tuple2<T, Double>>(locations.size());
1085     	
1086     	for (T location : locations) {
1087     		boolean accepted = true;
1088     		double distance = getDistance.getDistance(location, targetLoc);
1089     		for (IDistanceFilter filter : filters) {
1090     			if (!filter.isAccepted(location, targetLoc, distance)) {
1091     				accepted = false;
1092     				break;
1093     			}
1094     		}
1095     		if (!accepted) continue;
1096     		
1097     		distances.add(new Tuple2<T, Double>(location, distance));
1098     	}
1099     	
1100     	Collections.sort((List)distances, (Comparator)distancesComparator);
1101     	
1102     	List<T> result = new ArrayList<T>(distances.size());
1103     	
1104     	for (Tuple2<T, Double> location : distances) {
1105     		result.add(location.getFirst());
1106     	}
1107     	
1108     	return result;
1109     }
1110     
1111     /**
1112      * Returns "locations" accepted by all "filters" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1113      * <p><p>
1114      * WARNING: 2*O(n) + O(n*log n) complexity!
1115      * 
1116      * @param <T>
1117      * @param locations
1118      * @param target
1119      * @param filters
1120      * @return nearest object from collection of objects
1121      */
1122     public static <T extends ILocated> List<T> getDistanceSorted(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1123     	return getDistanceSorted(locations, target, getLocatedDistance3D, filters);
1124     }
1125 	
1126     /**
1127      * Returns "locations" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1128      * <p><p>
1129      * WARNING: 2*O(n) + O(n*log n) complexity!
1130      * 
1131      * @param <T>
1132      * @param locations
1133      * @param target
1134      * @return nearest object from collection of objects
1135      */
1136     public static <T extends ILocated> List<T> getDistanceSorted(Collection<T> locations, ILocated target) {
1137     	return getDistanceSorted(locations, target, getLocatedDistance3D);
1138     }
1139     
1140     /**
1141      * Returns "locations" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1142      * <p><p>
1143      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1144      * <p><p>
1145      * WARNING: 2*O(n) + O(n*log n) complexity!
1146      * 
1147      * 
1148      * @param <T>
1149      * @param locations
1150      * @param target
1151      * @param maxDistance
1152      * @return nearest object from collection of objects that is not further than 'maxDistance'.
1153      */
1154     public static <T extends ILocated> List<T> getDistanceSorted(Collection<T> locations, ILocated target, double maxDistance) {
1155     	return getDistanceSorted(locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1156     }
1157     
1158     /**
1159      * Returns "locations" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1160      * <p><p>
1161      * WARNING: 2*O(n) + O(n*log n) complexity!
1162      * 
1163      * @param <T>
1164      * @param locations
1165      * @param target
1166      * @param filter if null behave as if ALL locations are accepted
1167      * @return nearest object from collection of objects
1168      */
1169     public static <T extends ILocated> List<T> getDistanceSortedFiltered(Collection<T> locations, ILocated target, IFilter filter) {
1170     	if (filter == null) {
1171     		return getDistanceSorted(locations, target);
1172     	}
1173     	return getDistanceSorted(locations, target, new FilterAdapter<T>(filter));
1174     }
1175     
1176     /**
1177      * Returns visible "locations" sorted according to the distance to "target". Sorted from the nearest to the farthest.
1178      * <p><p>
1179      * WARNING: 2*O(n) + O(n*log n) complexity!
1180      * 
1181      * @param <T>
1182      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1183      * @param target
1184      * @return nearest visible object from collection of objects
1185      */
1186     public static <T extends IViewable> List<T> getDistanceSortedVisible(Collection<T> locations, ILocated target) {
1187     	return (List<T>) getDistanceSorted(locations, target, (IGetDistance)getLocatedDistance3D, (IDistanceFilter)visibleFilter);
1188     }
1189     
1190     // --------------
1191 	// =====================
1192 	// getSecondNearest()
1193 	// =====================
1194 	// --------------
1195     
1196     /**
1197      * Returns the second nearest object to 'target'.
1198      * <p><p>
1199      * Distance is provided by {@link IGetDistance#getDistance(Object, ILocated)}.
1200      * <p><p>
1201      * WARNING: O(n) complexity!
1202      * <p><p>
1203      * DEPRECATED: use {@link #getNthNearest(int, Collection, ILocated, IGetDistance)} instead!
1204      * 
1205      * @param <T>
1206      * @param locations
1207      * @param target
1208      * @return nearest object from collection of objects
1209      */
1210     @Deprecated
1211     public static <T> T getSecondNearest(Collection<T> locations, ILocated target, IGetDistance getDistance) {
1212     	return getNthNearest(2, locations, target, getDistance);
1213     }
1214     
1215     /**
1216      * Returns the second nearest object to 'target'.
1217      * <p><p>
1218      * WARNING: O(n) complexity!
1219      * <p><p>
1220      * DEPRECATED: use {@link #getNthNearest(int, Collection, ILocated, IGetDistance, IDistanceFilter...)} instead
1221      * 
1222      * @param <T>
1223      * @param locations
1224      * @param target
1225      * @return nearest object from collection of objects
1226      */
1227     @Deprecated
1228     public static <T> T getSecondNearest(Collection<T> locations, ILocated target, IGetDistance getDistance, IDistanceFilter... filters) {
1229     	return getNthNearest(2, locations, target, getDistance, filters);
1230     }
1231     
1232     /**
1233      * Returns the second nearest object to 'target' that is accepted by all 'filters'.
1234      * <p><p>
1235      * WARNING: O(n) complexity!
1236      * <p><p>
1237      * DEPRECATED: use {@link #getNthNearest(int, Collection, ILocated, IDistanceFilter...))} instead
1238      * 
1239      * @param <T>
1240      * @param locations
1241      * @param target
1242      * @param filters
1243      * @return nearest object from collection of objects
1244      */
1245     @Deprecated
1246     public static <T extends ILocated> T getSecondNearest(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1247     	return getNthNearest(2, locations, target, filters);
1248     }
1249 	
1250     /**
1251      * Returns the second nearest object to 'target'.
1252      * <p><p>
1253      * WARNING: O(n) complexity!
1254      * <p><p>
1255      * DEPRECATED: use {@link #getNthNearest(int, Collection, ILocated)} instead
1256      * 
1257      * @param <T>
1258      * @param locations
1259      * @param target
1260      * @return second nearest object from collection of objects
1261      */
1262     @Deprecated
1263     public static <T extends ILocated> T getSecondNearest(Collection<T> locations, ILocated target) {
1264     	return getNthNearest(2, locations, target);
1265     }
1266     
1267     /**
1268      * Returns the second nearest object to 'target' that is not further than 'maxDistance'.
1269      * <p><p>
1270      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1271      * <p><p>
1272      * WARNING: O(n) complexity!
1273      * <p><p>
1274      * DEPRECATED: use {@link #getNthNearest(int, Collection, ILocated, double)} instead
1275      * 
1276      * @param <T>
1277      * @param locations
1278      * @param target
1279      * @param maxDistance
1280      * @return second nearest object from collection of objects that is not further than 'maxDistance'.
1281      */
1282     @Deprecated
1283     public static <T extends ILocated> T getSecondNearest(Collection<T> locations, ILocated target, double maxDistance) {
1284     	return getNthNearest(2, locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1285     }
1286     
1287     /**
1288      * Returns the second nearest object to 'target' that is accepted by filter.
1289      * <p><p>
1290      * WARNING: O(n) complexity!
1291      * <p><p>
1292      * DEPRECATED: use {@link #getNthNearestFiltered(int, Collection, ILocated, IFilter)} instead
1293      * 
1294      * @param <T>
1295      * @param locations
1296      * @param target
1297      * @param filter if null behave as if ALL locations are accepted
1298      * @return second nearest object from collection of objects
1299      */
1300     @Deprecated
1301     public static <T extends ILocated> T getSecondNearestFiltered(Collection<T> locations, ILocated target, IFilter filter) {
1302     	return getNthNearestFiltered(2, locations, target, filter);
1303     }
1304     
1305     /**
1306      * Returns the second nearest object to 'target' that is visible (using {@link VisibleFilter}).
1307      * <p><p>
1308      * WARNING: O(n) complexity!
1309      * <p><p>
1310      * DEPRECATED: use {@link #getNthNearestVisible(int, Collection, ILocated)
1311      * 
1312      * @param <T>
1313      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1314      * @param target
1315      * @return second nearest visible object from collection of objects
1316      */
1317     @Deprecated
1318     public static <T extends IViewable> T getSecondNearestVisible(Collection<T> locations, ILocated target) {
1319     	return getNthNearestVisible(2, locations, target);
1320     }
1321     
1322     // --------------
1323 	// =====================
1324 	// getNearest2D()
1325 	// =====================
1326 	// --------------
1327     
1328     /**
1329      * Returns the nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by all 'filters'.
1330      * <p><p>
1331      * WARNING: O(n) complexity!
1332      * 
1333      * @param <T>
1334      * @param locations
1335      * @param target
1336      * @param filters
1337      * @return nearest (in 2D ~ [x,y]) object from 'locations'
1338      */
1339     public static <T extends ILocated> T getNearest2D(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1340     	return getNearest(locations, target, getLocatedDistance2D, filters);
1341     }
1342     
1343     /**
1344      * Returns the nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by all 'filters'.
1345      * <p><p>
1346      * WARNING: O(n) complexity!
1347      * 
1348      * @param <T>
1349      * @param nthNearest if &lt;= 0, returns the nearest
1350      * @param locations
1351      * @param target
1352      * @param filters
1353      * @return nearest (in 2D ~ [x,y]) object from 'locations'
1354      */
1355     public static <T extends ILocated> T getNthNearest2D(int nthNearest, Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1356     	return getNthNearest(nthNearest, locations, target, getLocatedDistance2D, filters);
1357     }
1358     
1359     /**
1360      * Returns the farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by all 'filters'.
1361      * <p><p>
1362      * WARNING: O(n) complexity!
1363      * 
1364      * @param <T>
1365      * @param locations
1366      * @param target
1367      * @param filters
1368      * @return farthest (in 2D ~ [x,y]) object from 'locations'
1369      */
1370     public static <T extends ILocated> T getFarthest2D(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1371     	return getFarthest(locations, target, getLocatedDistance2D, filters);
1372     }
1373     
1374     /**
1375      * Returns the nth-farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by all 'filters'.
1376      * <p><p>
1377      * WARNING: O(n) complexity!
1378      * 
1379      * @param <T>
1380      * @param nthFarthest if &lt;= 0, returns the farthest
1381      * @param locations
1382      * @param target
1383      * @param filters
1384      * @return nth-farthest (in 2D ~ [x,y]) object from 'locations'
1385      */
1386     public static <T extends ILocated> T getNthFarthest2D(int nthFarthest, Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1387     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance2D, filters);
1388     }
1389 	
1390     /**
1391      * Returns the nearest (in 2D ~ [x,y]) object from 'locations' to 'target'.
1392      * <p><p>
1393      * WARNING: O(n) complexity!
1394      * 
1395      * @param <T>
1396      * @param locations
1397      * @param target
1398      * @return nearest (in 2D ~ [x,y]) object from 'locations'
1399      */
1400     public static <T extends ILocated> T getNearest2D(Collection<T> locations, ILocated target) {
1401     	return getNearest(locations, target, getLocatedDistance2D);
1402     }
1403     
1404     /**
1405      * Returns the nth-nearest (in 2D ~ [x,y]) object from 'locations' to 'target'.
1406      * <p><p>
1407      * WARNING: O(n) complexity!
1408      * 
1409      * @param <T>
1410      * @param nthNearest if &lt;= 0, returns the nearest
1411      * @param locations
1412      * @param target
1413      * @return nth-nearest (in 2D ~ [x,y]) object from 'locations'
1414      */
1415     public static <T extends ILocated> T getNthNearest2D(int nthNearest, Collection<T> locations, ILocated target) {
1416     	return getNthNearest(nthNearest, locations, target, getLocatedDistance2D);
1417     }
1418     
1419     /**
1420      * Returns the farthest (in 2D ~ [x,y]) object from 'locations' to 'target'.
1421      * <p><p>
1422      * WARNING: O(n) complexity!
1423      * 
1424      * @param <T>
1425      * @param locations
1426      * @param target
1427      * @return farthest (in 2D ~ [x,y]) object from 'locations'
1428      */
1429     public static <T extends ILocated> T getFarthest2D(Collection<T> locations, ILocated target) {
1430     	return getFarthest(locations, target, getLocatedDistance2D);
1431     }
1432     
1433     /**
1434      * Returns the nth-farthest object from 'locations' to 'target'.
1435      * <p><p>
1436      * WARNING: O(n) complexity!
1437      * 
1438      * @param <T>
1439      * @param nthFarthest if &lt;= 0, returns the farthest
1440      * @param locations
1441      * @param target
1442      * @return nth-farthest (in 2D ~ [x,y]) object from 'locations'
1443      */
1444     public static <T extends ILocated> T getNthFarthest2D(int nthFarthest, Collection<T> locations, ILocated target) {
1445     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance2D);
1446     }
1447     
1448     /**
1449      * Returns the nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is not further than 'maxDistance'.
1450      * <p><p>
1451      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1452      * <p><p>
1453      * WARNING: O(n) complexity!
1454      * 
1455      * @param <T>
1456      * @param locations
1457      * @param target
1458      * @param maxDistance
1459      * @return nearest (in 2D ~ [x,y]) object from 'locations' that is not further than 'maxDistance'
1460      */
1461     public static <T extends ILocated> T getNearest2D(Collection<T> locations, ILocated target, double maxDistance) {
1462     	return getNearest2D(locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1463     }
1464     
1465     /**
1466      * Returns the nth-nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is not further than 'maxDistance'.
1467      * <p><p>
1468      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1469      * <p><p>
1470      * WARNING: O(n) complexity!
1471      * 
1472      * @param <T>
1473      * @param nthNearest if &lt;= 0, returns the nearest
1474      * @param locations
1475      * @param target
1476      * @param maxDistance
1477      * @return nth-nearest (in 2D ~ [x,y]) object from 'locations' that is not further than 'maxDistance'
1478      */
1479     public static <T extends ILocated> T getNthNearest2D(int nthNearest, Collection<T> locations, ILocated target, double maxDistance) {
1480     	return getNthNearest2D(nthNearest, locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1481     }
1482     
1483     /**
1484      * Returns the farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is not further than 'maxDistance'.
1485      * <p><p>
1486      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1487      * <p><p>
1488      * WARNING: O(n) complexity!
1489      * 
1490      * @param <T>
1491      * @param locations
1492      * @param target
1493      * @param maxDistance
1494      * @return farthest (in 2D ~ [x,y]) object from 'locations' that is not further than 'maxDistance'
1495      */
1496     public static <T extends ILocated> T getFarthest2D(Collection<T> locations, ILocated target, double maxDistance) {
1497     	return getFarthest2D(locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1498     }
1499     
1500     /**
1501      * Returns the nth-farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is not further than 'maxDistance'.
1502      * <p><p>
1503      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1504      * <p><p>
1505      * WARNING: O(n) complexity!
1506      * 
1507      * @param <T>
1508      * @param nthFarthest if &lt;= 0, returns the farthest
1509      * @param locations
1510      * @param target
1511      * @param maxDistance
1512      * @return nth-farthest (in 2D ~ [x,y]) object from 'locations' that is not further than 'maxDistance'
1513      */
1514     public static <T extends ILocated> T getNthFarthest2D(int nthFarthest, Collection<T> locations, ILocated target, double maxDistance) {
1515     	return getNthFarthest2D(nthFarthest, locations, target, new RangeDistanceFilter<T>(0, maxDistance));
1516     }
1517     
1518     /**
1519      * Returns the nearest (in 2D ~ [x,y]) object from 'location' to 'target' that is accepted by 'filter'.
1520      * <p><p>
1521      * WARNING: O(n) complexity!
1522      * 
1523      * @param <T>
1524      * @param locations
1525      * @param target
1526      * @param filter if null behave as if ALL locations are accepted
1527      * @return nearest (in 2D ~ [x,y]) object from 'locations' accepted by 'filter'
1528      */
1529     public static <T extends ILocated> T getNearestFiltered2D(Collection<T> locations, ILocated target, IFilter filter) {
1530     	if (filter == null) {
1531     		return getNearest2D(locations, target);
1532     	}
1533     	return getNearest2D(locations, target, new FilterAdapter<T>(filter));
1534     }
1535     
1536     /**
1537      * Returns the nth-nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by 'filter'.
1538      * <p><p>
1539      * WARNING: O(n) complexity!
1540      * 
1541      * @param <T>
1542      * @param nthNearest if &lt;= 0, returns the nearest
1543      * @param locations
1544      * @param target
1545      * @param filter if null behave as if ALL locations are accepted
1546      * @return nth-nearest (in 2D ~ [x,y]) object from 'locations' accepted by 'filter'
1547      */
1548     public static <T extends ILocated> T getNthNearestFiltered2D(int nthNearest, Collection<T> locations, ILocated target, IFilter filter) {
1549     	if (filter == null) {
1550     		return getNthNearest2D(nthNearest, locations, target);
1551     	}
1552     	return getNthNearest2D(nthNearest, locations, target, new FilterAdapter<T>(filter));
1553     }
1554     
1555     /**
1556      * Returns the farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by 'filter'.
1557      * <p><p>
1558      * WARNING: O(n) complexity!
1559      * 
1560      * @param <T>
1561      * @param locations
1562      * @param target
1563      * @param filter if null behave as if ALL locations are accepted
1564      * @return farthest (in 2D ~ [x,y]) object from 'locations' accepted by 'filter'
1565      */
1566     public static <T extends ILocated> T getFarthestFiltered2D(Collection<T> locations, ILocated target, IFilter filter) {
1567     	if (filter == null) {
1568     		return getFarthest2D(locations, target);
1569     	}
1570     	return getFarthest2D(locations, target, new FilterAdapter<T>(filter));
1571     }
1572     
1573     /**
1574      * Returns the nth-farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is accepted by 'filter'.
1575      * <p><p>
1576      * WARNING: O(n) complexity!
1577      * 
1578      * @param <T>
1579      * @param nthFarthest if &lt;= 0, returns the farthest
1580      * @param locations
1581      * @param target
1582      * @param filter if null behave as if ALL locations are accepted
1583      * @return nth-farthest (in 2D ~ [x,y]) object from 'locations' accepted by 'filter'
1584      */
1585     public static <T extends ILocated> T getNthFarthestFiltered2D(int nthFarthest, Collection<T> locations, ILocated target, IFilter filter) {
1586     	if (filter == null) {
1587     		return getNthFarthest2D(nthFarthest, locations, target);
1588     	}
1589     	return getNthFarthest2D(nthFarthest, locations, target, new FilterAdapter<T>(filter));
1590     }
1591     
1592     /**
1593      * Returns the nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
1594      * <p><p>
1595      * WARNING: O(n) complexity!
1596      * 
1597      * @param <T>
1598      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1599      * @param target
1600      * @return nearest (in 2D ~ [x,y]) visible object from 'locations'
1601      */
1602     public static <T extends IViewable> T getNearestVisible2D(Collection<T> locations, ILocated target) {
1603     	return getNearest(locations, target, getLocatedDistance2D, visibleFilter);
1604     }
1605     
1606     /**
1607      * Returns the nth-nearest (in 2D ~ [x,y]) object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
1608      * <p><p>
1609      * WARNING: O(n) complexity!
1610      * 
1611      * @param <T>
1612      * @param ntNearest if &lt;= 0, returns the nearest
1613      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1614      * @param target
1615      * @return nth-nearest (in 2D ~ [x,y]) visible object from 'locations'
1616      */
1617     public static <T extends IViewable> T getNthNearestVisible2D(int nthNearest, Collection<T> locations, ILocated target) {
1618     	return getNthNearest(nthNearest, locations, target, getLocatedDistance2D, visibleFilter);
1619     }
1620     
1621     /**
1622      * Returns the farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
1623      * <p><p>
1624      * WARNING: O(n) complexity!
1625      * 
1626      * @param <T>
1627      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1628      * @param target
1629      * @return farthest (in 2D ~ [x,y]) visible object from 'locations'
1630      */
1631     public static <T extends IViewable> T getFarthestVisible2D(Collection<T> locations, ILocated target) {
1632     	return getFarthest(locations, target, getLocatedDistance2D, visibleFilter);
1633     }
1634     
1635     /**
1636      * Returns the nth-farthest (in 2D ~ [x,y]) object from 'locations' to 'target' that is visible (using {@link VisibleFilter}).
1637      * <p><p>
1638      * WARNING: O(n) complexity!
1639      * 
1640      * @param <T>
1641      * @param ntFarthest if &lt;= 0, returns the farthest
1642      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1643      * @param target
1644      * @return nth-farthest (in 2D ~ [x,y]) visible object from 'locations'
1645      */
1646     public static <T extends IViewable> T getNthFarthestVisible2D(int nthFarthest, Collection<T> locations, ILocated target) {
1647     	return getNthFarthest(nthFarthest, locations, target, getLocatedDistance2D, visibleFilter);
1648     }
1649     
1650     // --------------
1651 	// =====================
1652 	// getSecondNearest2D()
1653 	// =====================
1654 	// --------------
1655 
1656     /**
1657      * Returns the second nearest (in 2D ~ [x,y]) object to 'target' that is accepted by all 'filters'.
1658      * <p><p>
1659      * WARNING: O(n) complexity!
1660      * <p><p>
1661      * DEPRECATED: use {@link #getNthNearest2D(int, Collection, ILocated, filters)} instead
1662      * 
1663      * @param <T>
1664      * @param locations
1665      * @param target
1666      * @param filters
1667      * @return second nearest (in 2D ~ [x,y]) object from collection of objects
1668      */
1669     @Deprecated
1670     public static <T extends ILocated> T getSecondNearest2D(Collection<T> locations, ILocated target, IDistanceFilter... filters) {
1671     	return getNthNearest2D(2, locations, target, filters);
1672     }
1673 	
1674     /**
1675      * Returns the second nearest (in 2D ~ [x,y]) object to 'target'.
1676      * <p><p>
1677      * WARNING: O(n) complexity!
1678      * <p><p>
1679      * DEPRECATAED: use {@link #getNthNearest2D(int, Collection, ILocated)} instead
1680      * 
1681      * @param <T>
1682      * @param locations
1683      * @param target
1684      * @return second nearest (in 2D ~ [x,y]) object from collection of objects
1685      */
1686     @Deprecated
1687     public static <T extends ILocated> T getSecondNearest2D(Collection<T> locations, ILocated target) {
1688     	return getNthNearest2D(2, locations, target);
1689     }
1690     
1691     /**
1692      * Returns the second nearest (in 2D ~ [x,y]) object to 'target' that is not further than 'maxDistance'.
1693      * <p><p>
1694      * Using {@link RangeDistanceFilter} (minDistance = 0, maxDistance is provided).
1695      * <p><p>
1696      * WARNING: O(n) complexity!
1697      * <p><p>
1698      * DEPRECATED: use {@link #getNthNearest2D(int, Collection, ILocated, double)} instead
1699      * 
1700      * @param <T>
1701      * @param locations
1702      * @param target
1703      * @param maxDistance
1704      * @return second nearest (in 2D ~ [x,y]) object from collection of objects that is not further than 'maxDistance'.
1705      */
1706     @Deprecated
1707     public static <T extends ILocated> T getSecondNearest2D(Collection<T> locations, ILocated target, double maxDistance) {
1708     	return getNthNearest2D(2, locations, target, maxDistance);
1709     }
1710     
1711     /**
1712      * Returns the second nearest (in 2D ~ [x,y]) object to 'target' that is accepted by filter.
1713      * <p><p>
1714      * WARNING: O(n) complexity!
1715      * <p><p>
1716      * DEPRECATED: use {@link #getNthNearestFiltered2D(int, Collection, ILocated, IFilter)} instead
1717      * 
1718      * @param <T>
1719      * @param locations
1720      * @param target
1721      * @param filter if null behave as if ALL locations are accepted
1722      * @return second nearest (in 2D ~ [x,y]) object from collection of objects
1723      */
1724     @Deprecated
1725     public static <T extends ILocated> T getSecondNearest2DFiltered(Collection<T> locations, ILocated target, IFilter<T> filter) {
1726     	if (filter == null) {
1727     		return getNthNearest2D(2, locations, target);
1728     	}
1729     	return getNthNearest2D(2, locations, target, new FilterAdapter<T>(filter));
1730     }
1731     
1732     /**
1733      * Returns the second nearest (in 2D ~ [x,y]) object to 'target' that is visible (using {@link VisibleFilter}).
1734      * <p><p>
1735      * WARNING: O(n) complexity!
1736      * <p><p>
1737      * DEPRECATED: use {@link #getNthNearestVisible2D(int, Collection, ILocated)} instead
1738      * 
1739      * @param <T>
1740      * @param locations must be objects implementing {@link IViewable} as well as {@link ILocated} (so {@link Item} or {@link Player} is usable)
1741      * @param target
1742      * @return second nearest (in 2D ~ [x,y]) visible object from collection of objects
1743      */
1744     @Deprecated
1745     public static <T extends IViewable> T getSecondNearest2DVisible(Collection<T> locations, ILocated target) {
1746     	return getNthNearestVisible2D(2, locations, target);
1747     }
1748 
1749 }