Skip to content

Commit

Permalink
improve performance of ParticlesNode (Canvas), #209
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed Dec 5, 2022
1 parent 90d2885 commit 6cde9b7
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 8 deletions.
9 changes: 8 additions & 1 deletion js/common/model/Solute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ export default class Solute extends PhetioObject {
// percent concentration [0,100] of stock solution, see https://github.com/phetsims/beers-law-lab/issues/149
public readonly stockSolutionPercentConcentration: number;

public constructor( providedOptions: SoluteOptions ) {
// Precomputed for rendering performance with Canvas.
public readonly fillStyle: string;
public readonly strokeStyle: string;

private constructor( providedOptions: SoluteOptions ) {

assert && assert( Solute.SoluteIO, 'SoluteIO and Solute instances are statics, so make sure SoluteIO exists' );

Expand Down Expand Up @@ -107,6 +111,9 @@ export default class Solute extends PhetioObject {
( Solvent.WATER.density + ( options.molarMass * options.stockSolutionConcentration ) );
assert && assert( this.stockSolutionPercentConcentration >= 0 && this.stockSolutionPercentConcentration <= 100 );

this.fillStyle = options.particleColor.getCanvasStyle();
this.strokeStyle = options.particleColor.darkerColor().getCanvasStyle();

this.addLinkedElement( options.nameProperty, {
tandem: options.tandem.createTandem( 'nameProperty' )
} );
Expand Down
2 changes: 1 addition & 1 deletion js/concentration/model/ConcentrationModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export default class ConcentrationModel implements TModel {
tandem: tandem.createTandem( 'shaker' )
} );

this.shakerParticles = new ShakerParticles( this.shaker, this.solution, this.beaker, {
this.shakerParticles = new ShakerParticles( this.solution, this.beaker, this.shaker, {
tandem: tandem.createTandem( 'shakerParticles' )
} );

Expand Down
40 changes: 40 additions & 0 deletions js/concentration/model/Particles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2022, University of Colorado Boulder

/**
* Particles is the base class for all systems of particles.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import Solute from '../../common/model/Solute.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';

export default class Particles {

protected readonly soluteProperty: TReadOnlyProperty<Solute>;

protected constructor( soluteProperty: TReadOnlyProperty<Solute> ) {
this.soluteProperty = soluteProperty;
}

/**
* Gets the size of all particles in the system. Particles are square.
*/
public getParticleSize(): number {
return this.soluteProperty.value.particleSize;
}

/**
* Gets the Canvas fillStyle for all particles in the system.
*/
public getFillStyle(): string {
return this.soluteProperty.value.fillStyle;
}

/**
* Gets the Canvas strokeStyle for all particles in the system.
*/
public getStrokeStyle(): string {
return this.soluteProperty.value.strokeStyle;
}
}
7 changes: 5 additions & 2 deletions js/concentration/model/Precipitate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@ import { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js';
import beersLawLab from '../../beersLawLab.js';
import Beaker from './Beaker.js';
import ConcentrationSolution from './ConcentrationSolution.js';
import Particles from './Particles.js';
import PrecipitateParticleGroup from './PrecipitateParticleGroup.js';

type SelfOptions = EmptySelfOptions;

type PrecipitateOptions = SelfOptions & PickRequired<PhetioObjectOptions, 'tandem'>;

export default class Precipitate {
export default class Precipitate extends Particles {

private readonly solution: ConcentrationSolution;
private readonly beaker: Beaker;
public readonly particleGroup: PrecipitateParticleGroup;

public constructor( solution: ConcentrationSolution, beaker: Beaker, providedOptions: PrecipitateOptions ) {

super( solution.soluteProperty );

this.solution = solution;
this.beaker = beaker;

Expand All @@ -40,7 +43,7 @@ export default class Precipitate {
this.solution.precipitateMolesProperty.link( () => this.updateParticles() );

// when the solute changes, remove all particles and create new particles for the solute
this.solution.soluteProperty.link( () => {
this.solution.soluteProperty.link( solute => {

// Remove all particles, unless solute was being restored by PhET-iO. Particles will be restored by particleGroup.
if ( !phet.joist.sim.isSettingPhetioStateProperty.value ) {
Expand Down
18 changes: 14 additions & 4 deletions js/concentration/model/ShakerParticles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import beersLawLab from '../../beersLawLab.js';
import BLLConstants from '../../common/BLLConstants.js';
import Beaker from './Beaker.js';
import ConcentrationSolution from './ConcentrationSolution.js';
import Particles from './Particles.js';
import Shaker from './Shaker.js';
import ShakerParticleGroup from './ShakerParticleGroup.js';

Expand All @@ -33,16 +34,25 @@ type SelfOptions = EmptySelfOptions;

type ShakerParticlesOptions = SelfOptions & PickRequired<PhetioObjectOptions, 'tandem'>;

export default class ShakerParticles {
export default class ShakerParticles extends Particles {

private readonly solution: ConcentrationSolution;
private readonly beaker: Beaker;
private readonly shaker: Shaker;
public readonly particleGroup: ShakerParticleGroup;
public readonly particlesMovedEmitter: Emitter; // emits on step if one or more particles has moved

public constructor( private readonly shaker: Shaker,
private readonly solution: ConcentrationSolution,
private readonly beaker: Beaker,
public constructor( solution: ConcentrationSolution,
beaker: Beaker,
shaker: Shaker,
providedOptions: ShakerParticlesOptions ) {

super( solution.soluteProperty );

this.solution = solution;
this.beaker = beaker;
this.shaker = shaker;

this.particleGroup = new ShakerParticleGroup( {
tandem: providedOptions.tandem.createTandem( 'particleGroup' )
} );
Expand Down

0 comments on commit 6cde9b7

Please sign in to comment.