我正在尝试按距离给定点排序点列表。
应用程序是找到当前gps坐标的最近地标(gps坐标)。
所以如果你采用以下代码:
public static void main(String[] args) throws SQLException {
ArrayList<Point2D.Double> points = new ArrayList<Point2D.Double>();
Point2D.Double point1 = new Point2D.Double(1,1);
Point2D.Double point2 = new Point2D.Double(2,2);
Point2D.Double point3 = new Point2D.Double(3,3);
points.add(point1);
points.add(point2);
points.add(point3);
Point2D.Double myPoint = new Point2D.Double(4,4);
}
如果我使用比较器对点数组进行排序,我会得到一个很好的有序点列表但是如何找到哪一个更接近myPoint?什么是距离。
这肯定应该回答我的问题,但是对于奖励积分......如果给出最大距离,我怎么能限制积分的结果。例如:返回一个不超过100英里的有序坐标列表。
答案 0 :(得分:4)
首先,一些小事:
ArrayList
,而应仅作为List
(What does it mean to "program to an interface"?)Point2D.Double
,而只应声明为Point2D
关于实际问题:Point2D
类已经有(欧几里德和其他)距离计算的方法。但是,对于存储地理坐标的点,您可能必须自己实现距离函数。
通常,比较距离给定点的距离可以如下例所示:
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class PointsByDistanceTest
{
public static void main(String[] args)
{
List<Point2D> points = new ArrayList<Point2D>();
points.add(new Point2D.Double(1,1));
points.add(new Point2D.Double(2,2));
points.add(new Point2D.Double(3,3));
points.add(new Point2D.Double(4,4));
points.add(new Point2D.Double(5,5));
points.add(new Point2D.Double(6,6));
Point2D myPoint = new Point2D.Double(4,4);
Collections.sort(points, createComparator(myPoint));
double maxDistance = 2.0;
int index = 0;
for (Point2D p : points)
{
if (p.distanceSq(myPoint) > maxDistance * maxDistance)
{
break;
}
index++;
}
List<Point2D> result = points.subList(0, index);
System.out.println(
"The closest points with distance <="+maxDistance+" are "+result);
}
private static Comparator<Point2D> createComparator(Point2D p)
{
final Point2D finalP = new Point2D.Double(p.getX(), p.getY());
return new Comparator<Point2D>()
{
@Override
public int compare(Point2D p0, Point2D p1)
{
double ds0 = p0.distanceSq(finalP);
double ds1 = p1.distanceSq(finalP);
return Double.compare(ds0, ds1);
}
};
}
}
此示例还针对限制点数的问题:它将返回距离不大于maxDistance
的点。但是,您仍然排序 整个点数列表。如果你想避免对整个列表进行排序,那么这将变成一个&#34; K最近邻居&#34;问题(http://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm)你可以使用一些非常复杂的数据结构...
答案 1 :(得分:1)
答案 2 :(得分:1)
您是否考虑过使用此算法 - Planar divide and conquer?
* Sort points according to their x-coordinates.
* Split the set of points into two equal-sized subsets by a vertical line x=xmid.
* Solve the problem recursively in the left and right subsets. This yields the
left-side and right-side minimum distances dLmin and dRmin, respectively.
* Find the minimal distance dLRmin among the pair of points in which one
point lies on the left of the dividing vertical and the second point lies
to the right.
* The final answer is the minimum among dLmin, dRmin, and dLRmin.
您还提到使用GPS坐标,如果这些坐标存储为纬度/经度,也许您应该使用Haversine formula来计算距离。
答案 3 :(得分:0)
如果您有有序列表,则可以通过编写两个列表来查找最近的点,其中一个用于X坐标,一个用于Y坐标。然后检查列表中点的位置,索引最低的点是最近点。
只是一个建议。
答案 4 :(得分:0)
public class DistanceComparator implements Comparator<Point2D.Double>{
Point2D.Double refPoint;
public DistanceComparator(Double refPoint) {
super();
this.refPoint = refPoint;
}
@Override
public int compare(Double o1, Double o2) {
return (refPoint.distance(o1)<refPoint.distance(o2)?-1:1);
}
}
答案 5 :(得分:0)
这应该做的工作:
public static void main(final String[] args) {
ArrayList<Point2D.Double> points = new ArrayList<Point2D.Double>();
Point2D.Double point1 = new Point2D.Double(1, 1);
Point2D.Double point2 = new Point2D.Double(2, 2);
Point2D.Double point3 = new Point2D.Double(3, 3);
points.add(point1);
points.add(point2);
points.add(point3);
final Point2D.Double myPoint = new Point2D.Double(4, 4);
Collections.sort(points, new Comparator<Point2D.Double>() {
@Override
public int compare(final Double o1, final Double o2) {
double dist1 = Math.sqrt(Math.pow(o1.x - myPoint.x, 2) - Math.pow(o1.y - myPoint.y, 2));
double dist2 = Math.sqrt(Math.pow(o2.x - myPoint.x, 2) - Math.pow(o2.y - myPoint.y, 2 ));
return Double.compare(dist1,dist2);
}
});
}