客户那边得到了一组点位数据,是阵列得来的,只给出了坐标,没有行列信息,可是客户给的打码内容,却是按照行列给出的,有对应的行列值,所以这里需要的是做到这些点位和行列打码内容一一对应关联。
我最初的想法是,既然打码内容是根据阵列来的,肯定是按照行列顺序来的,只需要把得到的打码内容根据行列坐标做对应的排序就可以了。这个方法也是可以的,只是客户给出的坐标不能确定是一直按照一种方式来的。
后来觉得,这样做的话,循环次数太多了,势必会浪费时间,但一时也找不到合适的解决方法,于是有了最初的算法实现。
- 先对阵列坐标进行一次排序,按照从做到右从上到下的顺序;
- 先得到阵列坐标的最上面一行的点,每得到一个最上面一行其中的一个点,放到一个组里面,然后再原有的容器中移除它;
- 再次执行判断得到原有容器中最上面一行的点,放到一个组里面,移除原有容器最上面一行的点。
- 2-3反复执行,即得的按行排列的多组容器。
- 点所在容器的顺序即是行号,点在这个容器的位置即是列号。
// 按照从做到右从上到下的顺序排序
std::sort(vPointSet.begin(), vPointSet.end(), v_LaserTypeCompare);
int nSize = vPointSet.size();
vector <pair<double, vector<sPoint>>> vSetDiv;
while (vPointSet.size())
{
vector<sPoint> vTmp;
vector<sPoint>::iterator iter = vPointSet.begin();
double x = iter->m_sPoint.x;
vTmp.push_back(*iter);
iter = vPointSet.erase(iter);
while (iter != vPointSet.end())
{
if (abs(x - iter->m_sPoint.x) <= 1)
{
vTmp.push_back(*iter);
iter = vPointSet.erase(iter);
continue;
}
iter++;
}
vSetDiv.push_back(pair<double, vector<sPoint>>(x, vTmp));
}
nSize = vSetDiv.size();
vPointSet.clear();
for (int i = 0; i < nSize; i++)
{
for (int n = 0; n < vSetDiv[i].second.size(); n++)
{
// 行号,列号存放到sPoint中
vSetDiv[i].second[n].m_sColRowPoint = sPoint(i+1, n+1);
}
vPointSet.insert(vPointSet.end(), vSetDiv[i].second.begin(), vSetDiv[i].second.end());
}
用上面的代码应付了事后,就再也没遇到类似这样的应用,最近想起来看自己有没有优化的可能,突然想到这算出来就根本不需要那么多次循环。就是个数学问题。
既然是阵列得来的点位,行坐标,列坐标大多都是一致的,可以从这方面入手解决。
- 得到阵列点中的y值,即是得到所有行的Y坐标,不同Y坐标的个数是和阵列行数一致的,存放到一个行容器中。
- 得到阵列点中的x值,即是得到所有列的X坐标,不同X坐标的个数是和阵列列数一致的,存放到一个列容器中。
- 阵列点其中元素X的值在列容器中的顺序,就是列号;阵列点其中元素Y的值在行容器中的顺序,就是行号。
vector < double > vRows, vCols;
int nSize = vPointSet.size();
for (int i = 0; i < nSize; i++)
{
// 得到每列坐标
if (std::find(vCols.begin(), vCols.end(), vPointSet[i].x) == vCols.end())
vCols.push_back(vPointSet[i].x);
// 得到每行坐标
if (std::find(vRows.begin(), vRows.end(), vPointSet[i].y) == vRows.end())
vRows.push_back(vPointSet[i].y);
}
std::sort(vRows.begin(), vRows.end());
std::sort(vCols.begin(), vCols.end());
// vPointSet元素中y的值在vRows中的顺序Index就是行号
// vPointSet元素中x的值在vCols中的顺序Index就是列号