aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PhysicsSimulationBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PhysicsSimulationBox.tsx')
-rw-r--r--src/client/views/nodes/PhysicsSimulationBox.tsx494
1 files changed, 0 insertions, 494 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsSimulationBox.tsx
deleted file mode 100644
index d0e854263..000000000
--- a/src/client/views/nodes/PhysicsSimulationBox.tsx
+++ /dev/null
@@ -1,494 +0,0 @@
-import "./PhysicsSimulationBox.scss";
-import { FieldView, FieldViewProps } from './FieldView';
-import React = require('react');
-import { ViewBoxAnnotatableComponent } from '../DocComponent';
-import { observer } from 'mobx-react';
-import "./PhysicsSimulationBox.scss";
-import Weight from "./PhysicsSimulationWeight";
-import Wall from "./PhysicsSimulationWall"
-import Wedge from "./PhysicsSimulationWedge"
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { CheckBox } from "../search/CheckBox";
-export interface IForce {
- description: string;
- magnitude: number;
- directionInDegrees: number;
-}
-export interface IWallProps {
- length: number;
- xPos: number;
- yPos: number;
- angleInDegrees: number;
-}
-
-interface PhysicsVectorTemplate {
- top: number;
- left: number;
- width: number;
- height: number;
- x1: number;
- y1: number;
- x2: number;
- y2: number;
- weightX: number;
- weightY: number;
-}
-
-@observer
-export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
-
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PhysicsSimulationBox, fieldKey); }
-
- // 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
- update = true
- menuIsOpen = false
-
- constructor(props: any) {
- super(props);
- }
-
- // Add one weight to the simulation
- addWeight () {
- this.dataDoc.weight = true;
- this.dataDoc.wedge = false;
- this.dataDoc.pendulum = false;
- this.addWalls();
- };
-
- // Set weight defaults
- setToWeightDefault () {
- this.dataDoc.startPosY = this.yMin+this.radius;
- this.dataDoc.startPosX = (this.xMax+this.xMin-this.radius)/2;
- this.dataDoc.updatedForces = [this.forceOfGravity];
- this.dataDoc.startForces = [this.forceOfGravity];
- }
-
- // Add a wedge with a One Weight to the simulation
- addWedge () {
- this.dataDoc.weight = true;
- this.dataDoc.wedge = true;
- this.dataDoc.pendulum = false;
- this.addWalls();
- };
-
- // Set wedge defaults
- setToWedgeDefault () {
- this.changeWedgeBasedOnNewAngle(26);
- this.updateForcesWithFriction(this.dataDoc.coefficientOfStaticFriction);
- }
-
- // Add a simple pendulum to the simulation
- addPendulum = () => {
- this.dataDoc.weight = true;
- this.dataDoc.wedge = false;
- this.dataDoc.pendulum = true;
- this.removeWalls();
- let angle = this.dataDoc.pendulumAngle;
- let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
- let forceOfTension: IForce = {
- description: "Tension",
- magnitude: mag,
- directionInDegrees: 90 - angle,
- };
- this.dataDoc.updatedForces = [this.forceOfGravity, forceOfTension];
- this.dataDoc.startForces = [this.forceOfGravity, forceOfTension];
- };
-
- // Set pendulum defaults
- setToPendulumDefault () {
- 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.dataDoc.startPosX = xPos;
- this.dataDoc.startPosY = yPos;
- let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
- this.dataDoc.pendulumAngle = angle;
- this.dataDoc.pendulumLength = length;
- this.dataDoc.startPendulumAngle = angle;
- this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
- }
-
- // Update forces when coefficient of static friction changes in freeform mode
- updateForcesWithFriction (
- coefficient: number,
- width: number = this.dataDoc.wedgeWidth,
- height: number = this.dataDoc.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.dataDoc.startForces = [this.forceOfGravity, normalForce, frictionForce];
- this.dataDoc.updatedForces = [this.forceOfGravity, normalForce, frictionForce];
- } else {
- this.dataDoc.startForces = [this.forceOfGravity, normalForce];
- this.dataDoc.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.dataDoc.wedgeWidth = width;
- this.dataDoc.wedgeHeight = height;
- } else if (angle < 70) {
- width = this.xMax*0.3;
- height = Math.tan((angle * Math.PI) / 180) * width;
- this.dataDoc.wedgeWidth = width;
- this.dataDoc.wedgeHeight = height;
- } else {
- width = this.xMax*0.15;
- height = Math.tan((angle * Math.PI) / 180) * width;
- this.dataDoc.wedgeWidth = width;
- this.dataDoc.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.dataDoc.startPosX = xPos;
- this.dataDoc.startPosY = this.getDisplayYPos(yPos);
- this.updateForcesWithFriction(
- Number(this.dataDoc.coefficientOfStaticFriction),
- width,
- height
- );
- this.dataDoc['updateDisplay'] = !this.dataDoc['updateDisplay']
- };
-
- // 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.dataDoc.sketching) {
- let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
- this.dataDoc.forceSketches = sketches;
- this.dataDoc.currentForceSketch = element;
- this.dataDoc.sketching = true;
- }
- };
-
- // In review mode, used to delete force arrow sketch on SHIFT+click
- deleteForce = (element: PhysicsVectorTemplate) => {
- if (!this.dataDoc.sketching) {
- let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
- this.dataDoc.forceSketches = sketches;
- }
- };
-
- // Remove floor and walls from simulation
- removeWalls = () => {
- this.dataDoc.wallPositions = []
- };
-
- // Add floor and walls to simulation
- addWalls = () => {
- 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.dataDoc.wallPositions = walls
- };
-
-
- componentDidMount() {
- this.xMax = this.layoutDoc._width;
- this.yMax = this.layoutDoc._height;
- this.radius = 0.1*this.layoutDoc._height;
-
- // Add weight
- if (this.dataDoc.simulationType == "Inclined Plane") {
- this.addWedge()
- } else if (this.dataDoc.simulationType == "Pendulum") {
- this.addPendulum()
- } else {
- this.dataDoc.simulationType = "Free Weight"
- this.addWeight()
- }
- this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
- this.dataDoc.accelerationYDisplay = this.dataDoc.accelerationYDisplay ?? 0;
- this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
- this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
- this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? [];
- this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
- this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
- this.dataDoc.pendulumAngle = this.dataDoc.pendulumAngle ?? 26;
- this.dataDoc.pendulumLength = this.dataDoc.pendulumLength ?? 300;
- this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
- this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
- this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
- this.dataDoc.showForceMagnitudes = this.dataDoc.showForceMagnitudes ?? false;
- this.dataDoc.showForces = this.dataDoc.showForces ?? false;
- this.dataDoc.showVelocity = this.dataDoc.showVelocity ?? false;
- this.dataDoc.startForces = this.dataDoc.startForces ?? [this.forceOfGravity];
- this.dataDoc.startPendulumAngle = this.dataDoc.startPendulumAngle ?? 0;
- this.dataDoc.startPosX = this.dataDoc.startPosX ?? 50;
- this.dataDoc.startPosY = this.dataDoc.startPosY ?? 50;
- this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
- this.dataDoc.updateDisplay = this.dataDoc.updateDisplay ?? false;
- this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [this.forceOfGravity];
- this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
- this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
- this.dataDoc.wallPositions = this.dataDoc.wallPositions ?? [];
- this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
- this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * this.xMax*0.6;
- this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? this.xMax*0.6;
-
- this.dataDoc.adjustPendulumAngle = true;
- this.dataDoc.simulationPaused = true;
- this.dataDoc.simulationReset = 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;
- }
- });
- }
-
- componentDidUpdate() {
- this.xMax = this.layoutDoc._width;
- this.yMax = this.layoutDoc._height;
- this.radius = 0.1*this.layoutDoc._height;
- }
-
- render () {
- return (
- <div>
- <div className="mechanicsSimulationContainer">
- <div className="mechanicsSimulationContentContainer">
- <div className="mechanicsSimulationButtonsAndElements">
- <div className="mechanicsSimulationElements">
- {this.dataDoc.weight && (
- <Weight
- adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
- color={"red"}
- dataDoc={this.dataDoc}
- mass={1}
- radius={this.radius}
- simulationReset={this.dataDoc.simulationReset}
- startPosX={this.dataDoc.startPosX}
- startPosY={this.dataDoc.startPosY}
- timestepSize={0.002}
- updateDisplay={this.dataDoc.updateDisplay}
- walls={this.dataDoc.wallPositions}
- wedge={this.dataDoc.wedge}
- wedgeWidth={this.dataDoc.wedgeWidth}
- wedgeHeight={this.dataDoc.wedgeHeight}
- xMax={this.xMax}
- xMin={this.xMin}
- yMax={this.yMax}
- yMin={this.yMin}
- />
- )}
- {this.dataDoc.wedge && (
- <Wedge
- startWidth={this.dataDoc.wedgeWidth}
- startHeight={this.dataDoc.wedgeHeight}
- startLeft={this.xMax * 0.2}
- xMax={this.xMax}
- yMax={this.yMax}
- />
- )}
- </div>
- <div>
- {(this.dataDoc.wallPositions ?? []).map((element: { length: number; xPos: number; yPos: number; angleInDegrees: number; }, index: React.Key | null | undefined) => {
- return (
- <div key={index}>
- <Wall
- length={element.length}
- xPos={element.xPos}
- yPos={element.yPos}
- angleInDegrees={element.angleInDegrees}
- />
- </div>
- );
- })}
- </div>
- </div>
- </div>
- <div style = {{width: this.layoutDoc._width+'px', height: this.layoutDoc._height+'px'}}>
- {this.menuIsOpen && (
- <div className="mechanicsSimulationSettingsMenu">
- <div className="close-button" onClick={() => {this.menuIsOpen = false; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>
- <FontAwesomeIcon icon={'times'} color="black" size={'lg'} />
- </div>
- <h4>Simulation Settings</h4>
- <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show forces</p></div>
- <div><input type="checkbox" checked={this.dataDoc.showForces} onClick={() => {this.dataDoc.showForces = !this.dataDoc.showForces}}/></div>
- </div>
- <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show acceleration</p></div>
- <div><input type="checkbox" checked={this.dataDoc.showAcceleration} onClick={() => {this.dataDoc.showAcceleration = !this.dataDoc.showAcceleration}}/></div>
- </div>
- <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription">
- <p>Show velocity</p></div>
- <div><input type="checkbox" checked={this.dataDoc.showVelocity} onClick={() => {this.dataDoc.showVelocity = !this.dataDoc.showVelocity}}/></div>
- </div>
- <hr/>
- {this.dataDoc.simulationType == "Free Weight" && <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Elastic collisions </p></div>
- <div><input type="checkbox" checked={this.dataDoc.elasticCollisions} onClick={() => {this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions}}/></div>
- </div>}
- {this.dataDoc.simulationType == "Pendulum" && <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Pendulum start angle</p></div>
- <div>
- <input
- type="number"
- value={this.dataDoc.startPendulumAngle}
- max={35}
- min={0}
- step={1}
- onInput={(e) => {
- let angle = e.target.value;
- if (angle > 35) {
- angle = 35
- }
- if (angle < 0) {
- angle = 0
- }
- let length = this.xMax*0.7;
- 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.dataDoc.startPosX = xPos;
- this.dataDoc.startPosY = yPos;
- let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
- this.dataDoc.pendulumAngle = angle;
- this.dataDoc.pendulumLength = length;
- this.dataDoc.startPendulumAngle = angle;
- this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
- }}
- />
- </div>
- </div>}
- {this.dataDoc.simulationType == "Inclined Plane" && <div className="mechanicsSimulationSettingsMenuRow">
- <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Inclined plane angle</p></div>
- <div>
- <input
- type="number"
- value={this.dataDoc.wedgeAngle}
- max={70}
- min={0}
- step={1}
- onInput={(e) => {
- let angle = e.target.value ?? 0
- if (angle > 70) {
- angle = 70
- }
- if (angle < 0) {
- angle = 0
- }
- this.dataDoc.wedgeAngle = angle
- this.changeWedgeBasedOnNewAngle(angle)
- }}
- />
- </div>
- </div>}
- </div>
- )}
- </div>
- <div className="mechanicsSimulationEquationContainer">
- <div className="mechanicsSimulationControls">
- <div>
- {this.dataDoc.simulationPaused && (
- <button onClick={() => {
- this.dataDoc.simulationPaused = false}
- } >START</button>
- )}
- {!this.dataDoc.simulationPaused && (
- <button onClick={() => {
- this.dataDoc.simulationPaused = true}
- } >PAUSE</button>
- )}
- {this.dataDoc.simulationPaused && (
- <button onClick={() => {
- this.dataDoc.simulationReset = !this.dataDoc.simulationReset}
- } >RESET</button>
- )}
- {this.dataDoc.simulationPaused && ( <button onClick={() => {
- if (!this.dataDoc.pendulum && !this.dataDoc.wedge) {
- this.addWedge()
- this.setToWedgeDefault()
- this.dataDoc.simulationType = "Inclined Plane"
- this.dataDoc.elasticCollisions = false
- }
- else if (!this.dataDoc.pendulum && this.dataDoc.wedge) {
- this.setToPendulumDefault()
- this.addPendulum()
- this.dataDoc.simulationType = "Pendulum"
- this.dataDoc.elasticCollisions = false
- }
- else {
- this.setToWeightDefault()
- this.addWeight()
- this.dataDoc.simulationType = "Free Weight"
- }
- this.dataDoc.simulationReset = !this.dataDoc.simulationReset
- }} >TYPE</button>)}
- <button onClick={() => {this.menuIsOpen=true; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>MENU</button>
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
- } \ No newline at end of file