Microscopic Traffic Simulator
SimulationTrafficRenderer.cs
Go to the documentation of this file.
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Windows;
8 using System.Windows.Media;
9 using System.Windows.Threading;
10 
11 namespace Microscopic_Traffic_Simulator.Renderers
12 {
18 
23  {
27  private CellularTopology cellularTopology;
31  internal CellularTopology CellularTopology { set { cellularTopology = value; } }
32 
36  private DateTime dateTimeOfLastSimStep;
37 
43  private bool wasSingleStepOrMaxSpeed;
44 
48  private DateTime dateTimeOfLastPause;
49 
54  internal SimulationTrafficRenderer(DrawingVisual visual) : base(visual) { }
55 
60  protected override void Render(Point currentMouseLocation)
61  {
62  if (cellularTopology != null)
63  {
64  if (cellularTopology.Simulation.SimulationState == SimulationState.Running &&
65  !cellularTopology.Simulation.IsMaxSimulationSpeed)
66  {
67  RenderSimulationTraffic(Rendering.Continuous);
68  }
69  else
70  {
71  RenderSimulationTraffic(Rendering.Single);
72  }
73  }
74  }
75 
79  internal void RenderSimulationTraffic(Rendering rendering = Rendering.Single)
80  {
81  using (DrawingContext dc = visual.RenderOpen())
82  {
83  //gain exclusive access to cars dictionaries in cellular topology.
84  cellularTopology.CarsDictionariesMutex.WaitOne();
85  Pen carPen = new Pen(Brushes.Green, 2.0 * PixelsPerMeter);
86  Pen gpsCarPen = new Pen(Brushes.LightGreen, 2.0 * PixelsPerMeter);
87  DateTime dateTimeNow = DateTime.Now;
88  foreach (KeyValuePair<Car, Cell> frontCellWithCar in
89  cellularTopology.CarsManager.CellsWithCarInPreviousStep)
90  {
91  Car car = frontCellWithCar.Key;
92  Cell previousFirstCell = frontCellWithCar.Value;
93  Cell currentFirstCell = cellularTopology.CarsManager.CellsWithCarInCurrentStep[car];
94  DrawCar(rendering, dc, dateTimeNow, car.Outside, car.Length, previousFirstCell.Location,
95  currentFirstCell.Location, currentFirstCell.NormalizedDirectionVector, carPen);
96  }
97  //for each records in current time
98  foreach (int carToRender in
99  cellularTopology.GpsRecordsManager.CarPreviousGPSInputLocations.Keys.Where(
100  i => cellularTopology.GpsRecordsManager.CarCurrentGPSInputLocations.ContainsKey(i)))
101  {
102  DrawCar(rendering, dc, dateTimeNow, 0, 4,
103  cellularTopology.GpsRecordsManager.CarPreviousGPSInputLocations[carToRender].Location,
104  cellularTopology.GpsRecordsManager.CarCurrentGPSInputLocations[carToRender].Location,
105  cellularTopology.GpsRecordsManager
106  .CarCurrentGPSInputLocations[carToRender].DirectionNormalizedVector, gpsCarPen);
107  }
108 
109  cellularTopology.CarsDictionariesMutex.ReleaseMutex();
110  }
111  }
112 
125  private void DrawCar(Rendering rendering, DrawingContext dc, DateTime dateTimeNow, int carOutsideOfTopology,
126  int carLength, Point previousLocation, Point currentLocation, Vector carDirectionNormalizedVector,
127  Pen carPen)
128  {
129  Point location;
130  if (rendering == Rendering.Continuous)
131  {
132  double timePortionElapsed =
133  (double)((dateTimeNow - dateTimeOfLastSimStep)
134  .Multiply(cellularTopology.Simulation.SimulationSpeed).Ticks) /
135  cellularTopology.Parameters.CellularTopologyParameters.P2_SimulationStepInterval.Ticks;
136  timePortionElapsed = Math.Min(timePortionElapsed, 1.0);
137  location = previousLocation + (currentLocation + carDirectionNormalizedVector * carOutsideOfTopology *
138  cellularTopology.Parameters.CellularTopologyParameters.P1_CellLength - previousLocation) *
139  timePortionElapsed;
140  }
141  else if (rendering == Rendering.Single)
142  {
143  location = currentLocation;
144  }
145  else
146  {
147  throw new ApplicationException("Not all of rendering types are implemented.");
148  }
149  //to prevent from visualization of cars which are already outside of
150  //topology.
151  if ((location - previousLocation).Length - (currentLocation - previousLocation).Length <=
152  carLength * cellularTopology.Parameters.CellularTopologyParameters.P1_CellLength)
153  {
154  dc.DrawLine(carPen, TransformRealWorldPoint(location - carLength * carDirectionNormalizedVector),
155  TransformRealWorldPoint(location));
156  }
157  }
158 
164  void simulation_SimulationPaused(object sender, EventArgs e)
165  {
166  PauseApplied();
167  Application.Current.Dispatcher.Invoke(() => RenderSimulationTraffic(), DispatcherPriority.Render);
168  }
169 
174  private void PauseApplied()
175  {
176  dateTimeOfLastPause = DateTime.Now;
177  }
178 
183  private void PauseReleased()
184  {
185  dateTimeOfLastSimStep += DateTime.Now - dateTimeOfLastPause;
186  }
187 
193  internal void SimulationFaster(double rate)
194  {
195  if (cellularTopology.Simulation.SimulationState != SimulationState.NotRunning)
196  {
197  dateTimeOfLastSimStep += (GetCurrentDateTime() - dateTimeOfLastSimStep).Divide(rate);
198  }
199  }
200 
206  internal void SimulationSlower(double rate)
207  {
208  if (cellularTopology.Simulation.SimulationState != SimulationState.NotRunning)
209  {
210  DateTime dateTimeNow = GetCurrentDateTime();
211  dateTimeOfLastSimStep = dateTimeNow - (dateTimeNow - dateTimeOfLastSimStep).Multiply(rate);
212  }
213  }
214 
219  private DateTime GetCurrentDateTime()
220  {
221  if (cellularTopology.Simulation.SimulationState == SimulationState.Running)
222  return DateTime.Now;
223  else if (cellularTopology.Simulation.SimulationState == SimulationState.Paused)
224  return dateTimeOfLastPause;
225  else
226  throw new ApplicationException("Simulation speed increased when simulation is not running");
227  }
228 
232  internal void Run()
233  {
234  if (cellularTopology.Simulation.SimulationState == SimulationState.Paused)
235  PauseReleased();
236  if (cellularTopology.Simulation.IsMaxSimulationSpeed)
237  {
238  wasSingleStepOrMaxSpeed = true;
239  }
240  else
241  {
242  if (wasSingleStepOrMaxSpeed)
243  AdjustLastSimulationStepTime();
244  wasSingleStepOrMaxSpeed = false;
245  }
246  }
247 
252  private void AdjustLastSimulationStepTime()
253  {
254  dateTimeOfLastSimStep = DateTime.Now -
255  cellularTopology.Parameters.CellularTopologyParameters.P2_SimulationStepInterval;
256  }
257 
261  internal void StepForward()
262  {
263  wasSingleStepOrMaxSpeed = true;
264  }
265 
269  internal void Stop()
270  {
271  RenderSimulationTraffic();
272  }
273 
277  internal void Pause()
278  {
279  if (cellularTopology.Simulation.IsMaxSimulationSpeed)
280  RenderSimulationTraffic(Rendering.Single);
281  else
282  RenderSimulationTraffic(Rendering.Continuous);
283  PauseApplied();
284  if (cellularTopology.Simulation.IsMaxSimulationSpeed)
285  wasSingleStepOrMaxSpeed = true;
286  }
287 
291  internal void DetachEventHandlerFromCellularTopology()
292  {
293  if (cellularTopology != null)
294  {
295  cellularTopology.Simulation.SimulationPaused -= simulation_SimulationPaused;
296  cellularTopology.Simulation.SingleSimulationActionPerformed -=
297  Simulation_SingleSimulationActionPerformed;
298  cellularTopology.Simulation.SimulationSpeedChanged -= Simulation_SimulationSpeedChanged;
299  cellularTopology.Simulation.IsMaxSimulationSpeedChange -= Simulation_IsMaxSimulationSpeedChange;
300  cellularTopology.NextTransitionFunctionStarted -= cellularTopology_NextTransitionFunctionStarted;
301  using (DrawingContext dc = visual.RenderOpen()) { } //clean canvas
302  }
303  }
304 
308  internal void AttachEventHandlerFromCellularTopology()
309  {
310  cellularTopology.Simulation.SimulationPaused += simulation_SimulationPaused;
311  cellularTopology.Simulation.SingleSimulationActionPerformed += Simulation_SingleSimulationActionPerformed;
312  cellularTopology.Simulation.SimulationSpeedChanged += Simulation_SimulationSpeedChanged;
313  cellularTopology.Simulation.IsMaxSimulationSpeedChange += Simulation_IsMaxSimulationSpeedChange;
314  cellularTopology.NextTransitionFunctionStarted += cellularTopology_NextTransitionFunctionStarted;
315  }
316 
322  void cellularTopology_NextTransitionFunctionStarted(object sender, DateTimeEventArgs e)
323  {
324  dateTimeOfLastSimStep = e.DateTime;
325  }
326 
332  void Simulation_IsMaxSimulationSpeedChange(object sender, EventArgs e)
333  {
334  if (cellularTopology.Simulation.SimulationState == SimulationState.Running)
335  {
336  if (cellularTopology.Simulation.IsMaxSimulationSpeed)
337  wasSingleStepOrMaxSpeed = true;
338  else
339  wasSingleStepOrMaxSpeed = false;
340  }
341  }
342 
348  void Simulation_SimulationSpeedChanged(object sender, SimulationSpeedChangeEventArgs e)
349  {
351  {
352  SimulationFaster(e.NewSimulationSpeed / e.OldSimulationSpeed);
353  }
354  else if (e.OldSimulationSpeed > e.NewSimulationSpeed)
355  {
356  SimulationSlower(e.OldSimulationSpeed / e.NewSimulationSpeed);
357  }
358  }
359 
366  private void Simulation_SingleSimulationActionPerformed(object sender, EventArgs e)
367  {
368  Application.Current.Dispatcher.Invoke(() => RenderSimulationTraffic(), DispatcherPriority.Render);
369  }
370  }
371 }
Vector NormalizedDirectionVector
Normalized direction vector.
Definition: Cell.cs:28
Simulation Simulation
Simulation object which controls the simulation on the cellular topology.
ReadOnlyDictionary< int, LocationAndDirection > CarCurrentGPSInputLocations
Dictionary mapping hash code of a recorded car to its location in current simulation step...
EventHandler< SimulationSpeedChangeEventArgs > SimulationSpeedChanged
Event of simulation speed change.
Definition: Simulation.cs:82
Mutex CarsDictionariesMutex
Mutex ensuring that cars are not rendering when the transition function is performing and vice versa...
EventHandler IsMaxSimulationSpeedChange
Event of activation or deactivation of maximum simulation speed.
Definition: Simulation.cs:87
EventHandler< DateTimeEventArgs > NextTransitionFunctionStarted
Event informing that next transition function already started.
Class representing event arguments consisting of property containing time information.
int Outside
Number of cells which car used if they would exist after the end of the blind lane.
Definition: Car.cs:66
EventHandler SimulationPaused
An event informing about applying of pause by the simulation control.
Definition: Simulation.cs:72
bool IsMaxSimulationSpeed
Indicates whether the simulation speed is maximal.
Definition: Simulation.cs:157
ReadOnlyDictionary< Car, Cell > CellsWithCarInPreviousStep
Read only dictionary containing all cars with their first cells which they occupied before last trans...
Definition: CarsManager.cs:23
override void Render(Point currentMouseLocation)
Redraw the simulation traffic while distinguishing whether to use single or continous rendering Curre...
SimulationState SimulationState
Current simulation status of simulation.
Definition: Simulation.cs:96
Rendering
Enumeration type containing values representing rendering of one single simulation step and rendering...
EventHandler SingleSimulationActionPerformed
An event informing about finishing of simulation action.
Definition: Simulation.cs:77
ReadOnlyDictionary< int, LocationAndDirection > CarPreviousGPSInputLocations
Dictionary mapping hash code of a recorded car to its location in previous simulation step...
double SimulationSpeed
Current simulation speed in model time speed divided by computer/user time speed
Definition: Simulation.cs:123
ReadOnlyDictionary< Car, Cell > CellsWithCarInCurrentStep
Read only dictionary containing all cars with their first cells which they occupied after last transi...
Definition: CarsManager.cs:37
int Length
Car&#39;s length in number of cells it uses.
Definition: Car.cs:47