diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationApp.tsx | 99 | ||||
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationWall.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationWeight.tsx | 346 |
3 files changed, 222 insertions, 227 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationApp.tsx b/src/client/views/nodes/PhysicsSimulationApp.tsx index bd218f63b..0536d0679 100644 --- a/src/client/views/nodes/PhysicsSimulationApp.tsx +++ b/src/client/views/nodes/PhysicsSimulationApp.tsx @@ -1,7 +1,7 @@ import React = require('react'); import "./PhysicsSimulationBox.scss"; import Weight, { IForce } from "./PhysicsSimulationWeight"; -import Wall from "./PhysicsSimulationWall" +import Wall, { IWallProps } from "./PhysicsSimulationWall" import Wedge from "./PhysicsSimulationWedge" import { props, any } from 'bluebird'; import { render } from 'react-dom'; @@ -153,7 +153,7 @@ export default class App extends React.Component<{}, IState> { let angle = 50; let x = length * Math.cos(((90 - angle) * Math.PI) / 180); let y = length * Math.sin(((90 - angle) * Math.PI) / 180); - let xPos = xMax / 2 - x - 50; + let xPos = this.xMax / 2 - x - 50; let yPos = y - 50 - 5; this.addPendulum(); this.setState({startPosX: xPos}) @@ -461,52 +461,50 @@ export default class App extends React.Component<{}, IState> { </div> ); })} */} - {/* {weight && ( + {/* {this.state.weight && ( <Weight - adjustPendulumAngle={adjustPendulumAngle} + adjustPendulumAngle={this.state.adjustPendulumAngle} color={"red"} - displayXPosition={positionXDisplay} - displayXVelocity={velocityXDisplay} - displayYPosition={positionYDisplay} - displayYVelocity={velocityYDisplay} - elasticCollisions={elasticCollisions} - incrementTime={timer} + 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={simulationPaused} - pendulum={pendulum} - pendulumAngle={pendulumAngle} - pendulumLength={pendulumLength} + paused={this.state.simulationPaused} + pendulum={this.state.pendulum} + pendulumAngle={this.state.pendulumAngle} + pendulumLength={this.state.pendulumLength} radius={50} - reset={simulationReset} - showForceMagnitudes={showForceMagnitudes} - setSketching={setSketching} - setDisplayXAcceleration={setAccelerationXDisplay} - setDisplayXPosition={setPositionXDisplay} - setDisplayXVelocity={setVelocityXDisplay} - setDisplayYAcceleration={setAccelerationYDisplay} - setDisplayYPosition={setPositionYDisplay} - setDisplayYVelocity={setVelocityYDisplay} - setPaused={setSimulationPaused} - setPendulumAngle={setPendulumAngle} - setPendulumLength={setPendulumLength} - setStartPendulumAngle={setStartPendulumAngle} - setUpdatedForces={setUpdatedForces} - showAcceleration={showAcceleration} - showForces={showForces} - showVelocity={showVelocity} - startForces={startForces} - startPosX={startPosX} - startPosY={startPosY} + 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={displayChange} - updatedForces={updatedForces} - walls={wallPositions} - wedge={wedge} - wedgeHeight={wedgeHeight} - wedgeWidth={wedgeWidth} - coefficientOfKineticFriction={Number( - coefficientOfKineticFriction - )} + 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} /> )} */} {this.state.wedge && ( @@ -520,13 +518,14 @@ export default class App extends React.Component<{}, IState> { <div> {this.state.wallPositions.map((element, index) => { return ( - <Wall - key={index} - length={element.length} - xPos={element.xPos} - yPos={element.yPos} - angleInDegrees={element.angleInDegrees} - /> + <div key={index}> + <Wall + length={element.length} + xPos={element.xPos} + yPos={element.yPos} + angleInDegrees={element.angleInDegrees} + /> + </div> ); })} </div> diff --git a/src/client/views/nodes/PhysicsSimulationWall.tsx b/src/client/views/nodes/PhysicsSimulationWall.tsx index a31704d2f..2608e4772 100644 --- a/src/client/views/nodes/PhysicsSimulationWall.tsx +++ b/src/client/views/nodes/PhysicsSimulationWall.tsx @@ -12,10 +12,10 @@ export interface IWallProps { angleInDegrees: number; } -export default class App extends React.Component<IWallProps, {}> { +export default class App extends React.Component<IWallProps> { constructor(props: any) { - super(props) + super(props) } wallStyle = { diff --git a/src/client/views/nodes/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsSimulationWeight.tsx index fb040c850..669aab67a 100644 --- a/src/client/views/nodes/PhysicsSimulationWeight.tsx +++ b/src/client/views/nodes/PhysicsSimulationWeight.tsx @@ -197,6 +197,77 @@ export default class Weight extends React.Component<IWeightProps, IState> { this.setState({yVelocity: this.props.startVelY ?? 0}) this.setDisplayValues(); } + if (this.props.adjustPendulumAngle != prevProps.adjustPendulumAngle) { + // Change pendulum angle based on input field + let length = this.props.adjustPendulumAngle.length; + const x = + length * Math.cos(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180); + const y = + length * Math.sin(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180); + const xPos = this.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) { + this.setState({updatedStartPosX: this.props.startPosX}) + this.setState({xPosition: this.props.startPosX}) + this.setXPosDisplay(this.props.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.state.xVelocity != prevState.xVelocity) { + if (this.props.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)), + directionInDegrees: + 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + }; + let frictionForce: IForce = { + description: "Kinetic Friction Force", + magnitude: + this.props.coefficientOfKineticFriction * + this.forceOfGravity.magnitude * + Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 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 (this.props.coefficientOfKineticFriction != 0) { + this.props.setUpdatedForces([this.forceOfGravity, normalForce, frictionForce]); + } else { + this.props.setUpdatedForces([this.forceOfGravity, normalForce]); + } + } + } } resetEverything = () => { @@ -209,23 +280,6 @@ export default class Weight extends React.Component<IWeightProps, IState> { this.setDisplayValues(); }; - // // Change pendulum angle based on input field - // useEffect(() => { - // let length = adjustPendulumAngle.length; - // const x = - // length * Math.cos(((90 - adjustPendulumAngle.angle) * Math.PI) / 180); - // const y = - // length * Math.sin(((90 - adjustPendulumAngle.angle) * Math.PI) / 180); - // const xPos = xMax / 2 - x - radius; - // const yPos = y - radius - 5; - // setXPosition(xPos); - // setYPosition(yPos); - // setUpdatedStartPosX(xPos); - // setUpdatedStartPosY(yPos); - // setPendulumAngle(adjustPendulumAngle.angle); - // setPendulumLength(adjustPendulumAngle.length); - // }, [adjustPendulumAngle]); - getNewAccelerationX = (forceList: IForce[]) => { let newXAcc = 0; forceList.forEach((force) => { @@ -294,41 +348,41 @@ export default class Weight extends React.Component<IWeightProps, IState> { return vel + acc * this.props.timestepSize; }; - // const checkForCollisionsWithWall = () => { - // let collision = false; - // const minX = this.state.xPosition; - // const maxX = this.state.xPosition + 2 * this.props.radius; - // const containerWidth = window.innerWidth; - // if (this.state.xVelocity != 0) { - // this.props.walls.forEach((wall) => { - // if (wall.angleInDegrees == 90) { - // const wallX = (wall.xPos / 100) * window.innerWidth; - // if (wall.xPos < 0.35) { - // if (minX <= wallX) { - // if (elasticCollisions) { - // setXVelocity(-xVelocity); - // } else { - // setXVelocity(0); - // setXPosition(wallX + 5); - // } - // collision = true; - // } - // } else { - // if (maxX >= wallX) { - // if (elasticCollisions) { - // setXVelocity(-xVelocity); - // } else { - // setXVelocity(0); - // setXPosition(wallX - 2 * radius + 5); - // } - // collision = true; - // } - // } - // } - // }); - // } - // return collision; - // }; + checkForCollisionsWithWall = () => { + let collision = false; + const minX = this.state.xPosition; + const maxX = this.state.xPosition + 2 * this.props.radius; + const containerWidth = window.innerWidth; + if (this.state.xVelocity != 0) { + this.props.walls.forEach((wall) => { + if (wall.angleInDegrees == 90) { + const wallX = (wall.xPos / 100) * window.innerWidth; + if (wall.xPos < 0.35) { + if (minX <= wallX) { + if (this.props.elasticCollisions) { + this.setState({xVelocity: -this.state.xVelocity}); + } else { + this.setState({xVelocity: 0}); + this.setState({xPosition: wallX+5}); + } + collision = true; + } + } else { + if (maxX >= wallX) { + if (this.props.elasticCollisions) { + this.setState({xVelocity: -this.state.xVelocity}); + } else { + this.setState({xVelocity: 0}); + this.setState({xPosition: wallX - 2 * this.props.radius + 5}); + } + collision = true; + } + } + } + }); + } + return collision; + }; checkForCollisionsWithGround = () => { let collision = false; @@ -363,115 +417,71 @@ export default class Weight extends React.Component<IWeightProps, IState> { return collision; }; - // useEffect(() => { - // if (wedge && xVelocity != 0 && mode != "Review" && !kineticFriction) { - // setKineticFriction(true); - // //switch from static to kinetic friction - // const normalForce: IForce = { - // description: "Normal Force", - // magnitude: - // forceOfGravity.magnitude * - // Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - // directionInDegrees: - // 180 - 90 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - // }; - // let frictionForce: IForce = { - // description: "Kinetic Friction Force", - // magnitude: - // coefficientOfKineticFriction * - // forceOfGravity.magnitude * - // Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - // directionInDegrees: - // 180 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - // }; - // // reduce magnitude of friction force if necessary such that block cannot slide up plane - // let yForce = -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) + - // forceOfGravity.magnitude) / - // Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); - // } - // if (coefficientOfKineticFriction != 0) { - // this.props.setUpdatedForces([forceOfGravity, normalForce, frictionForce]); - // } else { - // this.props.setUpdatedForces([forceOfGravity, normalForce]); - // } - // } - // }, [xVelocity]); - - // const update = () => { - // // RK4 update - // let xPos = xPosition; - // let yPos = yPosition; - // let xVel = xVelocity; - // let yVel = yVelocity; - // for (let i = 0; i < 60; i++) { - // let forces1 = this.getNewForces(xPos, yPos, xVel, yVel); - // const xAcc1 = this.getNewAccelerationX(forces1); - // const yAcc1 = this.getNewAccelerationY(forces1); - // const xVel1 = this.getNewVelocity(xVel, xAcc1); - // const yVel1 = this.getNewVelocity(yVel, yAcc1); - - // let xVel2 = getNewVelocity(xVel, xAcc1 / 2); - // let yVel2 = getNewVelocity(yVel, yAcc1 / 2); - // let xPos2 = getNewPosition(xPos, xVel1 / 2); - // let yPos2 = getNewPosition(yPos, yVel1 / 2); - // const forces2 = this.getNewForces(xPos2, yPos2, xVel2, yVel2); - // const xAcc2 = this.getNewAccelerationX(forces2); - // const yAcc2 = this.getNewAccelerationY(forces2); - // xVel2 = this.getNewVelocity(xVel2, xAcc2); - // yVel2 = this.getNewVelocity(yVel2, yAcc2); - // xPos2 = this.getNewPosition(xPos2, xVel2); - // yPos2 = this.getNewPosition(yPos2, yVel2); - - // let xVel3 = this.getNewVelocity(xVel, xAcc2 / 2); - // let yVel3 = this.getNewVelocity(yVel, yAcc2 / 2); - // let xPos3 = this.getNewPosition(xPos, xVel2 / 2); - // let yPos3 = this.getNewPosition(yPos, yVel2 / 2); - // const forces3 = this.getNewForces(xPos3, yPos3, xVel3, yVel3); - // const xAcc3 = this.getNewAccelerationX(forces3); - // const yAcc3 = this.getNewAccelerationY(forces3); - // xVel3 = this.getNewVelocity(xVel3, xAcc3); - // yVel3 = this.getNewVelocity(yVel3, yAcc3); - // xPos3 = this.getNewPosition(xPos3, xVel3); - // yPos3 = this.getNewPosition(yPos3, yVel3); - - // let xVel4 = this.getNewVelocity(xVel, xAcc3); - // let yVel4 = this.getNewVelocity(yVel, yAcc3); - // let xPos4 = this.getNewPosition(xPos, xVel3); - // let yPos4 = this.getNewPosition(yPos, yVel3); - // const forces4 = this.getNewForces(xPos4, yPos4, xVel4, yVel4); - // const xAcc4 = this.getNewAccelerationX(forces4); - // const yAcc4 = this.getNewAccelerationY(forces4); - // xVel4 = this.getNewVelocity(xVel4, xAcc4); - // yVel4 = this.getNewVelocity(yVel4, yAcc4); - // xPos4 = this.getNewPosition(xPos4, xVel4); - // yPos4 = this.getNewPosition(yPos4, yVel4); - - // xVel += - // timestepSize * (xAcc1 / 6.0 + xAcc2 / 3.0 + xAcc3 / 3.0 + xAcc4 / 6.0); - // yVel += - // timestepSize * (yAcc1 / 6.0 + yAcc2 / 3.0 + yAcc3 / 3.0 + yAcc4 / 6.0); - // xPos += - // timestepSize * (xVel1 / 6.0 + xVel2 / 3.0 + xVel3 / 3.0 + xVel4 / 6.0); - // yPos += - // timestepSize * (yVel1 / 6.0 + yVel2 / 3.0 + yVel3 / 3.0 + yVel4 / 6.0); - // } - - // setXVelocity(xVel); - // setYVelocity(yVel); - // setXPosition(xPos); - // setYPosition(yPos); - // this.props.setUpdatedForces(getNewForces(xPos, yPos, xVel, yVel)); - // }; + update = () => { + // RK4 update + let xPos = this.state.xPosition; + let yPos = this.state.yPosition; + let xVel = this.state.xVelocity; + let yVel = this.state.yVelocity; + for (let i = 0; i < 60; i++) { + let forces1 = this.getNewForces(xPos, yPos, xVel, yVel); + const xAcc1 = this.getNewAccelerationX(forces1); + const yAcc1 = this.getNewAccelerationY(forces1); + const xVel1 = this.getNewVelocity(xVel, xAcc1); + const yVel1 = this.getNewVelocity(yVel, yAcc1); + + let xVel2 = this.getNewVelocity(xVel, xAcc1 / 2); + let yVel2 = this.getNewVelocity(yVel, yAcc1 / 2); + let xPos2 = this.getNewPosition(xPos, xVel1 / 2); + let yPos2 = this.getNewPosition(yPos, yVel1 / 2); + const forces2 = this.getNewForces(xPos2, yPos2, xVel2, yVel2); + const xAcc2 = this.getNewAccelerationX(forces2); + const yAcc2 = this.getNewAccelerationY(forces2); + xVel2 = this.getNewVelocity(xVel2, xAcc2); + yVel2 = this.getNewVelocity(yVel2, yAcc2); + xPos2 = this.getNewPosition(xPos2, xVel2); + yPos2 = this.getNewPosition(yPos2, yVel2); + + let xVel3 = this.getNewVelocity(xVel, xAcc2 / 2); + let yVel3 = this.getNewVelocity(yVel, yAcc2 / 2); + let xPos3 = this.getNewPosition(xPos, xVel2 / 2); + let yPos3 = this.getNewPosition(yPos, yVel2 / 2); + const forces3 = this.getNewForces(xPos3, yPos3, xVel3, yVel3); + const xAcc3 = this.getNewAccelerationX(forces3); + const yAcc3 = this.getNewAccelerationY(forces3); + xVel3 = this.getNewVelocity(xVel3, xAcc3); + yVel3 = this.getNewVelocity(yVel3, yAcc3); + xPos3 = this.getNewPosition(xPos3, xVel3); + yPos3 = this.getNewPosition(yPos3, yVel3); + + let xVel4 = this.getNewVelocity(xVel, xAcc3); + let yVel4 = this.getNewVelocity(yVel, yAcc3); + let xPos4 = this.getNewPosition(xPos, xVel3); + let yPos4 = this.getNewPosition(yPos, yVel3); + const forces4 = this.getNewForces(xPos4, yPos4, xVel4, yVel4); + const xAcc4 = this.getNewAccelerationX(forces4); + const yAcc4 = this.getNewAccelerationY(forces4); + xVel4 = this.getNewVelocity(xVel4, xAcc4); + yVel4 = this.getNewVelocity(yVel4, yAcc4); + xPos4 = this.getNewPosition(xPos4, xVel4); + yPos4 = this.getNewPosition(yPos4, yVel4); + + xVel += + this.props.timestepSize * (xAcc1 / 6.0 + xAcc2 / 3.0 + xAcc3 / 3.0 + xAcc4 / 6.0); + yVel += + this.props.timestepSize * (yAcc1 / 6.0 + yAcc2 / 3.0 + yAcc3 / 3.0 + yAcc4 / 6.0); + xPos += + this.props.timestepSize * (xVel1 / 6.0 + xVel2 / 3.0 + xVel3 / 3.0 + xVel4 / 6.0); + yPos += + this.props.timestepSize * (yVel1 / 6.0 + yVel2 / 3.0 + yVel3 / 3.0 + yVel4 / 6.0); + } + + this.setState({xVelocity: xVel}); + this.setState({yVelocity: yVel}); + this.setState({xPosition: xPos}); + this.setState({yPosition: yPos}); + this.props.setUpdatedForces(this.getNewForces(xPos, yPos, xVel, yVel)); + }; weightStyle = { backgroundColor: this.props.color, @@ -491,20 +501,6 @@ export default class Weight extends React.Component<IWeightProps, IState> { labelBackgroundColor = `rgba(255,255,255,0.5)`; - // // Update x start position - // useEffect(() => { - // setUpdatedStartPosX(startPosX); - // setXPosition(startPosX); - // setXPosDisplay(startPosX); - // }, [startPosX]); - - // // Update y start position - // useEffect(() => { - // setUpdatedStartPosY(startPosY); - // setYPosition(startPosY); - // setYPosDisplay(startPosY); - // }, [startPosY]); - render () { return ( <div style={{ zIndex: -1000 }}> |