Skip to content

Commit

Permalink
initial work on Arrow scene, #228
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed Feb 10, 2022
1 parent 481d118 commit 1f25a3f
Show file tree
Hide file tree
Showing 22 changed files with 684 additions and 10 deletions.
3 changes: 3 additions & 0 deletions geometric-optics-strings_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
"valueCentimetersPattern": {
"value": "{{value}} cm"
},
"arrow": {
"value": "Arrow"
},
"pencil": {
"value": "Pencil"
},
Expand Down
Binary file added images/arrowIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions images/arrowIcon_png.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions images/license.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"arrowIcon.png": {
"text": [
"Copyright 2022 University of Colorado Boulder"
],
"projectURL": "https://phet.colorado.edu",
"license": "contact [email protected]"
},
"pencilIcon.png": {
"text": [
"Copyright 2021 University of Colorado Boulder"
Expand Down
16 changes: 16 additions & 0 deletions js/common/GOColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ const GOColors = {
default: 'black'
} ),

arrow1FillProperty: new ProfileColorProperty( geometricOptics, 'arrow1Fill', {
default: 'green'
} ),

arrow1StrokeProperty: new ProfileColorProperty( geometricOptics, 'arrow1Stroke', {
default: 'black'
} ),

arrow2FillProperty: new ProfileColorProperty( geometricOptics, 'arrow2Fill', {
default: 'rgb( 255, 51, 51 )' //TODO same as secondPointFillProperty
} ),

arrow2StrokeProperty: new ProfileColorProperty( geometricOptics, 'arrow2Stroke', {
default: 'black'
} ),

// Rays associated with the first Optical Object
rays1StrokeProperty: new ProfileColorProperty( geometricOptics, 'realRayOneStroke', {
default: 'rgb( 140, 140, 140 )'
Expand Down
8 changes: 8 additions & 0 deletions js/common/GOConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ const GOConstants = {
headWidth: 12,
headHeight: 8,
tailWidth: 3
},

ARROW_NODE_OPTIONS: {
headWidth: 24,
headHeight: 28,
tailWidth: 7,
isHeadDynamic: true,
fractionalHeadHeight: 0.5
}
};

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

/**
* ArrowImage is the model of the optical image associated with an arrow object.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import geometricOptics from '../../geometricOptics.js';
import OpticalImage, { OpticalImageOptions } from './OpticalImage.js';
import Optic from './Optic.js';
import merge from '../../../../phet-core/js/merge.js';
import ArrowObject from './ArrowObject.js';

class ArrowImage extends OpticalImage {

/**
* @param arrowObject
* @param optic
* @param providedOptions
*/
constructor( arrowObject: ArrowObject,
optic: Optic,
providedOptions: OpticalImageOptions ) {

const options = merge( {}, providedOptions );

super( arrowObject.positionProperty, optic, options );

//TODO more?
}
}

geometricOptics.register( 'ArrowImage', ArrowImage );
export default ArrowImage;
41 changes: 41 additions & 0 deletions js/common/model/ArrowObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2021-2022, University of Colorado Boulder

/**
* ArrowObject is the model for arrow objects.
*
* @author Martin Veillette
* @author Chris Malley (PixelZoom, Inc.)
*/

import geometricOptics from '../../geometricOptics.js';
import OpticalObject, { OpticalObjectOptions } from './OpticalObject.js';
import merge from '../../../../phet-core/js/merge.js';

type ArrowObjectOptions = {
fill: ColorDef
stroke: ColorDef
} & OpticalObjectOptions;

class ArrowObject extends OpticalObject {

public readonly fill: ColorDef;
public readonly stroke: ColorDef;

/**
* @param providedOptions
*/
constructor( providedOptions: ArrowObjectOptions ) {

const options = merge( {}, providedOptions );

super( options );

this.fill = options.fill;
this.stroke = options.stroke;

//TODO more?
}
}

geometricOptics.register( 'ArrowObject', ArrowObject );
export default ArrowObject;
161 changes: 161 additions & 0 deletions js/common/model/ArrowObjectScene.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2022, University of Colorado Boulder

//TODO lots of duplication with FramedObjectScene
/**
* ArrowObjectScene is a scene in which rays from two arrows interact with an optic and produce an Image.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import Range from '../../../../dot/js/Range.js';
import geometricOptics from '../../geometricOptics.js';
import Optic from './Optic.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import merge from '../../../../phet-core/js/merge.js';
import { RaysType } from './RaysType.js';
import NumberProperty from '../../../../axon/js/NumberProperty.js';
import LightRays from './LightRays.js';
import IReadOnlyProperty from '../../../../axon/js/IReadOnlyProperty.js';
import Lens from '../../lens/model/Lens.js';
import PhetioObject from '../../../../tandem/js/PhetioObject.js';
import Guides from '../../lens/model/Guides.js';
import ArrowObject from './ArrowObject.js';
import ArrowImage from './ArrowImage.js';
import GOColors from '../GOColors.js';

type ArrowObjectSceneOptions = {

// initial positions of the arrow objects
arrowObject1Position: Vector2,
arrowObject2Position: Vector2,

// phet-io options
tandem: Tandem
};

class ArrowObjectScene extends PhetioObject {

readonly optic: Optic;
readonly arrowObject1: ArrowObject;
readonly arrowObject2: ArrowObject;
readonly arrowImage1: ArrowImage;
readonly arrowImage2: ArrowImage;
readonly lightRaysAnimationTimeProperty: NumberProperty;
readonly lightRays1: LightRays;
readonly lightRays2: LightRays;
readonly guides1: Guides | null;
readonly guides2: Guides | null;
private readonly resetArrowObjectScene: () => void;

/**
* @param optic
* @param raysTypeProperty
* @param providedOptions
*/
constructor( optic: Optic,
raysTypeProperty: IReadOnlyProperty<RaysType>,
providedOptions: ArrowObjectSceneOptions ) {

const options = merge( {
phetioState: false
}, providedOptions );

super( options );

this.optic = optic;

this.addLinkedElement( optic, {
tandem: options.tandem.createTandem( 'optic' )
} );

this.arrowObject1 = new ArrowObject( {
position: options.arrowObject1Position,
fill: GOColors.arrow1FillProperty,
stroke: GOColors.arrow1StrokeProperty,
tandem: options.tandem.createTandem( 'arrowObject1' )
} );

this.arrowObject2 = new ArrowObject( {
position: options.arrowObject2Position,
fill: GOColors.arrow2FillProperty,
stroke: GOColors.arrow2StrokeProperty,
tandem: options.tandem.createTandem( 'arrowObject2' )
} );

this.arrowImage1 = new ArrowImage( this.arrowObject1, this.optic, {
tandem: options.tandem.createTandem( 'arrowImage1' ),
phetioDocumentation: 'optical image associated with the first arrow object'
} );

this.arrowImage2 = new ArrowImage( this.arrowObject2, this.optic, {
tandem: options.tandem.createTandem( 'arrowImage2' ),
phetioDocumentation: 'optical image associated with the second arrow object'
} );

this.lightRaysAnimationTimeProperty = new NumberProperty( 0, {
units: 's',
range: new Range( 0, 10 ), // determines the duration of the light rays animation
tandem: options.tandem.createTandem( 'lightRaysAnimationTimeProperty' ),
phetioReadOnly: true
} );

this.lightRays1 = new LightRays(
this.lightRaysAnimationTimeProperty,
raysTypeProperty,
this.arrowObject1.positionProperty,
this.optic,
this.arrowImage1
);

this.lightRays2 = new LightRays(
this.lightRaysAnimationTimeProperty,
raysTypeProperty,
this.arrowObject2.positionProperty,
this.optic,
this.arrowImage2
);

// Guides
if ( optic instanceof Lens ) {
this.guides1 = new Guides( this.optic, this.arrowObject1.positionProperty, {
tandem: options.tandem.createTandem( 'guides1' ),
phetioDocumentation: 'guides associated with the first arrow object'
} );
this.guides2 = new Guides( this.optic, this.arrowObject2.positionProperty, {
tandem: options.tandem.createTandem( 'guides2' ),
phetioDocumentation: 'guides associated with the second arrow object'
} );
}
else {
this.guides1 = null;
this.guides2 = null;
}

//TODO is this complete?
this.resetArrowObjectScene = () => {
this.arrowObject1.reset();
this.arrowObject2.reset();
this.lightRaysAnimationTimeProperty.reset();
};
}

public reset(): void {
this.resetArrowObjectScene();
}

/**
* Steps the animation of light rays.
* @param dt - time step, in seconds
*/
public stepLightRays( dt: number ): void {
const t = Math.min( this.lightRaysAnimationTimeProperty.value + dt, this.lightRaysAnimationTimeProperty.range!.max );
assert && assert( this.lightRaysAnimationTimeProperty.range ); // {Range|null}
if ( this.lightRaysAnimationTimeProperty.range!.contains( t ) ) {
this.lightRaysAnimationTimeProperty.value = t;
}
}
}

geometricOptics.register( 'ArrowObjectScene', ArrowObjectScene );
export default ArrowObjectScene;
3 changes: 1 addition & 2 deletions js/common/model/FramedImage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright 2021-2022, University of Colorado Boulder

//TODO this entire class needs to be reviewed/revised
/**
* FramedImage is the model of an optical image associated with a framed object.
* FramedImage is the model of the optical image associated with a framed object.
*
* @author Martin Veillette
* @author Chris Malley (PixelZoom, Inc.)
Expand Down
1 change: 0 additions & 1 deletion js/common/model/FramedObjectScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ class FramedObjectScene extends PhetioObject {

// Guides
if ( optic instanceof Lens ) {

this.guides1 = new Guides( this.optic, this.framedObject.positionProperty, {
tandem: options.tandem.createTandem( 'guides1' ),
phetioDocumentation: 'guides associated with the first point-of-interest on the framed object'
Expand Down
Loading

0 comments on commit 1f25a3f

Please sign in to comment.