对向量中的点进行排序以形成轮廓

Posted

技术标签:

【中文标题】对向量中的点进行排序以形成轮廓【英文标题】:Sort points in vector to form conture 【发布时间】:2016-05-19 11:37:19 【问题描述】:

我得到了一个带有 xy 点坐标的 n 行向量。这些点形成给定 CAD 模型的轮廓。现在我想恢复模型的轮廓。所以我尝试用 atan2 函数对这个点进行排序。 这是我用来对点进行排序的代码。

std::sort(matrix.begin(), matrix.end(), sort1);

matrix.erase(std::unique(matrix.begin(), matrix.end(), compare2),matrix.end());

matrix.push_back(std::vector<double>(3, 0));

首先我对向量矩阵中的点进行排序。作为比较功能,我使用此代码

bool sort1(vector<double> const& s1, vector<double> const& s2)

    return atan2(s1[1],s1[0])<atan2(s2[1],s2[0]);
 

向量排序后,我只是删除重复项以减小向量的大小。最后一步是将第一个点推回向量的末尾以关闭轮廓。 对于像立方体或球这样的标准模型,这可以正常工作,但对于更复杂的模型,atan2 函数可以正常工作。 所以这张图片显示了未排序的点。

当我对向量进行排序时,我得到了这个 conture 作为结果

我的第一个方法是检查 atan2 函数,但它工作正常。问题似乎是 atan2 函数的结果。所以这个列表显示了实际坐标和 atan2 函数的结果

   x             y      z     atan2
-5.44283    -1.94995    0   -2.79758
-5.36969    -1.93228    0   -2.79617
-5.33637    -1.92454    0   -2.79547
-13.15      -4.76500    0   -2.79395
-5.26308    -1.90750    0   -2.79389
-5.22970    -1.90005    0   -2.7931
-5.15626    -1.88364    0   -2.79134

正如您所见,当 x 和 y 坐标发生变化时,atan2 与其他值保持在同一范围内。对我来说,这就是问题所在,为什么我的观点不正确。我是否必须在我的排序功能中添加一些东西才能获得正确的结果?

我的一个想法是不仅按照 atan2 对坐标进行排序,而且还按照点之间的向量长度(最低 atan2 和所有其他点)对坐标进行排序。但这是我的问题。我会先按 atan2 排序,然后再按长度排序。但是第二次排序过程会破坏第一次排序函数的空洞结果。

【问题讨论】:

所以基本上,atan2 不是正确的排序方式,您想知道如何排序以获得任何给定点集的轮廓。这似乎与数学有关。 对我来说 atan2 似乎是对向量进行排序的一个好的开始。但我认为我需要的不仅仅是这一个函数来对整个向量进行排序。 atan2 执行循环扫描,这适用于有限的点集,不适用于更复杂的轮廓或原点不在内部的轮廓。 【参考方案1】:

atan2 在一般情况下显然无济于事。它主要适用于凸形图形。考虑一个内部有 (0,0) 的窄矩形和一个相邻的矩形,并尝试通过它们的 atan2 对它们的点进行排序。 您是否尝试过在集合中绘制一个点,然后寻找最近的尚未绘制的点作为迭代步骤?

【讨论】:

所以你的意思是我可以先按 atan2 对向量进行排序,搜索结果最低的点并将该点用作我的新起点。从这一点开始,我将搜索最近的点并将其添加为向量中的第二个点,并再次使用该点作为我的起点。我会继续这个直到我到达向量中的最后一点? 当然可以,但是这里完全不需要排序(取任意点并旋转坐标轴,使其落在x轴上,所以它的atan2为0;你可以看到,排序没有添加这里有任何东西)。一个更复杂的算法涉及回溯:当您选择下一个点但显然移动到它时,速度矢量的方向变化太大(大于 pi/2 是一个好的开始),您可能必须向后移动几个点并尝试另一个方式。 最后,您可以通过所有点绘制闭合轮廓作为开始,然后执行几个优化步骤以使其不那么弯曲:使用所有点的角速度变化的绝对值之和作为函数被最小化,然后尝试交换相邻顶点,看看它是否会使函数的值变小。 更简单,我认为最小化多边形长度就足够了,而且不会弄乱角度。【参考方案2】:

如果您只处理曲线,那么我建议使用以下算法:

    定义角度范围R 取初始点A,标记为已访问 找到最接近AB,将其标记为已访问 计算向量[A, B]形成的方向 在角度范围R中找到最接近B未访问点C并将其标记为已访问 转到第 4 步,将 B 设为 A,将 C 设为 B

这不是终极解决方案,但它应该能够找到基本曲线和一些多边形。使用更宽的角度范围R,您可以逼近更多的曲线。

【讨论】:

以上是关于对向量中的点进行排序以形成轮廓的主要内容,如果未能解决你的问题,请参考以下文章

坐标从左上到右下排序

OpenCV 将轮廓设置为 0

如何映射分类变量以在 R Plotly 中为 3D 散点图中的点轮廓着色?

OpenCV图像的轮廓

4opencv求解向量和轮廓的交点

18KW15/1-OpenCV入门-初识轮廓