/// <summary> /// Sets the facing of the cell /// </summary> /// <param name="direction"></param> public void Reorientate(Vector3 direction) { direction.unitVect(); orientation.x = direction.x; orientation.y = direction.y; orientation.z = direction.z; }
/// <summary> /// Private method for performing the spatial simulation. /// </summary> /// <param name="cell"></param> /// <param name="currentState"></param> /// <param name="time"></param> /// <param name="StepTime"></param> private void SpatialSimulator(CellInstance cell, StateSnapshot currentState, double time, double StepTime) { Vector3 p = cell.CellInstanceSpatialContext.Position; Vector3 v = cell.CellInstanceSpatialContext.Velocity; Vector3 ang = cell.CellInstanceSpatialContext.Orientation; float visc = currentState.SimulationEnvironment.Viscosity; float h = (float)StepTime; //viscous drag (Stokes's drag) v.x += -visc * h * v.x * 1.5f; v.y += -visc * h * v.y * 1.5f; v.z += -visc * h * v.z * 1.5f; //cell collisions if (currentState.SimulationEnvironment.EnableCellCollisions) { foreach (CellInstance cellB in currentState.Cells) { if (cell != cellB) //avoid collision with self { //the vector from the centre of this cell to cellB Vector3 dist = new Vector3(p.x - cellB.CellInstanceSpatialContext.Position.x, p.y - cellB.CellInstanceSpatialContext.Position.y, p.z - cellB.CellInstanceSpatialContext.Position.z); float distMag = dist.magnitude(); if (distMag < cell.CellInstanceSpatialContext.Radius*0.001 + cellB.CellInstanceSpatialContext.Radius*0.001) { /* * Collision occured: accelerate this cell away from the centre of the cell it is colliding with: */ dist.unitVect(); //normalize dist.x *= -h*0.1f; dist.y *= -h*0.1f; dist.z *= -h*0.1f; //accelerate this cell and the one it collided with in oppose directions: v.x -= dist.x; v.y -= dist.y; v.z -= dist.z; cellB.CellInstanceSpatialContext.Accelerate(dist); } } } } //positional change p.x += v.x * h; p.y += v.y * h; p.z += v.z * h; //check that boundary conditions are maintained (most of the time this will be true, and will be the only test needed) if (!currentState.SimulationEnvironment.Boundary.InsideBoundary(p)) { /* * If the cell is not inside the environment boundary, we move it back * and attempt to move the cell by individual components (this allows * the cell to "slide" along the edges of the boundary without * breaking the boundary conditions). In most cases these three boundary * checks should not be necessary */ //begin by checking x component, so move back y and z components p.y -= v.y * h; p.z -= v.z * h; if (!currentState.SimulationEnvironment.Boundary.InsideBoundary(p)) { //x failed, so move back x p.x -= v.x * h; } //check y component p.y += v.y * h; if (!currentState.SimulationEnvironment.Boundary.InsideBoundary(p)) { //y failed p.y -= v.y * h; } //check z component p.z += v.z * h; if (!currentState.SimulationEnvironment.Boundary.InsideBoundary(p)) { //z failed p.z -= v.z * h; } } cell.CellInstanceSpatialContext.Position = p; cell.CellInstanceSpatialContext.Velocity = v; cell.CellInstanceSpatialContext.Orientation = ang; }