Skip to content

Commit

Permalink
use ToleranceProperty for applied force and displacement, to avoid up…
Browse files Browse the repository at this point in the history
…date cycles, #52

Signed-off-by: Chris Malley <cmalley@pixelzoom.com>
  • Loading branch information
pixelzoom committed Aug 18, 2018
1 parent 2e1f18b commit dab4f7d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
12 changes: 10 additions & 2 deletions js/common/model/Spring.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ define( function( require ) {
var Range = require( 'DOT/Range' );
var RangeWithValue = require( 'DOT/RangeWithValue' );
var Tandem = require( 'TANDEM/Tandem' );
var ToleranceProperty = require( 'HOOKES_LAW/common/model/ToleranceProperty' );

// ifphetio
var NumberIO = require( 'ifphetio!PHET_IO/types/NumberIO' );
Expand Down Expand Up @@ -118,7 +119,10 @@ define( function( require ) {
// Properties

// @public applied force (F)
this.appliedForceProperty = new NumberProperty( this.appliedForceRange.defaultValue, {
// Computation of this Property's value often results in floating point error that cause update cycles,
// so use a Property that updates only if the new value is sufficiently different from the current value.
// See https://github.com/phetsims/hookes-law/issues/52
this.appliedForceProperty = new ToleranceProperty( this.appliedForceRange.defaultValue, {
range: this.appliedForceRange,
units: 'newtons',
tandem: options.tandem.createTandem( 'appliedForceProperty' )
Expand All @@ -136,7 +140,10 @@ define( function( require ) {
function( springConstant ) { phet.log( options.logName + ' springConstant=' + springConstant ); } );

// @public displacement from equilibrium position (x)
this.displacementProperty = new NumberProperty( this.displacementRange.defaultValue, {
// Computation of this Property's value often results in floating point error that cause update cycles,
// so use a Property that updates only if the new value is sufficiently different from the current value.
// See https://github.com/phetsims/hookes-law/issues/52
this.displacementProperty = new ToleranceProperty( this.displacementRange.defaultValue, {
range: this.displacementRange,
units: 'meters',
tandem: options.tandem.createTandem( 'displacementProperty' )
Expand Down Expand Up @@ -214,6 +221,7 @@ define( function( require ) {
function( length ) { phet.log( options.logName + ' length=' + length ); } );

// @public potential energy, E = ( k1 * x1 * x1 ) / 2
// To avoid intermediate values, define this *after* the listeners that update its dependencies.
this.potentialEnergyProperty = new DerivedProperty( [ this.springConstantProperty, this.displacementProperty ],
function( springConstant, displacement ) {
return ( springConstant * displacement * displacement ) / 2;
Expand Down
50 changes: 50 additions & 0 deletions js/common/model/ToleranceProperty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2018, University of Colorado Boulder

/**
* NumberProperty that sets its values only if the new value is sufficiently different from the current value.
* Used to avoid update cycles that are due to floating point error.
* See https://github.com/phetsims/hookes-law/issues/52
*
* @author Chris Malley (PixelZoom, Inc.)
*/
define( function( require ) {
'use strict';

// modules
var hookesLaw = require( 'HOOKES_LAW/hookesLaw' );
var inherit = require( 'PHET_CORE/inherit' );
var NumberProperty = require( 'AXON/NumberProperty' );

/**
* @param {number} value
* @param {Object} options
* @constructor
*/
function ToleranceProperty( value, options ) {

options = _.extend( {
tolerance: 1e-10
}, options );

// @private
this.tolerance = options.tolerance;

NumberProperty.call( this, value, options );
}

hookesLaw.register( 'ToleranceProperty', ToleranceProperty );

return inherit( NumberProperty, ToleranceProperty, {

/**
* Sets the value if it's difference from the current value exceeds some tolerance.
* Otherwise the value is not set, silently ignored, and this is a no-op.
* @param {number} value
*/
set: function( value ) {
if ( Math.abs( value - this.get() ) > this.tolerance ) {
NumberProperty.prototype.set.call( this, value );
}
}
} );
} );

0 comments on commit dab4f7d

Please sign in to comment.