From 18e458603d1c672b412c18237be73f6581d58137 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 23 May 2023 12:49:24 -0400 Subject: more physics fixes --- .../nodes/PhysicsBox/PhysicsSimulationBox.tsx | 66 ++++++---- .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx | 136 +++++++++------------ 2 files changed, 95 insertions(+), 107 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx index 9d75944f4..35e9c189f 100644 --- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx @@ -19,7 +19,7 @@ import Weight from './PhysicsSimulationWeight'; import React = require('react'); import { BoolCast, NumCast, StrCast } from '../../../../fields/Types'; import { List } from '../../../../fields/List'; -import { computed } from 'mobx'; +import { computed, trace } from 'mobx'; interface IWallProps { length: number; @@ -920,8 +920,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type != 'Inclined Plane' && (
-

{this.dataDoc.simulation_type} review problems in progress!

+

+ <>{this.dataDoc.simulation_type} review problems in progress! +


)} @@ -1437,7 +1439,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent - Speed} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit={'x'} upperBound={10} value={this.dataDoc.simulation_speed ?? 2} labelWidth={'5em'} /> + Speed} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit={'x'} upperBound={10} value={NumCast(this.dataDoc.simulation_speed, 2)} labelWidth={'5em'} /> {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Circular Motion' && ( Gravity} @@ -1639,11 +1641,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent - θ: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad -
- μ s: {this.dataDoc.coefficientOfStaticFriction} -
- μ k: {this.dataDoc.coefficientOfKineticFriction} + <> + θ: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad +
+ μ s: {this.dataDoc.coefficientOfStaticFriction} +
+ μ k: {this.dataDoc.coefficientOfKineticFriction} + )} {this.dataDoc.simulation_type == 'Pendulum' && !this.dataDoc.simulation_paused && ( @@ -1774,7 +1778,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponentPosition {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type == 'Inclined Plane' || this.dataDoc.simulation_type == 'Circular Motion' || this.dataDoc.simulation_type == 'Pulley') && ( - {this.dataDoc.mass1_positionX} m + + <>{this.dataDoc.mass1_positionX} m + )}{' '} {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Inclined Plane' && this.dataDoc.simulation_type != 'Circular Motion' && this.dataDoc.simulation_type != 'Pulley' && ( { this.dataDoc.mass1_xChange = value; - this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY; if (this.dataDoc.simulation_type == 'Suspension') { let x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; let x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius; @@ -1822,7 +1827,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent { - this.dataDoc.mass1_xChange = NumCast(this.dataDoc.mass1_positionX); this.dataDoc.mass1_yChange = value; if (this.dataDoc.simulation_type == 'Suspension') { let x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; @@ -1879,7 +1883,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent { this.dataDoc.mass1_velocityXstart = value; this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset; @@ -1924,7 +1928,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent )}{' '} - {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && {this.dataDoc.mass1_velocityY} m/s}{' '} + {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && ( + + <>{this.dataDoc.mass1_velocityY} m/s + + )}{' '} {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'One Weight' && ( { this.dataDoc.mass1_velocityYstart = -value; - this.dataDoc.mass1_xChange = this.dataDoc.mass1_positionX; - this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY; }} small={true} mode={'Freeform'} @@ -1961,10 +1967,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponentAcceleration - {this.dataDoc.mass1_accelerationX} m/s2 + <> + {this.dataDoc.mass1_accelerationX} m/s2 + - {this.dataDoc.mass1_accelerationY} m/s2 + <> + {this.dataDoc.mass1_accelerationY} m/s2 + @@ -2004,10 +2014,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponentAcceleration - {this.dataDoc.mass2_accelerationX} m/s2 + <> + {this.dataDoc.mass2_accelerationX} m/s2 + - {this.dataDoc.mass2_accelerationY} m/s2 + <> + {this.dataDoc.mass2_accelerationY} m/s2 + diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx index 94e101490..025c757c9 100644 --- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx @@ -1,7 +1,8 @@ +import { computed, trace } from 'mobx'; +import { observer } from 'mobx-react'; import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc'; -import React = require('react'); import './PhysicsSimulationBox.scss'; -import { computed } from 'mobx'; +import React = require('react'); interface IWallProps { length: number; @@ -54,8 +55,8 @@ export interface IWeightProps { startVelX: number; startVelY: number; timestepSize: number; - updateXDisplay: number; - updateYDisplay: number; + updateMassPosX: number; + updateMassPosY: number; forcesUpdated: () => IForce[]; setForcesUpdated: (x: IForce[]) => {}; wallPositions: IWallProps[]; @@ -86,7 +87,7 @@ interface IState { xAccel: number; yAccel: number; } - +@observer export default class Weight extends React.Component { constructor(props: any) { super(props); @@ -144,63 +145,54 @@ export default class Weight extends React.Component { }; // Helper function to go between display and real values - getDisplayYPos = (yPos: number) => { - return this.props.yMax - yPos - 2 * this.props.radius + 5; - }; - getYPosFromDisplay = (yDisplay: number) => { - return this.props.yMax - yDisplay - 2 * this.props.radius + 5; - }; + getDisplayYPos = (yPos: number) => this.props.yMax - yPos - 2 * this.props.radius + 5; // Set display values based on real values - setYPosDisplay = (yPos: number) => { - const displayPos = this.getDisplayYPos(yPos); + setPosition = (xPos: number | undefined, yPos: number | undefined) => { if (this.props.color == 'red') { - this.props.dataDoc.mass1_positionY = Math.round(displayPos * 100) / 100; + yPos !== undefined && (this.props.dataDoc.mass1_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100); + xPos !== undefined && (this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100); } else { - this.props.dataDoc.mass2_positionY = Math.round(displayPos * 100) / 100; + yPos !== undefined && (this.props.dataDoc.mass2_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100); + xPos !== undefined && (this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100); } }; - setXPosDisplay = (xPos: number) => { + setVelocity = (xVel: number | undefined, yVel: number | undefined) => { if (this.props.color == 'red') { - this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100; + yVel !== undefined && (this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100); + xVel !== undefined && (this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100); } else { - this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100; + yVel !== undefined && (this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100); + xVel !== undefined && (this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100); } }; - setYVelDisplay = (yVel: number) => { + setAcceleration = (xAccel: number, yAccel: number) => { if (this.props.color == 'red') { - this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100; + this.props.dataDoc.mass1_accelerationY = yAccel; + this.props.dataDoc.mass1_accelerationX = xAccel; } else { - this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100; - } - }; - setXVelDisplay = (xVel: number) => { - if (this.props.color == 'red') { - this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100; - } else { - this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100; + this.props.dataDoc.mass2_accelerationY = yAccel; + this.props.dataDoc.mass2_accelerationX = xAccel; } + + this.setState({ xAccel }); + this.setState({ yAccel }); }; // Update display values when simulation updates setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => { - this.setYPosDisplay(yPos); - this.setXPosDisplay(xPos); - this.setYVelDisplay(yVel); - this.setXVelDisplay(xVel); - if (this.props.color == 'red') { - this.props.dataDoc.mass1_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100; - this.props.dataDoc.mass1_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100; - } else { - this.props.dataDoc.mass2_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100; - this.props.dataDoc.mass2_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100; - } - - this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100 }); - this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100 }); + this.setPosition(xPos, yPos); + this.setVelocity(xVel, yVel); + this.setAcceleration(Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100, (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100); }; componentDidUpdate(prevProps: Readonly, prevState: Readonly, snapshot?: any): void { + if (prevProps.simulationType != this.props.simulationType) { + this.setState({ xVelocity: this.props.startVelX }); + this.setState({ yVelocity: this.props.startVelY }); + this.setDisplayValues(); + } + // Change pendulum angle from input field if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle || prevProps.adjustPendulumLength !== this.props.adjustPendulumLength) { let length = this.props.adjustPendulumLength; @@ -217,52 +209,33 @@ export default class Weight extends React.Component { } // When display values updated by user, update real value - if (prevProps.updateYDisplay != this.props.updateYDisplay || prevProps.updateXDisplay !== this.props.updateXDisplay) { - if (this.props.updateXDisplay != this.state.xPosition) { - let x = this.props.updateXDisplay; - x = Math.max(0, x); - x = Math.min(x, this.props.xMax - 2 * this.props.radius); - this.setState({ updatedStartPosX: x }); - this.setState({ xPosition: x }); - if (this.props.color == 'red') { - this.props.dataDoc.mass1_positionX = x; - } else { - this.props.dataDoc.mass2_positionX = x; - } - } - - if (this.props.updateYDisplay != this.getDisplayYPos(this.state.yPosition)) { - let y = this.props.updateYDisplay; - y = Math.max(0, y); - y = Math.min(y, this.props.yMax - 2 * this.props.radius); - let coordinatePosition = this.getYPosFromDisplay(y); - this.setState({ updatedStartPosY: coordinatePosition }); - this.setState({ yPosition: coordinatePosition }); - if (this.props.color == 'red') { - this.props.dataDoc.mass1_positionY = y; - } else { - this.props.dataDoc.mass2_positionY = y; - } - } + if (prevProps.updateMassPosX !== this.props.updateMassPosX) { + let x = this.props.updateMassPosX; + x = Math.max(0, x); + x = Math.min(x, this.props.xMax - 2 * this.props.radius); + this.setState({ updatedStartPosX: x }); + this.setState({ xPosition: x }); + this.setPosition(x, undefined); + } + if (prevProps.updateMassPosY != this.props.updateMassPosY) { + let y = this.props.updateMassPosY; + y = Math.max(0, y); + y = Math.min(y, this.props.yMax - 2 * this.props.radius); + let coordinatePosition = this.getDisplayYPos(y); + this.setState({ updatedStartPosY: coordinatePosition }); + this.setState({ yPosition: coordinatePosition }); + this.setPosition(undefined, y); if (this.props.displayXVelocity != this.state.xVelocity) { let x = this.props.displayXVelocity; this.setState({ xVelocity: x }); - if (this.props.color == 'red') { - this.props.dataDoc.mass1_velocityX = x; - } else { - this.props.dataDoc.mass2_velocityX = x; - } + this.setVelocity(x, undefined); } if (this.props.displayYVelocity != -this.state.yVelocity) { let y = this.props.displayYVelocity; this.setState({ yVelocity: -y }); - if (this.props.color == 'red') { - this.props.dataDoc.mass1_velocityY = y; - } else { - this.props.dataDoc.mass2_velocityY = y; - } + this.setVelocity(undefined, y); } } @@ -387,7 +360,7 @@ export default class Weight extends React.Component { if (this.props.paused && !isNaN(this.props.startPosX)) { this.setState({ xPosition: this.props.startPosX }); this.setState({ updatedStartPosX: this.props.startPosX }); - this.setXPosDisplay(this.props.startPosX); + this.setPosition(this.props.startPosX, undefined); } } @@ -396,7 +369,7 @@ export default class Weight extends React.Component { if (this.props.paused && !isNaN(this.props.startPosY)) { this.setState({ yPosition: this.props.startPosY }); this.setState({ updatedStartPosY: this.props.startPosY ?? 0 }); - this.setYPosDisplay(this.props.startPosY ?? 0); + this.setPosition(undefined, this.props.startPosY ?? 0); } } @@ -820,6 +793,7 @@ export default class Weight extends React.Component { // Render weight, spring, rod(s), vectors render() { + trace(); return (