diff options
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationApp.tsx | 461 | ||||
-rw-r--r-- | src/client/views/nodes/PhysicsSimulationWeight.tsx | 397 |
2 files changed, 409 insertions, 449 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationApp.tsx b/src/client/views/nodes/PhysicsSimulationApp.tsx index 414d61809..2277c7875 100644 --- a/src/client/views/nodes/PhysicsSimulationApp.tsx +++ b/src/client/views/nodes/PhysicsSimulationApp.tsx @@ -1,8 +1,8 @@ import React = require('react'); import "./PhysicsSimulationBox.scss"; -import { IForce, Weight } from "./PhysicsSimulationWeight"; -import {Wall, IWallProps } from "./PhysicsSimulationWall" -import {Wedge} from "./PhysicsSimulationWedge" +import Weight from "./PhysicsSimulationWeight"; +import Wall from "./PhysicsSimulationWall" +import Wedge from "./PhysicsSimulationWedge" import { props, any } from 'bluebird'; import { render } from 'react-dom'; @@ -329,235 +329,232 @@ export default class App extends React.Component<{}, IState> { render () { return ( - <p>Hello world!</p> - // <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> - // ); - // })} */} - // {weight && ( - // <Weight - // adjustPendulumAngle={adjustPendulumAngle} - // color={"red"} - // displayXPosition={positionXDisplay} - // displayXVelocity={velocityXDisplay} - // displayYPosition={positionYDisplay} - // displayYVelocity={velocityYDisplay} - // elasticCollisions={elasticCollisions} - // incrementTime={timer} - // mass={1} - // mode={mode} - // noMovement={noMovement} - // paused={simulationPaused} - // pendulum={pendulum} - // pendulumAngle={pendulumAngle} - // pendulumLength={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} - // timestepSize={0.002} - // updateDisplay={displayChange} - // updatedForces={updatedForces} - // walls={wallPositions} - // wedge={wedge} - // wedgeHeight={wedgeHeight} - // wedgeWidth={wedgeWidth} - // coefficientOfKineticFriction={Number( - // coefficientOfKineticFriction - // )} - // /> - // )} - // {wedge && ( - // <Wedge - // startWidth={wedgeWidth} - // startHeight={wedgeHeight} - // startLeft={xMax * 0.5 - 200} - // /> - // )} - // </div> - // <div> - // {wallPositions.map((element, index) => { - // return ( - // <Wall - // key={index} - // length={element.length} - // xPos={element.xPos} - // yPos={element.yPos} - // angleInDegrees={element.angleInDegrees} - // /> - // ); - // })} - // </div> - // </div> - // </div> - // <div className="mechanicsSimulationEquationContainer"> - // <div className="mechanicsSimulationControls"> - // <div> - // {simulationPaused && ( - // <button onClick={() => { - // setSimulationPaused(false); - // }} >START</button> - // )} - // {!simulationPaused && ( - // <button onClick={() => { - // setSimulationPaused(true); - // }} >PAUSE</button> - // )} - // {simulationPaused && ( - // <button onClick={() => { - // setSimulationReset(!simulationReset); - // }} >RESET</button> - // )} - // </div> - // </div> - // </div> - // </div> - // </div> + <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> + ); + })} */} + {/* {weight && ( + <Weight + adjustPendulumAngle={adjustPendulumAngle} + color={"red"} + displayXPosition={positionXDisplay} + displayXVelocity={velocityXDisplay} + displayYPosition={positionYDisplay} + displayYVelocity={velocityYDisplay} + elasticCollisions={elasticCollisions} + incrementTime={timer} + mass={1} + paused={simulationPaused} + pendulum={pendulum} + pendulumAngle={pendulumAngle} + pendulumLength={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} + timestepSize={0.002} + updateDisplay={displayChange} + updatedForces={updatedForces} + walls={wallPositions} + wedge={wedge} + wedgeHeight={wedgeHeight} + wedgeWidth={wedgeWidth} + coefficientOfKineticFriction={Number( + coefficientOfKineticFriction + )} + /> + )} */} + {this.state.wedge && ( + <Wedge + startWidth={this.state.wedgeWidth} + startHeight={this.state.wedgeHeight} + startLeft={this.xMax * 0.5 - 200} + /> + )} + </div> + <div> + {this.state.wallPositions.map((element, index) => { + return ( + <Wall + key={index} + length={element.length} + xPos={element.xPos} + yPos={element.yPos} + angleInDegrees={element.angleInDegrees} + /> + ); + })} + </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> + )} + </div> + </div> + </div> + </div> + </div> ); } } diff --git a/src/client/views/nodes/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsSimulationWeight.tsx index cc024f29a..d234c1395 100644 --- a/src/client/views/nodes/PhysicsSimulationWeight.tsx +++ b/src/client/views/nodes/PhysicsSimulationWeight.tsx @@ -1,6 +1,8 @@ +import React from "react"; import { useEffect, useState } from "react"; +import { render } from "react-dom"; import { IWallProps } from "./PhysicsSimulationWall"; -import { Wedge } from "./PhysicsSimulationWedge"; +import Wedge from "./PhysicsSimulationWedge"; export interface IForce { description: string; @@ -35,8 +37,6 @@ export interface IWeightProps { setPendulumLength: (val: number) => any; setStartPendulumAngle: (val: number) => any; showAcceleration: boolean; - mode: string; - noMovement: boolean; pendulumAngle: number; setSketching: (val: boolean) => any; showForces: boolean; @@ -56,154 +56,121 @@ export interface IWeightProps { wedgeHeight: number; } -export const Weight = (props: IWeightProps) => { - const { - adjustPendulumAngle, - color, - displayXPosition, - displayYPosition, - displayXVelocity, - displayYVelocity, - elasticCollisions, - startForces, - incrementTime, - mass, - paused, - pendulum, - pendulumLength, - wedge, - radius, - mode, - noMovement, - pendulumAngle, - reset, - setSketching, - setDisplayXAcceleration, - setDisplayXPosition, - setDisplayXVelocity, - setDisplayYAcceleration, - setDisplayYPosition, - setDisplayYVelocity, - setPaused, - setPendulumAngle, - setPendulumLength, - setStartPendulumAngle, - showAcceleration, - showForces, - showForceMagnitudes, - showVelocity, - startPosX, - startPosY, - startVelX, - startVelY, - timestepSize, - updateDisplay, - updatedForces, - setUpdatedForces, - walls, - coefficientOfKineticFriction, - wedgeWidth, - wedgeHeight, - } = props; +interface IState { + dragging: boolean, + kineticFriction: boolean, + updatedStartPosX: number, + updatedStartPosY: number, + xPosition: number, + yPosition: number, + xVelocity: number, + yVelocity: number, +} +export default class Weight extends React.Component<IWeightProps, IState> { + + constructor(props: any) { + super(props) + this.state = { + dragging: false, + kineticFriction: false, + updatedStartPosX: this.props.startPosX, + updatedStartPosY: this.props.startPosY, + xPosition: this.props.startPosX, + yPosition: this.props.startPosY, + xVelocity: this.props.startVelX ? this.props.startVelX: 0, + yVelocity: this.props.startVelY ? this.props.startVelY: 0, + } + } // Constants - const draggable = !wedge && mode == "Freeform"; - const epsilon = 0.0001; - - const forceOfGravity: IForce = { + draggable = !this.props.wedge; + epsilon = 0.0001; + forceOfGravity: IForce = { description: "Gravity", - magnitude: mass * 9.81, + magnitude: this.props.mass * 9.81, directionInDegrees: 270, }; - const xMax = window.innerWidth * 0.7; - const xMin = 0; - const yMax = window.innerHeight * 0.8; - const yMin = 0; - - // State hooks - const [dragging, setDragging] = useState(false); - const [kineticFriction, setKineticFriction] = useState(false); - const [updatedStartPosX, setUpdatedStartPosX] = useState(startPosX); - const [updatedStartPosY, setUpdatedStartPosY] = useState(startPosY); - const [xPosition, setXPosition] = useState(startPosX); - const [xVelocity, setXVelocity] = useState(startVelX ?? 0); - const [yPosition, setYPosition] = useState(startPosY); - const [yVelocity, setYVelocity] = useState(startVelY ?? 0); + xMax = window.innerWidth * 0.7; + xMin = 0; + yMax = window.innerHeight * 0.8; + yMin = 0; // Helper function to go between display and real values const getDisplayYPos = (yPos: number) => { - return yMax - yPos - 2 * radius + 5; + return this.yMax - yPos - 2 * this.props.radius + 5; }; const getYPosFromDisplay = (yDisplay: number) => { - return yMax - yDisplay - 2 * radius + 5; + return this.yMax - yDisplay - 2 * this.props.radius + 5; }; // Set display values based on real values const setYPosDisplay = (yPos: number) => { - const displayPos = getDisplayYPos(yPos); - setDisplayYPosition(Math.round(displayPos * 100) / 100); + const displayPos = this.getDisplayYPos(yPos); + this.props.setDisplayYPosition(Math.round(displayPos * 100) / 100) }; const setXPosDisplay = (xPos: number) => { - setDisplayXPosition(Math.round(xPos * 100) / 100); + this.props.setDisplayXPosition(Math.round(xPos * 100) / 100); }; const setYVelDisplay = (yVel: number) => { - setDisplayYVelocity((-1 * Math.round(yVel * 100)) / 100); + this.props.setDisplayYVelocity((-1 * Math.round(yVel * 100)) / 100); }; const setXVelDisplay = (xVel: number) => { - setDisplayXVelocity(Math.round(xVel * 100) / 100); + this.props.setDisplayXVelocity(Math.round(xVel * 100) / 100); }; const setDisplayValues = ( - xPos: number = xPosition, - yPos: number = yPosition, - xVel: number = xVelocity, - yVel: number = yVelocity + xPos: number = this.state.xPosition, + yPos: number = this.state.yPosition, + xVel: number = this.state.xVelocity, + yVel: number = this.state.yVelocity ) => { - setYPosDisplay(yPos); - setXPosDisplay(xPos); - setYVelDisplay(yVel); - setXVelDisplay(xVel); - setDisplayYAcceleration( - (-1 * Math.round(getNewAccelerationY(updatedForces) * 100)) / 100 + this.setYPosDisplay(yPos); + this.setXPosDisplay(xPos); + this.setYVelDisplay(yVel); + this.setXVelDisplay(xVel); + this.props.setDisplayYAcceleration( + (-1 * Math.round(getNewAccelerationY(this.props.updatedForces) * 100)) / 100 ); - setDisplayXAcceleration( - Math.round(getNewAccelerationX(updatedForces) * 100) / 100 + this.props.setDisplayXAcceleration( + Math.round(getNewAccelerationX(this.props.updatedForces) * 100) / 100 ); }; // When display values updated by user, update real values - useEffect(() => { - if (updateDisplay.xDisplay != xPosition) { - let x = updateDisplay.xDisplay; - x = Math.max(0, x); - x = Math.min(x, xMax - 2 * radius); - setUpdatedStartPosX(x); - setXPosition(x); - setDisplayXPosition(x); - } - - if (updateDisplay.yDisplay != getDisplayYPos(yPosition)) { - let y = updateDisplay.yDisplay; - y = Math.max(0, y); - y = Math.min(y, yMax - 2 * radius); - setDisplayYPosition(y); - let coordinatePosition = getYPosFromDisplay(y); - setUpdatedStartPosY(coordinatePosition); - setYPosition(coordinatePosition); - } - - if (displayXVelocity != xVelocity) { - let x = displayXVelocity; - setXVelocity(x); - setDisplayXVelocity(x); - } - - if (displayYVelocity != -yVelocity) { - let y = displayYVelocity; - setYVelocity(-y); - setDisplayYVelocity(y); + componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void { + if (this.props.updateDisplay != prevProps.updateDisplay) { + if (this.props.updateDisplay.xDisplay != this.state.xPosition) { + let x = this.props.updateDisplay.xDisplay; + x = Math.max(0, x); + x = Math.min(x, this.xMax - 2 * this.props.radius); + this.setState({updatedStartPosX: x}) + this.setState({xPosition: x}) + this.props.setDisplayXPosition(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.yMax - 2 * this.props.radius); + this.props.setDisplayYPosition(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; + this.setState({xVelocity: x}) + this.props.setDisplayXVelocity(x); + } + + if (this.props.displayYVelocity != this.state.yVelocity) { + let y = this.props.displayYVelocity; + this.setState({yVelocity: -y}) + this.props.setDisplayXVelocity(y); + } } - }, [updateDisplay]); + } // Check for collisions and update useEffect(() => { @@ -264,7 +231,7 @@ export const Weight = (props: IWeightProps) => { newXAcc += (force.magnitude * Math.cos((force.directionInDegrees * Math.PI) / 180)) / - mass; + this.props.mass; }); return newXAcc; }; @@ -276,7 +243,7 @@ export const Weight = (props: IWeightProps) => { (-1 * (force.magnitude * Math.sin((force.directionInDegrees * Math.PI) / 180))) / - mass; + this.props.mass; }); return newYAcc; }; @@ -287,11 +254,11 @@ export const Weight = (props: IWeightProps) => { xVel: number, yVel: number ) => { - if (!pendulum) { - return updatedForces; + if (!this.props.pendulum) { + return this.state.updatedForces; } - const x = xMax / 2 - xPos - radius; - const y = yPos + radius + 5; + const x = this.xMax / 2 - xPos - this.props.radius; + const y = yPos + this.props.radius + 5; let angle = (Math.atan(y / x) * 180) / Math.PI; if (angle < 0) { angle += 180; @@ -306,8 +273,8 @@ export const Weight = (props: IWeightProps) => { setPendulumLength(Math.sqrt(x * x + y * y)); const mag = - mass * 9.81 * Math.cos((oppositeAngle * Math.PI) / 180) + - (mass * (xVel * xVel + yVel * yVel)) / pendulumLength; + this.props.mass * 9.81 * Math.cos((oppositeAngle * Math.PI) / 180) + + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength; const forceOfTension: IForce = { description: "Tension", @@ -315,24 +282,24 @@ export const Weight = (props: IWeightProps) => { directionInDegrees: angle, }; - return [forceOfGravity, forceOfTension]; + return [this.forceOfGravity, forceOfTension]; }; const getNewPosition = (pos: number, vel: number) => { - return pos + vel * timestepSize; + return pos + vel * this.props.timestepSize; }; const getNewVelocity = (vel: number, acc: number) => { - return vel + acc * timestepSize; + return vel + acc * this.props.timestepSize; }; const checkForCollisionsWithWall = () => { let collision = false; - const minX = xPosition; - const maxX = xPosition + 2 * radius; + const minX = this.state.xPosition; + const maxX = this.state.xPosition + 2 * this.props.radius; const containerWidth = window.innerWidth; - if (xVelocity != 0) { - walls.forEach((wall) => { + 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) { @@ -542,43 +509,39 @@ export const Weight = (props: IWeightProps) => { setYPosDisplay(startPosY); }, [startPosY]); - return ( + render () { + return ( <div style={{ zIndex: -1000 }}> <div className="weightContainer" onPointerDown={(e) => { - if (draggable) { + if (this.props.draggable) { e.preventDefault(); - setPaused(true); - setDragging(true); + this.props.setPaused(true); + this.setState({dragging: true}); setClickPositionX(e.clientX); setClickPositionY(e.clientY); - } else if (mode == "Review") { - setSketching(true); } }} onPointerMove={(e) => { e.preventDefault(); - if (dragging) { - let newY = yPosition + e.clientY - clickPositionY; - if (newY > yMax - 2 * radius) { - newY = yMax - 2 * radius; + if (this.state.dragging) { + let newY = this.state.yPosition + e.clientY - clickPositionY; + if (newY > this.yMax - 2 * this.props.radius) { + newY = this.yMax - 2 * this.props.radius; } - let newX = xPosition + e.clientX - clickPositionX; - if (newX > xMax - 2 * radius) { - newX = xMax - 2 * radius; + let newX = this.state.xPosition + e.clientX - clickPositionX; + if (newX > this.xMax - 2 * this.props.radius) { + newX = this.xMax - 2 * this.props.radius; } else if (newX < 0) { newX = 0; } - - setXPosition(newX); - setYPosition(newY); - setUpdatedStartPosX(newX); - setUpdatedStartPosY(newY); - setDisplayYPosition( - Math.round((yMax - 2 * radius - newY + 5) * 100) / 100 - ); + this.setState({xPosition: newX}) + this.setState({yPosition: newY}) + this.setState({updatedStartPosX: newX}) + this.setState({updatedStartPosY: newY}) + this.setState({displayYPosition: Math.round((yMax - 2 * radius - newY + 5) * 100) / 100}) setClickPositionX(e.clientX); setClickPositionY(e.clientY); setDisplayValues(); @@ -591,20 +554,20 @@ export const Weight = (props: IWeightProps) => { resetEverything(); } setDragging(false); - let newY = yPosition + e.clientY - clickPositionY; - if (newY > yMax - 2 * radius) { - newY = yMax - 2 * radius; + let newY = this.state.yPosition + e.clientY - clickPositionY; + if (newY > this.yMax - 2 * this.props.radius) { + newY = this.yMax - 2 * this.props.radius; } let newX = xPosition + e.clientX - clickPositionX; - if (newX > xMax - 2 * radius) { - newX = xMax - 2 * radius; + if (newX > this.xMax - 2 * this.props.radius) { + newX = this.xMax - 2 * this.props.radius; } else if (newX < 0) { newX = 0; } - if (pendulum) { - const x = xMax / 2 - newX - radius; - const y = newY + radius + 5; + if (this.state.pendulum) { + const x = this.xMax / 2 - newX - this.props.radius; + const y = newY + this.props.radius + 5; let angle = (Math.atan(y / x) * 180) / Math.PI; if (angle < 0) { angle += 180; @@ -615,20 +578,19 @@ export const Weight = (props: IWeightProps) => { } const pendulumLength = Math.sqrt(x * x + y * y); - setPendulumAngle(oppositeAngle); - setPendulumLength(Math.sqrt(x * x + y * y)); + this.props.setPendulumAngle(oppositeAngle); + this.props.setPendulumLength(Math.sqrt(x * x + y * y)); const mag = 9.81 * Math.cos((oppositeAngle * Math.PI) / 180); const forceOfTension: IForce = { description: "Tension", magnitude: mag, directionInDegrees: angle, }; - - setKineticFriction(false); - setXVelocity(startVelX ?? 0); - setYVelocity(startVelY ?? 0); + this.setState({kineticFriction: false}) + this.setState({xVelocity: startVelX ?? 0}) + this.setState({yVelocity: startVelY ?? 0}) setDisplayValues(); - setUpdatedForces([forceOfGravity, forceOfTension]); + this.setState({updatedForces :[forceOfGravity, forceOfTension]}); } } }} @@ -637,7 +599,7 @@ export const Weight = (props: IWeightProps) => { <p className="weightLabel">{mass} kg</p> </div> </div> - {pendulum && ( + {this.state.pendulum && ( <div className="rod" style={{ @@ -648,45 +610,45 @@ export const Weight = (props: IWeightProps) => { zIndex: -2, }} > - <svg width={xMax + "px"} height={window.innerHeight + "px"}> + <svg width={this.xMax + "px"} height={window.innerHeight + "px"}> <line - x1={xPosition + radius} - y1={yPosition + radius} - x2={xMax / 2} + x1={this.state.xPosition + this.props.radius} + y1={this.state.yPosition + this.props.radius} + x2={this.xMax / 2} y2={-5} stroke={"#deb887"} strokeWidth="10" /> </svg> - {!dragging && ( + {!this.state.dragging && ( <div> <p style={{ position: "absolute", zIndex: 5, - left: xPosition + "px", - top: yPosition - 70 + "px", + left: this.state.xPosition + "px", + top: this.state.yPosition - 70 + "px", backgroundColor: labelBackgroundColor, }} > - {Math.round(pendulumLength)} m + {Math.round(this.props.pendulumLength)} m </p> <p style={{ position: "absolute", zIndex: -1, - left: xMax / 2 + "px", + left: this.xMax / 2 + "px", top: 30 + "px", backgroundColor: labelBackgroundColor, }} > - {Math.round(pendulumAngle * 100) / 100}° + {Math.round(this.props.pendulumAngle * 100) / 100}° </p> </div> )} </div> )} - {!dragging && showAcceleration && ( + {!this.state.dragging && this.props.showAcceleration && ( <div> <div style={{ @@ -697,7 +659,7 @@ export const Weight = (props: IWeightProps) => { top: 0, }} > - <svg width={xMax + "px"} height={window.innerHeight + "px"}> + <svg width={this.xMax + "px"} height={window.innerHeight + "px"}> <defs> <marker id="accArrow" @@ -712,10 +674,10 @@ export const Weight = (props: IWeightProps) => { </marker> </defs> <line - x1={xPosition + radius} - y1={yPosition + radius} - x2={xPosition + radius + getNewAccelerationX(updatedForces) * 5} - y2={yPosition + radius + getNewAccelerationY(updatedForces) * 5} + x1={this.state.xPosition + this.props.radius} + y1={this.state.yPosition + this.props.radius} + x2={this.state.xPosition + this.props.radius + getNewAccelerationX(this.state.updatedForces) * 5} + y2={this.state.yPosition + this.props.radius + getNewAccelerationY(this.state.updatedForces) * 5} stroke={"green"} strokeWidth="5" markerEnd="url(#accArrow)" @@ -726,15 +688,15 @@ export const Weight = (props: IWeightProps) => { pointerEvents: "none", position: "absolute", left: - xPosition + - radius + - getNewAccelerationX(updatedForces) * 5 + + this.state.xPosition + + this.props.radius + + getNewAccelerationX(this.state.updatedForces) * 5 + 25 + "px", top: - yPosition + - radius + - getNewAccelerationY(updatedForces) * 5 + + this.state.yPosition + + this.props.radius + + getNewAccelerationY(this.state.updatedForces) * 5 + 25 + "px", zIndex: -1, @@ -745,8 +707,8 @@ export const Weight = (props: IWeightProps) => { {Math.round( 100 * Math.sqrt( - Math.pow(getNewAccelerationX(updatedForces) * 3, 2) + - Math.pow(getNewAccelerationY(updatedForces) * 3, 2) + Math.pow(getNewAccelerationX(this.state.updatedForces) * 3, 2) + + Math.pow(getNewAccelerationY(this.state.updatedForces) * 3, 2) ) ) / 100}{" "} m/s<sup>2</sup> @@ -755,7 +717,7 @@ export const Weight = (props: IWeightProps) => { </div> </div> )} - {!dragging && showVelocity && ( + {!this.state.dragging && this.props.showVelocity && ( <div> <div style={{ @@ -766,7 +728,7 @@ export const Weight = (props: IWeightProps) => { top: 0, }} > - <svg width={xMax + "px"} height={window.innerHeight + "px"}> + <svg width={this.xMax + "px"} height={window.innerHeight + "px"}> <defs> <marker id="velArrow" @@ -781,10 +743,10 @@ export const Weight = (props: IWeightProps) => { </marker> </defs> <line - x1={xPosition + radius} - y1={yPosition + radius} - x2={xPosition + radius + xVelocity * 3} - y2={yPosition + radius + yVelocity * 3} + x1={this.state.xPosition + this.props.radius} + y1={this.state.yPosition + this.props.radius} + x2={this.state.xPosition + this.props.radius + this.state.xVelocity * 3} + y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 3} stroke={"blue"} strokeWidth="5" markerEnd="url(#velArrow)" @@ -794,15 +756,15 @@ export const Weight = (props: IWeightProps) => { style={{ pointerEvents: "none", position: "absolute", - left: xPosition + radius + xVelocity * 3 + 25 + "px", - top: yPosition + radius + yVelocity * 3 + "px", + left: this.state.xPosition + this.props.radius + this.state.xVelocity * 3 + 25 + "px", + top: this.state.yPosition + this.props.radius + this.state.yVelocity * 3 + "px", zIndex: -1, lineHeight: 0.5, }} > <p> {Math.round( - 100 * Math.sqrt(xVelocity * xVelocity + yVelocity * yVelocity) + 100 * Math.sqrt(this.state.xVelocity**2 + this.state.yVelocity**2) ) / 100}{" "} m/s </p> @@ -810,14 +772,14 @@ export const Weight = (props: IWeightProps) => { </div> </div> )} - {!dragging && - showForces && - updatedForces.map((force, index) => { - if (force.magnitude < epsilon) { + {!this.state.dragging && + this.props.showForces && + this.props.updatedForces.map((force, index) => { + if (force.magnitude < this.epsilon) { return; } - let arrowStartY: number = yPosition + radius; - const arrowStartX: number = xPosition + radius; + let arrowStartY: number = this.state.yPosition + this.props.radius; + const arrowStartX: number = this.state.xPosition + this.props.radius; let arrowEndY: number = arrowStartY - Math.abs(force.magnitude) * @@ -843,10 +805,10 @@ export const Weight = (props: IWeightProps) => { } else { labelTop -= 40; } - labelTop = Math.min(labelTop, yMax + 50); - labelTop = Math.max(labelTop, yMin); - labelLeft = Math.min(labelLeft, xMax - 60); - labelLeft = Math.max(labelLeft, xMin); + labelTop = Math.min(labelTop, this.yMax + 50); + labelTop = Math.max(labelTop, this.yMin); + labelLeft = Math.min(labelLeft, this.xMax - 60); + labelLeft = Math.max(labelLeft, this.xMin); return ( <div key={index}> @@ -908,5 +870,6 @@ export const Weight = (props: IWeightProps) => { ); })} </div> - ); + ); + } }; |