我正在努力寻找最佳性能的解决方案。
我需要在多段线(列表点)上找到给定点的壁橱点。
我的线有数千点,我需要每秒检查几次到这条线的距离。所以解决方案需要非常快。
现在我有类似下面的内容。它可以工作,但当线路有10000+点时它会很慢。
也许有人知道如何让它更快?
public static float GetSqrDistXZ(Vector3 a, Vector3 b)
{
Vector3 vector = new Vector3(a.x - b.x, 0, a.z - b.z);
return vector.sqrMagnitude;
}
public static Vector3 NearestPointOnFiniteLine(Vector3 start, Vector3 end, Vector3 pnt)
{
Vector3 line = (end - start);
float len = Mathf.Sqrt(line.sqrMagnitude);
line.Normalize();
Vector3 v = pnt - start;
float d = (v.x * line.x) + (v.z * line.z);
d = Mathf.Clamp(d, 0f, len);
return start + line * d;
}
int pointsCount = line.points3.Count - 1; // line - List<Vector3> points.
float[] distances = new float[pointsCount];
for (int i = 0; i < pointsCount+1; i++) {
if (i >= 1) {
distances [i - 1] = GetSqrDistXZ (point, NearestPointOnFiniteLine (line.points3 [i - 1], line.points3 [i], point));
}
}
int minListIndexLeft = System.Array.IndexOf (distances, Mathf.Min (distances));
float minimalDistance = distances[minListIndexLeft];
Vector3 closestPoint = NearestPointOnFiniteLine (line.points3[minListIndexLeft], line.points3[minListIndexLeft+1], point);
答案 0 :(得分:2)
您想要考虑空间分区。在这个例子中,我将假设一个2D空间,但这也适用于3D。还有更好的解决方案,如BSP树和东西,但我们会在这里保持简单。
想象一下,在2D空间上放置网格。您线条的每个线段(2点之间的距离)与该网格的一个或多个单元格相交。您需要做的是为每个单元格存储相交的段。如果您的线路没有变化,您可以在启动时一次性完成,甚至将该信息静态存储在资产中。
但是一旦获得了这些信息,您所需要做的就是计算您的点所在的单元格,然后只检查与该特定单元格或多个直接邻居相交的线段(见下文)。这样可以比较快速地找到最近点闪电。
如果你在一张纸上玩这个想法,你可能会遇到这种解决方案没有产生最近点的情况,因为它没有考虑包含更近点的相邻单元格。解决这个问题的最简单方法是采用以下方法:
1. Find cell C, which is the cell your point is in
2. Let cellRange = 0
3. Let point B be undefined
4. Find closest point P among all segments that intersect cell C and its neighboring cells of range cellRange*
5. If B is the same as newly found point P then P is the solution. You are done.
6. Increase cellRange by 1
7. Let B = P
8. Repeat from step 4
* "neighboring cells of range cellRange" means:
cellRange 0: only cell C, no neighbours
cellRange 1: cell C and direct neighbours
cellRange 2: cell C, direct neighbours and their direct neighbours
...
此解决方案基本上检查增加搜索范围是否改进了解决方案。一旦增加范围没有改善解决方案,你就找到了最接近的点。