我有一个表示道路网络的图形数据结构(节点是道路中的点/交叉点,边缘是道路)。 Node对象具有与之关联的纬度和经度。
我正在使用Accord的KDTree类来查找给定GPS坐标的附近节点。由于Accord似乎没有将Haversine距离作为内置距离函数(我错了吗?),我定义了自己的自定义距离函数,并将其作为额外参数传递给KDTree.FromData()方法,如下:
var nodes = graph.Nodes;
//Initialize KD-tree with distance function defined as the cartesian approximate distance (in meters)
Func<double[], double[], double> distanceFunc = (x, y) => DistanceFunctions.ApproximateDistance(x,y);
kdTreeOfNodes = KDTree.FromData<Node>(nodes.Select(x => new double[] { x.Value.Latitude, x.Value.Longitude }).ToArray(), nodes.ToArray(), distanceFunc);
请注意,'ApproximateDistance'在单独的类中被定义为静态方法,并且是更正确的Haversine距离的笛卡尔近似值。
我在尝试排除最后一行时遇到异常。在这一行中,我传入数据以放入KDTree(即lat / lon数组的数组)以及相关节点,再加上我的自定义距离函数。看起来这个FromData构造函数实际上(出于某种原因?)调用我的ApproximateDistance函数,数组[1]和[1]作为两个输入参数,显然引发了一个异常,因为这个方法需要两个二维数组。
我不知道为什么这个构造函数正在调用我的ApproximateDistance函数(尤其是这些奇怪的参数),并且似乎无法找到使用调试器......
答案 0 :(得分:2)
K-d-tree在搜索过程中不会使用点对点距离,直到达到实际数据点为止。
相反,它是与分裂平面的一维偏差。这里它是 纬度或经度。
这就是为什么k-d-tree除了Minkowski规范之外几乎不支持的原因。
答案 1 :(得分:1)
除非您在树中执行查找(即通过调用任何.Nearest或ApproximateNearest函数),否则Accord.NET中的K-d树不应该调用您的距离函数。正如Anony-Mousse所说,K-d树在到达实际数据点之前不会使用点对点距离,即在进行搜索时。
Inspecting the current code,在构造树之前,我无法看到代码是如何调用ApproximateDistance的,因为您可能会看到仅在该方法的最后设置。
如果您仍然遇到此问题,请在问题跟踪器中注册,并提供一个触发问题的小示例,以便最终修复。
此外,如果您需要依赖点对点距离的其他树种,您可能还需要查看最近添加的Vantage-Point Trees。
免责声明:我是Accord.NET中k-d树实现的作者。