diff options
Diffstat (limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx')
-rw-r--r-- | src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx | 419 |
1 files changed, 207 insertions, 212 deletions
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx index f43994346..4b3daa0d8 100644 --- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx @@ -11,7 +11,7 @@ export interface IForce { component: boolean; } export interface IWeightProps { - dataDoc: doc; + dataDoc: Doc; adjustPendulumAngle: { angle: number; length: number }; circularMotionRadius: number; coefficientOfKineticFriction: number; @@ -21,7 +21,6 @@ export interface IWeightProps { displayYVelocity: number; elasticCollisions: boolean; gravity: number; - incrementTime: number; mass: number; mode: string; noMovement: boolean; @@ -229,8 +228,213 @@ export default class Weight extends React.Component<IWeightProps, IState> { this.props.dataDoc['velocityYDisplay'] = y } } + + // Prevent bug when switching between sims + if (prevProps.startForces != this.props.startForces) { + this.setState({xVelocity: this.props.startVelX}) + this.setState({yVelocity: this.props.startVelY}) + this.setDisplayValues(); + } + + // Make sure weight doesn't go above max height + if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) { + if (this.props.dataDoc['simulationType'] == "One Weight") { + let maxYPos = this.state.updatedStartPosY; + if (this.props.startVelY != 0) { + maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity)); + } + if (maxYPos < 0) { + maxYPos = 0; + } + this.setState({maxPosYConservation: maxYPos}) + } + } + + // Check for collisions and update + if (prevState.timer != this.state.timer) { + if (!this.props.paused && !this.props.noMovement) { + let collisions = false; + if ( + this.props.dataDoc['simulationType'] == "One Weight" || + this.props.dataDoc['simulationType'] == "Inclined Plane" + ) { + const collisionsWithGround = this.checkForCollisionsWithGround(); + const collisionsWithWalls = this.checkForCollisionsWithWall(); + collisions = collisionsWithGround || collisionsWithWalls; + } + if (this.props.dataDoc['simulationType'] == "Pulley") { + if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) { + collisions = true; + } + } + if (!collisions) { + this.update(); + } + this.setDisplayValues(); + } + } + + // Reset everything on reset button click + if (prevProps.reset != this.props.reset) { + this.resetEverything(); + } + + // Convert from static to kinetic friction if/when weight slips on inclined plane + if (prevState.xVelocity != this.state.xVelocity) { + if ( + this.props.dataDoc['simulationType'] == "Inclined Plane" && + Math.abs(this.state.xVelocity) > 0.1 && + this.props.dataDoc['mode'] != "Review" && + !this.state.kineticFriction + ) { + this.setState({kineticFriction: true}) + const normalForce: IForce = { + description: "Normal Force", + magnitude: + this.props.mass * + Math.abs(this.props.gravity) * + Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + component: false, + }; + let frictionForce: IForce = { + description: "Kinetic Friction Force", + magnitude: + this.props.mass * + this.props.coefficientOfKineticFriction * + Math.abs(this.props.gravity) * + Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + component: false, + }; + // reduce magnitude of friction force if necessary such that block cannot slide up plane + let yForce = -Math.abs(this.props.gravity); + 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) + + Math.abs(this.props.gravity)) / + Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); + } + + const frictionForceComponent: IForce = { + description: "Kinetic Friction Force", + + magnitude: + this.props.mass * + this.props.coefficientOfKineticFriction * + Math.abs(this.props.gravity) * + Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + component: true, + }; + const normalForceComponent: IForce = { + description: "Normal Force", + magnitude: + this.props.mass * + Math.abs(this.props.gravity) * + Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + component: true, + }; + const gravityParallel: IForce = { + description: "Gravity Parallel Component", + magnitude: + this.props.mass * + Math.abs(this.props.gravity) * + Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 180 - + 90 - + (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI + + 180, + component: true, + }; + const gravityPerpendicular: IForce = { + description: "Gravity Perpendicular Component", + magnitude: + this.props.mass * + Math.abs(this.props.gravity) * + Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)), + directionInDegrees: + 360 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI, + component: true, + }; + const gravityForce: IForce = { + description: "Gravity", + magnitude: this.props.mass * Math.abs(this.props.gravity), + directionInDegrees: 270, + component: false, + }; + if (this.props.coefficientOfKineticFriction != 0) { + this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce, frictionForce]); + this.props.dataDoc['componentForces'] = ([ + frictionForceComponent, + normalForceComponent, + gravityParallel, + gravityPerpendicular, + ]); + } else { + this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce]); + this.props.dataDoc['componentForces'] = ([ + normalForceComponent, + gravityParallel, + gravityPerpendicular, + ]); + } + } + } + + // Add/remove walls when simulation type changes + if (prevProps.simulationType != this.props.simulationType) { + let w: IWallProps[] = []; + if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") { + w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 }); + w.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 }); + w.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 }); + w.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 }); + } + this.setState({walls: w}) + } - // TODO move all use effect code here + // Update x position when start pos x changes + if (prevProps.startPosX != this.props.startPosX) { + if (this.props.paused) { + this.setState({xPosition: this.props.startPosX}) + this.setState({updatedStartPosX: this.props.startPosX}) + this.props.dataDoc['positionXDisplay'] = this.props.startPosX + } + } + + + // Update y position when start pos y changes + if (prevProps.startPosY != this.props.startPosY) { + if (this.props.paused) { + this.setState({yPosition: this.props.startPosY}) + this.setState({updatedStartPosY: this.props.startPosY}) + this.props.dataDoc['positionYDisplay'] = this.props.startPosY + } + } + + // Update wedge coordinates + if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) { + const left = this.props.xMax * 0.5 - 200; + const coordinatePair1 = Math.round(left) + "," + this.props.yMax + " "; + const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + "," + this.props.yMax + " "; + const coordinatePair3 = Math.round(left) + "," + (this.props.yMax - this.props.wedgeHeight); + const coord = coordinatePair1 + coordinatePair2 + coordinatePair3; + this.setState({coordinates: coord}) + } } // Reset simulation on reset button click @@ -685,215 +889,6 @@ export default class Weight extends React.Component<IWeightProps, IState> { } }; - - // TODO - // Prevent bug when switching between sims - useEffect(() => { - setXVelocity(startVelX); - setYVelocity(startVelY); - setDisplayValues(); - }, [startForces]); - - // Make sure weight doesn't go above max height - useEffect(() => { - if (this.props.dataDoc['simulationType'] == "One Weight") { - let maxYPos = updatedStartPosY; - if (startVelY != 0) { - maxYPos -= (startVelY * startVelY) / (2 * Math.abs(gravity)); - } - if (maxYPos < 0) { - maxYPos = 0; - } - setMaxPosYConservation(maxYPos); - } - }, [updatedStartPosY, startVelY]); - - // Check for collisions and update - useEffect(() => { - if (!paused && !noMovement) { - let collisions = false; - if ( - this.props.dataDoc['simulationType'] == "One Weight" || - this.props.dataDoc['simulationType'] == "Inclined Plane" - ) { - const collisionsWithGround = checkForCollisionsWithGround(); - const collisionsWithWalls = checkForCollisionsWithWall(); - collisions = collisionsWithGround || collisionsWithWalls; - } - if (this.props.dataDoc['simulationType'] == "Pulley") { - if (yPosition <= yMin + 100 || yPosition >= yMax - 100) { - collisions = true; - } - } - if (!collisions) { - update(); - } - setDisplayValues(); - } - }, [incrementTime]); - - // Reset everything on reset button click - useEffect(() => { - resetEverything(); - }, [reset]); - - // Convert from static to kinetic friction if/when weight slips on inclined plane - useEffect(() => { - if ( - this.props.dataDoc['simulationType'] == "Inclined Plane" && - Math.abs(xVelocity) > 0.1 && - this.props.dataDoc['mode'] != "Review" && - !kineticFriction - ) { - setKineticFriction(true); - //switch from static to kinetic friction - const normalForce: IForce = { - description: "Normal Force", - magnitude: - mass * - Math.abs(gravity) * - Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 180 - 90 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - component: false, - }; - let frictionForce: IForce = { - description: "Kinetic Friction Force", - magnitude: - mass * - coefficientOfKineticFriction * - Math.abs(gravity) * - Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 180 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - component: false, - }; - // reduce magnitude of friction force if necessary such that block cannot slide up plane - let yForce = -Math.abs(gravity); - 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) + - Math.abs(gravity)) / - Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); - } - - const frictionForceComponent: IForce = { - description: "Kinetic Friction Force", - - magnitude: - mass * - coefficientOfKineticFriction * - Math.abs(gravity) * - Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 180 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - component: true, - }; - const normalForceComponent: IForce = { - description: "Normal Force", - magnitude: - mass * - Math.abs(gravity) * - Math.cos(Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 180 - 90 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - component: true, - }; - const gravityParallel: IForce = { - description: "Gravity Parallel Component", - magnitude: - mass * - Math.abs(gravity) * - Math.sin(Math.PI / 2 - Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 180 - - 90 - - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI + - 180, - component: true, - }; - const gravityPerpendicular: IForce = { - description: "Gravity Perpendicular Component", - magnitude: - mass * - Math.abs(gravity) * - Math.cos(Math.PI / 2 - Math.atan(wedgeHeight / wedgeWidth)), - directionInDegrees: - 360 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI, - component: true, - }; - const gravityForce: IForce = { - description: "Gravity", - magnitude: mass * Math.abs(gravity), - directionInDegrees: 270, - component: false, - }; - if (coefficientOfKineticFriction != 0) { - this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce, frictionForce]); - this.props.dataDoc['componentForces'] = ([ - frictionForceComponent, - normalForceComponent, - gravityParallel, - gravityPerpendicular, - ]); - } else { - this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce]); - this.props.dataDoc['componentForces'] = ([ - normalForceComponent, - gravityParallel, - gravityPerpendicular, - ]); - } - } - }, [xVelocity]); - - // Add/remove walls when simulation type changes - useEffect(() => { - let w: IWallProps[] = []; - if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") { - w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 }); - w.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 }); - w.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 }); - w.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 }); - } - setWalls(w); - }, [this.props.dataDoc['simulationType']]); - - // Update x position when start pos x changes - useEffect(() => { - if (paused) { - setUpdatedStartPosX(startPosX); - setXPosition(startPosX); - setXPosDisplay(startPosX); - } - }, [startPosX]); - - // Update y position when start pos y changes - useEffect(() => { - if (paused) { - setUpdatedStartPosY(startPosY); - setYPosition(startPosY); - setYPosDisplay(startPosY); - } - }, [startPosY]); - - // Update wedge coordinates - useEffect(() => { - const left = xMax * 0.5 - 200; - const coordinatePair1 = Math.round(left) + "," + yMax + " "; - const coordinatePair2 = Math.round(left + wedgeWidth) + "," + yMax + " "; - const coordinatePair3 = Math.round(left) + "," + (yMax - wedgeHeight); - const coord = coordinatePair1 + coordinatePair2 + coordinatePair3; - setCoordinates(coord); - }, [wedgeWidth, wedgeHeight]); - // Render weight, spring, rod(s), vectors return ( <div style={{ zIndex: -1000 }}> |