我正在修补地理空间数据,特别是轨道(由纬度和经度定义的有序地理位置序列)。
大多数应用程序要求我计算从开始到给定点的累积距离。所以,如果我打电话给track.totalDistance[20]
,我会得到从开始到索引为20的点的距离。
目前我通过预先计算每个连续距离,增加变量,并将值分配给每个点来解决这个问题,这不是一个好的行为,因为我打算编辑轨道(添加,删除和更新点),并且“总距离”实际上并不是轨迹点的固有属性,而是在其包含轨迹的上下文中的轨迹点。
另一方面,如果我推迟对getter函数的评估,比如getTotalDistance(track, 20)
,那么会有很多重复且实际上不必要的计算。
所以问题是:我怎么能以一种方式实现一个类,我可以随时更有效地获得任意索引的累积和,同时避免不必要的计算(完全初始化或重复)?
我使用的语言主要是Python,Javascript和C#,但我想答案可能是可以用任何语言实现的一般结构。
答案 0 :(得分:0)
您可以使用自平衡树,其节点如下:
public class Node
{
public Node(Node leftChild, Node rightChild)
{
FirstPoint = leftChild.FirstPoint;
LastPoint = rightChild.LastPoint;
LeafCount = leftChild.LeafCount + rightChild.LeafCount;
BetweenDistance = leftChild.LastPoint.DistanceTo(rightChild.FirstPoint);
TotalDistanceSum = leftChild.TotalDistanceSum
+ BetweenDistance
+ rightChild.TotalDistanceSum;
IsLeaf = false;
LeftChild = leftChild;
RightChild = rightChild;
}
public Node(Point p)
{
FirstPoint = p;
LastPoint = p;
LeafCount = 1;
IsLeaf = true;
}
/// The point of the leftmost decendant.
public Point FirstPoint { get; set; }
/// The point of the rightmost decendant.
public Point LastPoint { get; set; }
/// Number of leaves.
public int LeafCount { get; set; }
/// The distance from FirstPoint to LastPoint along the path.
public double TotalDistanceSum { get; set; }
/// The distance between LeftChild and RightChild.
public double BetweenDistance { get; set; }
/// Flag wheter this is a node or a leaf.
public bool IsLeaf { get; set; }
/// Left child of this non-leaf node.
public Node LeftChild { get; set; }
/// Right child of this non-leaf node.
public Node RightChild { get; set; }
/// Calculates the distance between two point along the path. 'start' is inclusive. 'end' is exclusive.
public double DistanceSum(int start, int end)
{
if (IsLeaf || start >= LeafCount || end < 0 || start >= end)
return 0;
if (end > LeafCount) end = LeafCount;
if (start < 0) start = 0;
if (start == 0 && end == LeafCount)
return TotalDistanceSum;
int n = LeftChild.LeafCount;
return LeftChild.DistanceSum(start, end)
+ BetweenDistance
+ RightChild.DistanceSum(start - n, end - n);
}
}
public class Point
{
public double X { get; private set; }
public double Y { get; private set; }
public Point(double x, double y)
{
X = x;
Y = y;
}
public double DistanceTo(Point other)
{
double dx = other.X - X;
double dy = other.Y - Y;
return Math.Sqrt(dx*dx + dy*dy);
}
}
示例:强>
var tree = new Node(
new Node(
new Node(new Point(0,0)),
new Node(new Point(1,0))
),
new Node(
new Node(new Point(1,1)),
new Node(new Point(0,1))
)
);
double dist = tree.DistanceSum(0,4); // returns 3.0