diff --git a/js/common/model/FELMovable.ts b/js/common/model/FELMovable.ts deleted file mode 100644 index 4e2dc244..00000000 --- a/js/common/model/FELMovable.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2023-2024, University of Colorado Boulder - -/** - * FELMovable is the base class for model elements that have a mutable position. - * - * This is based on FaradayObservable.java in the Java version of this sim. - * - * @author Chris Malley (PixelZoom, Inc.) - */ - -import PhetioObject, { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js'; -import Vector2 from '../../../../dot/js/Vector2.js'; -import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; -import faradaysElectromagneticLab from '../../faradaysElectromagneticLab.js'; -import Property from '../../../../axon/js/Property.js'; -import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; -import Vector2Property, { Vector2PropertyOptions } from '../../../../dot/js/Vector2Property.js'; -import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; -import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; - -type SelfOptions = { - - // Initial value of positionProperty, unitless - position?: Vector2; - - // Options passed to positionProperty - positionPropertyOptions?: Vector2PropertyOptions; -}; - -export type FELMovableOptions = SelfOptions & - PickOptional & - PickRequired; - -export default class FELMovable extends PhetioObject { - - public readonly positionProperty: Property; // unitless - - protected constructor( providedOptions: FELMovableOptions ) { - - const options = optionize, PhetioObjectOptions>()( { - - // SelfOptions - position: Vector2.ZERO, - - // PhetioObjectOptions - isDisposable: false, - phetioState: false, - phetioFeatured: true - }, providedOptions ); - - super( options ); - - this.positionProperty = new Vector2Property( options.position, combineOptions( { - tandem: options.tandem.createTandem( 'positionProperty' ), - phetioFeatured: true - }, options.positionPropertyOptions ) ); - } - - protected reset(): void { - this.positionProperty.reset(); - } -} - -faradaysElectromagneticLab.register( 'FELMovable', FELMovable ); \ No newline at end of file diff --git a/js/common/model/FieldMeasurementTool.ts b/js/common/model/FieldMeasurementTool.ts index f4e5f1e6..4251cd59 100644 --- a/js/common/model/FieldMeasurementTool.ts +++ b/js/common/model/FieldMeasurementTool.ts @@ -12,19 +12,28 @@ import Vector2 from '../../../../dot/js/Vector2.js'; import optionize from '../../../../phet-core/js/optionize.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import DerivedProperty from '../../../../axon/js/DerivedProperty.js'; -import FELMovable, { FELMovableOptions } from './FELMovable.js'; import Property from '../../../../axon/js/Property.js'; import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; +import Vector2Property from '../../../../dot/js/Vector2Property.js'; +import PhetioObject, { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js'; +import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; +import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; type SelfOptions = { + position?: Vector2; // Initial value of positionProperty, unitless visible?: boolean; }; -export type FieldMeasurementToolOptions = SelfOptions & FELMovableOptions; +export type FieldMeasurementToolOptions = SelfOptions & + PickOptional & + PickRequired; -export default class FieldMeasurementTool extends FELMovable { +export default class FieldMeasurementTool extends PhetioObject { - // The field vector at the meter's position, in gauss + // The tool's position, unitless. + public readonly positionProperty: Property; + + // The field vector at the tool's position, in gauss. public readonly fieldVectorProperty: TReadOnlyProperty; // Whether the tool is visible. @@ -32,14 +41,25 @@ export default class FieldMeasurementTool extends FELMovable { protected constructor( magnet: Magnet, providedOptions: FieldMeasurementToolOptions ) { - const options = optionize()( { + const options = optionize()( { + + // SelfOptions + position: Vector2.ZERO, + visible: true, - //SelfOptions - visible: true + // PhetioObjectOptions + isDisposable: false, + phetioState: false, + phetioFeatured: true }, providedOptions ); super( options ); + this.positionProperty = new Vector2Property( options.position, { + tandem: options.tandem.createTandem( 'positionProperty' ), + phetioFeatured: true + } ); + // This needs to be a new Vector2 instance, so do not pass an output vector to magnet.getFieldVector. this.fieldVectorProperty = new DerivedProperty( [ this.positionProperty, magnet.positionProperty, magnet.rotationProperty, magnet.strengthProperty ], @@ -56,8 +76,8 @@ export default class FieldMeasurementTool extends FELMovable { } ); } - public override reset(): void { - super.reset(); + public reset(): void { + this.positionProperty.reset(); this.visibleProperty.reset(); } } diff --git a/js/common/model/Magnet.ts b/js/common/model/Magnet.ts index 9fc9e5df..367beb30 100644 --- a/js/common/model/Magnet.ts +++ b/js/common/model/Magnet.ts @@ -13,8 +13,7 @@ import Range from '../../../../dot/js/Range.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import Property from '../../../../axon/js/Property.js'; import NumberProperty from '../../../../axon/js/NumberProperty.js'; -import optionize from '../../../../phet-core/js/optionize.js'; -import FELMovable, { FELMovableOptions } from './FELMovable.js'; +import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import Bounds2 from '../../../../dot/js/Bounds2.js'; @@ -22,9 +21,20 @@ import Dimension3 from '../../../../dot/js/Dimension3.js'; import Utils from '../../../../dot/js/Utils.js'; import FELQueryParameters from '../FELQueryParameters.js'; import FELConstants from '../FELConstants.js'; +import Vector2Property, { Vector2PropertyOptions } from '../../../../dot/js/Vector2Property.js'; +import PhetioObject, { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js'; +import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; +import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; +import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; type SelfOptions = { + // Initial value of positionProperty, unitless + position?: Vector2; + + // Options passed to positionProperty + positionPropertyOptions?: Vector2PropertyOptions; + // initial value of rotationProperty, radians rotation?: number; @@ -33,9 +43,11 @@ type SelfOptions = { size: Dimension3; }; -export type MagnetOptions = SelfOptions & FELMovableOptions; +export type MagnetOptions = SelfOptions & + PickOptional & + PickRequired; -export default abstract class Magnet extends FELMovable { +export default abstract class Magnet extends PhetioObject { // Dimensions of a 3D magnet, with origin at its center. public readonly size: Dimension3; @@ -43,6 +55,9 @@ export default abstract class Magnet extends FELMovable { // Bounds of the magnet in its local coordinate frame. public readonly localBounds: Bounds2; + // Position of the magnet, unitless. + public readonly positionProperty: Property; + // The range of the magnet's strength, in gauss. public readonly strengthRange: Range; @@ -68,10 +83,16 @@ export default abstract class Magnet extends FELMovable { protected constructor( strengthProperty: TReadOnlyProperty, strengthRange: Range, providedOptions: MagnetOptions ) { - const options = optionize()( { + const options = optionize, PhetioObjectOptions>()( { // SelfOptions - rotation: 0 + position: Vector2.ZERO, + rotation: 0, + + // PhetioObjectOptions + isDisposable: false, + phetioState: false, + phetioFeatured: true }, providedOptions ); super( options ); @@ -81,6 +102,11 @@ export default abstract class Magnet extends FELMovable { // Rectangular, with origin at the center this.localBounds = new Bounds2( -this.size.width / 2, -this.size.height / 2, this.size.width / 2, this.size.height / 2 ); + this.positionProperty = new Vector2Property( options.position, combineOptions( { + tandem: options.tandem.createTandem( 'positionProperty' ), + phetioFeatured: true + }, options.positionPropertyOptions ) ); + this.strengthRange = strengthRange; this.strengthProperty = strengthProperty; @@ -103,8 +129,8 @@ export default abstract class Magnet extends FELMovable { this.reusablePosition = new Vector2( 0, 0 ); } - protected override reset(): void { - super.reset(); + protected reset(): void { + this.positionProperty.reset(); this.rotationProperty.reset(); this.fieldVisibleProperty.reset(); // Do not reset Properties documented as 'DEBUG' above. diff --git a/js/common/model/PickupCoil.ts b/js/common/model/PickupCoil.ts index 29ad950a..902489a3 100644 --- a/js/common/model/PickupCoil.ts +++ b/js/common/model/PickupCoil.ts @@ -22,7 +22,6 @@ import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import LightBulb, { LightBulbOptions } from './LightBulb.js'; import Voltmeter, { VoltmeterOptions } from './Voltmeter.js'; import CurrentIndicator from './CurrentIndicator.js'; -import FELMovable, { FELMovableOptions } from './FELMovable.js'; import FELConstants from '../FELConstants.js'; import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; @@ -31,8 +30,13 @@ import FELQueryParameters, { CurrentFlow } from '../FELQueryParameters.js'; import NumberIO from '../../../../tandem/js/types/NumberIO.js'; import ConstantDtClock from './ConstantDtClock.js'; import Dimension2 from '../../../../dot/js/Dimension2.js'; +import PhetioObject, { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js'; +import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; +import Vector2Property, { Vector2PropertyOptions } from '../../../../dot/js/Vector2Property.js'; type SelfOptions = { + position?: Vector2; // Initial value of positionProperty, unitless + positionPropertyOptions?: Vector2PropertyOptions; // Options passed to positionProperty maxEMF: number; // the initial value of maxEMFProperty transitionSmoothingScale: number; // the initial value of transitionSmoothingScaleProperty samplePointsSpacing: number; // spacing between B-field sample points @@ -42,9 +46,11 @@ type SelfOptions = { voltmeterOptions?: PickOptional; // passed to Voltmeter }; -export type PickupCoilOptions = SelfOptions & FELMovableOptions; +export type PickupCoilOptions = SelfOptions & + PickOptional & + PickRequired; -export default class PickupCoil extends FELMovable { +export default class PickupCoil extends PhetioObject { // The magnet whose field this coil is in public readonly magnet: Magnet; @@ -52,6 +58,9 @@ export default class PickupCoil extends FELMovable { // The coil that induces the EMF public readonly coil: Coil; + // Position of the poickup coil, unitless. + public readonly positionProperty: Property; + // Flux in the coil private readonly _fluxProperty: Property; public readonly fluxProperty: TReadOnlyProperty; @@ -124,10 +133,18 @@ export default class PickupCoil extends FELMovable { public constructor( magnet: Magnet, currentFlowProperty: TReadOnlyProperty, providedOptions: PickupCoilOptions ) { - const options = optionize, FELMovableOptions>()( { + const options = optionize, + PhetioObjectOptions>()( { // SelfOptions - fluxAreaCompensationEnabled: true + position: Vector2.ZERO, + fluxAreaCompensationEnabled: true, + + // PhetioObjectOptions + isDisposable: false, + phetioState: false, + phetioFeatured: true }, providedOptions ); super( options ); @@ -136,6 +153,11 @@ export default class PickupCoil extends FELMovable { this.magnet = magnet; + this.positionProperty = new Vector2Property( options.position, combineOptions( { + tandem: options.tandem.createTandem( 'positionProperty' ), + phetioFeatured: true + }, options.positionPropertyOptions ) ); + // We want some Properties to appear to be children of the coil element. We could also have done this by // subclassing Coil, but having something like PickupCoilCoil seemed confusing, and unnecessary. const coilTandem = options.tandem.createTandem( 'coil' ); @@ -235,8 +257,8 @@ export default class PickupCoil extends FELMovable { this.fluxProperty = this._fluxProperty; } - public override reset(): void { - super.reset(); + public reset(): void { + this.positionProperty.reset(); this.coil.reset(); this._fluxProperty.reset(); this._deltaFluxProperty.reset();