From 8569d0107db43b533593f74814d477ce398edb07 Mon Sep 17 00:00:00 2001 From: pixelzoom Date: Wed, 13 Apr 2022 13:38:55 -0600 Subject: [PATCH] add LightSpot.intersectsProjectionScreenProperty, use it to set visibility of LightSpotNode and therefore filter out tool jump points, https://github.com/phetsims/geometric-optics/issues/426 --- js/common/model/LightSpot.ts | 17 +++++++++++++++-- js/common/model/ProjectionScreen.ts | 11 ++++++++--- js/common/view/LightSceneNode.ts | 20 ++++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/js/common/model/LightSpot.ts b/js/common/model/LightSpot.ts index e439dd1d..5798bacf 100644 --- a/js/common/model/LightSpot.ts +++ b/js/common/model/LightSpot.ts @@ -23,6 +23,7 @@ import PhetioObject, { PhetioObjectOptions } from '../../../../tandem/js/PhetioO import optionize from '../../../../phet-core/js/optionize.js'; import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; +import BooleanIO from '../../../../tandem/js/types/BooleanIO.js'; type PositionAndDiameter = { position: Vector2; // position of the light spot's center, in the vertical plane of the projection screen @@ -40,12 +41,15 @@ export default class LightSpot extends PhetioObject { // Intensity of the light spot, in the range [0,1], 0 if there is no light spot hitting the projection screen public readonly intensityProperty: IReadOnlyProperty; - // Position of the center of the light spot, which may not be on the screen, + // Position of the center of the light spot, which may not be on the screen public readonly positionProperty: IReadOnlyProperty; - // Diameter of the light spot in the y dimension, + // Diameter of the light spot in the y dimension public readonly diameterProperty: IReadOnlyProperty; + // Whether the light spot intersects the projection screen + public readonly intersectsProjectionScreenProperty: IReadOnlyProperty; + constructor( optic: Optic, projectionScreen: ProjectionScreen, lightObjectPositionProperty: IReadOnlyProperty, @@ -107,6 +111,15 @@ export default class LightSpot extends PhetioObject { phetioType: DerivedProperty.DerivedPropertyIO( NullableIO( NumberIO ) ), phetioDocumentation: 'intensity of the light spot, in the range [0,1]' } ); + + this.intersectsProjectionScreenProperty = new DerivedProperty( + [ this.positionProperty, this.diameterProperty, projectionScreen.positionProperty ], + ( position: Vector2, diameter: number, projectionScreenPosition: Vector2 ) => + position.y >= projectionScreenPosition.y - projectionScreen.height / 2 - diameter / 2 && + position.y <= projectionScreenPosition.y + projectionScreen.height / 2 + diameter / 2, { + tandem: options.tandem.createTandem( 'intersectsProjectionScreenProperty' ), + phetioType: DerivedProperty.DerivedPropertyIO( BooleanIO ) + } ); } public override dispose(): void { diff --git a/js/common/model/ProjectionScreen.ts b/js/common/model/ProjectionScreen.ts index 582b12f1..2f263ff4 100644 --- a/js/common/model/ProjectionScreen.ts +++ b/js/common/model/ProjectionScreen.ts @@ -38,6 +38,9 @@ export default class ProjectionScreen extends PhetioObject { // Shape of the screen, relative to positionProperty public readonly screenShape: Shape; + // Height of the screen at its centerX. + public readonly height: number; + // line that vertically bisects the screen, relative to positionProperty private readonly bisectorLine: Shape; @@ -69,11 +72,13 @@ export default class ProjectionScreen extends PhetioObject { .lineTo( -SCREEN_WIDTH / 2, -SCREEN_FAR_HEIGHT / 2 ) .close(); + // Height at the centerX of the screen, the average of its near and far perspective heights + this.height = ( SCREEN_NEAR_HEIGHT + SCREEN_FAR_HEIGHT ) / 2; + // Described from top to bottom, in model coordinates. - const averageScreenHeight = ( SCREEN_NEAR_HEIGHT + SCREEN_FAR_HEIGHT ) / 2; this.bisectorLine = new Shape() - .moveTo( 0, averageScreenHeight / 2 ) - .lineTo( 0, -averageScreenHeight / 2 ); + .moveTo( 0, this.height / 2 ) + .lineTo( 0, -this.height / 2 ); this.resetProjectionScreen = () => { this.positionProperty.reset(); diff --git a/js/common/view/LightSceneNode.ts b/js/common/view/LightSceneNode.ts index d8300cc6..f31ab64b 100644 --- a/js/common/view/LightSceneNode.ts +++ b/js/common/view/LightSceneNode.ts @@ -135,7 +135,11 @@ export default class LightSceneNode extends GOSceneNode { // LightSpot associated with the first light const lightSpot1NodeTandem = providedOptions.tandem.createTandem( 'lightSpot1Node' ); const lightSpot1Node = new LightSpotNode( scene.lightSpot1, scene.projectionScreen, modelViewTransform, { - visibleProperty: DerivedProperty.and( [ lightPropagationEnabledProperty, scene.opticalImage1.visibleProperty ], { + visibleProperty: DerivedProperty.and( [ + scene.lightSpot1.intersectsProjectionScreenProperty, + lightPropagationEnabledProperty, + scene.opticalImage1.visibleProperty + ], { tandem: lightSpot1NodeTandem.createTandem( 'visibleProperty' ), phetioType: DerivedProperty.DerivedPropertyIO( BooleanIO ) } ), @@ -146,11 +150,15 @@ export default class LightSceneNode extends GOSceneNode { // LightSpot associated with the second light const lightSpot2NodeTandem = providedOptions.tandem.createTandem( 'lightSpot2Node' ); const lightSpot2Node = new LightSpotNode( scene.lightSpot2, scene.projectionScreen, modelViewTransform, { - visibleProperty: DerivedProperty.and( - [ lightPropagationEnabledProperty, scene.opticalImage2.visibleProperty, visibleProperties.secondPointVisibleProperty ], { - tandem: lightSpot2NodeTandem.createTandem( 'visibleProperty' ), - phetioType: DerivedProperty.DerivedPropertyIO( BooleanIO ) - } ), + visibleProperty: DerivedProperty.and( [ + scene.lightSpot2.intersectsProjectionScreenProperty, + lightPropagationEnabledProperty, + scene.opticalImage2.visibleProperty, + visibleProperties.secondPointVisibleProperty + ], { + tandem: lightSpot2NodeTandem.createTandem( 'visibleProperty' ), + phetioType: DerivedProperty.DerivedPropertyIO( BooleanIO ) + } ), tandem: lightSpot2NodeTandem } ); this.opticalImagesLayer.addChild( lightSpot2Node );