/** * \brief Mutual shoving : The movement by shoving of an agent is calculated based on the cell * overlap and added to the agents movement vector. * * <p>Mutual shoving : The movement by shoving of an agent is calculated based on the cell overlap * and added to the agents movement vector. Both agents are moved of half the overlapping distance * in opposite directions. * * @param aNeighbour Reference to the potentially shoving neighbour * @param isMutual Whether movement is shared between two agents or applied only to this one * @param gain Double noting change in position * @return Boolean stating whether shoving is detected (true) or not (false) */ public boolean addPushMovement(LocatedAgent aNeighbour, boolean isMutual, double gain) { double d, distance; if (aNeighbour == this) return false; // Build the escape vector and find the distance between you and your // neighbourhood d = computeDifferenceVector(_location, aNeighbour._location); _diff.normalizeVector(); // Compute effective cell-cell distance distance = getShoveRadius() + aNeighbour.getShoveRadius(); distance += getSpeciesParam().shoveLimit; distance = d - distance; /* Apply shoving _________________________________________________ */ // Compute shoving distance for the current agent if (distance <= 0) { if (isMutual) { _diff.times(gain * 0.5 * Math.abs(distance)); this._movement.add(_diff); aNeighbour._movement.subtract(_diff); } else { _diff.times(Math.abs(gain * distance)); this._movement.add(_diff); } return true; } else { return false; } }
/** * \brief Set the movement vector that states where to put a newly-created particle * * <p>Set the movement vector that states where to put a newly-created particle * * @param distance Distance between the this agent and the new agent */ public void setDivisionDirection(double distance) { double phi, theta; phi = 2 * Math.PI * ExtraMath.getUniRandDbl(); theta = 2 * Math.PI * ExtraMath.getUniRandDbl(); _divisionDirection.x = distance * Math.sin(phi) * Math.cos(theta); _divisionDirection.y = distance * Math.sin(phi) * Math.sin(theta); _divisionDirection.z = (_agentGrid.is3D ? distance * Math.cos(phi) : 0); }
/** * \brief Pulling : The movement of agents by a shrinking biofilm. Move calculated and added to * the agents movement vector. * * <p>The movement of agents by a shrinking biofilm. Move calculated and added to the agents * movement vector. * * @param aNeighbor Reference to the potentially shoving neighbour * @param isMutual Whether movement is shared between two agents or applied only to this one * @param gain Double noting change in position * @return Boolean stating whether pulling is detected (true) or not (false) */ public boolean addSpringMovement(LocatedAgent aNeighbor, boolean isMutual, double gain) { double d, distance, delta; if (aNeighbor == this) return false; // Build the escape vector and find the distance between you and your // neighbourhood d = computeDifferenceVector(_location, aNeighbor._location); _diff.normalizeVector(); distance = getShoveRadius() + aNeighbor.getShoveRadius(); distance += getSpeciesParam().shoveLimit; delta = d - distance; double lMax = _totalRadius; if (delta > 0) gain *= Math.exp(-delta * 5 / (lMax)); if (delta > lMax) gain = 0; /* Apply shoving _________________________________________________ */ if (isMutual) { _diff.times(-0.5 * delta * gain); this._movement.add(_diff); aNeighbor._movement.subtract(_diff); } else { _diff.times(-delta * gain); this._movement.add(_diff); } return (_movement.norm() > _radius * gain); }
/** * \brief Computes the shortest distance between this agent and another, stored as * ContinuousVectors. This may be around the cyclic boundary * * <p>Computes the distance between this agent and another, stored as ContinuousVectors. This may * be around the cyclic boundary * * @param me ContinuousVector stating first agent location * @param him ContinuousVector stating other agent location * @return the shortest movement vector to go from a to b, take into account the cyclic boundary * @see addOverlapMovement * @see addPullMovement works in 2 and 3D */ public double computeDifferenceVector(ContinuousVector me, ContinuousVector him) { double gridLength; _diff.x = me.x - him.x; // check periodicity in X gridLength = _species.domain.length_X; if (Math.abs(_diff.x) > .5 * gridLength) _diff.x -= Math.signum(_diff.x) * gridLength; _diff.y = me.y - him.y; // check periodicity in Y gridLength = _species.domain.length_Y; if (Math.abs(_diff.y) > .5 * gridLength) _diff.y -= Math.signum(_diff.y) * gridLength; if (_agentGrid.is3D) { _diff.z = me.z - him.z; // check periodicity in Z gridLength = _species.domain.length_Z; if (Math.abs(_diff.z) > .5 * gridLength) _diff.z -= Math.signum(_diff.z) * gridLength; } else { _diff.z = 0; } double d = Math.sqrt(_diff.x * _diff.x + _diff.y * _diff.y + _diff.z * _diff.z); if (d == 0) { d = 1e-2 * _radius; _diff.alea(_agentGrid.is3D); } return d; }