simulation_group.dart 2.41 KB
Newer Older
1
// Copyright 2016 The Chromium Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7
import 'simulation.dart';
import 'tolerance.dart';
import 'utils.dart';
8

Ian Hickson's avatar
Ian Hickson committed
9 10 11 12 13 14 15 16 17 18 19 20
/// Base class for composite simulations.
///
/// Concrete subclasses must implement the [currentSimulation] getter, the
/// [currentIntervalOffset] getter, and the [step] function to select the
/// appropriate simulation at a given time interval. This class implements the
/// [x], [dx], and [isDone] functions by calling the [step] method if necessary
/// and then deferring to the [currentSimulation]'s methods with a time offset
/// by [currentIntervalOffset].
///
/// The tolerance of this simulation is pushed to the simulations that are used
/// by this group as they become active. This mean simulations should not be
/// shared among different groups that are active at the same time.
21
abstract class SimulationGroup extends Simulation {
22

Ian Hickson's avatar
Ian Hickson committed
23 24 25 26
  /// The currently active simulation.
  ///
  /// This getter should return the same value until [step] is called and
  /// returns true.
27 28
  Simulation get currentSimulation;

Ian Hickson's avatar
Ian Hickson committed
29 30
  /// The time offset applied to the currently active simulation when deferring
  /// [x], [dx], and [isDone] to it.
31 32 33
  double get currentIntervalOffset;

  /// Called when a significant change in the interval is detected. Subclasses
Ian Hickson's avatar
Ian Hickson committed
34 35 36 37 38 39 40
  /// must decide if the current simulation must be switched (or updated).
  ///
  /// Must return true if the simulation was switched in this step, otherwise
  /// false.
  ///
  /// If this function returns true, then [currentSimulation] must start
  /// returning a new value.
41
  bool step(double time);
42

Ian Hickson's avatar
Ian Hickson committed
43 44 45 46 47 48 49 50 51 52
  double _lastStep = -1.0;
  void _stepIfNecessary(double time) {
    if (nearEqual(_lastStep, time, Tolerance.defaultTolerance.time))
      return;

    _lastStep = time;
    if (step(time))
      currentSimulation.tolerance = tolerance;
  }

53
  @override
54 55
  double x(double time) {
    _stepIfNecessary(time);
56
    return currentSimulation.x(time - currentIntervalOffset);
57 58
  }

59
  @override
60 61
  double dx(double time) {
    _stepIfNecessary(time);
62
    return currentSimulation.dx(time - currentIntervalOffset);
63 64 65 66 67
  }

  @override
  bool isDone(double time) {
    _stepIfNecessary(time);
68
    return currentSimulation.isDone(time - currentIntervalOffset);
69 70
  }

Ian Hickson's avatar
Ian Hickson committed
71
  @override
72
  set tolerance(Tolerance t) {
Ian Hickson's avatar
Ian Hickson committed
73 74
    currentSimulation.tolerance = t;
    super.tolerance = t;
75 76
  }
}