void Transport::UpdatePosition(float x, float y, float z, float o) { bool newActive = GetMap()->IsGridLoaded(x, y); Cell oldCell(GetPositionX(), GetPositionY()); Relocate(x, y, z, o); m_stationaryPosition.SetOrientation(o); UpdateModelPosition(); UpdatePassengerPositions(_passengers); /* There are four possible scenarios that trigger loading/unloading passengers: 1. transport moves from inactive to active grid 2. the grid that transport is currently in becomes active 3. transport moves from active to inactive grid 4. the grid that transport is currently in unloads */ if (_staticPassengers.empty() && newActive) // 1. LoadStaticPassengers(); else if (!_staticPassengers.empty() && !newActive && oldCell.DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3. UnloadStaticPassengers(); else UpdatePassengerPositions(_staticPassengers); // 4. is handed by grid unload }
void GCellsShearing::runEvent(Particle& part, const double) const { Sim->dynamics->updateParticle(part); size_t oldCell(partCellData[part.getID()]); magnet::math::MortonNumber<3> oldCellCoords(oldCell); Vector oldCellPosition(calcPosition(oldCellCoords)); //Determine the cell transition direction, its saved int cellDirectionInt(Sim->dynamics-> getSquareCellCollision3(part, oldCellPosition, cellDimension)); size_t cellDirection = abs(cellDirectionInt) - 1; magnet::math::MortonNumber<3> endCell = oldCellCoords; //The ID of the cell the particle enters if ((cellDirection == 1) && (oldCellCoords[1] == ((cellDirectionInt < 0) ? 0 : (cellCount[1] - 1)))) { //We're wrapping in the y direction, we have to compute //which cell its entering endCell[1] = (endCell[1].getRealValue() + cellCount[1] + ((cellDirectionInt < 0) ? -1 : 1)) % cellCount[1]; //Remove the old x contribution //Calculate the final x value //Time till transition, assumes the particle is up to date double dt = Sim->dynamics->getSquareCellCollision2(part, oldCellPosition, cellDimension); //Predict the position of the particle in the x dimension Sim->dynamics->advanceUpdateParticle(part, dt); Vector tmpPos = part.getPosition(); //This rewinds the particle again Sim->dynamics->updateParticle(part); //Adding this extra half cell ensures we get into the next //simulation image, to calculate the position of the new cell tmpPos[1] += ((cellDirectionInt < 0) ? -0.5 : 0.5) * cellDimension[1]; //Determine the x position (in cell coords) of the particle and //add it to the endCellID Sim->BCs->applyBC(tmpPos, dt); endCell[0] = getCellID(tmpPos)[0]; removeFromCell(part.getID()); addToCell(part.getID(), endCell.getMortonNum()); //Get rid of the virtual event that is next, update is delayed till //after all events are added Sim->ptrScheduler->popNextEvent(); //Check the entire neighbourhood, could check just the new //neighbours and the extra LE neighbourhood strip but its a lot //of code if (isUsedInScheduler) { BOOST_FOREACH(const size_t& id2, getParticleNeighbours(part)) { Sim->ptrScheduler->addInteractionEvent(part, id2); BOOST_FOREACH(const nbHoodSlot& nbs, sigNewNeighbourNotify) nbs.second(part, id2); } }