Skip to content

Conversation

@Texriya
Copy link

@Texriya Texriya commented Dec 19, 2025

What this PR adds

  • Introduces a new Magnetic Field simulation to PhysicsHub
  • Adds core physics logic and configuration support
  • Integrates the simulation into the existing UI and navigation
Screenshot 2025-12-19 181751

Implementation details

  • Physics logic: app/(core)/physics/MagneticField.js
  • Configuration: app/(core)/data/configs/MagneticField.js
  • UI page: app/(pages)/simulations/MagneticField/page.jsx
Screenshot 2025-12-19 181836

Testing

  • Tested locally
  • Simulation renders and behaves as expected
  • No regressions in existing simulations

##Suggestions
-Would appreciate it if the icon for magnetic field simulation was added,language change and the order of chapter 8 was corrected and implemented to this as well!
Screenshot 2025-12-19 181714

Notes

  • Single clean commit
  • No unrelated changes

Copilot AI review requested due to automatic review settings December 19, 2025 18:36
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new interactive Magnetic Field simulation to PhysicsHub, allowing users to visualize magnetic dipole field lines and manipulate a magnetic rod's orientation and position. The implementation includes physics calculations, UI components, and navigation integration.

Key Changes

  • New magnetic dipole field simulation with interactive rod manipulation
  • Fixed pointer-events handling for simulation info panels to allow canvas interaction
  • Downgraded npm dependencies from v11 to v10 and semantic-release packages

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
app/(pages)/simulations/MagneticField/page.jsx New simulation page with interactive magnetic rod and field line visualization
app/(core)/physics/MagneticField.js Physics implementation for magnetic dipole field calculations and particle classes
app/(core)/data/configs/MagneticField.js Configuration and input mappings for the simulation
app/(core)/data/chapters.js Added chapter entry for Magnetic Field simulation with theory documentation
app/(core)/components/P5Wrapper.jsx Restructured to allow pointer events through to canvas
app/(core)/components/Theme.tsx Fixed hydration mismatch by deferring animations until client mount
app/(core)/styles/index.css CSS updates for pointer-events handling (contains critical bug)
package.json Added dev:local script
package-lock.json Downgraded npm and semantic-release dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 2183 to +2194
.contribution-card::before {
content: "";
/* Let pointer events pass through the panel background so the canvas below
can receive mouse input; keep controls inside the panel interactive. */
pointer-events: none; /* allow clicks to reach canvas */
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
.sim-info-panel * {
pointer-events: auto;
}
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CSS structure is malformed here. The .contribution-card::before pseudo-element is missing its content property and has an unrelated .sim-info-panel * selector embedded within it. This breaks the CSS syntax and will cause styling issues.

The correct structure should have:

  1. The content: ""; property at the beginning of the .contribution-card::before block
  2. The .sim-info-panel * rule should be a separate, standalone CSS rule, not nested inside .contribution-card::before

Copilot uses AI. Check for mistakes.
this.length = length; // meters
this.angle = (angleDeg * Math.PI) / 180; // radians
this.moment = moment; // dipole moment magnitude (A·m^2)
this.color = "#ffcc00";
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The color property is defined in the constructor but never used in the code. Either use it in the draw method to style the rod, or remove it to avoid confusion.

Copilot uses AI. Check for mistakes.
Comment on lines +106 to +119
applyLorentz(Bvec) {
// In 2D, v x B (with B in-plane vector) -> use 3D cross via scalar Bz if necessary.
// Here Bvec is a vector in-plane; assume B has only in-plane components from dipole.
// Force = q (v × B) -> compute as 2D cross: F = q*(v_x * B_y - v_y * B_x) out-of-plane
// To keep particle in plane, approximate using perpendicular acceleration a = (q/m) * (v ⨯ B)_z rotated back.
const v = this.state.vel;
// Compute pseudo-acc: a = (q/m) * (v × B) rotated 90° -> aVec = (q/m) * (v.y*Bz, -v.x*Bz) but Bz unknown.
// Simpler: approximate with a = (q/m) * (v ⨯ B_scalar) where B_scalar = (B.x * nx + B.y * ny)
// For visualization we use (q/m) * (v ⨯ B_perp) where B_perp = scalar perpendicular magnitude
const Bz = 0; // dipole field is in-plane; full Lorentz would need 3D. Use small placeholder to allow curved motion.
const ax = (this.charge / this.mass) * (v.y * Bz);
const ay = (this.charge / this.mass) * (-v.x * Bz);
this.state.acc.add(this.p.createVector(ax, ay));
}
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The applyLorentz method always sets Bz = 0, making the computed acceleration always zero (ax and ay are always 0). This means the Lorentz force is never actually applied to the particle. If this class is intended to be unused, consider removing it or documenting why it's incomplete.

Copilot uses AI. Check for mistakes.
} catch (e) {}
}
}
if (particleRef.current) particleRef.current.stopDragging();
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The particleRef is defined but never initialized or used meaningfully. Line 234 attempts to call particleRef.current.stopDragging() but particleRef.current is always null. Either remove this unused ref and the related line, or implement the particle functionality if it's intended to be used.

Suggested change
if (particleRef.current) particleRef.current.stopDragging();

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +231
try {
setInputs((prev) => ({ ...prev, rodX: Number(rod.pos.x.toFixed(2)), rodY: Number(rod.pos.y.toFixed(2)) }));
} catch (e) {}
return;
}

if (!rod.isDragging) return;
const mxM = toMeters(p.mouseX);
const myM = toMeters(p.mouseY);
const dx = mxM - rod.pos.x;
const dy = rod.pos.y - myM; // upward positive
const ang = (Math.atan2(dy, dx) * 180) / Math.PI;
setInputs((prev) => ({ ...prev, angle: Number(ang.toFixed(2)) }));
};

p.mouseReleased = () => {
if (rod) {
rod.isDragging = false;
if (rod.isTranslating) {
rod.isTranslating = false;
// ensure final sidebar position saved
try {
setInputs((prev) => ({ ...prev, rodX: Number(rod.pos.x.toFixed(2)), rodY: Number(rod.pos.y.toFixed(2)) }));
} catch (e) {}
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty catch blocks silently suppress errors without any logging or handling. This makes debugging difficult. Consider at least logging the error with console.error(e) or documenting why errors are intentionally ignored.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,166 @@
import { toMeters, toPixels } from "../constants/Utils.js";
import { integrate } from "../constants/Utils.js";
import { SCALE } from "../constants/Config.js";
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import SCALE.

Suggested change
import { SCALE } from "../constants/Config.js";

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +23
import {
computeDelta,
resetTime,
isPaused,
setPause,
} from "../../../(core)/constants/Time.js";
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import computeDelta.

Copilot uses AI. Check for mistakes.
setPause,
} from "../../../(core)/constants/Time.js";
import getBackgroundColor from "../../../(core)/utils/getBackgroundColor";
import { drawGlow } from "../../../(core)/utils/drawUtils.js";
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import drawGlow.

Suggested change
import { drawGlow } from "../../../(core)/utils/drawUtils.js";

Copilot uses AI. Check for mistakes.
};

p.draw = () => {
const { clientWidth: w, clientHeight: h } = p._userNode;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable w.

Suggested change
const { clientWidth: w, clientHeight: h } = p._userNode;
const { clientHeight: h } = p._userNode;

Copilot uses AI. Check for mistakes.
};

p.draw = () => {
const { clientWidth: w, clientHeight: h } = p._userNode;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable h.

Suggested change
const { clientWidth: w, clientHeight: h } = p._userNode;
const { clientWidth: w } = p._userNode;

Copilot uses AI. Check for mistakes.
@mattqdev
Copy link
Collaborator

mattqdev commented Dec 19, 2025

Can you please send a full video that shows how to use this simulation, I can't fully understand how it works with screenshots. What is that green line on the bottom of the canvas? Can you fix the simInfos container css, it seems to be a little bit moved off its position.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants