вставка и стирание stdvector - PullRequest
0 голосов
/ 28 июля 2011

Мне нужно контролировать количество точек касания в моем приложении, для этого я использую векторный контейнер, и моя базовая настройка такова:

//--------------------------------------------------------------
void testApp::touchDown(ofTouchEventArgs &touch){
    isTouching = true;

    touchPoints.push_back( ofVec2f( touch.x, touch.y ) );
}

//--------------------------------------------------------------
void testApp::touchMoved(ofTouchEventArgs &touch){
    for ( int i = 0; i < touchPoints.size(); i++ ) {
        if ( touch.id == i ) {
            touchPoints[i] = ofVec2f( touch.x, touch.y );
        }
    }
}

//--------------------------------------------------------------
void testApp::touchUp(ofTouchEventArgs &touch){
    isTouching = false;

    int i = 0;
    for ( vector<ofVec2f>::iterator iter = touchPoints.begin(); iter != touchPoints.end(); ) {
        //int i = std::distance( touchPoints.begin(), iter );
        cout << "i: " << i << endl;
        if ( touch.id == i ) {
            iter = touchPoints.erase( iter );
        }
        i++;
        ++iter;
    }
}

Но когда я поднимаю палец вверх, приложение зависает, поэтому в touchUp () чаще всего что-то не так, есть идеи?

Ответы [ 2 ]

4 голосов
/ 28 июля 2011

Многое: во-первых, вы не можете изменить (стереть / вставить) контейнер и ожидать, что итераторы останутся действительными!

Давайте посмотрим.Я также хочу изменить touchMove:

void testApp::touchMoved(const ofTouchEventArgs & touch)
{
  if (touch.id < touchPoints.size())
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
}

Далее, большое:

void testApp::touchUp(const ofTouchEventArgs & touch)
{
  if (touch.id < touchPoints.size())
    touchPoints.erase(touchPoints.begin() + touch.id);
}

В основном touch.id это просто индекс ввектор, так что мы можем использовать это напрямую.Чтобы стереть элемент из середины, мы просто вызываем erase на соответствующем итераторе.Так как вектор имеет итераторы произвольного доступа, мы можем сказать begin() + touch.id в постоянное время.

Обновление: На самом деле я думаю, что ваш код не работает: после того, как вы удалите элемент из вектора, другойэлементы перемещаются вверх, поэтому вы потеряете связь между touch.id и элементом контейнера!Вам нужно, как вы уже догадались, ассоциативный контейнер:

struct testApp
{
  std::map<int, ofVec2f> touchPoints;
  bool isTouching;

  void touchDown(const ofTouchEventArgs & touch)
  {
    isTouching = true;
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
  }

  void touchMoved(const ofTouchEventArgs & touch)
  {
    touchPoints[touch.id] = ofVec2f(touch.x, touch.y);
  }

  void touchUp(const ofTouchEventArgs & touch)
  {
    isTouching = false;
    touchPoints.erase(touch.id);
  }
};
0 голосов
/ 28 июля 2011

Если вы сделали iter=touchPoints.erase(iter), вам не следует делать ++iter;Вы уже перешли к следующему пункту.

...