aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-05-23 12:49:24 -0400
committerbobzel <zzzman@gmail.com>2023-05-23 12:49:24 -0400
commit18e458603d1c672b412c18237be73f6581d58137 (patch)
treeb69a88256e09e613b488119266360a2ce248038c
parent4832bb8e9589a786ac08d24b6e55bb23d19ce855 (diff)
more physics fixes
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx66
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx136
2 files changed, 95 insertions, 107 deletions
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<FieldViewP
startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
timestepSize={0.05}
- updateXDisplay={NumCast(this.dataDoc.mass1_xChange)}
- updateYDisplay={NumCast(this.dataDoc.mass1_yChange)}
+ updateMassPosX={NumCast(this.dataDoc.mass1_xChange)}
+ updateMassPosY={NumCast(this.dataDoc.mass1_yChange)}
forcesUpdated={this.forcesUpdated1}
setForcesUpdated={this.setForcesUpdated1}
wedgeHeight={NumCast(this.dataDoc.wedge_height)}
@@ -972,8 +972,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
startVelX={NumCast(this.dataDoc.mass2_velocityXstart)}
startVelY={NumCast(this.dataDoc.mass2_velocityYstart)}
timestepSize={0.05}
- updateXDisplay={NumCast(this.dataDoc.mass2_xChange)}
- updateYDisplay={NumCast(this.dataDoc.mass2_yChange)}
+ updateMassPosX={NumCast(this.dataDoc.mass2_xChange)}
+ updateMassPosY={NumCast(this.dataDoc.mass2_yChange)}
forcesUpdated={this.forcesUpdated2}
setForcesUpdated={this.setForcesUpdated2}
wedgeHeight={NumCast(this.dataDoc.wedge_height)}
@@ -1055,7 +1055,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
</div>
{this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type != 'Inclined Plane' && (
<div className="wordProblemBox">
- <p>{this.dataDoc.simulation_type} review problems in progress!</p>
+ <p>
+ <>{this.dataDoc.simulation_type} review problems in progress!</>
+ </p>
<hr />
</div>
)}
@@ -1437,7 +1439,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
label="Show velocity vector"
labelPlacement="start"
/>
- <InputField label={<Box>Speed</Box>} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit={'x'} upperBound={10} value={this.dataDoc.simulation_speed ?? 2} labelWidth={'5em'} />
+ <InputField label={<Box>Speed</Box>} 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' && (
<InputField
label={<Box>Gravity</Box>}
@@ -1639,11 +1641,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
)}
{this.dataDoc.simulation_type == 'Inclined Plane' && !this.dataDoc.simulation_paused && (
<Typography>
- &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad
- <br />
- &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
- <br />
- &mu; <sub>k</sub>: {this.dataDoc.coefficientOfKineticFriction}
+ <>
+ &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad
+ <br />
+ &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
+ <br />
+ &mu; <sub>k</sub>: {this.dataDoc.coefficientOfKineticFriction}
+ </>
</Typography>
)}
{this.dataDoc.simulation_type == 'Pendulum' && !this.dataDoc.simulation_paused && (
@@ -1774,7 +1778,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
<Box>Position</Box>
</td>
{(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type == 'Inclined Plane' || this.dataDoc.simulation_type == 'Circular Motion' || this.dataDoc.simulation_type == 'Pulley') && (
- <td style={{ cursor: 'default' }}>{this.dataDoc.mass1_positionX} m</td>
+ <td style={{ cursor: 'default' }}>
+ <>{this.dataDoc.mass1_positionX} m</>
+ </td>
)}{' '}
{this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Inclined Plane' && this.dataDoc.simulation_type != 'Circular Motion' && this.dataDoc.simulation_type != 'Pulley' && (
<td
@@ -1791,7 +1797,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
value={NumCast(this.dataDoc.mass1_positionX)}
effect={value => {
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<FieldViewP
directionInDegrees: 270,
component: false,
};
- this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+ this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
}
}}
small={true}
@@ -1847,7 +1852,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
upperBound={this.yMax - 110}
value={NumCast(this.dataDoc.mass1_positionY)}
effect={value => {
- 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<FieldViewP
directionInDegrees: 270,
component: false,
};
- this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+ this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
}
}}
small={true}
@@ -1914,7 +1918,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
step={1}
unit={'m/s'}
upperBound={50}
- value={this.dataDoc.mass1_velocityX}
+ value={NumCast(this.dataDoc.mass1_velocityX)}
effect={value => {
this.dataDoc.mass1_velocityXstart = value;
this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
@@ -1924,7 +1928,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
/>
</td>
)}{' '}
- {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && <td style={{ cursor: 'default' }}>{this.dataDoc.mass1_velocityY} m/s</td>}{' '}
+ {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && (
+ <td style={{ cursor: 'default' }}>
+ <>{this.dataDoc.mass1_velocityY} m/s</>
+ </td>
+ )}{' '}
{this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'One Weight' && (
<td
style={{
@@ -1937,11 +1945,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
step={1}
unit={'m/s'}
upperBound={50}
- value={this.dataDoc.mass1_velocityY}
+ value={NumCast(this.dataDoc.mass1_velocityY)}
effect={value => {
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 ViewBoxAnnotatableComponent<FieldViewP
<Box>Acceleration</Box>
</td>
<td style={{ cursor: 'default' }}>
- {this.dataDoc.mass1_accelerationX} m/s<sup>2</sup>
+ <>
+ {this.dataDoc.mass1_accelerationX} m/s<sup>2</sup>
+ </>
</td>
<td style={{ cursor: 'default' }}>
- {this.dataDoc.mass1_accelerationY} m/s<sup>2</sup>
+ <>
+ {this.dataDoc.mass1_accelerationY} m/s<sup>2</sup>
+ </>
</td>
</tr>
<tr>
@@ -2004,10 +2014,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
<Box>Acceleration</Box>
</td>
<td style={{ cursor: 'default' }}>
- {this.dataDoc.mass2_accelerationX} m/s<sup>2</sup>
+ <>
+ {this.dataDoc.mass2_accelerationX} m/s<sup>2</sup>
+ </>
</td>
<td style={{ cursor: 'default' }}>
- {this.dataDoc.mass2_accelerationY} m/s<sup>2</sup>
+ <>
+ {this.dataDoc.mass2_accelerationY} m/s<sup>2</sup>
+ </>
</td>
</tr>
<tr>
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<IWeightProps, IState> {
constructor(props: any) {
super(props);
@@ -144,63 +145,54 @@ export default class Weight extends React.Component<IWeightProps, IState> {
};
// 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<IWeightProps>, prevState: Readonly<IState>, 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<IWeightProps, IState> {
}
// 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<IWeightProps, IState> {
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<IWeightProps, IState> {
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<IWeightProps, IState> {
// Render weight, spring, rod(s), vectors
render() {
+ trace();
return (
<div>
<div