【发布时间】:2017-04-15 20:56:35
【问题描述】:
我有两组点(source 和 target)。目标是在target 中为每个source 点找到一个唯一的1:1 最近邻 点。
我的尝试按预期工作,但速度慢得离谱。我已经测试了几千点,但在实际场景中点数将是数百万。我不是 STL 方面的专家。有什么建议可以优化吗?
std::vector<UT_Vector3> targetPosVector;
for (auto i = 0; i < targetNumPoints; i++)
{
auto pos = target->getPos3(i);
targetPosVector.push_back(pos);
}
std::vector<int> uniqueNeighborVector;
for (auto ptoff = 0; ptoff < sourceNumPoints; ptoff++)
{
std::vector<std::pair<int, fpreal>> nearpointVector; // neighbor vector in form of "(idx, dist)"
auto pos = source->getPos3(ptoff);
for (auto j = 0; j < targetNumPoints; j++)
{
fpreal dist = pos.distance(targetPosVector[j]);
std::pair<int, fpreal> neighbor {j, dist};
nearpointVector.push_back(neighbor);
}
std::sort(nearpointVector.begin(), nearpointVector.end(), [](const std::pair<int, fpreal> &left,
const std::pair<int, fpreal> &right)
{ return left.second < right.second; });
std::vector<int> neighborVector;
for (auto i : nearpointVector)
{
neighborVector.push_back(i.first);
}
// trying to imitate Python's next() function
// uniqueNeighborList[]
// uneighbor = next(i for i in neighborVector if i not in uniqueNeighborVector)
// uniqueNeighborVector = set(uniqueNeighborList.append(uneighbor))
for (auto i : neighborVector)
{
if (std::find(uniqueNeighborVector.begin(), uniqueNeighborVector.end(), i) == uniqueNeighborVector.end())
{
int uneighbor = i; // later on binds to the geometry attribute
uniqueNeighborVector.push_back(i);
break;
}
}
}
在哪里:
-
source和target是Detail Geometry数据 -
distance是一个计算两个向量之间距离的函数 -
getPos3是获取3-float vector点位置的函数 -
fpreal又名64-bit float -
UT_Vector3是3-float vector -
sourceNumPoints和targetNumPoints是点数source和target几何。
【问题讨论】:
-
标准库确实没有针对这个任务进行优化。看看专门的库,比如PCL。
-
这里的问题与其说是 STL,不如说是所选择的算法。您正在生成二次距离对,因此这种方法不会扩展到数百万个点。您将需要使用某种形式的空间细分来快速拒绝不可能的配对,而不是盲目地尝试所有组合。
-
即便如此,即使是目前的蛮力实现也显得不必要地令人费解。我收集到一个目标点可能只匹配一次,低阶源获得第一个 dib。如果是这样,那么与其生成和排序一个临时向量,然后线性扫描整个目标集,我建议删除使用过的目标(通过交换回)并在没有中间缓冲和排序的情况下在线选择最佳匹配。诚然,它不会让您进入数百万美元,但它可能是一个开始。
-
目标点随机分布。让我们假设第一个点的最近邻居是 1203,而第二个点可能是 719123 之类的任何东西或具有巨大跳跃的东西。
-
@Pradeep Barua:太好了,(均匀的)随机分布应该让事情相对容易处理。例如,您可以尝试将目标点划分为 3D 网格结构。然后在搜索过程中直接索引最近的网格条目并逐渐向外扫描,返回并删除找到的第一个点。随着网格大小调整到密度,我相信这应该大致是线性的。
标签: c++ algorithm stl computational-geometry point-clouds