Skip to content

Commit

Permalink
use computeShapeBounds optimization for histograms, #146
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed Aug 26, 2019
1 parent 0efca66 commit 5760808
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 47 deletions.
13 changes: 13 additions & 0 deletions js/energy/view/BarPlotNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define( require => {
'use strict';

// modules
const Bounds2 = require( 'DOT/Bounds2' );
const ColorDef = require( 'SCENERY/util/ColorDef' );
const Dimension2 = require( 'DOT/Dimension2' );
const gasProperties = require( 'GAS_PROPERTIES/gasProperties' );
Expand Down Expand Up @@ -36,6 +37,7 @@ define( require => {
// @private
this.chartSize = chartSize;
this.yScaleProperty = yScaleProperty;
this.shapeBounds = new Bounds2( 0, 0, chartSize.width, chartSize.height );
}

/**
Expand Down Expand Up @@ -67,6 +69,17 @@ define( require => {
}
this.shape = shape;
}

/**
* Always use the full chart bounds, as a performance optimization.
* See https://github.com/phetsims/gas-properties/issues/146
* @returns {Bounds2}
* @public
* @override
*/
computeShapeBounds() {
return this.shapeBounds;
}
}

return gasProperties.register( 'BarPlotNode', BarPlotNode );
Expand Down
49 changes: 5 additions & 44 deletions js/energy/view/HistogramNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,15 @@ define( require => {
const Emitter = require( 'AXON/Emitter' );
const gasProperties = require( 'GAS_PROPERTIES/gasProperties' );
const GasPropertiesColorProfile = require( 'GAS_PROPERTIES/common/GasPropertiesColorProfile' );
const GasPropertiesConstants = require( 'GAS_PROPERTIES/common/GasPropertiesConstants' );
const IntervalLinesNode = require( 'GAS_PROPERTIES/energy/view/IntervalLinesNode' );
const LinePlotNode = require( 'GAS_PROPERTIES/energy/view/LinePlotNode' );
const Node = require( 'SCENERY/nodes/Node' );
const NumberProperty = require( 'AXON/NumberProperty' );
const Path = require( 'SCENERY/nodes/Path' );
const PhetFont = require( 'SCENERY_PHET/PhetFont' );
const Property = require( 'AXON/Property' );
const Rectangle = require( 'SCENERY/nodes/Rectangle' );
const Shape = require( 'KITE/Shape' );
const Tandem = require( 'TANDEM/Tandem' );
const Text = require( 'SCENERY/nodes/Text' );
const Util = require( 'DOT/Util' );

// Options for all histogram axis labels
const HISTOGRAM_AXIS_LABEL_OPTIONS = {
Expand Down Expand Up @@ -76,25 +73,13 @@ define( require => {
plotLineWidth: 2, // lineWidth for line segment plots
barColor: 'white', // {ColorDef}

// {number} space between the interval lines, in number of particles
intervalLinesSpacing: GasPropertiesConstants.HISTOGRAM_LINE_SPACING,

// options that style the interval lines
intervalLineOptions: {
stroke: 'white', // {ColorDef}
opacity: 0.5, // (0,1)
lineWidth: 0.5
},

// phet-io
tandem: Tandem.required

}, options );

assert && assert( options.barColor !== null && ColorDef.isColorDef( options.barColor ),
`invalid barColor: ${options.barColor}` );
assert && assert( options.intervalLinesSpacing > 0 && Util.isInteger( options.intervalLinesSpacing ),
'intervalLinesSpacing must be a positive integer: ' + options.intervalLinesSpacing );

// Background appears behind plotted data
const background = new Rectangle( 0, 0, options.chartSize.width, options.chartSize.height, {
Expand All @@ -121,10 +106,8 @@ define( require => {
children: [ allPlotNode, heavyPlotNode, lightPlotNode ]
} );

// Horizontal lines that appear at equally-spaced intervals based on y-axis scale.
// These lines are intended to cue the student about the relative scale of the y axis.
// More lines means a larger value for 'Number of Particles'.
const intervalLines = new Path( null, options.intervalLineOptions );
// Horizontal lines that indicate y-axis scale.
const intervalLines = new IntervalLinesNode( options.chartSize );

// x-axis label
const xAxisLabelNode = new Text( xAxisString, _.extend( {}, HISTOGRAM_AXIS_LABEL_OPTIONS, {
Expand Down Expand Up @@ -172,35 +155,13 @@ define( require => {
}
};

// Update the interval lines if the y-axis scale has changed.
let previousMaxY = null;
const updateIntervalLines = () => {
const maxY = yScaleProperty.value;
if ( previousMaxY === null || previousMaxY !== maxY ) {

const shape = new Shape();

const numberOfLines = Math.floor( maxY / options.intervalLinesSpacing );
const ySpacing = ( options.intervalLinesSpacing / maxY ) * options.chartSize.height;

for ( let i = 1; i <= numberOfLines; i++ ) {
const y = options.chartSize.height - ( i * ySpacing );
shape.moveTo( 0, y ).lineTo( options.chartSize.width, y );
}

intervalLines.shape = shape;

previousMaxY = maxY;
}
};

// Update everything
const update = () => {
updatePlots();
updateIntervalLines();
intervalLines.update( yScaleProperty.value );
};

// @public whether update are enabled, false ignores binCountsUpdatedEmitter.
// @public whether updates are enabled, false ignores binCountsUpdatedEmitter.
// This is used to prevent updates when the accordion box containing a histogram is collapsed.
this.updateEnabledProperty = new BooleanProperty( true );
this.updateEnabledProperty.lazyLink( updateEnabled => {
Expand Down
77 changes: 77 additions & 0 deletions js/energy/view/IntervalLinesNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2019, University of Colorado Boulder

/**
* IntervalLinesNode renders the horizontal lines that appear at equally-spaced intervals based on a histogram's
* y-axis scale. These lines are intended to cue the student about the relative scale of the y axis. More lines
* means a larger value for 'Number of Particles'.
*
* @author Chris Malley (PixelZoom, Inc.)
*/
define( require => {
'use strict';

// modules
const Bounds2 = require( 'DOT/Bounds2' );
const Dimension2 = require( 'DOT/Dimension2' );
const gasProperties = require( 'GAS_PROPERTIES/gasProperties' );
const GasPropertiesConstants = require( 'GAS_PROPERTIES/common/GasPropertiesConstants' );
const Path = require( 'SCENERY/nodes/Path' );
const Shape = require( 'KITE/Shape' );

class IntervalLinesNode extends Path {

/**
* @param {Dimension2} chartSize - dimensions of the chart
*/
constructor( chartSize ) {
assert && assert( chartSize instanceof Dimension2, `invalid chartSize: ${chartSize}` );

super( new Shape(), {
stroke: 'white', // {ColorDef}
opacity: 0.5, // (0,1)
lineWidth: 0.5
} );

// @private
this.chartSize = chartSize;
this.shapeBounds = new Bounds2( 0, 0, chartSize.width, chartSize.height );
}

/**
* Updates the lines to match the current y scale.
* @param {number} maxY
* @public
*/
update( maxY ) {
if ( this.previousMaxY === null || this.previousMaxY !== maxY ) {

const shape = new Shape();

const numberOfLines = Math.floor( maxY / GasPropertiesConstants.HISTOGRAM_LINE_SPACING );
const ySpacing = ( GasPropertiesConstants.HISTOGRAM_LINE_SPACING / maxY ) * this.chartSize.height;

for ( let i = 1; i <= numberOfLines; i++ ) {
const y = this.chartSize.height - ( i * ySpacing );
shape.moveTo( 0, y ).lineTo( this.chartSize.width, y );
}

this.shape = shape;

this.previousMaxY = maxY;
}
}

/**
* Always use the full chart bounds, as a performance optimization.
* See https://github.com/phetsims/gas-properties/issues/146
* @returns {Bounds2}
* @public
* @override
*/
computeShapeBounds() {
return this.shapeBounds;
}
}

return gasProperties.register( 'IntervalLinesNode', IntervalLinesNode );
} );
19 changes: 16 additions & 3 deletions js/energy/view/LinePlotNode.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2019, University of Colorado Boulder

/**
* LinePlotNode plots histogram data as a set of connected line segments. It is used to overlay specifies-specific
* LinePlotNode plots histogram data as a set of connected line segments. It is used to overlay species-specific
* histogram data on top of a more typical bar-style histogram.
*
* @author Chris Malley (PixelZoom, Inc.)
Expand All @@ -10,6 +10,7 @@ define( require => {
'use strict';

// modules
const Bounds2 = require( 'DOT/Bounds2' );
const ColorDef = require( 'SCENERY/util/ColorDef' );
const Dimension2 = require( 'DOT/Dimension2' );
const gasProperties = require( 'GAS_PROPERTIES/gasProperties' );
Expand All @@ -32,14 +33,15 @@ define( require => {
assert && assert( typeof lineWidth === 'number' && lineWidth > 0, `invalid lineWidth: ${lineWidth}` );

super( new Shape(), {
fill: null,
stroke: color, // to hide seams
fill: null, // because we're drawing lines
stroke: color,
lineWidth: lineWidth
} );

// @private
this.chartSize = chartSize;
this.yScaleProperty = yScaleProperty;
this.shapeBounds = new Bounds2( 0, 0, chartSize.width, chartSize.height );
}

/**
Expand Down Expand Up @@ -73,6 +75,17 @@ define( require => {
}
this.shape = shape;
}

/**
* Always use the full chart bounds, as a performance optimization.
* See https://github.com/phetsims/gas-properties/issues/146
* @returns {Bounds2}
* @public
* @override
*/
computeShapeBounds() {
return this.shapeBounds;
}
}

return gasProperties.register( 'LinePlotNode', LinePlotNode );
Expand Down

0 comments on commit 5760808

Please sign in to comment.