aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PhysicsSimulationWeight.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PhysicsSimulationWeight.tsx')
-rw-r--r--src/client/views/nodes/PhysicsSimulationWeight.tsx860
1 files changed, 0 insertions, 860 deletions
diff --git a/src/client/views/nodes/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsSimulationWeight.tsx
deleted file mode 100644
index 39b3249e8..000000000
--- a/src/client/views/nodes/PhysicsSimulationWeight.tsx
+++ /dev/null
@@ -1,860 +0,0 @@
-import React = require('react');
-import { Doc } from '../../../fields/Doc';
-import { IWallProps } from "./PhysicsSimulationWall";
-
-export interface IForce {
- description: string;
- magnitude: number;
- directionInDegrees: number;
-}
-export interface IWeightProps {
- adjustPendulumAngle: boolean;
- color: string;
- dataDoc: Doc;
- mass: number;
- radius: number;
- simulationReset: boolean;
- startPosX: number;
- startPosY: number;
- startVelX?: number;
- startVelY?: number;
- timestepSize: number;
- updateDisplay: boolean,
- walls: IWallProps[];
- wedge: boolean;
- wedgeHeight: number;
- wedgeWidth: number;
- xMax: number;
- xMin: number;
- yMax: number;
- yMin: number;
-}
-
-interface IState {
- angleLabel: number,
- clickPositionX: number,
- clickPositionY: number,
- dragging: boolean,
- kineticFriction: boolean,
- timer: number;
- update: boolean,
- updatedStartPosX: number,
- updatedStartPosY: number,
- xPosition: number,
- xVelocity: number,
- yPosition: number,
- yVelocity: number,
-}
-export default class Weight extends React.Component<IWeightProps, IState> {
-
- constructor(props: any) {
- super(props)
- this.state = {
- clickPositionX: 0,
- clickPositionY: 0,
- dragging: false,
- kineticFriction: false,
- timer: 0,
- angleLabel: 0,
- updatedStartPosX: this.props.dataDoc['startPosX'],
- updatedStartPosY: this.props.dataDoc['startPosY'],
- xPosition: this.props.dataDoc['startPosX'],
- xVelocity: this.props.startVelX ? this.props.startVelX: 0,
- yPosition: this.props.dataDoc['startPosY'],
- yVelocity: this.props.startVelY ? this.props.startVelY: 0,
- }
- }
-
- // Constants
- draggable = !this.props.dataDoc['wedge'] ;
- epsilon = 0.0001;
- forceOfGravity: IForce = {
- description: "Gravity",
- magnitude: this.props.mass * 9.81,
- directionInDegrees: 270,
- };
-
- // Var
- weightStyle = {
- alignItems: "center",
- backgroundColor: this.props.color,
- borderColor: "black",
- borderRadius: 50 + "%",
- borderStyle: "solid",
- display: "flex",
- height: 2 * this.props.radius + "px",
- justifyContent: "center",
- left: this.props.dataDoc['startPosX'] + "px",
- position: "absolute" as "absolute",
- top: this.props.dataDoc['startPosY'] + "px",
- touchAction: "none",
- width: 2 * this.props.radius + "px",
- zIndex: 5,
- };
-
- // Helper function to go between display and real values
- getDisplayYPos = (yPos: number) => {
- return this.props.yMax - yPos - 2 * this.props.radius + 5;
- };
- getYPosFromDisplay = (yDisplay: number) => {
- return this.props.yMax - yDisplay - 2 * this.props.radius + 5;
- };
-
- // Set display values based on real values
- setYPosDisplay = (yPos: number) => {
- const displayPos = this.getDisplayYPos(yPos);
- this.props.dataDoc['positionYDisplay'] = Math.round(displayPos * 100) / 100
- };
- setXPosDisplay = (xPos: number) => {
- this.props.dataDoc['positionXDisplay'] = Math.round(xPos * 100) / 100;
- };
- setYVelDisplay = (yVel: number) => {
- this.props.dataDoc['velocityYDisplay'] = (-1 * Math.round(yVel * 100)) / 100;
- };
- setXVelDisplay = (xVel: number) => {
- this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
- };
-
- setDisplayValues = (
- xPos: number = this.state.xPosition,
- yPos: number = this.state.yPosition,
- xVel: number = this.state.xVelocity,
- yVel: number = this.state.yVelocity
- ) => {
- this.setYPosDisplay(yPos);
- this.setXPosDisplay(xPos);
- this.setYVelDisplay(yVel);
- this.setXVelDisplay(xVel);
- this.props.dataDoc['accelerationYDisplay'] =
- (-1 * Math.round(this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 100)) / 100
- ;
- this.props.dataDoc['accelerationXDisplay'] =
- Math.round(this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 100) / 100
- ;
- };
-
- componentDidMount() {
- // Timer for animating the simulation
- setInterval(() => {
- this.setState({timer: this.state.timer + 1});
- }, 60);
- }
-
- componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
-
- // When display values updated by user, update real values
- if (this.props.updateDisplay != prevProps.updateDisplay) {
- if (this.props.dataDoc['positionXDisplay'] != this.state.xPosition) {
- let x = this.props.dataDoc['positionXDisplay'];
- x = Math.max(0, x);
- x = Math.min(x, this.props.xMax - 2 * this.props.radius);
- this.setState({updatedStartPosX: x})
- this.setState({xPosition: x})
- this.props.dataDoc['positionXDisplay'] = x;
- }
-
- if (this.props.dataDoc['positionYDisplay'] != this.getDisplayYPos(this.state.yPosition)) {
- let y = this.props.dataDoc['positionYDisplay'];
- y = Math.max(0, y);
- y = Math.min(y, this.props.yMax - 2 * this.props.radius);
- this.props.dataDoc['positionYDisplay'] = y;
- let coordinatePosition = this.getYPosFromDisplay(y);
- this.setState({updatedStartPosY: coordinatePosition})
- this.setState({yPosition: coordinatePosition})
- }
-
- if (this.props.dataDoc['velocityXDisplay'] != this.state.xVelocity) {
- let x = this.props.dataDoc['velocityXDisplay'];
- this.setState({xVelocity: x})
- this.props.dataDoc['velocityXDisplay'] = x;
- }
-
- if (this.props.dataDoc['velocityYDisplay'] != this.state.yVelocity) {
- let y = this.props.dataDoc['velocityYDisplay'];
- this.setState({yVelocity: -y})
- this.props.dataDoc['velocityYDisplay']
- }
- }
- // Update sim
- if (this.state.timer != prevState.timer) {
- if (!this.props.dataDoc['simulationPaused']) {
- let collisions = false;
- if (!this.props.dataDoc['pendulum']) {
- const collisionsWithGround = this.checkForCollisionsWithGround();
- const collisionsWithWalls = this.checkForCollisionsWithWall();
- collisions = collisionsWithGround || collisionsWithWalls;
- }
- if (!collisions) {
- this.update();
- }
- this.setDisplayValues();
- }
- }
-
- if (this.props.simulationReset != prevProps.simulationReset) {
- this.resetEverything();
- }
- if (this.props.adjustPendulumAngle != prevProps.adjustPendulumAngle) {
- console.log('update angle')
- // Change pendulum angle based on input field
- let length = this.props.dataDoc['pendulumLength'] ?? 0;
- const x =
- length * Math.cos(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
- const y =
- length * Math.sin(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
- const xPos = this.props.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.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle'] * 100) / 100})
- }
- // Update x start position
- if (this.props.startPosX != prevProps.startPosX) {
- this.setState({updatedStartPosX: this.props.dataDoc['startPosX']})
- this.setState({xPosition: this.props.dataDoc['startPosX']})
- this.setXPosDisplay(this.props.dataDoc['startPosX']);
- }
- // Update y start position
- if (this.props.startPosY != prevProps.startPosY) {
- this.setState({updatedStartPosY: this.props.dataDoc['startPosY']})
- this.setState({yPosition: this.props.dataDoc['startPosY']})
- this.setYPosDisplay(this.props.dataDoc['startPosY']);
- }
- if (!this.props.dataDoc['simulationPaused']) {
- if (this.state.xVelocity != prevState.xVelocity) {
- if (this.props.dataDoc['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.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] )),
- directionInDegrees:
- 180 - 90 - (Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] ) * 180) / Math.PI,
- };
- let frictionForce: IForce = {
- description: "Kinetic Friction Force",
- magnitude:
- this.props.dataDoc['coefficientOfKineticFriction'] *
- this.forceOfGravity.magnitude *
- Math.cos(Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['wedgeWidth'] )),
- directionInDegrees:
- 180 - (Math.atan(this.props.dataDoc['wedgeHeight'] / this.props.dataDoc['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.dataDoc['coefficientOfKineticFriction'] != 0) {
- this.props.dataDoc['updatedForces'] = [this.forceOfGravity, normalForce, frictionForce];
- } else {
- this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, normalForce]);
- }
- }
- }
- }
-
- this.weightStyle = {
- alignItems: "center",
- backgroundColor: this.props.color,
- borderColor: this.state.dragging ? "lightblue" : "black",
- borderRadius: 50 + "%",
- borderStyle: "solid",
- display: "flex",
- height: 2 * this.props.radius + "px",
- justifyContent: "center",
- left: this.state.xPosition + "px",
- position: "absolute" as "absolute",
- top: this.state.yPosition + "px",
- touchAction: "none",
- width: 2 * this.props.radius + "px",
- zIndex: 5,
- };
- }
-
- resetEverything = () => {
- this.setState({kineticFriction: false})
- this.setState({xPosition: this.state.updatedStartPosX})
- this.setState({yPosition: this.state.updatedStartPosY})
- this.setState({xVelocity: this.props.startVelX ?? 0})
- this.setState({yVelocity: this.props.startVelY ?? 0})
- this.props.dataDoc['updatedForces'] = (this.props.dataDoc['startForces'])
- this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle']* 100) / 100})
- this.setDisplayValues();
- };
-
- getNewAccelerationX = (forceList: IForce[]) => {
- let newXAcc = 0;
- if (forceList) {
- forceList.forEach((force) => {
- newXAcc +=
- (force.magnitude *
- Math.cos((force.directionInDegrees * Math.PI) / 180)) /
- this.props.mass;
- });
- }
- return newXAcc;
- };
-
- getNewAccelerationY = (forceList: IForce[]) => {
- let newYAcc = 0;
- if (forceList) {
- forceList.forEach((force) => {
- newYAcc +=
- (-1 *
- (force.magnitude *
- Math.sin((force.directionInDegrees * Math.PI) / 180))) /
- this.props.mass;
- });
- }
- return newYAcc;
- };
-
- getNewForces = (
- xPos: number,
- yPos: number,
- xVel: number,
- yVel: number
- ) => {
- if (!this.props.dataDoc['pendulum']) {
- return this.props.dataDoc['updatedForces'];
- }
- const x = this.props.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;
- }
- let oppositeAngle = 90 - angle;
- if (oppositeAngle < 0) {
- oppositeAngle = 90 - (180 - angle);
- }
-
- const pendulumLength = Math.sqrt(x * x + y * y);
- this.props.dataDoc['pendulumAngle'] = oppositeAngle;
- this.props.dataDoc['pendulumLength'] = Math.sqrt(x * x + y * y);
-
- const mag =
- this.props.mass * 9.81 * Math.cos((oppositeAngle * Math.PI) / 180) +
- (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
-
- const forceOfTension: IForce = {
- description: "Tension",
- magnitude: mag,
- directionInDegrees: angle,
- };
- this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle']* 100) / 100})
-
- return [this.forceOfGravity, forceOfTension];
- };
-
- getNewPosition = (pos: number, vel: number) => {
- return pos + vel * this.props.timestepSize;
- };
-
- getNewVelocity = (vel: number, acc: number) => {
- return vel + acc * this.props.timestepSize;
- };
-
- checkForCollisionsWithWall = () => {
- let collision = false;
- const minX = this.state.xPosition;
- const maxX = this.state.xPosition + 2 * this.props.radius;
- const containerWidth = 300;
- if (this.state.xVelocity != 0) {
- if (this.props.dataDoc.wallPositions) {
- this.props.dataDoc['wallPositions'].forEach((wall) => {
- if (wall.angleInDegrees == 90) {
- const wallX = (wall.xPos / 100) * 300;
- if (wall.xPos < 0.35) {
- if (minX <= wallX) {
- if (this.props.dataDoc['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.dataDoc['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;
- const maxY = this.state.yPosition + 2 * this.props.radius;
- if (this.state.yVelocity > 0) {
- if (this.props.dataDoc.wallPositions) {
- this.props.dataDoc['wallPositions'].forEach((wall) => {
- if (wall.angleInDegrees == 0) {
- const groundY = (wall.yPos / 100) * this.props.yMax;
- if (maxY >= groundY) {
- if (this.props.dataDoc['elasticCollisions']) {
- this.setState({yVelocity: -this.state.yVelocity})
- } else {
- this.setState({yVelocity: 0})
- this.setState({yPosition: groundY - 2 * this.props.radius + 5})
- const forceOfGravity: IForce = {
- description: "Gravity",
- magnitude: 9.81 * this.props.mass,
- directionInDegrees: 270,
- };
- const normalForce: IForce = {
- description: "Normal force",
- magnitude: 9.81 * this.props.mass,
- directionInDegrees: wall.angleInDegrees + 90,
- };
- this.props.dataDoc['updatedForces'] = ([forceOfGravity, normalForce]);
- }
- collision = true;
- }
- }
- });
- }
- }
- return collision;
- };
-
- 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.dataDoc['updatedForces'] = (this.getNewForces(xPos, yPos, xVel, yVel));
- };
-
-
- labelBackgroundColor = `rgba(255,255,255,0.5)`;
-
- render () {
- return (
- <div>
- <div
- className="weightContainer"
- // onPointerDown={(e) => {
- // if (this.draggable) {
- // e.preventDefault();
- // this.props.dataDoc['simulationPaused'] = true;
- // this.setState({dragging: true});
- // this.setState({clickPositionX: e.clientX})
- // this.setState({clickPositionY: e.clientY})
- // }
- // }}
- // onPointerMove={(e) => {
- // e.preventDefault();
- // if (this.state.dragging) {
- // let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
- // if (newY > this.props.yMax - 2 * this.props.radius) {
- // newY = this.props.yMax - 2 * this.props.radius;
- // }
-
- // let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
- // if (newX > this.props.xMax - 2 * this.props.radius) {
- // newX = this.props.xMax - 2 * this.props.radius;
- // } else if (newX < 0) {
- // newX = 0;
- // }
- // this.setState({xPosition: newX})
- // this.setState({yPosition: newY})
- // this.setState({updatedStartPosX: newX})
- // this.setState({updatedStartPosY: newY})
- // this.props.dataDoc['positionYDisplay'] = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
- // this.setState({clickPositionX: e.clientX})
- // this.setState({clickPositionY: e.clientY})
- // this.setDisplayValues();
- // }
- // }}
- // onPointerUp={(e) => {
- // if (this.state.dragging) {
- // e.preventDefault();
- // if (!this.props.dataDoc['pendulum']) {
- // this.resetEverything();
- // }
- // this.setState({dragging: false});
- // let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
- // if (newY > this.props.yMax - 2 * this.props.radius) {
- // newY = this.props.yMax - 2 * this.props.radius;
- // }
-
- // let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
- // if (newX > this.props.xMax - 2 * this.props.radius) {
- // newX = this.props.xMax - 2 * this.props.radius;
- // } else if (newX < 0) {
- // newX = 0;
- // }
- // if (this.props.dataDoc['pendulum']) {
- // const x = this.props.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;
- // }
- // let oppositeAngle = 90 - angle;
- // if (oppositeAngle < 0) {
- // oppositeAngle = 90 - (180 - angle);
- // }
-
- // const pendulumLength = Math.sqrt(x * x + y * y);
- // this.props.dataDoc['pendulumAngle'] = oppositeAngle;
- // this.props.dataDoc['pendulumLength'] = 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,
- // };
- // this.setState({kineticFriction: false})
- // this.setState({xVelocity: this.props.startVelX ?? 0})
- // this.setState({yVelocity: this.props.startVelY ?? 0})
- // this.setDisplayValues();
- // this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, forceOfTension]);
- // }
- // }
- // }}
- >
- <div className="weight" style={this.weightStyle}>
- <p className="weightLabel">{this.props.mass} kg</p>
- </div>
- </div>
- {this.props.dataDoc['pendulum'] && (
- <div
- className="rod"
- style={{
- pointerEvents: "none",
- position: "absolute",
- left: 0,
- top: 0,
- }}
- >
- <svg width={this.props.xMax + "px"} height={300 + "px"}>
- <line
- x1={this.state.xPosition + this.props.radius}
- y1={this.state.yPosition + this.props.radius}
- x2={this.props.xMax / 2}
- y2={-5}
- stroke={"#deb887"}
- strokeWidth="10"
- />
- </svg>
- {!this.state.dragging && (
- <div>
- <p
- style={{
- position: "absolute",
- left: this.props.xMax / 2 + "px",
- top: 30 + "px",
- backgroundColor: this.labelBackgroundColor,
- }}
- >
- {this.state.angleLabel}°
- </p>
- </div>
- )}
- </div>
- )}
- {!this.state.dragging && this.props.dataDoc['showAcceleration'] && (
- <div>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- left: 0,
- top: 0,
- }}
- >
- <svg width={this.props.xMax + "px"} height={300 + "px"}>
- <defs>
- <marker
- id="accArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="3"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,6 L9,3 z" fill="green" />
- </marker>
- </defs>
- <line
- x1={this.state.xPosition + this.props.radius}
- y1={this.state.yPosition + this.props.radius}
- x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5}
- y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5}
- stroke={"green"}
- strokeWidth="5"
- markerEnd="url(#accArrow)"
- />
- </svg>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- left:
- this.state.xPosition +
- this.props.radius +
- this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5 +
- 25 +
- "px",
- top:
- this.state.yPosition +
- this.props.radius +
- this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5 +
- 25 +
- "px",
- lineHeight: 0.5,
- }}
- >
- <p>
- {Math.round(
- 100 *
- Math.sqrt(
- Math.pow(this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 3, 2) +
- Math.pow(this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 3, 2)
- )
- ) / 100}{" "}
- m/s<sup>2</sup>
- </p>
- </div>
- </div>
- </div>
- )}
- {!this.state.dragging && this.props.dataDoc['showVelocity'] && (
- <div>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- left: 0,
- top: 0,
- }}
- >
- <svg width={this.props.xMax + "px"} height={300 + "px"}>
- <defs>
- <marker
- id="velArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="3"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,6 L9,3 z" fill="blue" />
- </marker>
- </defs>
- <line
- 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)"
- />
- </svg>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- 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",
- lineHeight: 0.5,
- }}
- >
- <p>
- {Math.round(
- 100 * Math.sqrt(this.state.xVelocity**2 + this.state.yVelocity**2)
- ) / 100}{" "}
- m/s
- </p>
- </div>
- </div>
- </div>
- )}
- {!this.state.dragging &&
- this.props.dataDoc['showForces'] &&
- this.props.dataDoc['updatedForces'].map((force, index) => {
- if (force.magnitude < this.epsilon) {
- return;
- }
- 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) *
- 10 *
- Math.sin((force.directionInDegrees * Math.PI) / 180);
- const arrowEndX: number =
- arrowStartX +
- Math.abs(force.magnitude) *
- 10 *
- Math.cos((force.directionInDegrees * Math.PI) / 180);
-
- let color = "#0d0d0d";
-
- let labelTop = arrowEndY;
- let labelLeft = arrowEndX;
- if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
- labelLeft -= 120;
- } else {
- labelLeft += 30;
- }
- if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
- labelTop += 40;
- } else {
- labelTop -= 40;
- }
- labelTop = Math.min(labelTop, this.props.yMax + 50);
- labelTop = Math.max(labelTop, this.props.yMin);
- labelLeft = Math.min(labelLeft, this.props.xMax - 60);
- labelLeft = Math.max(labelLeft, this.props.xMin);
-
- return (
- <div key={index}>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- left: this.props.xMin,
- top: this.props.yMin,
- }}
- >
- <svg
- width={this.props.xMax - this.props.xMin + "px"}
- height={300 + "px"}
- >
- <defs>
- <marker
- id="forceArrow"
- markerWidth="10"
- markerHeight="10"
- refX="0"
- refY="3"
- orient="auto"
- markerUnits="strokeWidth"
- >
- <path d="M0,0 L0,6 L9,3 z" fill={color} />
- </marker>
- </defs>
- <line
- x1={arrowStartX}
- y1={arrowStartY}
- x2={arrowEndX}
- y2={arrowEndY}
- stroke={color}
- strokeWidth="5"
- markerEnd="url(#forceArrow)"
- />
- </svg>
- </div>
- <div
- style={{
- pointerEvents: "none",
- position: "absolute",
- left: labelLeft + "px",
- top: labelTop + "px",
- lineHeight: 0.5,
- backgroundColor: this.labelBackgroundColor,
- }}
- >
- {force.description && <p>{force.description}</p>}
- {!force.description && <p>Force</p>}
- {this.props.dataDoc['showForceMagnitudes'] && (
- <p>{Math.round(100 * force.magnitude) / 100} N</p>
- )}
- </div>
- </div>
- );
- })}
- </div>
- );
- }
-};