diff options
Diffstat (limited to 'src/client/views/nodes/PhysicsSimulationApp.tsx')
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationApp.tsx | 557 |
1 files changed, 0 insertions, 557 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> - ); - } -} |