aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/PhysicsSimulationApp.tsx557
-rw-r--r--src/client/views/nodes/PhysicsSimulationBox.tsx194
-rw-r--r--src/client/views/nodes/PhysicsSimulationWeight.tsx129
3 files changed, 55 insertions, 825 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationApp.tsx b/src/client/views/nodes/PhysicsSimulationApp.tsx
deleted file mode 100644
index acca65b08..000000000
--- a/src/client/views/nodes/PhysicsSimulationApp.tsx
+++ /dev/null
@@ -1,557 +0,0 @@
-import React = require('react');
-import "./PhysicsSimulationBox.scss";
-import Weight, { IForce } from "./PhysicsSimulationWeight";
-import Wall, { IWallProps } from "./PhysicsSimulationWall"
-import Wedge from "./PhysicsSimulationWedge"
-
-interface PhysicsVectorTemplate {
- top: number;
- left: number;
- width: number;
- height: number;
- x1: number;
- y1: number;
- x2: number;
- y2: number;
- weightX: number;
- weightY: number;
-}
-
-interface IState {
- accelerationXDisplay: number,
- accelerationYDisplay: number,
- adjustPendulumAngle: {angle: number, length: number},
- coefficientOfKineticFriction: number,
- coefficientOfStaticFriction: number,
- currentForceSketch: PhysicsVectorTemplate | null,
- deleteMode: boolean,
- displayChange: {xDisplay: number, yDisplay: number},
- elasticCollisions: boolean,
- forceSketches: PhysicsVectorTemplate[],
- pendulum: boolean,
- pendulumAngle: number,
- pendulumLength: number,
- positionXDisplay: number,
- positionYDisplay: number,
- showAcceleration: boolean,
- showForceMagnitudes: boolean,
- showForces: boolean,
- showVelocity: boolean,
- simulationPaused: boolean,
- simulationReset: boolean,
- simulationType: "Inclined Plane",
- sketching: boolean,
- startForces: IForce[],
- startPendulumAngle: number,
- startPosX: number,
- startPosY: number,
- stepNumber: number,
- timer: number,
- updatedForces: IForce[],
- velocityXDisplay: number,
- velocityYDisplay: number,
- wallPositions: IWallProps[],
- wedge: boolean,
- wedgeAngle: number,
- wedgeHeight: number,
- wedgeWidth: number,
- weight: boolean,
-}
-export default class App extends React.Component<{}, IState> {
-
- // Constants
- gravityMagnitude = 9.81;
- forceOfGravity: IForce = {
- description: "Gravity",
- magnitude: this.gravityMagnitude,
- directionInDegrees: 270,
- };
- xMin = 0;
- yMin = 0;
- xMax = 300;
- yMax = 300;
- color = `rgba(0,0,0,0.5)`;
- radius = 0.1*this.yMax
-
- constructor(props: any) {
- super(props)
- this.state = {
- accelerationXDisplay: 0,
- accelerationYDisplay: 0,
- adjustPendulumAngle: {angle: 0, length: 0},
- coefficientOfKineticFriction: 0,
- coefficientOfStaticFriction: 0,
- currentForceSketch: null,
- deleteMode: false,
- displayChange: {xDisplay: 0, yDisplay: 0},
- elasticCollisions: false,
- forceSketches: [],
- pendulum: false,
- pendulumAngle: 0,
- pendulumLength: 300,
- positionXDisplay: 0,
- positionYDisplay: 0,
- showAcceleration: false,
- showForceMagnitudes: false,
- showForces: false,
- showVelocity: false,
- simulationPaused: true,
- simulationReset: false,
- simulationType: "Inclined Plane",
- sketching: false,
- startForces: [this.forceOfGravity],
- startPendulumAngle: 0,
- startPosX: 0,
- startPosY: 0,
- stepNumber: 0,
- timer: 0,
- updatedForces: [this.forceOfGravity],
- velocityXDisplay: 0,
- velocityYDisplay: 0,
- wallPositions: [],
- wedge: false,
- wedgeAngle: 26,
- wedgeHeight: Math.tan((26 * Math.PI) / 180) * this.xMax*0.6,
- wedgeWidth: this.xMax*0.6,
- weight: false,
- }
- }
-
- // Add one weight to the simulation
- addWeight () {
- this.setState({weight: true})
- this.setState({wedge: false})
- this.setState({pendulum: false})
- this.setState({startPosY: this.yMin+this.radius})
- this.setState({startPosX: (this.xMax+this.xMin-this.radius)/2})
- this.setState({updatedForces: [this.forceOfGravity]})
- this.setState({startForces: [this.forceOfGravity]})
- this.addWalls();
- this.setState({simulationReset: !this.state.simulationReset})
- };
-
- // Add a wedge with a One Weight to the simulation
- addWedge () {
- this.setState({weight: true})
- this.setState({wedge: true})
- this.setState({pendulum: false})
- this.changeWedgeBasedOnNewAngle(26);
- this.addWalls();
- this.setState({startForces: [this.forceOfGravity]})
- this.updateForcesWithFriction(this.state.coefficientOfStaticFriction);
- };
-
- // Add a simple pendulum to the simulation
- addPendulum = () => {
- this.setState({weight: true})
- this.setState({wedge: false})
- this.setState({pendulum: true})
- let length = this.xMax*0.7;
- let angle = 35;
- let x = length * Math.cos(((90 - angle) * Math.PI) / 180);
- let y = length * Math.sin(((90 - angle) * Math.PI) / 180);
- let xPos = this.xMax / 2 - x - this.radius;
- let yPos = y - this.radius;
- this.setState({startPosX: xPos})
- this.setState({startPosY: yPos})
- let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
- let forceOfTension: IForce = {
- description: "Tension",
- magnitude: mag,
- directionInDegrees: 90 - angle,
- };
- this.setState({updatedForces: [this.forceOfGravity, forceOfTension]})
- this.setState({startForces: [this.forceOfGravity, forceOfTension]})
- this.setState({pendulumAngle: angle})
- this.setState({pendulumLength: length})
- this.setState({adjustPendulumAngle: {angle: angle, length: length}})
- this.removeWalls();
- };
-
- // Update forces when coefficient of static friction changes in freeform mode
- updateForcesWithFriction (
- coefficient: number,
- width: number = this.state.wedgeWidth,
- height: number = this.state.wedgeHeight
- ) {
- let normalForce = {
- description: "Normal Force",
- magnitude: this.forceOfGravity.magnitude * Math.cos(Math.atan(height / width)),
- directionInDegrees:
- 180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
- };
- let frictionForce: IForce = {
- description: "Static Friction Force",
- magnitude:
- coefficient *
- this.forceOfGravity.magnitude *
- Math.cos(Math.atan(height / width)),
- directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI,
- };
- // reduce magnitude of friction force if necessary such that block cannot slide up plane
- let yForce = -this.forceOfGravity.magnitude;
- yForce +=
- normalForce.magnitude *
- Math.sin((normalForce.directionInDegrees * Math.PI) / 180);
- yForce +=
- frictionForce.magnitude *
- Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
- if (yForce > 0) {
- frictionForce.magnitude =
- (-normalForce.magnitude *
- Math.sin((normalForce.directionInDegrees * Math.PI) / 180) +
- this.forceOfGravity.magnitude) /
- Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
- }
- if (coefficient != 0) {
- this.setState({startForces: [this.forceOfGravity, normalForce, frictionForce]})
- this.setState({updatedForces: [this.forceOfGravity, normalForce, frictionForce]});
- } else {
- this.setState({startForces: [this.forceOfGravity, normalForce]})
- this.setState({updatedForces: [this.forceOfGravity, normalForce]});
- }
- };
-
- // Change wedge height and width and weight position to match new wedge angle
- changeWedgeBasedOnNewAngle = (angle: number) => {
- let width = 0;
- let height = 0;
- if (angle < 50) {
- width = this.xMax*0.6;
- height = Math.tan((angle * Math.PI) / 180) * width;
- this.setState({wedgeWidth: width})
- this.setState({wedgeHeight: height})
- } else if (angle < 70) {
- width = this.xMax*0.3;
- height = Math.tan((angle * Math.PI) / 180) * width;
- this.setState({wedgeWidth: width})
- this.setState({wedgeHeight: height})
- } else {
- width = this.xMax*0.15;
- height = Math.tan((angle * Math.PI) / 180) * width;
- this.setState({wedgeWidth: width})
- this.setState({wedgeHeight: height})
- }
-
- // update weight position based on updated wedge width/height
- let xPos = (this.xMax * 0.2)-this.radius;
- let yPos = width * Math.tan((angle * Math.PI) / 180) - this.radius;
-
- this.setState({startPosX: xPos});
- this.setState({startPosY: this.getDisplayYPos(yPos)});
- this.updateForcesWithFriction(
- Number(this.state.coefficientOfStaticFriction),
- width,
- height
- );
- };
-
- // Helper function to go between display and real values
- getDisplayYPos = (yPos: number) => {
- return this.yMax - yPos - 2 * 50 + 5;
- };
-
- // In review mode, edit force arrow sketch on mouse movement
- editForce = (element: PhysicsVectorTemplate) => {
- if (!this.state.sketching) {
- let sketches = this.state.forceSketches.filter((sketch) => sketch != element);
- this.setState({forceSketches: sketches})
- this.setState({currentForceSketch: element})
- this.setState({sketching: true})
- }
- };
-
- // In review mode, used to delete force arrow sketch on SHIFT+click
- deleteForce = (element: PhysicsVectorTemplate) => {
- if (!this.state.sketching) {
- let sketches = this.state.forceSketches.filter((sketch) => sketch != element);
- this.setState({forceSketches: sketches})
- }
- };
-
- // Remove floor and walls from simulation
- removeWalls = () => {
- this.setState({wallPositions: []})
- };
-
- // Add floor and walls to simulation
- addWalls = () => {
- if (this.state.wallPositions.length == 0) {
- let walls = [];
- walls.push({ length: 100, xPos: 0, yPos: 97, angleInDegrees: 0 });
- walls.push({ length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 });
- walls.push({ length: 100, xPos: 97, yPos: 0, angleInDegrees: 90 });
- this.setState({wallPositions: walls})
- }
- };
-
-
- componentDidMount() {
- // 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.setState({deleteMode: true})
- }
- });
- document.addEventListener("keyup", (e) => {
- if (e.shiftKey) {
- this.setState({deleteMode: false})
- }
- });
-
- // Timer for animating the simulation
- setInterval(() => {
- this.setState({timer: this.state.timer+1})
- }, 60);
- }
-
- render () {
- return (
- <div>
- <div className="mechanicsSimulationContainer">
- <div
- className="mechanicsSimulationContentContainer"
- onPointerMove={(e) => {
- // if (sketching) {
- // x1 = positionXDisplay + 50;
- // y1 = yMax - positionYDisplay - 2 * 50 + 5 + 50;
- // x2 = e.clientX;
- // y2 = e.clientY;
- // height = Math.abs(y1 - y2) + 120;
- // width = Math.abs(x1 - x2) + 120;
- // top = Math.min(y1, y2) - 60;
- // left = Math.min(x1, x2) - 60;
- // x1Updated = x1 - left;
- // x2Updated = x2 - left;
- // y1Updated = y1 - top;
- // y2Updated = y2 - top;
- // setCurrentForceSketch({
- // top: top,
- // left: left,
- // width: width,
- // height: height,
- // x1: x1Updated,
- // y1: y1Updated,
- // x2: x2Updated,
- // y2: y2Updated,
- // weightX: positionXDisplay,
- // weightY: positionYDisplay,
- // });
- // }
- }}
- onPointerDown={(e) => {
- // if (sketching && currentForceSketch) {
- // setSketching(false);
- // sketches = forceSketches;
- // sketches.push(currentForceSketch);
- // setForceSketches(sketches);
- // setCurrentForceSketch(null);
- // }
- }}
- >
- <div className="mechanicsSimulationButtonsAndElements">
- <div className="mechanicsSimulationElements">
- {/* {showForces && currentForceSketch && simulationPaused && (
- <div
- style={{
- position: "fixed",
- top: currentForceSketch.top,
- left: currentForceSketch.left,
- }}
- >
- <svg
- width={currentForceSketch.width + "px"}
- height={currentForceSketch.height + "px"}
- >
- <defs>
- <marker
- id="sketchArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="2"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,4 L6,2 z" fill={color} />
- </marker>
- </defs>
- <line
- x1={currentForceSketch.x1}
- y1={currentForceSketch.y1}
- x2={currentForceSketch.x2}
- y2={currentForceSketch.y2}
- stroke={color}
- strokeWidth="10"
- markerEnd="url(#sketchArrow)"
- />
- </svg>
- </div>
- )} */}
- {/* {showForces &&
- forceSketches.length > 0 &&
- simulationPaused &&
- forceSketches.map((element: PhysicsVectorTemplate, index) => {
- return (
- <div
- key={index}
- style={{
- position: "fixed",
- top: element.top + (positionYDisplay - element.weightY),
- left:
- element.left + (positionXDisplay - element.weightX),
- }}
- >
- <svg
- width={element.width + "px"}
- height={element.height + "px"}
- >
- <defs>
- <marker
- id="sketchArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="2"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,4 L6,2 z" fill={color} />
- </marker>
- </defs>
- <line
- x1={element.x1}
- y1={element.y1}
- x2={element.x2}
- y2={element.y2}
- stroke={color}
- strokeWidth="10"
- markerEnd="url(#sketchArrow)"
- onClick={() => {
- if (deleteMode) {
- deleteForce(element);
- } else {
- editForce(element);
- }
- }}
- />
- </svg>
- </div>
- );
- })} */}
- {this.state.weight && (
- <Weight
- adjustPendulumAngle={this.state.adjustPendulumAngle}
- color={"red"}
- displayXPosition={this.state.positionXDisplay}
- displayXVelocity={this.state.velocityXDisplay}
- displayYPosition={this.state.positionYDisplay}
- displayYVelocity={this.state.velocityYDisplay}
- elasticCollisions={this.state.elasticCollisions}
- incrementTime={this.state.timer}
- mass={1}
- paused={this.state.simulationPaused}
- pendulum={this.state.pendulum}
- pendulumAngle={this.state.pendulumAngle}
- pendulumLength={this.state.pendulumLength}
- radius={this.radius}
- reset={this.state.simulationReset}
- showForceMagnitudes={this.state.showForceMagnitudes}
- setSketching={(val: boolean) => {this.setState({sketching: val})}}
- setDisplayXAcceleration={(val: number) => {this.setState({accelerationXDisplay: val})}}
- setDisplayXPosition={(val: number) => {this.setState({positionXDisplay: val})}}
- setDisplayXVelocity={(val: number) => {this.setState({velocityXDisplay: val})}}
- setDisplayYAcceleration={(val: number) => {this.setState({accelerationYDisplay: val})}}
- setDisplayYPosition={(val: number) => {this.setState({positionYDisplay: val})}}
- setDisplayYVelocity={(val: number) => {this.setState({velocityYDisplay: val})}}
- setPaused={(val: boolean) => {this.setState({simulationPaused: val})}}
- setPendulumAngle={(val: number) => {this.setState({pendulumAngle: val})}}
- setPendulumLength={(val: number) => {this.setState({pendulumLength: val})}}
- setStartPendulumAngle={(val: number) => {this.setState({startPendulumAngle: val})}}
- setUpdatedForces={(val: IForce[]) => {this.setState({updatedForces: val})}}
- showAcceleration={this.state.showAcceleration}
- showForces={this.state.showForces}
- showVelocity={this.state.showVelocity}
- startForces={this.state.startForces}
- startPosX={this.state.startPosX}
- startPosY={this.state.startPosY}
- timestepSize={0.002}
- updateDisplay={this.state.displayChange}
- updatedForces={this.state.updatedForces}
- walls={this.state.wallPositions}
- wedge={this.state.wedge}
- wedgeHeight={this.state.wedgeHeight}
- wedgeWidth={this.state.wedgeWidth}
- coefficientOfKineticFriction={this.state.coefficientOfKineticFriction}
- xMax={this.xMax}
- yMax={this.yMax}
- xMin={this.xMin}
- yMin={this.yMin}
- />
- )}
- {this.state.wedge && (
- <Wedge
- startWidth={this.state.wedgeWidth}
- startHeight={this.state.wedgeHeight}
- startLeft={this.xMax * 0.2}
- xMax={this.xMax}
- yMax={this.yMax}
- />
- )}
- </div>
- <div>
- {this.state.wallPositions.map((element, index) => {
- return (
- <div key={index}>
- <Wall
- length={element.length}
- xPos={element.xPos}
- yPos={element.yPos}
- angleInDegrees={element.angleInDegrees}
- />
- </div>
- );
- })}
- </div>
- </div>
- </div>
- <div className="mechanicsSimulationEquationContainer">
- <div className="mechanicsSimulationControls">
- <div>
- {this.state.simulationPaused && (
- <button onClick={() => {
- this.setState({simulationPaused: false});
- }} >START</button>
- )}
- {!this.state.simulationPaused && (
- <button onClick={() => {
- this.setState({simulationPaused: true});
- }} >PAUSE</button>
- )}
- {this.state.simulationPaused && (
- <button onClick={() => {
- this.setState({simulationReset: !this.state.simulationReset});
- }} >RESET</button>
- )}
- <button onClick={() => {
- if (!this.state.pendulum && !this.state.wedge) {
- this.addWedge()
- }
- else if (!this.state.pendulum && this.state.wedge) {
- this.addPendulum()
- }
- else {
- this.addWeight()
- }
- }} >TYPE</button>
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
-}
diff --git a/src/client/views/nodes/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsSimulationBox.tsx
index 3ea4fba9f..9d91adefb 100644
--- a/src/client/views/nodes/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsSimulationBox.tsx
@@ -33,46 +33,6 @@ interface PhysicsVectorTemplate {
weightY: number;
}
-interface IState {
- accelerationXDisplay: number,
- accelerationYDisplay: number,
- adjustPendulumAngle: {angle: number, length: number},
- coefficientOfKineticFriction: number,
- coefficientOfStaticFriction: number,
- currentForceSketch: PhysicsVectorTemplate | null,
- deleteMode: boolean,
- displayChange: {xDisplay: number, yDisplay: number},
- elasticCollisions: boolean,
- forceSketches: PhysicsVectorTemplate[],
- pendulum: boolean,
- pendulumAngle: number,
- pendulumLength: number,
- positionXDisplay: number,
- positionYDisplay: number,
- showAcceleration: boolean,
- showForceMagnitudes: boolean,
- showForces: boolean,
- showVelocity: boolean,
- simulationPaused: boolean,
- simulationReset: boolean,
- simulationType: "Inclined Plane",
- sketching: boolean,
- startForces: IForce[],
- startPendulumAngle: number,
- startPosX: number,
- startPosY: number,
- stepNumber: number,
- timer: number,
- updatedForces: IForce[],
- velocityXDisplay: number,
- velocityYDisplay: number,
- wallPositions: IWallProps[],
- wedge: boolean,
- wedgeAngle: number,
- wedgeHeight: number,
- wedgeWidth: number,
- weight: boolean,
-}
@observer
export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -96,7 +56,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
super(props);
this.dataDoc.accelerationXDisplay = 0;
this.dataDoc.accelerationYDisplay = 0;
- this.dataDoc.adjustPendulumAngle = {angle: 0, length: 0};
+ this.dataDoc.adjustPendulumAngle = true;
this.dataDoc.coefficientOfKineticFriction = 0;
this.dataDoc.coefficientOfStaticFriction = 0;
this.dataDoc.currentForceSketch = [];
@@ -181,7 +141,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
this.dataDoc.startForces = [this.forceOfGravity, forceOfTension];
this.dataDoc.pendulumAngle = angle;
this.dataDoc.pendulumLength = length;
- this.dataDoc.adjustPendulumAngle = {angle: angle, length: length};
+ this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
this.removeWalls();
};
@@ -329,166 +289,20 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
return (
<div>
<div className="mechanicsSimulationContainer">
- <div
- className="mechanicsSimulationContentContainer"
- onPointerMove={(e) => {
- // if (sketching) {
- // x1 = positionXDisplay + 50;
- // y1 = yMax - positionYDisplay - 2 * 50 + 5 + 50;
- // x2 = e.clientX;
- // y2 = e.clientY;
- // height = Math.abs(y1 - y2) + 120;
- // width = Math.abs(x1 - x2) + 120;
- // top = Math.min(y1, y2) - 60;
- // left = Math.min(x1, x2) - 60;
- // x1Updated = x1 - left;
- // x2Updated = x2 - left;
- // y1Updated = y1 - top;
- // y2Updated = y2 - top;
- // setCurrentForceSketch({
- // top: top,
- // left: left,
- // width: width,
- // height: height,
- // x1: x1Updated,
- // y1: y1Updated,
- // x2: x2Updated,
- // y2: y2Updated,
- // weightX: positionXDisplay,
- // weightY: positionYDisplay,
- // });
- // }
- }}
- onPointerDown={(e) => {
- // if (sketching && currentForceSketch) {
- // setSketching(false);
- // sketches = forceSketches;
- // sketches.push(currentForceSketch);
- // setForceSketches(sketches);
- // setCurrentForceSketch(null);
- // }
- }}
- >
+ <div className="mechanicsSimulationContentContainer">
<div className="mechanicsSimulationButtonsAndElements">
<div className="mechanicsSimulationElements">
- {/* {showForces && currentForceSketch && simulationPaused && (
- <div
- style={{
- position: "fixed",
- top: currentForceSketch.top,
- left: currentForceSketch.left,
- }}
- >
- <svg
- width={currentForceSketch.width + "px"}
- height={currentForceSketch.height + "px"}
- >
- <defs>
- <marker
- id="sketchArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="2"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,4 L6,2 z" fill={color} />
- </marker>
- </defs>
- <line
- x1={currentForceSketch.x1}
- y1={currentForceSketch.y1}
- x2={currentForceSketch.x2}
- y2={currentForceSketch.y2}
- stroke={color}
- strokeWidth="10"
- markerEnd="url(#sketchArrow)"
- />
- </svg>
- </div>
- )} */}
- {/* {showForces &&
- forceSketches.length > 0 &&
- simulationPaused &&
- forceSketches.map((element: PhysicsVectorTemplate, index) => {
- return (
- <div
- key={index}
- style={{
- position: "fixed",
- top: element.top + (positionYDisplay - element.weightY),
- left:
- element.left + (positionXDisplay - element.weightX),
- }}
- >
- <svg
- width={element.width + "px"}
- height={element.height + "px"}
- >
- <defs>
- <marker
- id="sketchArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="2"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,4 L6,2 z" fill={color} />
- </marker>
- </defs>
- <line
- x1={element.x1}
- y1={element.y1}
- x2={element.x2}
- y2={element.y2}
- stroke={color}
- strokeWidth="10"
- markerEnd="url(#sketchArrow)"
- onClick={() => {
- if (deleteMode) {
- deleteForce(element);
- } else {
- editForce(element);
- }
- }}
- />
- </svg>
- </div>
- );
- })} */}
{this.dataDoc.weight && (
<Weight
- adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
color={"red"}
- displayXPosition={this.dataDoc.positionXDisplay}
- displayXVelocity={this.dataDoc.velocityXDisplay}
- displayYPosition={this.dataDoc.positionYDisplay}
- displayYVelocity={this.dataDoc.velocityYDisplay}
- elasticCollisions={this.dataDoc.elasticCollisions}
- incrementTime={this.dataDoc.timer}
+ dataDoc={this.dataDoc}
mass={1}
- paused={this.dataDoc.simulationPaused}
pendulum={this.dataDoc.pendulum}
pendulumAngle={this.dataDoc.pendulumAngle}
pendulumLength={this.dataDoc.pendulumLength}
radius={this.radius}
reset={this.dataDoc.simulationReset}
showForceMagnitudes={this.dataDoc.showForceMagnitudes}
- setSketching={(val: boolean) => {this.dataDoc.sketching = val}}
- setDisplayXAcceleration={(val: number) => {this.dataDoc.accelerationXDisplay = val}}
- setDisplayXPosition={(val: number) => {this.dataDoc.positionXDisplay = val}}
- setDisplayXVelocity={(val: number) => {this.dataDoc.velocityXDisplay = val}}
- setDisplayYAcceleration={(val: number) => {this.dataDoc.accelerationYDisplay = val}}
- setDisplayYPosition={(val: number) => {this.dataDoc.positionYDisplay = val}}
- setDisplayYVelocity={(val: number) => {this.dataDoc.velocityYDisplay = val}}
- setPaused={(val: boolean) => {this.dataDoc.simulationPaused = val}}
- setPendulumAngle={(val: number) => {this.dataDoc.pendulumAngle = val}}
- setPendulumLength={(val: number) => {this.dataDoc.pendulumLength = val}}
- setStartPendulumAngle={(val: number) => {this.dataDoc.startPendulumAngle = val}}
- setUpdatedForces={(val: IForce[]) => {this.dataDoc.updatedForces = val}}
showAcceleration={this.dataDoc.showAcceleration}
showForces={this.dataDoc.showForces}
showVelocity={this.dataDoc.showVelocity}
diff --git a/src/client/views/nodes/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsSimulationWeight.tsx
index dfd463bbe..fcfb149c9 100644
--- a/src/client/views/nodes/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsSimulationWeight.tsx
@@ -1,4 +1,5 @@
import React = require('react');
+import { Doc } from '../../../fields/Doc';
import { IWallProps } from "./PhysicsSimulationWall";
export interface IForce {
@@ -7,35 +8,17 @@ export interface IForce {
directionInDegrees: number;
}
export interface IWeightProps {
- adjustPendulumAngle: { angle: number; length: number };
+ dataDoc: Doc;
color: string;
- displayXPosition: number;
- displayYPosition: number;
- displayXVelocity: number;
- displayYVelocity: number;
- elasticCollisions: boolean;
startForces: IForce[];
- incrementTime: number;
mass: number;
- paused: boolean;
pendulum: boolean;
pendulumLength: number;
wedge: boolean;
radius: number;
reset: boolean;
- setDisplayXAcceleration: (val: number) => any;
- setDisplayXPosition: (val: number) => any;
- setDisplayXVelocity: (val: number) => any;
- setDisplayYAcceleration: (val: number) => any;
- setDisplayYPosition: (val: number) => any;
- setDisplayYVelocity: (val: number) => any;
- setPaused: (bool: boolean) => any;
- setPendulumAngle: (val: number) => any;
- setPendulumLength: (val: number) => any;
- setStartPendulumAngle: (val: number) => any;
showAcceleration: boolean;
pendulumAngle: number;
- setSketching: (val: boolean) => any;
showForces: boolean;
showForceMagnitudes: boolean;
showVelocity: boolean;
@@ -46,7 +29,6 @@ export interface IWeightProps {
timestepSize: number;
updateDisplay: { xDisplay: number; yDisplay: number };
updatedForces: IForce[];
- setUpdatedForces: (val: IForce[]) => any;
walls: IWallProps[];
coefficientOfKineticFriction: number;
wedgeWidth: number;
@@ -125,16 +107,16 @@ export default class Weight extends React.Component<IWeightProps, IState> {
// Set display values based on real values
setYPosDisplay = (yPos: number) => {
const displayPos = this.getDisplayYPos(yPos);
- this.props.setDisplayYPosition(Math.round(displayPos * 100) / 100)
+ this.props.dataDoc['positionYDisplay'] = Math.round(displayPos * 100) / 100
};
setXPosDisplay = (xPos: number) => {
- this.props.setDisplayXPosition(Math.round(xPos * 100) / 100);
+ this.props.dataDoc['positionXDisplay'] = Math.round(xPos * 100) / 100;
};
setYVelDisplay = (yVel: number) => {
- this.props.setDisplayYVelocity((-1 * Math.round(yVel * 100)) / 100);
+ this.props.dataDoc['velocityYDisplay'] = (-1 * Math.round(yVel * 100)) / 100;
};
setXVelDisplay = (xVel: number) => {
- this.props.setDisplayXVelocity(Math.round(xVel * 100) / 100);
+ this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
};
setDisplayValues = (
@@ -147,12 +129,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setXPosDisplay(xPos);
this.setYVelDisplay(yVel);
this.setXVelDisplay(xVel);
- this.props.setDisplayYAcceleration(
+ this.props.dataDoc['accelerationYDisplay'] =
(-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100
- );
- this.props.setDisplayXAcceleration(
+ ;
+ this.props.dataDoc['accelerationXDisplay'] =
Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100
- );
+ ;
};
componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
@@ -164,34 +146,34 @@ export default class Weight extends React.Component<IWeightProps, IState> {
x = Math.min(x, this.props.xMax - 2 * this.props.radius);
this.setState({updatedStartPosX: x})
this.setState({xPosition: x})
- this.props.setDisplayXPosition(x);
+ this.props.dataDoc['positionXDisplay'] = x;
}
if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
let y = this.props.updateDisplay.yDisplay;
y = Math.max(0, y);
y = Math.min(y, this.props.yMax - 2 * this.props.radius);
- this.props.setDisplayYPosition(y);
+ this.props.dataDoc['positionYDisplay'] = y;
let coordinatePosition = this.getYPosFromDisplay(y);
this.setState({updatedStartPosY: coordinatePosition})
this.setState({yPosition: coordinatePosition})
}
- if (this.props.displayXVelocity != this.state.xVelocity) {
- let x = this.props.displayXVelocity;
+ if (this.props.dataDoc['velocityXDisplay'] != this.state.xVelocity) {
+ let x = this.props.dataDoc['velocityXDisplay'];
this.setState({xVelocity: x})
- this.props.setDisplayXVelocity(x);
+ this.props.dataDoc['velocityXDisplay'] = x;
}
- if (this.props.displayYVelocity != this.state.yVelocity) {
- let y = this.props.displayYVelocity;
+ if (this.props.dataDoc['velocityYDisplay'] != this.state.yVelocity) {
+ let y = this.props.dataDoc['velocityYDisplay'];
this.setState({yVelocity: -y})
- this.props.setDisplayXVelocity(y);
+ this.props.dataDoc['velocityYDisplay']
}
}
// Update sim
- if (this.props.incrementTime != prevProps.incrementTime) {
- if (!this.props.paused) {
+ if (this.props.dataDoc['incrementTime'] != prevProps.dataDoc['incrementTime']) {
+ if (!this.props.dataDoc['simulationPaused']) {
let collisions = false;
if (!this.props.pendulum) {
const collisionsWithGround = this.checkForCollisionsWithGround();
@@ -229,21 +211,19 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({yVelocity: this.props.startVelY ?? 0})
this.setDisplayValues();
}
- if (this.props.adjustPendulumAngle != prevProps.adjustPendulumAngle) {
+ if (this.props.dataDoc['adjustPendulumAngle'] != prevProps.dataDoc['adjustPendulumAngle']) {
// Change pendulum angle based on input field
- let length = this.props.adjustPendulumAngle.length;
+ let length = this.props.dataDoc['pendulumLength'] ?? 0;
const x =
- length * Math.cos(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180);
+ length * Math.cos(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
const y =
- length * Math.sin(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180);
+ length * Math.sin(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
const xPos = this.props.xMax / 2 - x - this.props.radius;
const yPos = y - this.props.radius - 5;
this.setState({xPosition: xPos})
this.setState({yPosition: yPos})
this.setState({updatedStartPosX: xPos})
this.setState({updatedStartPosY: yPos})
- this.props.setPendulumAngle(this.props.adjustPendulumAngle.angle);
- this.props.setPendulumLength(this.props.adjustPendulumAngle.length);
}
// Update x start position
if (this.props.startPosX != prevProps.startPosX) {
@@ -314,24 +294,28 @@ export default class Weight extends React.Component<IWeightProps, IState> {
getNewAccelerationX = (forceList: IForce[]) => {
let newXAcc = 0;
- forceList.forEach((force) => {
- newXAcc +=
- (force.magnitude *
- Math.cos((force.directionInDegrees * Math.PI) / 180)) /
- this.props.mass;
- });
+ if (forceList) {
+ forceList.forEach((force) => {
+ newXAcc +=
+ (force.magnitude *
+ Math.cos((force.directionInDegrees * Math.PI) / 180)) /
+ this.props.mass;
+ });
+ }
return newXAcc;
};
getNewAccelerationY = (forceList: IForce[]) => {
let newYAcc = 0;
- forceList.forEach((force) => {
- newYAcc +=
- (-1 *
- (force.magnitude *
- Math.sin((force.directionInDegrees * Math.PI) / 180))) /
- this.props.mass;
- });
+ if (forceList) {
+ forceList.forEach((force) => {
+ newYAcc +=
+ (-1 *
+ (force.magnitude *
+ Math.sin((force.directionInDegrees * Math.PI) / 180))) /
+ this.props.mass;
+ });
+ }
return newYAcc;
};
@@ -356,8 +340,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
}
const pendulumLength = Math.sqrt(x * x + y * y);
- this.props.setPendulumAngle(oppositeAngle);
- this.props.setPendulumLength(Math.sqrt(x * x + y * y));
+ this.props.dataDoc['pendulumAngle'] = oppositeAngle;
+ this.props.dataDoc['pendulumLength'] = Math.sqrt(x * x + y * y);
const mag =
this.props.mass * 9.81 * Math.cos((oppositeAngle * Math.PI) / 180) +
@@ -391,7 +375,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const wallX = (wall.xPos / 100) * 300;
if (wall.xPos < 0.35) {
if (minX <= wallX) {
- if (this.props.elasticCollisions) {
+ if (this.props.dataDoc['elasticCollisions']) {
this.setState({xVelocity: -this.state.xVelocity});
} else {
this.setState({xVelocity: 0});
@@ -401,7 +385,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
}
} else {
if (maxX >= wallX) {
- if (this.props.elasticCollisions) {
+ if (this.props.dataDoc['elasticCollisions']) {
this.setState({xVelocity: -this.state.xVelocity});
} else {
this.setState({xVelocity: 0});
@@ -424,7 +408,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
if (wall.angleInDegrees == 0) {
const groundY = (wall.yPos / 100) * this.props.yMax;
if (maxY >= groundY) {
- if (this.props.elasticCollisions) {
+ if (this.props.dataDoc['elasticCollisions']) {
this.setState({yVelocity: -this.state.yVelocity})
} else {
this.setState({yVelocity: 0})
@@ -525,7 +509,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
onPointerDown={(e) => {
if (this.draggable) {
e.preventDefault();
- this.props.setPaused(true);
+ this.props.dataDoc['simulationPaused'] = true;
this.setState({dragging: true});
this.setState({clickPositionX: e.clientX})
this.setState({clickPositionY: e.clientY})
@@ -549,7 +533,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.setState({yPosition: newY})
this.setState({updatedStartPosX: newX})
this.setState({updatedStartPosY: newY})
- this.props.setDisplayYPosition(Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100)
+ this.props.dataDoc['positionYDisplay'] = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
this.setState({clickPositionX: e.clientX})
this.setState({clickPositionY: e.clientY})
this.setDisplayValues();
@@ -586,8 +570,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
}
const pendulumLength = Math.sqrt(x * x + y * y);
- this.props.setPendulumAngle(oppositeAngle);
- this.props.setPendulumLength(Math.sqrt(x * x + y * y));
+ this.props.dataDoc['pendulumAngle'] = oppositeAngle;
+ this.props.dataDoc['pendulumLength'] = Math.sqrt(x * x + y * y);
const mag = 9.81 * Math.cos((oppositeAngle * Math.PI) / 180);
const forceOfTension: IForce = {
description: "Tension",
@@ -629,17 +613,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</svg>
{!this.state.dragging && (
<div>
- {/* <p
- style={{
- position: "absolute",
- zIndex: 5,
- left: this.state.xPosition + "px",
- top: this.state.yPosition - 70 + "px",
- backgroundColor: this.labelBackgroundColor,
- }}
- >
- {Math.round(this.props.pendulumLength)} m
- </p> */}
<p
style={{
position: "absolute",
@@ -648,7 +621,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
backgroundColor: this.labelBackgroundColor,
}}
>
- {Math.round(this.props.pendulumAngle * 100) / 100}°
+ {Math.round(this.props.dataDoc['pendulumAngle'] * 100) / 100}°
</p>
</div>
)}