From 13a67dc19a25e7e26a211254081d8136153f7bc4 Mon Sep 17 00:00:00 2001 From: Luisav1 Date: Fri, 14 Oct 2022 10:14:23 -0600 Subject: [PATCH] Factor out functions that determine the electron cloud size from ChartIntroScreenView.ts and DecayScreenView.ts to BANScreenView.ts. See https://github.com/phetsims/build-a-nucleus/issues/46. --- js/chart-intro/view/ChartIntroScreenView.ts | 49 +------------------ js/common/view/BANScreenView.ts | 52 +++++++++++++++++++++ js/decay/view/DecayScreenView.ts | 49 +------------------ 3 files changed, 56 insertions(+), 94 deletions(-) diff --git a/js/chart-intro/view/ChartIntroScreenView.ts b/js/chart-intro/view/ChartIntroScreenView.ts index 5b81c05..21bfcd0 100644 --- a/js/chart-intro/view/ChartIntroScreenView.ts +++ b/js/chart-intro/view/ChartIntroScreenView.ts @@ -12,13 +12,12 @@ import ChartIntroModel from '../model/ChartIntroModel.js'; import optionize, { EmptySelfOptions } from '../../../../phet-core/js/optionize.js'; import BANScreenView, { BANScreenViewOptions } from '../../common/view/BANScreenView.js'; import BANConstants from '../../common/BANConstants.js'; -import { Color, RadialGradient, Text } from '../../../../scenery/js/imports.js'; +import { Color, Text } from '../../../../scenery/js/imports.js'; import PhetFont from '../../../../scenery-phet/js/PhetFont.js'; import AtomIdentifier from '../../../../shred/js/AtomIdentifier.js'; import Particle from '../../../../shred/js/model/Particle.js'; import ParticleAtom from '../../../../shred/js/model/ParticleAtom.js'; import ParticleType from '../../common/view/ParticleType.js'; -import LinearFunction from '../../../../dot/js/LinearFunction.js'; import Multilink from '../../../../axon/js/Multilink.js'; import PeriodicTableAndIsotopeSymbol from './PeriodicTableAndIsotopeSymbol.js'; @@ -43,52 +42,8 @@ class ChartIntroScreenView extends BANScreenView { this.model = model; - // function that updates the size of the electron cloud based on the protonNumber since the nuclides created are neutral - // meaning the number of electrons is the same as the number of protons - const updateCloudSize = ( protonCount: number ) => { - if ( protonCount === 0 ) { - this.electronCloud.radius = 1E-5; // arbitrary non-zero value - this.electronCloud.fill = 'transparent'; - } - else { - const radius = this.modelViewTransform.modelToViewDeltaX( getElectronShellDiameter( protonCount ) / 2 ); - this.electronCloud.radius = radius * 0.65; - this.electronCloud.fill = new RadialGradient( 0, 0, 0, 0, 0, radius * 0.65 ) - .addColorStop( 0, 'rgba( 0, 0, 255, 200 )' ) - .addColorStop( 0.9, 'rgba( 0, 0, 255, 0 )' ); - } - }; - // update the cloud size as the massNumber changes - model.particleAtom.protonCountProperty.link( updateCloudSize ); - - // Maps a number of electrons to a diameter in screen coordinates for the electron shell. This mapping function is - // based on the real size relationships between the various atoms, but has some tweakable parameters to reduce the - // range and scale to provide values that are usable for our needs on the canvas. - const getElectronShellDiameter = ( numElectrons: number ) => { - const maxElectrons = this.model.protonCountRange.max; // for uranium - const atomicRadius = AtomIdentifier.getAtomicRadius( numElectrons ); - if ( atomicRadius ) { - return reduceRadiusRange( atomicRadius, this.model.protonCountRange.min + 1, maxElectrons ); - } - else { - assert && assert( numElectrons <= maxElectrons, `Atom has more than supported number of electrons, ${numElectrons}` ); - return 0; - } - }; - - // This method increases the value of the smaller radius values and decreases the value of the larger ones. - // This effectively reduces the range of radii values used. - // This is a very specialized function for the purposes of this class. - const reduceRadiusRange = ( value: number, minShellRadius: number, maxShellRadius: number ) => { - // The following two factors define the way in which an input value is increased or decreased. These values - // can be adjusted as needed to make the cloud size appear as desired. - const minChangedRadius = 70; - const maxChangedRadius = 95; - - const compressionFunction = new LinearFunction( minShellRadius, maxShellRadius, minChangedRadius, maxChangedRadius ); - return compressionFunction.evaluate( value ); - }; + model.particleAtom.protonCountProperty.link( protonCount => this.updateCloudSize( protonCount, 0.65, 10, 20 ) ); // Create the textual readout for the element name. const elementName = new Text( '', { diff --git a/js/common/view/BANScreenView.ts b/js/common/view/BANScreenView.ts index 285f344..2fdee71 100644 --- a/js/common/view/BANScreenView.ts +++ b/js/common/view/BANScreenView.ts @@ -36,6 +36,7 @@ import AtomNode from '../../../../shred/js/view/AtomNode.js'; import Property from '../../../../axon/js/Property.js'; import StringUtils from '../../../../phetcommon/js/util/StringUtils.js'; import ShredConstants from '../../../../shred/js/ShredConstants.js'; +import LinearFunction from '../../../../dot/js/LinearFunction.js'; // empirically determined, from the ElectronCloudView radius const MIN_ELECTRON_CLOUD_RADIUS = 42.5; @@ -479,6 +480,57 @@ abstract class BANScreenView extends ScreenView { this.protonArrowButtons = protonArrowButtons; } + /** + * This method increases the value of the smaller radius values and decreases the value of the larger ones. + * This effectively reduces the range of radii values used. + * This is a very specialized function for the purposes of this class. + * + * minChangedRadius and maxChangedRadius define the way in which an input value is increased or decreased. These values + * can be adjusted as needed to make the cloud size appear as desired. + */ + private static reduceRadiusRange( value: number, minShellRadius: number, maxShellRadius: number, + minChangedRadius: number, maxChangedRadius: number ): number { + const compressionFunction = new LinearFunction( minShellRadius, maxShellRadius, minChangedRadius, maxChangedRadius ); + return compressionFunction.evaluate( value ); + } + + /** + * Maps a number of electrons to a diameter in screen coordinates for the electron shell. This mapping function is + * based on the real size relationships between the various atoms, but has some tweakable parameters to reduce the + * range and scale to provide values that are usable for our needs on the canvas. + */ + private getElectronShellDiameter( numElectrons: number, minChangedRadius: number, maxChangedRadius: number ): number { + const maxElectrons = this.model.protonCountRange.max; + const atomicRadius = AtomIdentifier.getAtomicRadius( numElectrons ); + if ( atomicRadius ) { + return BANScreenView.reduceRadiusRange( atomicRadius, this.model.protonCountRange.min + 1, maxElectrons, + minChangedRadius, maxChangedRadius ); + } + else { + assert && assert( numElectrons <= maxElectrons, `Atom has more than supported number of electrons, ${numElectrons}` ); + return 0; + } + } + + /** + * Update size of electron cloud based on protonNumber since the nuclides created are neutral, meaning the number of + * electrons is the same as the number of protons. + */ + protected updateCloudSize( protonCount: number, factor: number, minChangedRadius: number, maxChangedRadius: number ): void { + if ( protonCount === 0 ) { + this.electronCloud.radius = 1E-5; // arbitrary non-zero value + this.electronCloud.fill = 'transparent'; + } + else { + const radius = this.modelViewTransform.modelToViewDeltaX( + this.getElectronShellDiameter( protonCount, minChangedRadius, maxChangedRadius ) / 2 ); + this.electronCloud.radius = radius * factor; + this.electronCloud.fill = new RadialGradient( 0, 0, 0, 0, 0, radius * factor ) + .addColorStop( 0, 'rgba( 0, 0, 255, 200 )' ) + .addColorStop( 0.9, 'rgba( 0, 0, 255, 0 )' ); + } + } + /** * Get information for a specific particle type. */ diff --git a/js/decay/view/DecayScreenView.ts b/js/decay/view/DecayScreenView.ts index b188c10..2728a1a 100644 --- a/js/decay/view/DecayScreenView.ts +++ b/js/decay/view/DecayScreenView.ts @@ -29,7 +29,6 @@ import Particle from '../../../../shred/js/model/Particle.js'; import ParticleAtom from '../../../../shred/js/model/ParticleAtom.js'; import ParticleType from '../../common/view/ParticleType.js'; import Checkbox from '../../../../sun/js/Checkbox.js'; -import LinearFunction from '../../../../dot/js/LinearFunction.js'; import dotRandom from '../../../../dot/js/dotRandom.js'; import Animation from '../../../../twixt/js/Animation.js'; import Easing from '../../../../twixt/js/Easing.js'; @@ -253,54 +252,10 @@ class DecayScreenView extends BANScreenView { }; model.doesNuclideExistBooleanProperty.link( updateStabilityIndicatorVisibility ); - // function that updates the size of the electron cloud based on the protonNumber since the nuclides created are neutral - // meaning the number of electrons is the same as the number of protons - const updateCloudSize = ( protonCount: number ) => { - if ( protonCount === 0 ) { - this.electronCloud.radius = 1E-5; // arbitrary non-zero value - this.electronCloud.fill = 'transparent'; - } - else { - const radius = this.modelViewTransform.modelToViewDeltaX( getElectronShellDiameter( protonCount ) / 2 ); - this.electronCloud.radius = radius * 2; - this.electronCloud.fill = new RadialGradient( 0, 0, 0, 0, 0, radius * 2 ) - .addColorStop( 0, 'rgba( 0, 0, 255, 200 )' ) - .addColorStop( 0.9, 'rgba( 0, 0, 255, 0 )' ); - } - }; - // update the cloud size as the massNumber changes - model.particleAtom.protonCountProperty.link( updateCloudSize ); - - // TODO: should be moved to BANScreenView bc repeated in Chart screen view - // Maps a number of electrons to a diameter in screen coordinates for the electron shell. This mapping function is - // based on the real size relationships between the various atoms, but has some tweakable parameters to reduce the - // range and scale to provide values that are usable for our needs on the canvas. - const getElectronShellDiameter = ( numElectrons: number ) => { - const maxElectrons = this.model.protonCountRange.max; // for uranium - const atomicRadius = AtomIdentifier.getAtomicRadius( numElectrons ); - if ( atomicRadius ) { - return reduceRadiusRange( atomicRadius, this.model.protonCountRange.min + 1, maxElectrons ); - } - else { - assert && assert( numElectrons <= maxElectrons, `Atom has more than supported number of electrons, ${numElectrons}` ); - return 0; - } - }; - - // This method increases the value of the smaller radius values and decreases the value of the larger ones. - // This effectively reduces the range of radii values used. - // This is a very specialized function for the purposes of this class. - const reduceRadiusRange = ( value: number, minShellRadius: number, maxShellRadius: number ) => { - // The following two factors define the way in which an input value is increased or decreased. These values - // can be adjusted as needed to make the cloud size appear as desired. - const minChangedRadius = 70; - const maxChangedRadius = 95; - - const compressionFunction = new LinearFunction( minShellRadius, maxShellRadius, minChangedRadius, maxChangedRadius ); - return compressionFunction.evaluate( value ); - }; + model.particleAtom.protonCountProperty.link( protonCount => this.updateCloudSize( protonCount, 2, 70, 95 ) ); + // TODO: move elementName to BANScreenView bc text node the same, just positioning different // Create the textual readout for the element name. const elementName = new Text( '', { font: LABEL_FONT,