3

我需要做一个相当具体的空间搜索。基本上,有一个具有两个位置的对象(我们称之为 obj1),我们称之为点 A 和点 B。

然后我有一组对象(让我们称每个对象为 obj2),每个对象都有自己的 A 和 B 位置。

我想从按以下方式排序的集合中返回前 10 个对象:

(obj1 A 到 obj2A 的距离) + (obj1B 到 obj2B 的距离)

有任何想法吗?谢谢,尼克

更新:这里有更多关于文件的细节以及我想如何比较它们。

领域模型:

列表:ListingId int Title string Price double 起始位置 目的地位置

位置:邮政/邮政编码字符串 纬度小数 经度小数

我想要做的是获取一个列表对象(不在数据库中)并将其与数据库中的列表集合进行比较。我希望查询返回前 12(或 x)个列表,这些列表按乌鸦与起点的距离加上乌鸦与目的地的距离排序。

我不关心从起点到目的地的距离——只关心起点到起点的距离加上目的地到终点的距离。

基本上我试图找到开始和结束位置接近的列表。

如果我能澄清更多,请告诉我。谢谢!

4

4 回答 4

0

从算法的角度来看,我会找到边界框的中心,然后在找到足够多的时候选择半径增加的候选者。

另外我只想提醒一下,全球的乌鸦飞行距离不是毕达哥拉斯距离,必须使用不同的公式:

public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
    double deltaLat = DegreesToRadians(lat2 - lat1);
    double deltaLong = DegreesToRadians(lng2 - lng1);

    double a = Math.Pow(Math.Sin(deltaLat / 2), 2) +
        Math.Cos(DegreesToRadians(lat1))
        * Math.Cos(DegreesToRadians(lat2))
        * Math.Pow(Math.Sin(deltaLong / 2), 2);

    return earthMeanRadiusMiles * (2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)));
}
于 2011-01-06T00:04:12.747 回答
0

我不认为您可以直接找到解决方案。

如果您使用边界球而不是边界框来指定对象,则效率会更高。 http://en.wikipedia.org/wiki/Bounding_sphere

     C = ( A + B)/2 and R = distance(A,B) /2

您不精确要比较多少数据。如果您想查看最近或最远的对象对。

对于这两种情况,我认为如果使用 3D,则必须将 C 坐标编码为八叉树中的路径;如果使用 2D,则必须将 C 坐标编码为四叉树。 http://en.wikipedia.org/wiki/Quadtree

这是初稿,如果还不够,我可以添加更多信息。如果您不熟悉 3D,则从 2D 开始更容易开始。

我展示了您的最新添加,看来您的问题与冲突检测算法非常相似。

我认为,如果您通过相对于“起点”的极坐标来更改“终点”的坐标系。如果您将径向坐标四舍五入到您的公差(x 英里),并按此值排序。

于 2010-12-31T13:19:57.067 回答
0

听起来你正在建立一个拼车网站。:)

底线是,为了按表面距离对查询结果进行排序,您需要在数据库引擎中内置空间索引。我认为您的选择是带有 OpenGIS 扩展的 MySQL(已经提到)或带有 PostGIS 的 PostgreSQL。看起来它在 ravenDB 中也是可能的:http ://ravendb.net/documentation/indexes/sptial

但如果这不是一个选择,还有其他一些方法。让我们简化问题并假设您只想按数据库记录到位置 A 的距离对数据库记录进行排序,因为您只是这样做了两次并对结果求和。

最简单的解决方案是从数据库中提取每条记录,并在代码中逐一计算到位置 A 的距离,然后排序。麻烦的是,您最终会进行大量冗余计算并为每个查询拉下整个表。

让我们再次简化并假设我们只关心Chebyshev(最大)距离。这将有助于在我们变得更准确之前缩小我们在数据库中的范围。我们可以对附近的记录进行“二分搜索”。我们必须确定要返回的最接近记录的大致数量;比方说10。然后我们在一个正方形区域内进行查询,比如说感兴趣位置周围的 1 度纬度乘 1 度经度(大约 60x60 英里)。假设我们感兴趣的位置是 lat,lng=43.5,86.5。然后我们的数据库查询是 SELECT COUNT(*) FROM locations WHERE (lat > 43 AND lat < 44) AND (lng > 86 AND lng < 87)。如果您在 lat/lng 字段上有索引,那应该是一个快速查询。

我们的目标是在框内获得略高于10 个的总结果。这就是“二分搜索”的用武之地。如果我们只得到 5 个结果,我们将框区域加倍并再次搜索。如果我们得到 100 个结果,我们将区域减半并再次搜索。如果我们在那之后立即得到 3 个结果,我们将框面积增加 50%(而不是 100%)并重试,直到我们足够接近我们的 10 个结果目标。

最后,我们采用这组可管理的记录并计算它们与感兴趣位置的欧几里德距离,并在代码中进行排序。

祝你好运!

于 2011-01-06T05:57:38.947 回答
0

以下是解决此类问题的方法

mysql 4.1 &

mysql 5 .

来自 mysql 4.1 的链接似乎很有帮助,尤其是。第一个例子,这几乎就是你要问的。

但如果这不是很有帮助,我想你必须循环并在 obj1 或 obj2 上对其对应表进行查询。

于 2011-01-05T03:56:32.737 回答