// Main simulation loop. Runs the simulation and updates CurrentFields/NumberOfSteps until a pause is requested. private void SimulationLoop() { while (true) { // If a pause has been requested, pause the simulation, announce it's been paused, and then wait // for the pause monitor to reset. if (!_pauseSimulation.WaitOne(0)) { _simulationIsPaused.Set(); _pauseSimulation.WaitOne(); _simulationIsPaused.Reset(); } _stepper.StepSimulation(); NumberOfSteps = NumberOfSteps + 1; _currentFieldsCache = _stepper.CurrentFields; // If termination has been requested, exit the loop. if (_terminationRequested) { return; } } }
public void OnGUI(PrognosticFields fields) { var height = UpdateHeightAtCursor(fields); var speed = UpdateSpeedAtCursor(fields); var style = new GUIStyle { normal = new GUIStyleState { textColor = Color.black } }; var labelText = String.Format("Height: {0:N0}m\nSpeed: {1:N1}kph", 1000 * height, 3600 * speed); GUI.Label(new Rect(10, 10, 200, 40), labelText, style); }
/// <summary> /// Construct and start a simulation on the given surface using the given options. /// </summary> /// <param name="surface"></param> /// <param name="options"></param> public SimulationController(IPolyhedron surface, ISimulationControllerOptions options) { _options = options; var initialFields = InitialFieldsFactory.Build(surface, options); _stepper = new SimulationRunner(surface, initialFields, options); _currentFieldsCache = _stepper.CurrentFields; _pauseSimulation = new ManualResetEvent(false); _simulationIsPaused = new ManualResetEvent(false); _simulationThread = new Thread(SimulationLoop); _simulationThread.Start(); }
private double?UpdateSpeedAtCursor(PrognosticFields fields) { double?speedAtCursor; var vertexUnderCursor = _cursorTracker.TryGetVertexUnderCursor(); if (vertexUnderCursor != null) { speedAtCursor = fields.Velocity[vertexUnderCursor].Norm(); } else { speedAtCursor = null; } return(speedAtCursor); }
private double?UpdateHeightAtCursor(PrognosticFields fields) { double?heightAtCursor; var faceUnderCursor = _cursorTracker.TryGetFaceUnderCursor(); if (faceUnderCursor != null) { heightAtCursor = fields.Height[faceUnderCursor]; } else { heightAtCursor = null; } return(heightAtCursor); }
public static PrognosticFields Build(IPolyhedron polyhedron, IInitialFieldParameters parameters) { var height = parameters.InitialHeightFunction(polyhedron, parameters.InitialAverageHeight, parameters.InitialMaxDeviationOfHeight); var velocity = parameters.InitialVelocityFunction(polyhedron, parameters.InitialAverageVelocity, parameters.InitialMaxDeviationOfVelocity); var zeroVector = Vector.Zeros(3); var fields = new PrognosticFields { DerivativeOfHeight = ScalarFieldFactory.ConstantScalarField(polyhedron, 0, 0), DerivativeOfVelocity = VectorFieldFactory.ConstantVectorField(polyhedron, zeroVector, 0), Height = height, Velocity = velocity, }; return(fields); }
/// <summary> /// Servant for Unity's Update() function. Allows the simulation to be paused & reset. /// </summary> public void Update() { if (Input.GetKeyDown(_options.PauseSimulationKey)) { TogglePause(); } else if (Input.GetKeyDown(_options.ResetSimulationKey)) { // If a reset is requested, pause the simulation, reset the stepper and update the fields cache to the // reset values. _pauseSimulation.Reset(); _simulationIsPaused.WaitOne(); NumberOfSteps = 0; _stepper.Reset(); _currentFieldsCache = _stepper.CurrentFields; } }