2015-04-01 113 views
0

我有一个结构的载体如何内双擦除向量元素的循环

vector<contour> hotspots; 

轮廓是我有一个像下面

struct contour 
{ 
    double arc; 
    double area; 
    Point2f center; 
    double me; 
    double hullArea; 
    vector<Point> contourVector; 
    vector<Point> hullVector; 

    bool operator <(const contour& comp) 
    { 
     return me < comp.me; 
    } 
}; 

所以我试图做定义的结构是通过循环,并删除包含在另一个轮廓中的每个轮廓,我可以得到它的大部分工作,但我有时会得到一个索引错误,我认为它有什么与当我擦除一个元素索引的弄乱所以我超出范围。下面是我的循环,我写道:

vector<vector<Point>> cleanUp(vector<Point2f> centers, vector<Moments> areas, vector<vector<Point>> contours) 
{ 
    for (int i = 0; i < contours.size(); i++) 
     for (int j = 0; j < contours.size(); j++) 
      if (i != j) 
      { 
       if ((areas[i].m00 < areas[j].m00) == true && (pointPolygonTest(contours[j], centers[i], false) > 0) == true) 
       { 
        contours.erase(contours.begin() + i); 
        centers.erase(centers.begin() + i); 
        areas.erase(areas.begin() + i); 
       } 
      } 

    return contours; 
} 

我已经尝试了一些不同的解决方案,如我 - 1但删除了错误的轮廓,而不是使用擦除,覆盖元素我想删除与上一个然后使用.pop_back删除最后一个元素,但似乎没有工作。有任何想法吗?

编辑:修正了不同步的问题与地区和中心,但现在的问题马上,只要我调用该函数删除一些轮廓显示出来。

+0

第一次删除后,您的“区域”和“轮廓”会变得“不同步”。你应该从两者中删除东西,或者想出其他方式将区域和轮廓表示为单个项目。 – dasblinkenlight 2015-04-01 01:57:20

+0

上帝......我甚至没有意识到我没有那样做,当我计划时我甚至想过......谢谢。 – 2015-04-01 01:58:07

回答

0

迭代器,我想尝试这种方法:

#include <iterator> 

template <typename BinaryPred> 
void RemoveIfPairwise(std::vector<T> & v, BinaryPred f) 
{ 
    for (auto it1 = v.begin(); it1 != v.end(); ++it1) 
    { 
     for (auto it2 = std::next(it1); it2 != v.end();) 
     { 
      if (f(*it1, *it2)) { it2 = v.erase(it2); } 
      else    { ++it2;    } 
     } 
    } 
} 

它使用的std::vector迭代非无效担保,例如擦除不会擦除前点无效迭代器(所以it1不需要特殊治疗)。

请注意,此循环只检查不同元素对;你需要修改它来检查对角线。

+0

你能否澄清你对对角线的含义?谢谢。 – 2015-04-01 02:07:10

+1

我认为他的意思是'i == j'的情况。 – 2015-04-01 02:10:59

+0

'v.erase(it2 ++);'应该是'it2 = v.erase(it2);'因为我能想到的两个理由,都是UB。 (增量后使用无效的迭代器;如果我们在擦除后前进,我们可以跳过结束)。 – Yakk 2015-04-01 02:21:31

0

您可以保留要删除项目的索引列表,并在最后删除这些索引项目。

vector<vector<Point>> cleanUp(vector<Point2f> centers, 
           vector<Moments> areas, 
           vector<vector<Point>> contours) 
{ 
    std::<int> itemsToErase; 

    for (int i = 0; i < contours.size(); i++) 
     for (int j = 0; j < contours.size(); j++) 
      if (i != j) 
      { 
       if ((areas[i].m00 < areas[j].m00) == true && 
        (pointPolygonTest(contours[j], centers[i], false) > 0) == true) 
       { 
        itemsToErase.push_front(i); 
       } 
      } 

    while (!itemsToErase.empty()) 
    { 
     int i = itemsToErase.back(); 
     contours.erase(contours.begin() + i); 
     centers.erase(centers.begin() + i); 
     areas.erase(areas.begin() + i); 
     itemsToErase.pop_back(); 
    } 

    return contours; 
}