2015-04-01 54 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; 
}