bool Game::cop_isObjectNotIntersectingBox() { debug(DBG_OPCODES, "Game::cop_isObjectNotIntersectingBox()"); int16 var1A = _objectScript.fetchNextWord(); int var18 = findObjectByName(_objectScript.currentObjectNum, _objectScript.testObjectNum, &_objectScript.objectFound); if (var18 != -1) { SceneObject *so = derefSceneObject(var18); if (so->statePrev != 0) { int16 var1E = getObjectTransformXPos(var18); int16 var22 = getObjectTransformYPos(var18); var18 = findObjectByName(_objectScript.currentObjectNum, _objectScript.testObjectNum, &_objectScript.objectFound); if (var18 != -1) { so = derefSceneObject(var18); if (so->statePrev != 0) { int16 var20 = getObjectTransformXPos(var18); int16 var24 = getObjectTransformYPos(var18); bool foundBox = false; for (int i = 0; i < _boxesCountTable[var1A]; ++i) { if (intersectsBox(var1A, i, var1E, var22, var20, var24)) { foundBox = true; break; } } if (foundBox) { if (var18 == _objectScript.testObjectNum) { _objectScript.dataOffset = _objectScript.testDataOffset; assert(0); // XXX return true; } return false; } foundBox = false; for (int i = 0; i < _boxesCountTable[10 + var1A]; ++i) { if (intersectsBox(10 + var1A, i, var1E, var22, var20, var24)) { foundBox = true; break; } } if (foundBox) { if (var18 == _objectScript.testObjectNum) { _objectScript.dataOffset = _objectScript.testDataOffset; assert(0); // XXX return true; } return false; } return true; } } } } if (var18 == _objectScript.testObjectNum) { _objectScript.dataOffset = _objectScript.testDataOffset; assert(0); // XXX return true; } return false; }
// Fills the stack, but only checks a maximum number of maxToCheck points at a time. // Further calls to this function will continue the expand/check neighbors algorithm. void GeoBrowse::fillStack(int maxToCheck, int maxToAdd, bool onlyExpand) { if(maxToAdd < 0) maxToAdd = maxToCheck; int maxFound = _foundInExp + maxToCheck; verify(maxToCheck > 0); verify(maxFound > 0); verify(_found <= 0x7fffffff); // conversion to int int maxAdded = static_cast<int>(_found) + maxToAdd; verify(maxAdded >= 0); // overflow check bool isNeighbor = _centerPrefix.constrains(); // Starting a box expansion if (_state == START) { // Get the very first hash point, if required if(! isNeighbor) _prefix = expandStartHash(); if (!BtreeLocation::initial(_descriptor, _params, _min, _max, _prefix)) { _state = isNeighbor ? DONE_NEIGHBOR : DONE; } else { _state = DOING_EXPAND; _lastPrefix.reset(); } } // Doing the actual box expansion if (_state == DOING_EXPAND) { while (true) { // Record the prefix we're actively exploring... _expPrefix.reset(new GeoHash(_prefix)); // Find points inside this prefix while (checkAndAdvance(&_min, _prefix, _foundInExp) && _foundInExp < maxFound && _found < maxAdded) {} while (checkAndAdvance(&_max, _prefix, _foundInExp) && _foundInExp < maxFound && _found < maxAdded) {} if(_foundInExp >= maxFound || _found >= maxAdded) return; // We've searched this prefix fully, remember _lastPrefix.reset(new GeoHash(_prefix)); // If we've searched the entire space, we're finished. if (! _prefix.constrains()) { _state = DONE; notePrefix(); return; } // If we won't fit in the box, and we're not doing a sub-scan, increase the size if (! fitsInBox(_converter->sizeEdge(_prefix)) && _fringe.size() == 0) { // If we're still not expanded bigger than the box size, expand again _prefix = _prefix.up(); continue; } // We're done and our size is large enough _state = DONE_NEIGHBOR; // Go to the next sub-box, if applicable if(_fringe.size() > 0) _fringe.pop_back(); // Go to the next neighbor if this was the last sub-search if(_fringe.size() == 0) _neighbor++; break; } notePrefix(); } // If we doeighbors if(onlyExpand) return; // If we're done expanding the current box... if(_state == DONE_NEIGHBOR) { // Iterate to the next neighbor // Loop is useful for cases where we want to skip over boxes entirely, // otherwise recursion increments the neighbors. for (; _neighbor < 9; _neighbor++) { // If we have no fringe for the neighbor, make sure we have the default fringe if(_fringe.size() == 0) _fringe.push_back(""); if(! isNeighbor) { _centerPrefix = _prefix; _centerBox = makeBox(_centerPrefix); isNeighbor = true; } int i = (_neighbor / 3) - 1; int j = (_neighbor % 3) - 1; if ((i == 0 && j == 0) || (i < 0 && _centerPrefix.atMinX()) || (i > 0 && _centerPrefix.atMaxX()) || (j < 0 && _centerPrefix.atMinY()) || (j > 0 && _centerPrefix.atMaxY())) { continue; // main box or wrapped edge // TODO: We may want to enable wrapping in future, probably best as layer // on top of this search. } // Make sure we've got a reasonable center verify(_centerPrefix.constrains()); GeoHash _neighborPrefix = _centerPrefix; _neighborPrefix.move(i, j); while(_fringe.size() > 0) { _prefix = _neighborPrefix + _fringe.back(); Box cur(makeBox(_prefix)); double intAmt = intersectsBox(cur); // No intersection if(intAmt <= 0) { _fringe.pop_back(); continue; } else if(intAmt < 0.5 && _prefix.canRefine() && _fringe.back().size() < 4 /* two bits */) { // Small intersection, refine search string lastSuffix = _fringe.back(); _fringe.pop_back(); _fringe.push_back(lastSuffix + "00"); _fringe.push_back(lastSuffix + "01"); _fringe.push_back(lastSuffix + "11"); _fringe.push_back(lastSuffix + "10"); continue; } // Restart our search from a diff box. _state = START; verify(! onlyExpand); verify(_found <= 0x7fffffff); fillStack(maxFound - _foundInExp, maxAdded - static_cast<int>(_found)); // When we return from the recursive fillStack call, we'll either have // checked enough points or be entirely done. Max recurse depth is < 8 * // 16. // If we're maxed out on points, return if(_foundInExp >= maxFound || _found >= maxAdded) { // Make sure we'll come back to add more points verify(_state == DOING_EXPAND); return; } // Otherwise we must be finished to return verify(_state == DONE); return; } } // Finished with neighbors _state = DONE; } }