aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-05-24 16:39:38 -0400
committerbobzel <zzzman@gmail.com>2023-05-24 16:39:38 -0400
commit9e1c341955fb016f4a62339e4f11ac42d9572e95 (patch)
tree007a18eb3daba387144e00131a93d6e3fa5c91ef /src
parent4c96bbd25d84964811838d005ff4e40487e1ec41 (diff)
render cleanup for phys vector arrows.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss6
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx6
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx288
3 files changed, 120 insertions, 180 deletions
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 2e6ad413f..5f142df19 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -22,7 +22,11 @@
justify-content: space-between;
}
}
- .rod {
+ .rod,
+ .spring,
+ .wheel,
+ .showvecs,
+ .wedge {
pointer-events: none;
position: absolute;
left: 0;
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index d3e1c6fd2..f4acba2a6 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -87,7 +87,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
wallPositions: IWallProps[] = [];
@computed get circularMotionRadius() {
- return NumCast(this.dataDoc.circularMotionRadius, 150);
+ return (NumCast(this.dataDoc.circularMotionRadius, 150) * this.props.PanelWidth()) / 1000;
}
@computed get gravity() {
return NumCast(this.dataDoc.simulation_gravity, -9.81);
@@ -757,7 +757,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
};
- pause = () => (this.dataDoc.paused = true);
+ pause = () => (this.dataDoc.simulation_paused = true);
componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces));
setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces));
componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces));
@@ -810,7 +810,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
yMax: this.yMax,
yMin: this.yMin,
wallPositions: this.wallPositions,
- gravity: this.gravity,
+ gravity: Math.abs(this.gravity),
timestepSize: 0.05,
showComponentForces: BoolCast(this.dataDoc.simulation_showComponentForces),
coefficientOfKineticFriction: NumCast(this.dataDoc.coefficientOfKineticFriction),
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 98b0e3f04..f533df109 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -116,9 +116,20 @@ export default class Weight extends React.Component<IWeightProps, IState> {
};
}
- componentDidMount() {
- // Timer for animating the simulation
- setInterval(() => this.setState({ timer: this.state.timer + 1 }), 50);
+ _timer: NodeJS.Timeout | undefined;
+
+ componentWillUnmount() {
+ this._timer && clearTimeout(this._timer);
+ }
+ componentWillUpdate(nextProps: Readonly<IWeightProps>, nextState: Readonly<IState>, nextContext: any): void {
+ if (nextProps.simulationType !== this.props.simulationType) setTimeout(() => this.setState({ timer: this.state.timer + 1 }));
+ if (nextProps.paused) {
+ this._timer && clearTimeout(this._timer);
+ this._timer = undefined;
+ } else if (this.props.paused) {
+ this._timer && clearTimeout(this._timer);
+ this._timer = setInterval(() => this.setState({ timer: this.state.timer + 1 }), 50);
+ }
}
// Constants
@@ -154,7 +165,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
// Helper function to go between display and real values
getDisplayYPos = (yPos: number) => this.props.yMax - yPos - 2 * this.props.radius + 5;
-
+ gravityForce = (): IForce => ({
+ description: 'Gravity',
+ magnitude: this.props.mass * this.props.gravity,
+ directionInDegrees: 270,
+ });
// Update display values when simulation updates
setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => {
this.props.setPosition(xPos, this.getDisplayYPos(yPos));
@@ -210,7 +225,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
if (this.props.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));
+ maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * this.props.gravity);
}
if (maxYPos < 0) maxYPos = 0;
@@ -247,51 +262,41 @@ export default class Weight extends React.Component<IWeightProps, IState> {
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)),
+ magnitude: this.props.mass * 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,
};
const 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)),
+ magnitude: this.props.mass * this.props.coefficientOfKineticFriction * 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,
};
// reduce magnitude of friction force if necessary such that block cannot slide up plane
// prettier-ignore
- const yForce = -Math.abs(this.props.gravity) +
+ const yForce = - this.props.gravity +
normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) +
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);
+ frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + 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,
- };
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)),
+ magnitude: this.props.mass * 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,
};
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)),
+ magnitude: this.props.mass * 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,
};
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)),
+ magnitude: this.props.mass * 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,
};
- const gravityForce: IForce = {
- description: 'Gravity',
- magnitude: this.props.mass * Math.abs(this.props.gravity),
- directionInDegrees: 270,
- };
- const kineticFriction = this.props.coefficientOfKineticFriction != 0;
- this.props.setForcesUpdated([gravityForce, normalForce, ...(kineticFriction ? [frictionForce] : [])]);
- this.props.setComponentForces([normalForceComponent, gravityParallel, gravityPerpendicular, ...(kineticFriction ? [frictionForceComponent] : [])]);
+ const kineticFriction = this.props.coefficientOfKineticFriction != 0 ? [frictionForce] : [];
+ this.props.setForcesUpdated([this.gravityForce(), normalForce, ...kineticFriction]);
+ this.props.setComponentForces([normalForceComponent, gravityParallel, gravityPerpendicular, ...kineticFriction]);
}
}
@@ -317,13 +322,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
}
// Update wedge coordinates
- if (this.state.coordinates === '' || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
+ if (!this.state.coordinates || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
const left = this.props.xMax * 0.25;
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 });
+ this.setState({ coordinates: coordinatePair1 + coordinatePair2 + coordinatePair3 });
}
if (this.state.xPosition != prevState.xPosition || this.state.yPosition != prevState.yPosition) {
@@ -395,11 +399,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const yPosPlus = yPos - this.props.springRestLength > 0;
const yPosMinus = yPos - this.props.springRestLength < 0;
return [
- {
- description: 'Gravity',
- magnitude: Math.abs(this.props.gravity) * this.props.mass,
- directionInDegrees: 270,
- },
+ this.gravityForce(),
{
description: 'Spring Force',
magnitude: this.props.springConstant * (yPos - this.props.springRestLength) * (yPosPlus ? 1 : yPosMinus ? -1 : 0),
@@ -412,10 +412,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
getNewPendulumForces = (xPos: number, yPos: number, xVel: number, yVel: number): IForce[] => {
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;
- }
+ const angle = (ang => (ang < 0 ? ang + 180 : ang))((Math.atan(y / x) * 180) / Math.PI);
+
let oppositeAngle = 90 - angle;
if (oppositeAngle < 0) {
oppositeAngle = 90 - (180 - angle);
@@ -424,14 +422,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const pendulumLength = Math.sqrt(x * x + y * y);
this.props.setPendulumAngle(oppositeAngle, undefined);
- const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+ const mag = this.props.mass * this.props.gravity * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
return [
- {
- description: 'Gravity',
- magnitude: Math.abs(this.props.gravity) * this.props.mass,
- directionInDegrees: 270,
- },
+ this.gravityForce(),
{
description: 'Tension',
magnitude: mag,
@@ -471,11 +465,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
this.state.walls.forEach(wall => {
if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
const groundY = (wall.yPos / 100) * this.props.panelHeight();
- const gravity: IForce = {
- description: 'Gravity',
- magnitude: Math.abs(this.props.gravity) * this.props.mass,
- directionInDegrees: 270,
- };
+ const gravity = this.gravityForce();
if (maxY > groundY) {
this.setState({ yPosition: groundY - 2 * this.props.radius - 0.01 });
if (this.props.elasticCollisions) {
@@ -536,11 +526,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
getForces = (xPos: number, yPos: number, xVel: number, yVel: number) => {
// prettier-ignore
switch (this.props.simulationType) {
- case 'Pendulum': return this.getNewPendulumForces(xPos, yPos, xVel, yVel);
- case 'Spring' : return this.getNewSpringForces(yPos);
- case 'Circular Motion': return this.getNewCircularMotionForces(xPos, yPos);
- default: return this.props.forcesUpdated();
- }
+ case 'Pendulum': return this.getNewPendulumForces(xPos, yPos, xVel, yVel);
+ case 'Spring' : return this.getNewSpringForces(yPos);
+ case 'Circular Motion': return this.getNewCircularMotionForces(xPos, yPos);
+ default: return this.props.forcesUpdated();
+ }
};
// Update position, velocity using RK4 method
@@ -569,13 +559,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
// make sure harmonic motion maintained and errors don't propagate
switch (this.props.simulationType) {
case 'Spring':
+ const equilibriumPos = this.props.springRestLength + (this.props.mass * this.props.gravity) / this.props.springConstant;
+ const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
if (startYVel < 0 && yVel > 0 && yPos < this.props.springRestLength) {
- const equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
- const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
yPos = equilibriumPos - amplitude;
} else if (startYVel > 0 && yVel < 0 && yPos > this.props.springRestLength) {
- const equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
- const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
yPos = equilibriumPos + amplitude;
}
break;
@@ -620,32 +608,30 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const pendulumLength = Math.sqrt(x * x + y * y);
- const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
-
const tensionComponent: IForce = {
description: 'Tension',
- magnitude: mag,
+ magnitude: this.props.mass * this.props.gravity * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength,
directionInDegrees: angle,
};
const gravityParallel: IForce = {
description: 'Gravity Parallel Component',
- magnitude: Math.abs(this.props.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+ magnitude: this.props.gravity * Math.cos(((90 - angle) * Math.PI) / 180),
directionInDegrees: 270 - (90 - angle),
};
const gravityPerpendicular: IForce = {
description: 'Gravity Perpendicular Component',
- magnitude: Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+ magnitude: this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180),
directionInDegrees: -(90 - angle),
};
- if (Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
- gravityPerpendicular.magnitude = Math.abs(Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180));
+ if (this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
+ gravityPerpendicular.magnitude = Math.abs(this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180));
gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
}
this.props.setComponentForces([tensionComponent, gravityParallel, gravityPerpendicular]);
}
};
- renderForce = (force: IForce, index: number, asComponent: boolean) => {
+ renderForce = (force: IForce, index: number, asComponent: boolean, color = '#0d0d0d') => {
if (force.magnitude < this.epsilon) return;
const angle = (force.directionInDegrees * Math.PI) / 180;
@@ -654,8 +640,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const arrowEndY = arrowStartY - Math.abs(force.magnitude) * Math.sin(angle) - this.props.radius * Math.sin(angle);
const arrowEndX = arrowStartX + Math.abs(force.magnitude) * Math.cos(angle) + this.props.radius * Math.cos(angle);
- const color = '#0d0d0d';
-
let labelTop = arrowEndY + (force.directionInDegrees >= 0 && force.directionInDegrees < 180 ? 40 : -40);
let labelLeft = arrowEndX + (force.directionInDegrees > 90 && force.directionInDegrees < 270 ? -120 : 30);
@@ -696,6 +680,40 @@ export default class Weight extends React.Component<IWeightProps, IState> {
);
};
+ renderVector = (id: string, magX: number, magY: number, color: string, label: string) => {
+ const mag = Math.sqrt(magX * magX + magY * magY);
+ return (
+ <div className="showvecs" style={{ zIndex: 6 }}>
+ <svg width={this.panelWidth} height={this.panelHeight}>
+ <defs>
+ <marker id={id} 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={this.state.xPosition + this.props.radius + (magX / mag) * this.props.radius}
+ y1={this.state.yPosition + this.props.radius + (magY / mag) * this.props.radius}
+ x2={this.state.xPosition + this.props.radius + (magX / mag) * this.props.radius + magX}
+ y2={this.state.yPosition + this.props.radius + (magY / mag) * this.props.radius + magY}
+ stroke={color}
+ strokeWidth="5"
+ markerEnd={`url(#${id})`}
+ />
+ </svg>
+ <div
+ style={{
+ pointerEvents: 'none',
+ position: 'absolute',
+ left: this.state.xPosition + this.props.radius + 2 * (magX / mag) * this.props.radius + magX + 'px',
+ top: this.state.yPosition + this.props.radius + 2 * (magY / mag) * this.props.radius + magY + 'px',
+ lineHeight: 1,
+ }}>
+ {/* <p>{label}</p> */}
+ </div>
+ </div>
+ );
+ };
+
// Render weight, spring, rod(s), vectors
render() {
return (
@@ -784,7 +802,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
const deltaY = this.state.yPosition + this.props.radius;
const dir1T = Math.PI - Math.atan(deltaY / deltaX1);
const dir2T = Math.atan(deltaY / deltaX2);
- const tensionMag2 = (this.props.mass * Math.abs(this.props.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+ const tensionMag2 = (this.props.mass * this.props.gravity) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T);
const tensionForce1: IForce = {
description: 'Tension',
@@ -796,12 +814,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
magnitude: tensionMag2,
directionInDegrees: (dir2T * 180) / Math.PI,
};
- const grav: IForce = {
- description: 'Gravity',
- magnitude: this.props.mass * Math.abs(this.props.gravity),
- directionInDegrees: 270,
- };
- this.props.setForcesUpdated([tensionForce1, tensionForce2, grav]);
+ this.props.setForcesUpdated([tensionForce1, tensionForce2, this.gravityForce()]);
}
}
}}>
@@ -810,22 +823,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</div>
</div>
{this.props.simulationType == 'Spring' && (
- <div
- className="spring"
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: 0,
- top: 0,
- }}>
+ <div className="spring">
<svg width={this.panelWidth} height={this.panelHeight}>
- {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(val => {
+ {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(val => {
const count = 10;
const xPos1 = this.state.xPosition + this.props.radius + (val % 2 === 0 ? -20 : 20);
+ const xPos2 = this.state.xPosition + this.props.radius + (val === 10 ? 0 : val % 2 === 0 ? 20 : -20);
const yPos1 = (val * this.state.yPosition) / count;
- const xPos2 = this.state.xPosition + this.props.radius + (val % 2 === 0 ? 20 : -20);
- const yPos2 = ((val + 1) * this.state.yPosition) / count;
- return <line key={val} x1={xPos1} y1={yPos1} x2={xPos2} y2={yPos2} stroke={'#808080'} strokeWidth="10" />;
+ const yPos2 = val === 10 ? this.state.yPosition + this.props.radius : ((val + 1) * this.state.yPosition) / count;
+ return <line key={val} x1={xPos1} strokeLinecap="round" y1={yPos1} x2={xPos2} y2={yPos2} stroke={'#808080'} strokeWidth="10" />;
})}
</svg>
</div>
@@ -846,14 +852,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</div>
)}
{this.props.simulationType == 'Pulley' && (
- <div
- className="wheel"
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: 0,
- top: 0,
- }}>
+ <div className="wheel">
<svg width={this.panelWidth} height={this.panelHeight}>
<circle cx={(this.props.xMax + this.props.xMin) / 2} cy={this.props.radius} r={this.props.radius * 1.5} fill={'#808080'} />
</svg>
@@ -895,7 +894,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
/>
</svg>
</div>
-
<p
style={{
position: 'absolute',
@@ -956,12 +954,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
)}
{this.props.simulationType == 'Inclined Plane' && (
<div>
- <div style={{ position: 'absolute', left: '0', top: '0' }}>
+ <div className="wedge">
<svg width={this.panelWidth} height={this.props.yMax + 'px'}>
<polygon points={this.state.coordinates} style={{ fill: 'burlywood' }} />
</svg>
</div>
-
<p
style={{
position: 'absolute',
@@ -972,85 +969,24 @@ export default class Weight extends React.Component<IWeightProps, IState> {
</p>
</div>
)}
- {!this.state.dragging && this.props.showAcceleration && (
- <div>
- <div
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: 0,
- top: 0,
- }}>
- <svg width={this.panelWidth} height={this.panelHeight}>
- <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.forcesUpdated()) * 15}
- y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.forcesUpdated()) * 15}
- stroke={'green'}
- strokeWidth="5"
- markerEnd="url(#accArrow)"
- />
- </svg>
- <div
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: this.state.xPosition + this.props.radius + this.state.xAccel * 15 + 25 + 'px',
- top: this.state.yPosition + this.props.radius + this.state.yAccel * 15 + 70 + 'px',
- lineHeight: 1,
- }}>
- <p>
- {Math.round(100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)) / 100} m/s
- <sup>2</sup>
- </p>
- </div>
- </div>
- </div>
- )}
- {!this.state.dragging && this.props.showVelocity && (
- <div>
- <div
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: 0,
- top: 0,
- }}>
- <svg width={this.panelWidth} height={this.panelHeight}>
- <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 * 7}
- y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 7}
- stroke={'blue'}
- strokeWidth="5"
- markerEnd="url(#velArrow)"
- />
- </svg>
- <div
- style={{
- pointerEvents: 'none',
- position: 'absolute',
- left: this.state.xPosition + this.props.radius + this.state.xVelocity * 7 + 25 + 'px',
- top: this.state.yPosition + this.props.radius + this.state.yVelocity * 7 + 'px',
- lineHeight: 1,
- }}>
- <p>{Math.round(100 * Math.sqrt(this.props.displayXVelocity * this.props.displayXVelocity + this.props.displayYVelocity * this.props.displayYVelocity)) / 100} m/s</p>
- </div>
- </div>
- </div>
- )}
+ {!this.state.dragging &&
+ this.props.showAcceleration &&
+ this.renderVector(
+ 'accArrow',
+ this.getNewAccelerationX(this.props.forcesUpdated()),
+ this.getNewAccelerationY(this.props.forcesUpdated()),
+ 'green',
+ `${Math.round(100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)) / 100} m/s^2`
+ )}
+ {!this.state.dragging &&
+ this.props.showVelocity &&
+ this.renderVector(
+ 'velArrow',
+ this.state.xVelocity,
+ this.state.yVelocity,
+ 'blue',
+ `${Math.round(100 * Math.sqrt(this.props.displayXVelocity * this.props.displayXVelocity + this.props.displayYVelocity * this.props.displayYVelocity)) / 100} m/s`
+ )}
{!this.state.dragging && this.props.showComponentForces && this.props.componentForces().map((force, index) => this.renderForce(force, index, true))}
{!this.state.dragging && this.props.showForces && this.props.forcesUpdated().map((force, index) => this.renderForce(force, index, false))}
</div>