aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/nodes/PhysicsSimulationBox.tsx56
-rw-r--r--src/client/views/nodes/PhysicsSimulationWeight.tsx142
2 files changed, 91 insertions, 107 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsSimulationBox.tsx
index 9d91adefb..13b4fe0b2 100644
--- a/src/client/views/nodes/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsSimulationBox.tsx
@@ -61,7 +61,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
this.dataDoc.coefficientOfStaticFriction = 0;
this.dataDoc.currentForceSketch = [];
this.dataDoc.deleteMode = false;
- this.dataDoc.displayChange = {xDisplay: 0, yDisplay: 0};
+ this.dataDoc.updateDisplay = false;
this.dataDoc.elasticCollisions = false;
this.dataDoc.forceSketches = [];
this.dataDoc.pendulum = false;
@@ -264,25 +264,25 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
componentDidMount() {
- // Add weight
- this.addPendulum()
+ // Add weight
+ this.addPendulum()
- // Add listener for SHIFT key, which determines if sketch force arrow will be edited or deleted on click
- document.addEventListener("keydown", (e) => {
- if (e.shiftKey) {
- this.dataDoc.deleteMode = true;
- }
- });
- document.addEventListener("keyup", (e) => {
- if (e.shiftKey) {
- this.dataDoc.deleteMode = false;
- }
- });
+ // Add listener for SHIFT key, which determines if sketch force arrow will be edited or deleted on click
+ document.addEventListener("keydown", (e) => {
+ if (e.shiftKey) {
+ this.dataDoc.deleteMode = true;
+ }
+ });
+ document.addEventListener("keyup", (e) => {
+ if (e.shiftKey) {
+ this.dataDoc.deleteMode = false;
+ }
+ });
- // Timer for animating the simulation
- setInterval(() => {
- this.dataDoc.timer = this.dataDoc.timer+1;
- }, 60);
+ // // Timer for animating the simulation
+ // setInterval(() => {
+ // this.dataDoc.timer = this.dataDoc.timer+1;
+ // }, 60);
}
render () {
@@ -297,26 +297,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
color={"red"}
dataDoc={this.dataDoc}
mass={1}
- pendulum={this.dataDoc.pendulum}
- pendulumAngle={this.dataDoc.pendulumAngle}
- pendulumLength={this.dataDoc.pendulumLength}
radius={this.radius}
- reset={this.dataDoc.simulationReset}
- showForceMagnitudes={this.dataDoc.showForceMagnitudes}
- showAcceleration={this.dataDoc.showAcceleration}
- showForces={this.dataDoc.showForces}
- showVelocity={this.dataDoc.showVelocity}
- startForces={this.dataDoc.startForces}
- startPosX={this.dataDoc.startPosX}
- startPosY={this.dataDoc.startPosY}
timestepSize={0.002}
- updateDisplay={this.dataDoc.displayChange}
- updatedForces={this.dataDoc.updatedForces}
- walls={this.dataDoc.wallPositions}
- wedge={this.dataDoc.wedge}
- wedgeHeight={this.dataDoc.wedgeHeight}
- wedgeWidth={this.dataDoc.wedgeWidth}
- coefficientOfKineticFriction={this.dataDoc.coefficientOfKineticFriction}
xMax={this.xMax}
yMax={this.yMax}
xMin={this.xMin}
@@ -354,11 +336,13 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
<div>
{this.dataDoc.simulationPaused && (
<button onClick={() => {
+ console.log('start sim')
this.dataDoc.simulationPaused = false}
} >START</button>
)}
{!this.dataDoc.simulationPaused && (
<button onClick={() => {
+ console.log('pause sim')
this.dataDoc.simulationPaused = true}
} >PAUSE</button>
)}
diff --git a/src/client/views/nodes/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsSimulationWeight.tsx
index fcfb149c9..e7bd86915 100644
--- a/src/client/views/nodes/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsSimulationWeight.tsx
@@ -10,27 +10,13 @@ export interface IForce {
export interface IWeightProps {
dataDoc: Doc;
color: string;
- startForces: IForce[];
mass: number;
- pendulum: boolean;
- pendulumLength: number;
wedge: boolean;
radius: number;
- reset: boolean;
- showAcceleration: boolean;
- pendulumAngle: number;
- showForces: boolean;
- showForceMagnitudes: boolean;
- showVelocity: boolean;
- startPosX: number;
- startPosY: number;
startVelX?: number;
startVelY?: number;
timestepSize: number;
- updateDisplay: { xDisplay: number; yDisplay: number };
- updatedForces: IForce[];
walls: IWallProps[];
- coefficientOfKineticFriction: number;
wedgeWidth: number;
wedgeHeight: number;
xMax: number;
@@ -46,6 +32,7 @@ interface IState {
kineticFriction: boolean,
updatedStartPosX: number,
updatedStartPosY: number,
+ timer: number;
xPosition: number,
yPosition: number,
xVelocity: number,
@@ -60,17 +47,18 @@ export default class Weight extends React.Component<IWeightProps, IState> {
clickPositionY: 0,
dragging: false,
kineticFriction: false,
- updatedStartPosX: this.props.startPosX,
- updatedStartPosY: this.props.startPosY,
- xPosition: this.props.startPosX,
- yPosition: this.props.startPosY,
+ timer: 0,
+ updatedStartPosX: this.props.dataDoc['startPosX'],
+ updatedStartPosY: this.props.dataDoc['startPosY'],
+ xPosition: this.props.dataDoc['startPosX'],
+ yPosition: this.props.dataDoc['startPosY'],
xVelocity: this.props.startVelX ? this.props.startVelX: 0,
yVelocity: this.props.startVelY ? this.props.startVelY: 0,
}
}
// Constants
- draggable = !this.props.wedge;
+ draggable = !this.props.dataDoc['wedge'] ;
epsilon = 0.0001;
forceOfGravity: IForce = {
description: "Gravity",
@@ -84,8 +72,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
borderStyle: "solid",
borderColor: "black",
position: "absolute" as "absolute",
- left: this.props.startPosX + "px",
- top: this.props.startPosY + "px",
+ left: this.props.dataDoc['startPosX'] + "px",
+ top: this.props.dataDoc['startPosY'] + "px",
width: 2 * this.props.radius + "px",
height: 2 * this.props.radius + "px",
zIndex: 5,
@@ -130,18 +118,25 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setYVelDisplay(yVel);
this.setXVelDisplay(xVel);
this.props.dataDoc['accelerationYDisplay'] =
- (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100
+ (-1 * Math.round(this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 100)) / 100
;
this.props.dataDoc['accelerationXDisplay'] =
- Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100
+ Math.round(this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 100) / 100
;
};
+ componentDidMount() {
+ // Timer for animating the simulation
+ setInterval(() => {
+ this.setState({timer: this.state.timer + 1});
+ }, 60);
+ }
+
componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
// When display values updated by user, update real values
- if (this.props.updateDisplay != prevProps.updateDisplay) {
- if (this.props.updateDisplay.xDisplay != this.state.xPosition) {
- let x = this.props.updateDisplay.xDisplay;
+ if (this.props.dataDoc['updateDisplay'] != prevProps.dataDoc['updateDisplay']) {
+ if (this.props.dataDoc['positionXDisplay'] != this.state.xPosition) {
+ let x = this.props.dataDoc['positionXDisplay'];
x = Math.max(0, x);
x = Math.min(x, this.props.xMax - 2 * this.props.radius);
this.setState({updatedStartPosX: x})
@@ -149,8 +144,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.props.dataDoc['positionXDisplay'] = x;
}
- if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
- let y = this.props.updateDisplay.yDisplay;
+ if (this.props.dataDoc['positionYDisplay'] != this.getDisplayYPos(this.state.yPosition)) {
+ let y = this.props.dataDoc['positionYDisplay'];
y = Math.max(0, y);
y = Math.min(y, this.props.yMax - 2 * this.props.radius);
this.props.dataDoc['positionYDisplay'] = y;
@@ -172,10 +167,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
}
}
// Update sim
- if (this.props.dataDoc['incrementTime'] != prevProps.dataDoc['incrementTime']) {
+ if (this.state.timer != prevState.timer) {
if (!this.props.dataDoc['simulationPaused']) {
+ console.log('update')
let collisions = false;
- if (!this.props.pendulum) {
+ if (!this.props.dataDoc['pendulum']) {
const collisionsWithGround = this.checkForCollisionsWithGround();
const collisionsWithWalls = this.checkForCollisionsWithWall();
collisions = collisionsWithGround || collisionsWithWalls;
@@ -203,10 +199,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
touchAction: "none",
};
- if (this.props.reset != prevProps.reset) {
+ if (this.props.dataDoc['simulationReset'] != prevProps.dataDoc['simulationReset']) {
this.resetEverything();
}
- if (this.props.startForces != prevProps.startForces) {
+ if (this.props.dataDoc['startForces'] != prevProps.dataDoc['startForces']) {
this.setState({xVelocity: this.props.startVelX ?? 0})
this.setState({yVelocity: this.props.startVelY ?? 0})
this.setDisplayValues();
@@ -226,37 +222,37 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({updatedStartPosY: yPos})
}
// Update x start position
- if (this.props.startPosX != prevProps.startPosX) {
- this.setState({updatedStartPosX: this.props.startPosX})
- this.setState({xPosition: this.props.startPosX})
- this.setXPosDisplay(this.props.startPosX);
+ if (this.props.dataDoc['startPosX'] != prevProps.dataDoc['startPosX']) {
+ this.setState({updatedStartPosX: this.props.dataDoc['startPosX']})
+ this.setState({xPosition: this.props.dataDoc['startPosX']})
+ this.setXPosDisplay(this.props.dataDoc['startPosX']);
}
// Update y start position
- if (this.props.startPosY != prevProps.startPosY) {
- this.setState({updatedStartPosY: this.props.startPosY})
- this.setState({yPosition: this.props.startPosY})
- this.setYPosDisplay(this.props.startPosY);
+ if (this.props.dataDoc['startPosY'] != prevProps.dataDoc['startPosY']) {
+ this.setState({updatedStartPosY: this.props.dataDoc['startPosY']})
+ this.setState({yPosition: this.props.dataDoc['startPosY']})
+ this.setYPosDisplay(this.props.dataDoc['startPosY']);
}
if (this.state.xVelocity != prevState.xVelocity) {
- if (this.props.wedge && this.state.xVelocity != 0 && !this.state.kineticFriction) {
+ if (this.props.dataDoc['wedge'] && this.state.xVelocity != 0 && !this.state.kineticFriction) {
this.setState({kineticFriction: true});
//switch from static to kinetic friction
const normalForce: IForce = {
description: "Normal Force",
magnitude:
this.forceOfGravity.magnitude *
- Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+ Math.cos(Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] )),
directionInDegrees:
- 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+ 180 - 90 - (Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] ) * 180) / Math.PI,
};
let frictionForce: IForce = {
description: "Kinetic Friction Force",
magnitude:
- this.props.coefficientOfKineticFriction *
+ this.props.dataDoc['coefficientOfKineticFriction'] *
this.forceOfGravity.magnitude *
- Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+ Math.cos(Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] )),
directionInDegrees:
- 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+ 180 - (Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] ) * 180) / Math.PI,
};
// reduce magnitude of friction force if necessary such that block cannot slide up plane
let yForce = -this.forceOfGravity.magnitude;
@@ -273,10 +269,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.forceOfGravity.magnitude) /
Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
}
- if (this.props.coefficientOfKineticFriction != 0) {
- this.props.setUpdatedForces([this.forceOfGravity, normalForce, frictionForce]);
+ if (this.props.dataDoc['coefficientOfKineticFriction'] != 0) {
+ this.props.dataDoc['updatedForces'] = [this.forceOfGravity, normalForce, frictionForce];
} else {
- this.props.setUpdatedForces([this.forceOfGravity, normalForce]);
+ this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, normalForce]);
}
}
}
@@ -288,7 +284,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({yPosition: this.state.updatedStartPosY})
this.setState({xVelocity: this.props.startVelX ?? 0})
this.setState({yVelocity: this.props.startVelY ?? 0})
- this.props.setUpdatedForces(this.props.startForces)
+ this.props.dataDoc['updatedForces'] = (this.props.dataDoc['startForces'])
this.setDisplayValues();
};
@@ -325,8 +321,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
xVel: number,
yVel: number
) => {
- if (!this.props.pendulum) {
- return this.props.updatedForces;
+ if (!this.props.dataDoc['pendulum']) {
+ return this.props.dataDoc['updatedForces'];
}
const x = this.props.xMax / 2 - xPos - this.props.radius;
const y = yPos + this.props.radius + 5;
@@ -370,7 +366,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const maxX = this.state.xPosition + 2 * this.props.radius;
const containerWidth = 300;
if (this.state.xVelocity != 0) {
- this.props.walls.forEach((wall) => {
+ this.props.dataDoc['wallPositions'].forEach((wall) => {
if (wall.angleInDegrees == 90) {
const wallX = (wall.xPos / 100) * 300;
if (wall.xPos < 0.35) {
@@ -404,7 +400,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
let collision = false;
const maxY = this.state.yPosition + 2 * this.props.radius;
if (this.state.yVelocity > 0) {
- this.props.walls.forEach((wall) => {
+ this.props.dataDoc['wallPositions'] .forEach((wall) => {
if (wall.angleInDegrees == 0) {
const groundY = (wall.yPos / 100) * this.props.yMax;
if (maxY >= groundY) {
@@ -423,7 +419,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
magnitude: 9.81 * this.props.mass,
directionInDegrees: wall.angleInDegrees + 90,
};
- this.props.setUpdatedForces([forceOfGravity, normalForce]);
+ this.props.dataDoc['updatedForces'] = ([forceOfGravity, normalForce]);
}
collision = true;
}
@@ -496,9 +492,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({yVelocity: yVel});
this.setState({xPosition: xPos});
this.setState({yPosition: yPos});
- this.props.setUpdatedForces(this.getNewForces(xPos, yPos, xVel, yVel));
+ this.props.dataDoc['updatedForces'] = (this.getNewForces(xPos, yPos, xVel, yVel));
};
+
+
+
+
labelBackgroundColor = `rgba(255,255,255,0.5)`;
render () {
@@ -542,7 +542,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
onPointerUp={(e) => {
if (this.state.dragging) {
e.preventDefault();
- if (!this.props.pendulum) {
+ if (!this.props.dataDoc['pendulum']) {
this.resetEverything();
}
this.setState({dragging: false});
@@ -557,7 +557,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
} else if (newX < 0) {
newX = 0;
}
- if (this.props.pendulum) {
+ if (this.props.dataDoc['pendulum']) {
const x = this.props.xMax / 2 - newX - this.props.radius;
const y = newY + this.props.radius + 5;
let angle = (Math.atan(y / x) * 180) / Math.PI;
@@ -582,7 +582,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({xVelocity: this.props.startVelX ?? 0})
this.setState({yVelocity: this.props.startVelY ?? 0})
this.setDisplayValues();
- this.props.setUpdatedForces([this.forceOfGravity, forceOfTension]);
+ this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, forceOfTension]);
}
}
}}
@@ -591,7 +591,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
<p className="weightLabel">{this.props.mass} kg</p>
</div>
</div>
- {this.props.pendulum && (
+ {this.props.dataDoc['pendulum'] && (
<div
className="rod"
style={{
@@ -627,7 +627,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
)}
</div>
)}
- {!this.state.dragging && this.props.showAcceleration && (
+ {!this.state.dragging && this.props.dataDoc['showAcceleration'] && (
<div>
<div
style={{
@@ -654,8 +654,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
<line
x1={this.state.xPosition + this.props.radius}
y1={this.state.yPosition + this.props.radius}
- x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.updatedForces) * 5}
- y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.updatedForces) * 5}
+ x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5}
+ y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5}
stroke={"green"}
strokeWidth="5"
markerEnd="url(#accArrow)"
@@ -668,13 +668,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
left:
this.state.xPosition +
this.props.radius +
- this.getNewAccelerationX(this.props.updatedForces) * 5 +
+ this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5 +
25 +
"px",
top:
this.state.yPosition +
this.props.radius +
- this.getNewAccelerationY(this.props.updatedForces) * 5 +
+ this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5 +
25 +
"px",
lineHeight: 0.5,
@@ -684,8 +684,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
{Math.round(
100 *
Math.sqrt(
- Math.pow(this.getNewAccelerationX(this.props.updatedForces) * 3, 2) +
- Math.pow(this.getNewAccelerationY(this.props.updatedForces) * 3, 2)
+ Math.pow(this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 3, 2) +
+ Math.pow(this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 3, 2)
)
) / 100}{" "}
m/s<sup>2</sup>
@@ -694,7 +694,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</div>
</div>
)}
- {!this.state.dragging && this.props.showVelocity && (
+ {!this.state.dragging && this.props.dataDoc['showVelocity'] && (
<div>
<div
style={{
@@ -748,8 +748,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</div>
)}
{!this.state.dragging &&
- this.props.showForces &&
- this.props.updatedForces.map((force, index) => {
+ this.props.dataDoc['showForces'] &&
+ this.props.dataDoc['updatedForces'].map((force, index) => {
if (force.magnitude < this.epsilon) {
return;
}
@@ -836,7 +836,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
>
{force.description && <p>{force.description}</p>}
{!force.description && <p>Force</p>}
- {this.props.showForceMagnitudes && (
+ {this.props.dataDoc['showForceMagnitudes'] && (
<p>{Math.round(100 * force.magnitude) / 100} N</p>
)}
</div>