void FindingStartCursor::next() { if ( !_findingStartCursor || !_findingStartCursor->ok() ) { _findingStart = false; _c = _qp.newCursor(); // on error, start from beginning destroyClientCursor(); return; } switch( _findingStartMode ) { case Initial: { if ( !_matcher->matchesCurrent( _findingStartCursor->c() ) ) { _findingStart = false; // found first record out of query range, so scan normally _c = _qp.newCursor( _findingStartCursor->currLoc() ); destroyClientCursor(); return; } _findingStartCursor->advance(); RARELY { if ( _findingStartTimer.seconds() >= __findingStartInitialTimeout ) { createClientCursor( startLoc( _findingStartCursor->currLoc() ) ); _findingStartMode = FindExtent; return; } } return; } case FindExtent: { if ( !_matcher->matchesCurrent( _findingStartCursor->c() ) ) { _findingStartMode = InExtent; return; } DiskLoc prev = prevLoc( _findingStartCursor->currLoc() ); if ( prev.isNull() ) { // hit beginning, so start scanning from here createClientCursor(); _findingStartMode = InExtent; return; } // There might be a more efficient implementation than creating new cursor & client cursor each time, // not worrying about that for now createClientCursor( prev ); return; } case InExtent: { if ( _matcher->matchesCurrent( _findingStartCursor->c() ) ) { _findingStart = false; // found first record in query range, so scan normally _c = _qp.newCursor( _findingStartCursor->currLoc() ); destroyClientCursor(); return; } _findingStartCursor->advance(); return; } default: { massert( 14038, "invalid _findingStartMode", false ); } } }
void EraserTracker::feed(std::vector<EraserDetector::Eraser> objects, float searchRadius, float dt) { // grab only 1 eraser if(objects.size() > 1) objects.resize(1); else if(objects.size() < 1) { if(_historySize > 0 && (_history[ _historySize-1 ]._timeToLive)-- <= 0) _historySize = 0; return; } // configure a new point EraserDetector::Eraser& e = objects[0]; e.startX = e.x; e.startY = e.y; e.surfaceStartX = e.surfaceX; e.surfaceStartY = e.surfaceY; e.speedX = e.speedY = 0.0f; e.surfaceSpeedX = e.surfaceSpeedY = 0.0f; e._timeToLive = INITIAL_TIMETOLIVE; // greedy matching if(_historySize > 0) { EraserDetector::Eraser& last = _history[ _historySize-1 ]; ofVec2f prevLoc(last.x, last.y); ofVec2f prevSpeed(last.speedX, last.speedY); ofVec2f predictedPosition = prevLoc + (prevSpeed * dt); ofVec2f curLoc(e.x, e.y); if(curLoc.distance(predictedPosition) <= searchRadius) { e._id = last._id; e.startX = last.startX; e.startY = last.startY; e.surfaceStartX = last.surfaceStartX; e.surfaceStartY = last.surfaceStartY; e.speedX = (float)(e.x - last.x) / dt; e.speedY = (float)(e.y - last.y) / dt; e.surfaceSpeedX = (float)(e.surfaceX - last.surfaceX) / dt; e.surfaceSpeedY = (float)(e.surfaceY - last.surfaceY) / dt; } else { _historySize = 0; e._id = _newId++; } } else e._id = _newId++; // add the eraser to the history if(_historySize == _storedSamples) { for(int i=1; i<_storedSamples; i++) _history[i-1] = _history[i]; _history[_storedSamples-1] = e; } else if(_historySize < _storedSamples) _history[_historySize++] = e; // forget the last eraser...! if( (_history[ _historySize-1 ]._timeToLive)-- <= 0 ) _historySize = 0; }