@classytic/stage 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +5 -1
- package/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/assets/index.mjs +0 -1
- package/dist/atomic/aufbau.d.mts +144 -0
- package/dist/atomic/aufbau.mjs +384 -0
- package/dist/atomic/elements.d.mts +67 -0
- package/dist/atomic/elements.mjs +785 -0
- package/dist/atomic/emission.d.mts +112 -0
- package/dist/atomic/emission.mjs +179 -0
- package/dist/atomic/index.d.mts +8 -0
- package/dist/atomic/index.mjs +9 -0
- package/dist/atomic/periodic.d.mts +82 -0
- package/dist/atomic/periodic.mjs +231 -0
- package/dist/atomic/properties.d.mts +100 -0
- package/dist/atomic/properties.mjs +574 -0
- package/dist/atomic/shells.d.mts +137 -0
- package/dist/atomic/shells.mjs +170 -0
- package/dist/atomic/trends.d.mts +148 -0
- package/dist/atomic/trends.mjs +225 -0
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +15 -73
- package/dist/chem/chromatography.d.mts +66 -0
- package/dist/chem/chromatography.mjs +63 -0
- package/dist/chem/complex.d.mts +114 -0
- package/dist/chem/complex.mjs +234 -0
- package/dist/chem/cycle.d.mts +75 -0
- package/dist/chem/cycle.mjs +145 -0
- package/dist/chem/equation.d.mts +86 -0
- package/dist/chem/equation.mjs +168 -0
- package/dist/chem/formula.d.mts +90 -0
- package/dist/chem/formula.mjs +201 -0
- package/dist/chem/functional-groups.d.mts +31 -0
- package/dist/chem/functional-groups.mjs +187 -0
- package/dist/chem/hazard.d.mts +94 -0
- package/dist/chem/hazard.mjs +329 -0
- package/dist/chem/index.d.mts +34 -33
- package/dist/chem/index.mjs +34 -28
- package/dist/chem/ionic.d.mts +98 -0
- package/dist/chem/ionic.mjs +156 -0
- package/dist/chem/layout.d.mts +46 -0
- package/dist/chem/layout.mjs +342 -0
- package/dist/chem/lewis.d.mts +79 -0
- package/dist/chem/lewis.mjs +163 -0
- package/dist/chem/molecular-orbital.d.mts +114 -0
- package/dist/chem/molecular-orbital.mjs +201 -0
- package/dist/chem/molecule.d.mts +154 -0
- package/dist/chem/molecule.mjs +282 -0
- package/dist/chem/nmr.d.mts +153 -0
- package/dist/chem/nmr.mjs +165 -0
- package/dist/chem/polymer.d.mts +65 -0
- package/dist/chem/polymer.mjs +179 -0
- package/dist/chem/redox.d.mts +138 -0
- package/dist/chem/redox.mjs +328 -0
- package/dist/chem/relations.d.mts +183 -0
- package/dist/chem/relations.mjs +299 -0
- package/dist/chem/skeleton.d.mts +51 -0
- package/dist/chem/skeleton.mjs +186 -0
- package/dist/chem/solution.d.mts +116 -0
- package/dist/chem/solution.mjs +186 -0
- package/dist/chem/species.d.mts +47 -0
- package/dist/chem/species.mjs +128 -0
- package/dist/chem/stereo.d.mts +108 -0
- package/dist/chem/stereo.mjs +286 -0
- package/dist/chem/stoichiometry.d.mts +95 -0
- package/dist/chem/stoichiometry.mjs +145 -0
- package/dist/chem/synthesis.d.mts +113 -0
- package/dist/chem/synthesis.mjs +281 -0
- package/dist/chem/vsepr.d.mts +80 -0
- package/dist/chem/vsepr.mjs +247 -0
- package/dist/circuit/ac.d.mts +163 -0
- package/dist/circuit/ac.mjs +452 -0
- package/dist/circuit/dc.d.mts +92 -0
- package/dist/circuit/dc.mjs +333 -0
- package/dist/circuit/index.d.mts +5 -92
- package/dist/circuit/index.mjs +5 -332
- package/dist/circuit/network.d.mts +99 -0
- package/dist/circuit/network.mjs +440 -0
- package/dist/circuit/topology.d.mts +102 -0
- package/dist/circuit/topology.mjs +143 -0
- package/dist/colour/absorption.d.mts +79 -0
- package/dist/colour/absorption.mjs +137 -0
- package/dist/colour/index.d.mts +6 -0
- package/dist/colour/index.mjs +7 -0
- package/dist/colour/name.d.mts +14 -0
- package/dist/colour/name.mjs +76 -0
- package/dist/colour/observer.d.mts +31 -0
- package/dist/colour/observer.mjs +46 -0
- package/dist/colour/spectrum.d.mts +61 -0
- package/dist/colour/spectrum.mjs +108 -0
- package/dist/colour/srgb.d.mts +49 -0
- package/dist/colour/srgb.mjs +108 -0
- package/dist/core/constants.d.mts +138 -0
- package/dist/core/constants.mjs +139 -0
- package/dist/core/index.d.mts +4 -1
- package/dist/core/index.mjs +4 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/core/vec3.d.mts +94 -0
- package/dist/core/vec3.mjs +123 -0
- package/dist/core/worked.d.mts +35 -0
- package/dist/core/worked.mjs +44 -0
- package/dist/electro/cell.d.mts +102 -0
- package/dist/electro/cell.mjs +170 -0
- package/dist/electro/conductivity.d.mts +157 -0
- package/dist/electro/conductivity.mjs +156 -0
- package/dist/electro/couples.d.mts +114 -0
- package/dist/electro/couples.mjs +334 -0
- package/dist/electro/electrolysis.d.mts +96 -0
- package/dist/electro/electrolysis.mjs +274 -0
- package/dist/electro/faraday.d.mts +150 -0
- package/dist/electro/faraday.mjs +118 -0
- package/dist/electro/index.d.mts +6 -0
- package/dist/electro/index.mjs +7 -0
- package/dist/finance/accounting/adjustments.d.mts +17 -0
- package/dist/finance/accounting/adjustments.mjs +202 -0
- package/dist/finance/accounting/analysis.d.mts +8 -0
- package/dist/finance/accounting/analysis.mjs +205 -0
- package/dist/finance/accounting/clubs.d.mts +21 -0
- package/dist/finance/accounting/clubs.mjs +217 -0
- package/dist/finance/accounting/company-statements.d.mts +7 -0
- package/dist/finance/accounting/company-statements.mjs +150 -0
- package/dist/finance/accounting/harness.d.mts +7 -0
- package/dist/finance/accounting/harness.mjs +45 -0
- package/dist/finance/accounting/index.d.mts +18 -0
- package/dist/finance/accounting/index.mjs +18 -0
- package/dist/finance/accounting/journalize.d.mts +16 -0
- package/dist/finance/accounting/journalize.mjs +128 -0
- package/dist/finance/accounting/manufacturing.d.mts +8 -0
- package/dist/finance/accounting/manufacturing.mjs +236 -0
- package/dist/finance/accounting/partnership.d.mts +7 -0
- package/dist/finance/accounting/partnership.mjs +152 -0
- package/dist/finance/accounting/period-case.d.mts +6 -0
- package/dist/finance/accounting/period-case.mjs +71 -0
- package/dist/finance/accounting/post.d.mts +9 -0
- package/dist/finance/accounting/post.mjs +84 -0
- package/dist/finance/accounting/precision.d.mts +9 -0
- package/dist/finance/accounting/precision.mjs +15 -0
- package/dist/finance/accounting/rules.d.mts +21 -0
- package/dist/finance/accounting/rules.mjs +37 -0
- package/dist/finance/accounting/solve.d.mts +28 -0
- package/dist/finance/accounting/solve.mjs +92 -0
- package/dist/finance/accounting/statements.d.mts +7 -0
- package/dist/finance/accounting/statements.mjs +142 -0
- package/dist/finance/accounting/types.d.mts +649 -0
- package/dist/finance/accounting/validate.d.mts +7 -0
- package/dist/finance/accounting/validate.mjs +67 -0
- package/dist/finance/accounting/verification.d.mts +24 -0
- package/dist/finance/accounting/verification.mjs +386 -0
- package/dist/finance/bizsim.d.mts +75 -0
- package/dist/finance/bizsim.mjs +296 -0
- package/dist/finance/index.d.mts +95 -0
- package/dist/finance/index.mjs +145 -0
- package/dist/finance/investment-math.d.mts +7 -0
- package/dist/finance/investment-math.mjs +18 -0
- package/dist/finance/management-accounting/budgeting.d.mts +7 -0
- package/dist/finance/management-accounting/budgeting.mjs +189 -0
- package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
- package/dist/finance/management-accounting/cash-budget.mjs +154 -0
- package/dist/finance/management-accounting/costing.d.mts +8 -0
- package/dist/finance/management-accounting/costing.mjs +175 -0
- package/dist/finance/management-accounting/decisions.d.mts +8 -0
- package/dist/finance/management-accounting/decisions.mjs +164 -0
- package/dist/finance/management-accounting/index.d.mts +13 -0
- package/dist/finance/management-accounting/index.mjs +13 -0
- package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
- package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
- package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
- package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
- package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
- package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
- package/dist/finance/management-accounting/management-case.d.mts +8 -0
- package/dist/finance/management-accounting/management-case.mjs +91 -0
- package/dist/finance/management-accounting/master-budget.d.mts +7 -0
- package/dist/finance/management-accounting/master-budget.mjs +137 -0
- package/dist/finance/management-accounting/production-costing.d.mts +8 -0
- package/dist/finance/management-accounting/production-costing.mjs +214 -0
- package/dist/finance/management-accounting/types.d.mts +644 -0
- package/dist/finance/management-accounting/variances.d.mts +7 -0
- package/dist/finance/management-accounting/variances.mjs +150 -0
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +5 -5
- package/dist/interaction/MovableDot.mjs +19 -0
- package/dist/interaction/useDraggable.mjs +24 -4
- package/dist/math/analysis.d.mts +61 -0
- package/dist/math/analysis.mjs +187 -0
- package/dist/math/answer-check.d.mts +50 -0
- package/dist/math/answer-check.mjs +106 -0
- package/dist/math/calculus.d.mts +17 -1
- package/dist/math/calculus.mjs +365 -2
- package/dist/math/complex.d.mts +93 -0
- package/dist/math/complex.mjs +239 -0
- package/dist/math/expr.d.mts +23 -0
- package/dist/math/expr.mjs +36 -0
- package/dist/math/index.d.mts +9 -23
- package/dist/math/index.mjs +9 -38
- package/dist/math/latex.mjs +10 -1
- package/dist/math/parse.mjs +1 -1
- package/dist/math/poly.d.mts +55 -0
- package/dist/math/poly.mjs +273 -0
- package/dist/math/rearrange.d.mts +14 -0
- package/dist/math/rearrange.mjs +125 -0
- package/dist/math/solve.d.mts +21 -0
- package/dist/math/solve.mjs +75 -0
- package/dist/networking/addressing.d.mts +26 -0
- package/dist/networking/addressing.mjs +33 -0
- package/dist/networking/cloud/access.d.mts +36 -0
- package/dist/networking/cloud/access.mjs +95 -0
- package/dist/networking/cloud/containers.d.mts +43 -0
- package/dist/networking/cloud/containers.mjs +54 -0
- package/dist/networking/cloud/edge.d.mts +17 -0
- package/dist/networking/cloud/edge.mjs +31 -0
- package/dist/networking/cloud/failure-domains.d.mts +19 -0
- package/dist/networking/cloud/failure-domains.mjs +22 -0
- package/dist/networking/cloud/geo-routing.d.mts +22 -0
- package/dist/networking/cloud/geo-routing.mjs +64 -0
- package/dist/networking/cloud/index.d.mts +18 -0
- package/dist/networking/cloud/index.mjs +19 -0
- package/dist/networking/cloud/inference-reliability.d.mts +30 -0
- package/dist/networking/cloud/inference-reliability.mjs +76 -0
- package/dist/networking/cloud/inference.d.mts +118 -0
- package/dist/networking/cloud/inference.mjs +179 -0
- package/dist/networking/cloud/infrastructure.d.mts +45 -0
- package/dist/networking/cloud/infrastructure.mjs +96 -0
- package/dist/networking/cloud/observability.d.mts +24 -0
- package/dist/networking/cloud/observability.mjs +34 -0
- package/dist/networking/cloud/orchestration.d.mts +32 -0
- package/dist/networking/cloud/orchestration.mjs +38 -0
- package/dist/networking/cloud/recovery.d.mts +21 -0
- package/dist/networking/cloud/recovery.mjs +27 -0
- package/dist/networking/cloud/releases.d.mts +42 -0
- package/dist/networking/cloud/releases.mjs +135 -0
- package/dist/networking/cloud/scaling.d.mts +25 -0
- package/dist/networking/cloud/scaling.mjs +65 -0
- package/dist/networking/cloud/secrets.d.mts +39 -0
- package/dist/networking/cloud/secrets.mjs +68 -0
- package/dist/networking/cloud/server-deployment.d.mts +29 -0
- package/dist/networking/cloud/server-deployment.mjs +72 -0
- package/dist/networking/cloud/storage.d.mts +16 -0
- package/dist/networking/cloud/storage.mjs +58 -0
- package/dist/networking/cloud/vpc.d.mts +18 -0
- package/dist/networking/cloud/vpc.mjs +100 -0
- package/dist/networking/delivery.d.mts +34 -0
- package/dist/networking/delivery.mjs +52 -0
- package/dist/networking/index.d.mts +47 -0
- package/dist/networking/index.mjs +47 -0
- package/dist/networking/ipv6.d.mts +28 -0
- package/dist/networking/ipv6.mjs +17 -0
- package/dist/networking/journeys.d.mts +83 -0
- package/dist/networking/journeys.mjs +161 -0
- package/dist/networking/models/airtime.d.mts +87 -0
- package/dist/networking/models/airtime.mjs +130 -0
- package/dist/networking/models/cellular.d.mts +157 -0
- package/dist/networking/models/cellular.mjs +252 -0
- package/dist/networking/models/encapsulation.d.mts +98 -0
- package/dist/networking/models/encapsulation.mjs +132 -0
- package/dist/networking/models/handover.d.mts +116 -0
- package/dist/networking/models/handover.mjs +209 -0
- package/dist/networking/models/handshake.d.mts +90 -0
- package/dist/networking/models/handshake.mjs +122 -0
- package/dist/networking/models/index.d.mts +14 -0
- package/dist/networking/models/index.mjs +15 -0
- package/dist/networking/models/media.d.mts +82 -0
- package/dist/networking/models/media.mjs +188 -0
- package/dist/networking/models/satellite.d.mts +86 -0
- package/dist/networking/models/satellite.mjs +121 -0
- package/dist/networking/models/spectrum.d.mts +83 -0
- package/dist/networking/models/spectrum.mjs +235 -0
- package/dist/networking/models/switch.d.mts +80 -0
- package/dist/networking/models/switch.mjs +155 -0
- package/dist/networking/models/vlan.d.mts +62 -0
- package/dist/networking/models/vlan.mjs +100 -0
- package/dist/networking/models/vpn.d.mts +66 -0
- package/dist/networking/models/vpn.mjs +125 -0
- package/dist/networking/models/wifi-privacy.d.mts +82 -0
- package/dist/networking/models/wifi-privacy.mjs +130 -0
- package/dist/networking/models/wifi.d.mts +240 -0
- package/dist/networking/models/wifi.mjs +562 -0
- package/dist/networking/nat-traversal.d.mts +24 -0
- package/dist/networking/nat-traversal.mjs +38 -0
- package/dist/networking/protocols.d.mts +17 -0
- package/dist/networking/protocols.mjs +57 -0
- package/dist/networking/queue.d.mts +12 -0
- package/dist/networking/queue.mjs +18 -0
- package/dist/networking/route-learning.d.mts +23 -0
- package/dist/networking/route-learning.mjs +43 -0
- package/dist/networking/routing.d.mts +11 -0
- package/dist/networking/routing.mjs +25 -0
- package/dist/networking/signals.d.mts +26 -0
- package/dist/networking/signals.mjs +35 -0
- package/dist/networking/subnet.d.mts +49 -0
- package/dist/networking/subnet.mjs +89 -0
- package/dist/networking/tcp-reliability.d.mts +24 -0
- package/dist/networking/tcp-reliability.mjs +38 -0
- package/dist/networking/topology/contract.d.mts +123 -0
- package/dist/networking/topology/index.d.mts +4 -0
- package/dist/networking/topology/index.mjs +4 -0
- package/dist/networking/topology/presets.d.mts +7 -0
- package/dist/networking/topology/presets.mjs +302 -0
- package/dist/networking/topology/simulation.d.mts +8 -0
- package/dist/networking/topology/simulation.mjs +179 -0
- package/dist/networking/wireless.d.mts +11 -0
- package/dist/networking/wireless.mjs +17 -0
- package/dist/optics/imaging.d.mts +218 -0
- package/dist/optics/imaging.mjs +276 -0
- package/dist/optics/index.d.mts +7 -0
- package/dist/optics/index.mjs +8 -0
- package/dist/optics/laws.d.mts +70 -0
- package/dist/optics/laws.mjs +195 -0
- package/dist/optics/prism.d.mts +148 -0
- package/dist/optics/prism.mjs +197 -0
- package/dist/optics/refraction.d.mts +201 -0
- package/dist/optics/refraction.mjs +270 -0
- package/dist/optics/wave-optics.d.mts +171 -0
- package/dist/optics/wave-optics.mjs +259 -0
- package/dist/physics/ac/index.d.mts +183 -0
- package/dist/physics/ac/index.mjs +203 -0
- package/dist/physics/dynamics/forces.d.mts +98 -0
- package/dist/physics/dynamics/forces.mjs +153 -0
- package/dist/physics/dynamics/friction.d.mts +76 -0
- package/dist/physics/dynamics/friction.mjs +119 -0
- package/dist/physics/dynamics/system.d.mts +68 -0
- package/dist/physics/dynamics/system.mjs +125 -0
- package/dist/physics/electrostatics/index.d.mts +169 -0
- package/dist/physics/electrostatics/index.mjs +249 -0
- package/dist/physics/energy/centre-of-mass.d.mts +115 -0
- package/dist/physics/energy/centre-of-mass.mjs +180 -0
- package/dist/physics/energy/conservation.d.mts +81 -0
- package/dist/physics/energy/conservation.mjs +129 -0
- package/dist/physics/energy/power.d.mts +90 -0
- package/dist/physics/energy/power.mjs +167 -0
- package/dist/physics/energy/spring.d.mts +73 -0
- package/dist/physics/energy/spring.mjs +129 -0
- package/dist/physics/energy/store.d.mts +63 -0
- package/dist/physics/energy/store.mjs +108 -0
- package/dist/physics/energy/theorem.d.mts +65 -0
- package/dist/physics/energy/theorem.mjs +113 -0
- package/dist/physics/energy/work.d.mts +114 -0
- package/dist/physics/energy/work.mjs +219 -0
- package/dist/physics/gravitation/body.d.mts +85 -0
- package/dist/physics/gravitation/body.mjs +168 -0
- package/dist/physics/gravitation/kepler.d.mts +127 -0
- package/dist/physics/gravitation/kepler.mjs +216 -0
- package/dist/physics/gravitation/law.d.mts +117 -0
- package/dist/physics/gravitation/law.mjs +175 -0
- package/dist/physics/gravitation/orbit.d.mts +119 -0
- package/dist/physics/gravitation/orbit.mjs +202 -0
- package/dist/physics/gravitation/potential.d.mts +114 -0
- package/dist/physics/gravitation/potential.mjs +202 -0
- package/dist/physics/gravitation/variation.d.mts +97 -0
- package/dist/physics/gravitation/variation.mjs +175 -0
- package/dist/physics/index.d.mts +35 -0
- package/dist/physics/index.mjs +36 -0
- package/dist/physics/integral-sweep.d.mts +63 -0
- package/dist/physics/integral-sweep.mjs +126 -0
- package/dist/physics/kinematics/equations.d.mts +47 -0
- package/dist/physics/kinematics/equations.mjs +126 -0
- package/dist/physics/kinematics/free-fall.d.mts +53 -0
- package/dist/physics/kinematics/free-fall.mjs +71 -0
- package/dist/physics/kinematics/given.d.mts +16 -0
- package/dist/physics/kinematics/given.mjs +55 -0
- package/dist/physics/kinematics/roots.d.mts +41 -0
- package/dist/physics/kinematics/roots.mjs +72 -0
- package/dist/physics/kinematics/solve.d.mts +52 -0
- package/dist/physics/kinematics/solve.mjs +172 -0
- package/dist/physics/magnetism/biot-savart.d.mts +161 -0
- package/dist/physics/magnetism/biot-savart.mjs +353 -0
- package/dist/physics/magnetism/flux.d.mts +94 -0
- package/dist/physics/magnetism/flux.mjs +313 -0
- package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
- package/dist/physics/magnetism/geomagnetism.mjs +184 -0
- package/dist/physics/magnetism/index.d.mts +12 -0
- package/dist/physics/magnetism/index.mjs +74 -0
- package/dist/physics/magnetism/lorentz.d.mts +28 -0
- package/dist/physics/magnetism/lorentz.mjs +88 -0
- package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
- package/dist/physics/magnetism/magnetic-force.mjs +169 -0
- package/dist/physics/momentum/collide.d.mts +77 -0
- package/dist/physics/momentum/collide.mjs +115 -0
- package/dist/physics/momentum/impulse.d.mts +89 -0
- package/dist/physics/momentum/impulse.mjs +159 -0
- package/dist/physics/momentum/planar.d.mts +60 -0
- package/dist/physics/momentum/planar.mjs +110 -0
- package/dist/physics/projectile.d.mts +107 -0
- package/dist/physics/projectile.mjs +185 -0
- package/dist/physics/rotation/angular.d.mts +85 -0
- package/dist/physics/rotation/angular.mjs +130 -0
- package/dist/physics/rotation/circular.d.mts +79 -0
- package/dist/physics/rotation/circular.mjs +131 -0
- package/dist/physics/rotation/inertia.d.mts +164 -0
- package/dist/physics/rotation/inertia.mjs +332 -0
- package/dist/physics/rotation/torque.d.mts +65 -0
- package/dist/physics/rotation/torque.mjs +134 -0
- package/dist/physics/vectors.d.mts +64 -0
- package/dist/physics/vectors.mjs +114 -0
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +33 -17
- package/dist/primitives/Grid.mjs +89 -17
- package/dist/primitives/Label.d.mts +1 -14
- package/dist/primitives/Label.mjs +3 -2
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/quantity/index.d.mts +119 -0
- package/dist/quantity/index.mjs +417 -0
- package/dist/relation/derive.d.mts +74 -0
- package/dist/relation/derive.mjs +73 -0
- package/dist/relation/index.d.mts +56 -0
- package/dist/relation/index.mjs +234 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +15 -40
- package/dist/scene/evaluators.mjs +1 -1
- package/dist/sim/thermal.mjs +45 -20
- package/dist/thermo/calorimetry.d.mts +207 -0
- package/dist/thermo/calorimetry.mjs +345 -0
- package/dist/thermo/cycles.d.mts +142 -0
- package/dist/thermo/cycles.mjs +256 -0
- package/dist/thermo/entropy.d.mts +87 -0
- package/dist/thermo/entropy.mjs +140 -0
- package/dist/thermo/expansion.d.mts +130 -0
- package/dist/thermo/expansion.mjs +178 -0
- package/dist/thermo/gas.d.mts +197 -0
- package/dist/thermo/gas.mjs +279 -0
- package/dist/thermo/heat-transfer.d.mts +164 -0
- package/dist/thermo/heat-transfer.mjs +217 -0
- package/dist/thermo/index.d.mts +9 -82
- package/dist/thermo/index.mjs +9 -132
- package/dist/thermo/processes.d.mts +95 -0
- package/dist/thermo/processes.mjs +154 -0
- package/dist/thermo/temperature.d.mts +174 -0
- package/dist/thermo/temperature.mjs +236 -0
- package/dist/view/Stage.mjs +4 -11
- package/dist/waves/damping.d.mts +224 -0
- package/dist/waves/damping.mjs +317 -0
- package/dist/waves/doppler.d.mts +72 -0
- package/dist/waves/doppler.mjs +125 -0
- package/dist/waves/index.d.mts +10 -0
- package/dist/waves/index.mjs +10 -0
- package/dist/waves/pendulum.d.mts +130 -0
- package/dist/waves/pendulum.mjs +211 -0
- package/dist/waves/pitch.d.mts +125 -0
- package/dist/waves/pitch.mjs +158 -0
- package/dist/waves/shm.d.mts +170 -0
- package/dist/waves/shm.mjs +279 -0
- package/dist/waves/springs.d.mts +103 -0
- package/dist/waves/springs.mjs +176 -0
- package/dist/waves/superposition.d.mts +124 -0
- package/dist/waves/superposition.mjs +196 -0
- package/dist/waves/wave.d.mts +154 -0
- package/dist/waves/wave.mjs +178 -0
- package/package.json +103 -23
- package/styles.css +125 -8
- package/dist/assets/kit/index.mjs +0 -4
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../core/worked.mjs";
|
|
2
|
+
import { compose, resolve, toDegrees, toRadians } from "./vectors.mjs";
|
|
3
|
+
import { G_EARTH, vertical } from "./kinematics/free-fall.mjs";
|
|
4
|
+
import { MOTION_UNITS_TEX } from "./kinematics/equations.mjs";
|
|
5
|
+
import { motion, timeToReach } from "./kinematics/solve.mjs";
|
|
6
|
+
|
|
7
|
+
//#region src/physics/projectile.ts
|
|
8
|
+
/**
|
|
9
|
+
* Projectile motion, as what it actually is: TWO straight-line motions sharing one clock.
|
|
10
|
+
*
|
|
11
|
+
* Every formula in a projectile chapter is a consequence of three sentences:
|
|
12
|
+
*
|
|
13
|
+
* 1. Horizontally there is no force, so the horizontal velocity never changes: `x = u_x t`.
|
|
14
|
+
* 2. Vertically there is gravity and nothing else, so it is ordinary SUVAT with `a = −g`.
|
|
15
|
+
* 3. The two motions share `t`, and that is the only thing connecting them.
|
|
16
|
+
*
|
|
17
|
+
* So this module declares almost no formulas of its own. It resolves the launch into components
|
|
18
|
+
* with `vectors`, hands the vertical part to `kinematics`, and multiplies the horizontal one out.
|
|
19
|
+
* A chapter's worth of results, range and time of flight and maximum height, fall out of that,
|
|
20
|
+
* and crucially they fall out IN THE SAME WAY for the cases textbooks separate into different
|
|
21
|
+
* "types": launched from the ground, launched from a cliff, launched downwards. Those are the same
|
|
22
|
+
* three sentences with a different starting height, and building them as one thing rather than as
|
|
23
|
+
* three is the whole point.
|
|
24
|
+
*
|
|
25
|
+
* The two-motion structure is also what makes the derivations honest. When {@link flightSteps}
|
|
26
|
+
* shows a time of flight, the quadratic and its rejected root come from the kinematics kernel, not
|
|
27
|
+
* from a projectile-shaped formula that hides them.
|
|
28
|
+
*
|
|
29
|
+
* Pure: no React, no pixels.
|
|
30
|
+
*/
|
|
31
|
+
const gravityOf = (launch) => launch.g ?? 9.8;
|
|
32
|
+
const heightOf = (launch) => launch.height ?? 0;
|
|
33
|
+
/** The launch speed split into its horizontal and vertical parts. */
|
|
34
|
+
const launchVelocity = (launch) => resolve(launch.speed, launch.angleDeg);
|
|
35
|
+
/** The vertical half of a flight, as the signed SUVAT a falling-body question would use. */
|
|
36
|
+
const verticalHalf = (uy, fallsBy, g) => vertical({
|
|
37
|
+
speed: Math.abs(uy),
|
|
38
|
+
direction: uy >= 0 ? "up" : "down",
|
|
39
|
+
fallsBy,
|
|
40
|
+
g
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Everything about one flight.
|
|
44
|
+
*
|
|
45
|
+
* The time of flight goes through the kinematics solver rather than through a closed form, because
|
|
46
|
+
* with a launch height it IS a quadratic with a root to reject, and routing it through the same
|
|
47
|
+
* code path as the level-ground case means the level-ground case cannot quietly be a different
|
|
48
|
+
* piece of physics.
|
|
49
|
+
*/
|
|
50
|
+
function flight(launch) {
|
|
51
|
+
const g = gravityOf(launch);
|
|
52
|
+
const h = heightOf(launch);
|
|
53
|
+
const { x: ux, y: uy } = launchVelocity(launch);
|
|
54
|
+
const timeOfFlight = motion("t", verticalHalf(uy, h, g)).value;
|
|
55
|
+
const range = ux * timeOfFlight;
|
|
56
|
+
const timeToPeak = uy > 0 ? uy / g : 0;
|
|
57
|
+
const peakRise = uy > 0 ? uy * uy / (2 * g) : 0;
|
|
58
|
+
const impact = velocityAt(launch, timeOfFlight);
|
|
59
|
+
const { magnitude, angleDeg } = compose(impact.x, impact.y);
|
|
60
|
+
return {
|
|
61
|
+
launchVelocity: {
|
|
62
|
+
x: ux,
|
|
63
|
+
y: uy
|
|
64
|
+
},
|
|
65
|
+
timeOfFlight,
|
|
66
|
+
range,
|
|
67
|
+
timeToPeak,
|
|
68
|
+
peakRise,
|
|
69
|
+
maxHeight: h + peakRise,
|
|
70
|
+
impactSpeed: magnitude,
|
|
71
|
+
impactAngleDeg: -angleDeg
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Where the projectile is at time `t`, measured from the launch point. */
|
|
75
|
+
function positionAt(launch, t) {
|
|
76
|
+
const g = gravityOf(launch);
|
|
77
|
+
const { x: ux, y: uy } = launchVelocity(launch);
|
|
78
|
+
return {
|
|
79
|
+
x: ux * t,
|
|
80
|
+
y: uy * t - .5 * g * t * t
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** How fast and which way it is going at time `t`. Horizontal never changes; that is the point. */
|
|
84
|
+
function velocityAt(launch, t) {
|
|
85
|
+
const g = gravityOf(launch);
|
|
86
|
+
const { x: ux, y: uy } = launchVelocity(launch);
|
|
87
|
+
return {
|
|
88
|
+
x: ux,
|
|
89
|
+
y: uy - g * t
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** The arc, sampled for drawing. Always includes the landing point exactly. */
|
|
93
|
+
function arc(launch, samples = 64) {
|
|
94
|
+
const total = flight(launch).timeOfFlight;
|
|
95
|
+
const points = [];
|
|
96
|
+
for (let i = 0; i <= samples; i++) points.push(positionAt(launch, total * i / samples));
|
|
97
|
+
return points;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Every moment the projectile is at a given height above the LAUNCH point.
|
|
101
|
+
*
|
|
102
|
+
* Usually two, and that is the interesting part: on the way up and on the way down. A lab that
|
|
103
|
+
* draws both, and a lesson that says why there are two, turns a confusing quadratic into the
|
|
104
|
+
* obvious fact that the arc is symmetric.
|
|
105
|
+
*/
|
|
106
|
+
function timeAtHeight(launch, heightAboveLaunch) {
|
|
107
|
+
const g = gravityOf(launch);
|
|
108
|
+
const { y: uy } = launchVelocity(launch);
|
|
109
|
+
return timeToReach(heightAboveLaunch, {
|
|
110
|
+
u: uy,
|
|
111
|
+
a: -g
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The launch angles that put a projectile a given distance away on level ground.
|
|
116
|
+
*
|
|
117
|
+
* There are normally TWO, one low and flat and one high and lobbed, and they are complementary
|
|
118
|
+
* (they add to 90°). That pair is the most under-taught fact in the topic: a mortar and a rifle
|
|
119
|
+
* hitting the same target is the same equation twice. Returns null when the target is out of
|
|
120
|
+
* range at that speed, which is the honest answer and the one a game needs.
|
|
121
|
+
*/
|
|
122
|
+
function anglesForRange(range, speed, g = G_EARTH) {
|
|
123
|
+
const sin2theta = range * g / (speed * speed);
|
|
124
|
+
if (sin2theta > 1 || sin2theta < -1) return null;
|
|
125
|
+
const low = toDegrees(Math.asin(sin2theta)) / 2;
|
|
126
|
+
return {
|
|
127
|
+
low,
|
|
128
|
+
high: 90 - low
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The smallest launch speed that can reach a distance on level ground, and the angle that does it.
|
|
133
|
+
*
|
|
134
|
+
* `R = v² sin 2θ / g` is largest for a given speed when `sin 2θ = 1`, so the cheapest shot is
|
|
135
|
+
* always at 45° and needs `v = √(Rg)`. Worth having as its own function because "what is the
|
|
136
|
+
* minimum speed" is a standard exam question and because the answer explains why 45° is the angle
|
|
137
|
+
* everybody remembers.
|
|
138
|
+
*/
|
|
139
|
+
function minimumSpeedForRange(range, g = G_EARTH) {
|
|
140
|
+
return {
|
|
141
|
+
speed: Math.sqrt(range * g),
|
|
142
|
+
angleDeg: 45
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The launch angle at which the range equals the maximum height.
|
|
147
|
+
*
|
|
148
|
+
* `R = H` gives `tan θ = 4`, independent of speed and of gravity, which is a genuinely surprising
|
|
149
|
+
* result and a good lab question: the learner predicts whether firing harder changes the angle,
|
|
150
|
+
* and it does not.
|
|
151
|
+
*/
|
|
152
|
+
const angleWhereRangeEqualsHeight = () => toDegrees(Math.atan(4));
|
|
153
|
+
/**
|
|
154
|
+
* The worked solution for a flight, as a lesson would set it out.
|
|
155
|
+
*
|
|
156
|
+
* Structured as resolve, then vertical, then horizontal, in that order and labelled as such,
|
|
157
|
+
* because that ordering IS the method. A derivation that jumps to `R = u² sin 2θ / g` gives a
|
|
158
|
+
* student a formula to memorise; this one gives them something they can redo when the question has
|
|
159
|
+
* a cliff in it and the memorised formula does not apply.
|
|
160
|
+
*/
|
|
161
|
+
function flightSteps(launch, sf = 3) {
|
|
162
|
+
const g = gravityOf(launch);
|
|
163
|
+
const h = heightOf(launch);
|
|
164
|
+
const { x: ux, y: uy } = launchVelocity(launch);
|
|
165
|
+
const f = flight(launch);
|
|
166
|
+
const w = calc();
|
|
167
|
+
const SPEED = MOTION_UNITS_TEX.u;
|
|
168
|
+
w.step(`u_x = u\\cos\\theta = ${texSigFigs(launch.speed, sf)}\\cos ${texSigFigs(launch.angleDeg, sf)}^\\circ = ${texSigFigs(ux, sf)}\\ ${SPEED}`, "step 1: split the launch into two motions");
|
|
169
|
+
w.step(`u_y = u\\sin\\theta = ${texSigFigs(launch.speed, sf)}\\sin ${texSigFigs(launch.angleDeg, sf)}^\\circ = ${texSigFigs(uy, sf)}\\ ${SPEED}`);
|
|
170
|
+
const verticalSolve = motion("t", verticalHalf(uy, h, g), sf);
|
|
171
|
+
w.step(`\\text{up is positive} \\;\\Rightarrow\\; a = -g, \\quad s = ${h > 0 ? "-h" : "0"}`, h > 0 ? "step 2: the vertical motion. It lands below the launch point, so its displacement is negative" : "step 2: the vertical motion. It lands back at launch height, so its displacement is zero");
|
|
172
|
+
for (const step of verticalSolve.worked.steps.slice(1)) w.step(step.tex, step.note);
|
|
173
|
+
w.step(`x = u_x t = ${texSigFigs(ux, sf + 1)} \\times ${texSigFigs(f.timeOfFlight, sf + 1)} = ${texSigFigs(f.range, sf + 1)}\\ \\mathrm{m}`, "step 3: the horizontal motion, which never accelerated, over that same time");
|
|
174
|
+
return w.done(f.range);
|
|
175
|
+
}
|
|
176
|
+
/** The working for the peak: why the highest point is where the vertical velocity is zero. */
|
|
177
|
+
function peakSteps(launch, sf = 3) {
|
|
178
|
+
const g = gravityOf(launch);
|
|
179
|
+
const { y: uy } = launchVelocity(launch);
|
|
180
|
+
const f = flight(launch);
|
|
181
|
+
return calc().step(`v_y = 0 \\text{ at the top}`, "it is still moving horizontally, but for that instant it is going neither up nor down").step(`t = \\frac{u_y}{g} = \\frac{${texSigFigs(uy, sf)}}{${texSigFigs(g, sf)}} = ${texSigFigs(f.timeToPeak, sf)}\\ \\mathrm{s}`, "from v = u + at with v = 0").step(`H = \\frac{u_y^2}{2g} = ${texSigFigs(f.peakRise, sf)}\\ \\mathrm{m}`, "from v² = u² + 2as with v = 0").done(f.peakRise);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
export { angleWhereRangeEqualsHeight, anglesForRange, arc, flight, flightSteps, launchVelocity, minimumSpeedForRange, peakSteps, positionAt, timeAtHeight, velocityAt };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Worked } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/rotation/angular.d.ts
|
|
4
|
+
/** Revolutions per second to radians per second. */
|
|
5
|
+
declare const fromRevsPerSecond: (n: number) => number;
|
|
6
|
+
/** Revolutions per minute to radians per second. */
|
|
7
|
+
declare const fromRPM: (rpm: number) => number;
|
|
8
|
+
/** `L = Iω`, for a body whose moment of inertia you know. */
|
|
9
|
+
declare const angularMomentum: (inertia: number, omega: number) => number;
|
|
10
|
+
/**
|
|
11
|
+
* `L = mvr` for a point mass on a string, which is `Iω` with `I = mr²` written out.
|
|
12
|
+
*
|
|
13
|
+
* Kept because that is how the question is posed, and because seeing the two forms give the same
|
|
14
|
+
* number is what makes `I = mr²` feel like a definition rather than another formula.
|
|
15
|
+
*/
|
|
16
|
+
declare function angularMomentumOfPoint(mass: number, speed: number, radius: number, sf?: number): {
|
|
17
|
+
value: number;
|
|
18
|
+
worked: Worked;
|
|
19
|
+
};
|
|
20
|
+
interface SpinChange {
|
|
21
|
+
readonly omega2: number;
|
|
22
|
+
readonly energyBefore: number;
|
|
23
|
+
readonly energyAfter: number;
|
|
24
|
+
/** Positive when the body ends up with MORE energy, which pulling in always does. */
|
|
25
|
+
readonly workDone: number;
|
|
26
|
+
readonly worked: Worked;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The skater: `I₁ω₁ = I₂ω₂` when nothing external twists the system.
|
|
30
|
+
*
|
|
31
|
+
* Returns the energy on both sides as well as the new spin rate, because the energy is the
|
|
32
|
+
* interesting half and a function that returned only `ω₂` would hide it.
|
|
33
|
+
*/
|
|
34
|
+
declare function conserveSpin(inertia1: number, omega1: number, inertia2: number, sf?: number): SpinChange;
|
|
35
|
+
/**
|
|
36
|
+
* The shape factor `k²/r²` for the bodies a rolling question uses.
|
|
37
|
+
*
|
|
38
|
+
* Derived from the standard results rather than listed as folklore: a solid disc is `½MR²`, so
|
|
39
|
+
* `k²/r² = ½`, and so on. Everything about a rolling race follows from this one column.
|
|
40
|
+
*/
|
|
41
|
+
declare const ROLLING_SHAPES: {
|
|
42
|
+
readonly hoop: {
|
|
43
|
+
readonly label: "hoop or thin ring";
|
|
44
|
+
readonly factor: 1;
|
|
45
|
+
};
|
|
46
|
+
readonly disc: {
|
|
47
|
+
readonly label: "solid disc or cylinder";
|
|
48
|
+
readonly factor: 0.5;
|
|
49
|
+
};
|
|
50
|
+
readonly sphere: {
|
|
51
|
+
readonly label: "solid sphere";
|
|
52
|
+
readonly factor: 0.4;
|
|
53
|
+
};
|
|
54
|
+
readonly shell: {
|
|
55
|
+
readonly label: "hollow sphere";
|
|
56
|
+
readonly factor: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
type RollingShape = keyof typeof ROLLING_SHAPES;
|
|
60
|
+
interface RollingEnergy {
|
|
61
|
+
readonly translational: number;
|
|
62
|
+
readonly rotational: number;
|
|
63
|
+
readonly total: number;
|
|
64
|
+
/** The fraction of the energy that is in the spin. Shape alone decides it. */
|
|
65
|
+
readonly spinShare: number;
|
|
66
|
+
readonly worked: Worked;
|
|
67
|
+
}
|
|
68
|
+
/** How a rolling body's kinetic energy divides between going along and going round. */
|
|
69
|
+
declare function rollingEnergy(mass: number, speed: number, shape: RollingShape, sf?: number): RollingEnergy;
|
|
70
|
+
/**
|
|
71
|
+
* The speed a body reaches rolling from rest down a height `h`.
|
|
72
|
+
*
|
|
73
|
+
* `v = √(2gh / (1 + k²/r²))`. Mass and radius cancel completely, so the race down a slope is
|
|
74
|
+
* decided by shape and nothing else: sphere, then disc, then hollow sphere, then hoop, every time,
|
|
75
|
+
* whatever they weigh. Worth having a learner predict first, because the intuition is that the
|
|
76
|
+
* heavy one wins.
|
|
77
|
+
*/
|
|
78
|
+
declare function rollingSpeedFromHeight(height: number, shape: RollingShape, g?: number, sf?: number): {
|
|
79
|
+
speed: number;
|
|
80
|
+
worked: Worked;
|
|
81
|
+
};
|
|
82
|
+
/** Order a set of shapes by how fast they finish a roll: the race, as a prediction to check. */
|
|
83
|
+
declare const rollingRace: (shapes?: readonly RollingShape[]) => RollingShape[];
|
|
84
|
+
//#endregion
|
|
85
|
+
export { ROLLING_SHAPES, RollingEnergy, RollingShape, SpinChange, angularMomentum, angularMomentumOfPoint, conserveSpin, fromRPM, fromRevsPerSecond, rollingEnergy, rollingRace, rollingSpeedFromHeight };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/rotation/angular.ts
|
|
4
|
+
/**
|
|
5
|
+
* Angular momentum, rotational energy, and rolling.
|
|
6
|
+
*
|
|
7
|
+
* THE SKATER. Angular momentum is conserved when no external torque acts, and `L = Iω` means that
|
|
8
|
+
* pulling your arms in cuts `I` and so must raise `ω`. Everyone has seen this and almost nobody is
|
|
9
|
+
* told the surprising half: the kinetic energy goes UP, not stays the same. `E = ½Iω²` and `L = Iω`
|
|
10
|
+
* together give `E = L²/2I`, so halving `I` at constant `L` DOUBLES the energy. It comes from the
|
|
11
|
+
* skater's muscles doing work pulling the arms in against the outward pull, which is a real,
|
|
12
|
+
* checkable, slightly startling fact and a much better question than "what is the new ω".
|
|
13
|
+
*
|
|
14
|
+
* ROLLING. A rolling body carries its energy in two places at once, `½mv²` in its motion and `½Iω²`
|
|
15
|
+
* in its spin, and the split depends only on SHAPE. `v = rω` links them, so
|
|
16
|
+
*
|
|
17
|
+
* E = ½mv²(1 + k²/r²)
|
|
18
|
+
*
|
|
19
|
+
* where `k` is the radius of gyration. A hoop puts half its energy into spin and a sphere only
|
|
20
|
+
* two-sevenths, so racing them down a slope sorts them by shape with mass and radius cancelling
|
|
21
|
+
* out entirely. That cancellation is the best prediction question in the topic, because everybody
|
|
22
|
+
* guesses the heavy one wins.
|
|
23
|
+
*
|
|
24
|
+
* Pure: no React, no pixels.
|
|
25
|
+
*/
|
|
26
|
+
/** Revolutions per second to radians per second. */
|
|
27
|
+
const fromRevsPerSecond = (n) => 2 * Math.PI * n;
|
|
28
|
+
/** Revolutions per minute to radians per second. */
|
|
29
|
+
const fromRPM = (rpm) => 2 * Math.PI * rpm / 60;
|
|
30
|
+
/** `L = Iω`, for a body whose moment of inertia you know. */
|
|
31
|
+
const angularMomentum = (inertia, omega) => inertia * omega;
|
|
32
|
+
/**
|
|
33
|
+
* `L = mvr` for a point mass on a string, which is `Iω` with `I = mr²` written out.
|
|
34
|
+
*
|
|
35
|
+
* Kept because that is how the question is posed, and because seeing the two forms give the same
|
|
36
|
+
* number is what makes `I = mr²` feel like a definition rather than another formula.
|
|
37
|
+
*/
|
|
38
|
+
function angularMomentumOfPoint(mass, speed, radius, sf = 3) {
|
|
39
|
+
const value = mass * speed * radius;
|
|
40
|
+
return {
|
|
41
|
+
value,
|
|
42
|
+
worked: calc().step("L = I\\omega = (mr^2)\\left(\\frac{v}{r}\\right) = mvr", "the same thing written two ways").step(`L = ${texSigFigs(mass, sf)} \\times ${texSigFigs(speed, sf)} \\times ${texSigFigs(radius, sf)} = ${texSigFigs(value, sf)}\\ \\mathrm{kg\\,m^2\\,s^{-1}}`).done(value)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The skater: `I₁ω₁ = I₂ω₂` when nothing external twists the system.
|
|
47
|
+
*
|
|
48
|
+
* Returns the energy on both sides as well as the new spin rate, because the energy is the
|
|
49
|
+
* interesting half and a function that returned only `ω₂` would hide it.
|
|
50
|
+
*/
|
|
51
|
+
function conserveSpin(inertia1, omega1, inertia2, sf = 3) {
|
|
52
|
+
if (inertia1 <= 0 || inertia2 <= 0) throw new Error("Moments of inertia must be positive.");
|
|
53
|
+
const omega2 = inertia1 * omega1 / inertia2;
|
|
54
|
+
const energyBefore = .5 * inertia1 * omega1 * omega1;
|
|
55
|
+
const energyAfter = .5 * inertia2 * omega2 * omega2;
|
|
56
|
+
const worked = calc().step("I_1\\omega_1 = I_2\\omega_2", "no external torque, so the angular momentum cannot change").step(`\\omega_2 = \\frac{${texSigFigs(inertia1, sf)} \\times ${texSigFigs(omega1, sf)}}{${texSigFigs(inertia2, sf)}} = ${texSigFigs(omega2, sf)}\\ \\mathrm{rad\\,s^{-1}}`).step(`E = \\frac{L^2}{2I}: ${texSigFigs(energyBefore, sf)} \\to ${texSigFigs(energyAfter, sf)}\\ \\mathrm{J}`, energyAfter > energyBefore + 1e-12 ? "the energy ROSE, and it came from the muscles pulling the arms in against the outward pull" : energyAfter < energyBefore - 1e-12 ? "the energy fell: letting the arms out, work is done BY the body" : "unchanged, because the moment of inertia did not change").done(omega2);
|
|
57
|
+
return {
|
|
58
|
+
omega2,
|
|
59
|
+
energyBefore,
|
|
60
|
+
energyAfter,
|
|
61
|
+
workDone: energyAfter - energyBefore,
|
|
62
|
+
worked
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The shape factor `k²/r²` for the bodies a rolling question uses.
|
|
67
|
+
*
|
|
68
|
+
* Derived from the standard results rather than listed as folklore: a solid disc is `½MR²`, so
|
|
69
|
+
* `k²/r² = ½`, and so on. Everything about a rolling race follows from this one column.
|
|
70
|
+
*/
|
|
71
|
+
const ROLLING_SHAPES = {
|
|
72
|
+
hoop: {
|
|
73
|
+
label: "hoop or thin ring",
|
|
74
|
+
factor: 1
|
|
75
|
+
},
|
|
76
|
+
disc: {
|
|
77
|
+
label: "solid disc or cylinder",
|
|
78
|
+
factor: .5
|
|
79
|
+
},
|
|
80
|
+
sphere: {
|
|
81
|
+
label: "solid sphere",
|
|
82
|
+
factor: .4
|
|
83
|
+
},
|
|
84
|
+
shell: {
|
|
85
|
+
label: "hollow sphere",
|
|
86
|
+
factor: 2 / 3
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
/** How a rolling body's kinetic energy divides between going along and going round. */
|
|
90
|
+
function rollingEnergy(mass, speed, shape, sf = 3) {
|
|
91
|
+
const { factor, label } = ROLLING_SHAPES[shape];
|
|
92
|
+
const translational = .5 * mass * speed * speed;
|
|
93
|
+
const rotational = factor * translational;
|
|
94
|
+
const total = translational + rotational;
|
|
95
|
+
const worked = calc().step("E = \\tfrac{1}{2}mv^2 + \\tfrac{1}{2}I\\omega^2 = \\tfrac{1}{2}mv^2\\left(1 + \\frac{k^2}{r^2}\\right)", `v = rω links the two, and for a ${label} the shape factor is ${factor}`).step(`E = ${texSigFigs(translational, sf)} + ${texSigFigs(rotational, sf)} = ${texSigFigs(total, sf)}\\ \\mathrm{J}`, `${texSigFigs(100 * (rotational / total), sf)}% of it is in the spin, and that share depends on SHAPE alone`).done(total);
|
|
96
|
+
return {
|
|
97
|
+
translational,
|
|
98
|
+
rotational,
|
|
99
|
+
total,
|
|
100
|
+
spinShare: rotational / total,
|
|
101
|
+
worked
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The speed a body reaches rolling from rest down a height `h`.
|
|
106
|
+
*
|
|
107
|
+
* `v = √(2gh / (1 + k²/r²))`. Mass and radius cancel completely, so the race down a slope is
|
|
108
|
+
* decided by shape and nothing else: sphere, then disc, then hollow sphere, then hoop, every time,
|
|
109
|
+
* whatever they weigh. Worth having a learner predict first, because the intuition is that the
|
|
110
|
+
* heavy one wins.
|
|
111
|
+
*/
|
|
112
|
+
function rollingSpeedFromHeight(height, shape, g = 9.8, sf = 3) {
|
|
113
|
+
if (height < 0) throw new Error("The drop must not be negative.");
|
|
114
|
+
const { factor, label } = ROLLING_SHAPES[shape];
|
|
115
|
+
const speed = Math.sqrt(2 * g * height / (1 + factor));
|
|
116
|
+
return {
|
|
117
|
+
speed,
|
|
118
|
+
worked: calc().step("mgh = \\tfrac{1}{2}mv^2\\left(1 + \\frac{k^2}{r^2}\\right)", "all the lost height becomes both kinds of motion").step("v = \\sqrt{\\frac{2gh}{1 + k^2/r^2}}", "the mass cancels, and so does the radius: only the SHAPE is left").step(`v = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`, `for a ${label}. A body that puts more energy into spinning arrives slower, whatever it weighs`).done(speed)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** Order a set of shapes by how fast they finish a roll: the race, as a prediction to check. */
|
|
122
|
+
const rollingRace = (shapes = [
|
|
123
|
+
"sphere",
|
|
124
|
+
"disc",
|
|
125
|
+
"shell",
|
|
126
|
+
"hoop"
|
|
127
|
+
]) => [...shapes].sort((a, b) => ROLLING_SHAPES[a].factor - ROLLING_SHAPES[b].factor);
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
export { ROLLING_SHAPES, angularMomentum, angularMomentumOfPoint, conserveSpin, fromRPM, fromRevsPerSecond, rollingEnergy, rollingRace, rollingSpeedFromHeight };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Worked } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/rotation/circular.d.ts
|
|
4
|
+
/** `a = v²/r = ω²r`, directed at the centre. */
|
|
5
|
+
declare const centripetalAcceleration: (speed: number, radius: number) => number;
|
|
6
|
+
/** `F = mv²/r`: not an extra force, but what the real ones have to add up to. */
|
|
7
|
+
declare function centripetalForce(mass: number, speed: number, radius: number, sf?: number): {
|
|
8
|
+
value: number;
|
|
9
|
+
acceleration: number;
|
|
10
|
+
worked: Worked;
|
|
11
|
+
};
|
|
12
|
+
/** The same thing from a spin rate: `F = mω²r`, which is what a whirled string question gives. */
|
|
13
|
+
declare const centripetalFromOmega: (mass: number, omega: number, radius: number) => number;
|
|
14
|
+
/**
|
|
15
|
+
* The fastest a vehicle can take a FLAT bend before it slides.
|
|
16
|
+
*
|
|
17
|
+
* Friction is the only thing pointing at the centre, so `μmg ≥ mv²/r` and the mass cancels: a
|
|
18
|
+
* loaded lorry and an empty one slide at the same speed, which is not what anyone expects.
|
|
19
|
+
*/
|
|
20
|
+
declare function maxSpeedFlat(radius: number, mu: number, g?: number, sf?: number): {
|
|
21
|
+
speed: number;
|
|
22
|
+
worked: Worked;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The angle a bend should be banked to, so that no friction is needed at all: `tan θ = v²/rg`.
|
|
26
|
+
*
|
|
27
|
+
* At this angle the track's normal force alone leans inward enough to turn the vehicle, and the
|
|
28
|
+
* tyres do no sideways work. It is the design speed of the bend, and again the mass cancels, so one
|
|
29
|
+
* bank angle serves a bicycle and a lorry.
|
|
30
|
+
*/
|
|
31
|
+
declare function bankingAngle(speed: number, radius: number, g?: number, sf?: number): {
|
|
32
|
+
degrees: number;
|
|
33
|
+
worked: Worked;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* How much higher the outer rail must sit, given the gauge.
|
|
37
|
+
*
|
|
38
|
+
* The railway form of the same question: the bank angle is set by raising one rail, so
|
|
39
|
+
* `h = gauge · sin θ`. Their worked example is a 98 m bend at 9.8 m/s on a 1.525 m gauge.
|
|
40
|
+
*/
|
|
41
|
+
declare function railCant(speed: number, radius: number, gauge: number, g?: number, sf?: number): {
|
|
42
|
+
height: number;
|
|
43
|
+
degrees: number;
|
|
44
|
+
worked: Worked;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The fastest a vehicle can take a BANKED bend that also has friction.
|
|
48
|
+
*
|
|
49
|
+
* Both help: the bank leans the normal force inward and friction adds to it. The denominator is
|
|
50
|
+
* what makes this interesting, because `cos θ − μ sin θ` goes to zero at `μ = cot θ` and the
|
|
51
|
+
* predicted speed goes to infinity. That is not a bug in the algebra, it is the statement that a
|
|
52
|
+
* bend banked steeply enough, with grippy enough tyres, cannot be slid out of at any speed. Real
|
|
53
|
+
* tracks do not go that far, and the function says so rather than returning Infinity quietly.
|
|
54
|
+
*/
|
|
55
|
+
declare function maxSpeedBanked(radius: number, angleDeg: number, mu: number, g?: number, sf?: number): {
|
|
56
|
+
speed: number;
|
|
57
|
+
worked: Worked;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* The tension in a string whirling a mass in a VERTICAL circle, at any angle from the top.
|
|
61
|
+
*
|
|
62
|
+
* `T = mv²/r − mg cos φ` measuring `φ` from the top, so the string is slackest at the top and
|
|
63
|
+
* tightest at the bottom, with the difference `2mg`. Gravity helps provide the centripetal force at
|
|
64
|
+
* the top and fights it at the bottom, and that single sentence is the whole of the topic.
|
|
65
|
+
*/
|
|
66
|
+
declare function verticalCircleTension(mass: number, speed: number, radius: number, angleFromTopDeg: number, g?: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* The slowest a mass can go round a vertical circle without the string going slack at the top.
|
|
69
|
+
*
|
|
70
|
+
* At the critical speed the string carries nothing and gravity alone supplies the whole centripetal
|
|
71
|
+
* requirement: `mg = mv²/r`, so `v = √(gr)`. Below it the string cannot push, so the mass leaves
|
|
72
|
+
* the circular path, which is why a bucket of water must be swung fast enough and not merely swung.
|
|
73
|
+
*/
|
|
74
|
+
declare function minimumSpeedAtTop(radius: number, g?: number, sf?: number): {
|
|
75
|
+
speed: number;
|
|
76
|
+
worked: Worked;
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
export { bankingAngle, centripetalAcceleration, centripetalForce, centripetalFromOmega, maxSpeedBanked, maxSpeedFlat, minimumSpeedAtTop, railCant, verticalCircleTension };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { calc, texSigFigs } from "../../core/worked.mjs";
|
|
2
|
+
import { toDegrees, toRadians } from "../vectors.mjs";
|
|
3
|
+
import { G_EARTH } from "../kinematics/free-fall.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/physics/rotation/circular.ts
|
|
6
|
+
/**
|
|
7
|
+
* Going round in a circle: what holds you in, and how fast you can take the bend.
|
|
8
|
+
*
|
|
9
|
+
* ONE CORRECTION FIRST, because it is the misconception the whole topic trips on. There is no
|
|
10
|
+
* outward force. A body moving in a circle is ACCELERATING, towards the centre, and something real
|
|
11
|
+
* has to supply that: friction on tyres, tension in a string, gravity on a satellite. The outward
|
|
12
|
+
* push a passenger feels is their own inertia continuing in a straight line while the car turns
|
|
13
|
+
* under them. "Centrifugal force" names that feeling, not a force, and a diagram that draws it
|
|
14
|
+
* alongside the real forces has two arrows where physics has one.
|
|
15
|
+
*
|
|
16
|
+
* So `F = mv²/r` is never an extra force to add. It is what the forces you already have must SUM
|
|
17
|
+
* TO. Every question in the topic is that one sentence: find the real forces, resolve them towards
|
|
18
|
+
* the centre, set the total equal to `mv²/r`.
|
|
19
|
+
*
|
|
20
|
+
* Pure: no React, no pixels.
|
|
21
|
+
*/
|
|
22
|
+
/** `a = v²/r = ω²r`, directed at the centre. */
|
|
23
|
+
const centripetalAcceleration = (speed, radius) => {
|
|
24
|
+
if (radius <= 0) throw new Error("The radius must be positive.");
|
|
25
|
+
return speed * speed / radius;
|
|
26
|
+
};
|
|
27
|
+
/** `F = mv²/r`: not an extra force, but what the real ones have to add up to. */
|
|
28
|
+
function centripetalForce(mass, speed, radius, sf = 3) {
|
|
29
|
+
const acceleration = centripetalAcceleration(speed, radius);
|
|
30
|
+
const value = mass * acceleration;
|
|
31
|
+
return {
|
|
32
|
+
value,
|
|
33
|
+
acceleration,
|
|
34
|
+
worked: calc().step("\\sum F_{\\text{towards centre}} = \\frac{mv^2}{r}", "the REQUIREMENT, not an extra arrow. Something real has to supply it").step(`\\frac{mv^2}{r} = \\frac{${texSigFigs(mass, sf)} \\times ${texSigFigs(speed, sf)}^2}{${texSigFigs(radius, sf)}} = ${texSigFigs(value, sf)}\\ \\mathrm{N}`).done(value)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** The same thing from a spin rate: `F = mω²r`, which is what a whirled string question gives. */
|
|
38
|
+
const centripetalFromOmega = (mass, omega, radius) => mass * omega * omega * radius;
|
|
39
|
+
/**
|
|
40
|
+
* The fastest a vehicle can take a FLAT bend before it slides.
|
|
41
|
+
*
|
|
42
|
+
* Friction is the only thing pointing at the centre, so `μmg ≥ mv²/r` and the mass cancels: a
|
|
43
|
+
* loaded lorry and an empty one slide at the same speed, which is not what anyone expects.
|
|
44
|
+
*/
|
|
45
|
+
function maxSpeedFlat(radius, mu, g = G_EARTH, sf = 3) {
|
|
46
|
+
if (radius <= 0 || mu < 0) throw new Error("Radius must be positive and friction cannot be negative.");
|
|
47
|
+
const speed = Math.sqrt(mu * radius * g);
|
|
48
|
+
return {
|
|
49
|
+
speed,
|
|
50
|
+
worked: calc().step("\\mu m g \\geq \\frac{mv^2}{r}", "friction is the only force pointing at the centre").step("v \\leq \\sqrt{\\mu r g}", "the mass cancels: how heavily loaded it is makes no difference").step(`v_{\\max} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`).done(speed)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The angle a bend should be banked to, so that no friction is needed at all: `tan θ = v²/rg`.
|
|
55
|
+
*
|
|
56
|
+
* At this angle the track's normal force alone leans inward enough to turn the vehicle, and the
|
|
57
|
+
* tyres do no sideways work. It is the design speed of the bend, and again the mass cancels, so one
|
|
58
|
+
* bank angle serves a bicycle and a lorry.
|
|
59
|
+
*/
|
|
60
|
+
function bankingAngle(speed, radius, g = G_EARTH, sf = 3) {
|
|
61
|
+
if (radius <= 0) throw new Error("The radius must be positive.");
|
|
62
|
+
const ratio = speed * speed / (radius * g);
|
|
63
|
+
const degrees = toDegrees(Math.atan(ratio));
|
|
64
|
+
return {
|
|
65
|
+
degrees,
|
|
66
|
+
worked: calc().step("N\\sin\\theta = \\frac{mv^2}{r}, \\quad N\\cos\\theta = mg", "the track pushes perpendicular to itself; tilt it and part of that push aims at the centre").step("\\tan\\theta = \\frac{v^2}{rg}", "dividing kills both N and m, so one angle suits every vehicle").step(`\\theta = \\arctan ${texSigFigs(ratio, sf)} = ${texSigFigs(degrees, sf)}^\\circ`, "at this speed the tyres need no sideways grip at all").done(degrees)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* How much higher the outer rail must sit, given the gauge.
|
|
71
|
+
*
|
|
72
|
+
* The railway form of the same question: the bank angle is set by raising one rail, so
|
|
73
|
+
* `h = gauge · sin θ`. Their worked example is a 98 m bend at 9.8 m/s on a 1.525 m gauge.
|
|
74
|
+
*/
|
|
75
|
+
function railCant(speed, radius, gauge, g = G_EARTH, sf = 3) {
|
|
76
|
+
const { degrees } = bankingAngle(speed, radius, g);
|
|
77
|
+
const height = gauge * Math.sin(toRadians(degrees));
|
|
78
|
+
return {
|
|
79
|
+
height,
|
|
80
|
+
degrees,
|
|
81
|
+
worked: calc().step("\\tan\\theta = \\frac{v^2}{rg}", "the bank angle the bend needs").step(`\\theta = ${texSigFigs(degrees, sf)}^\\circ`).step(`h = L\\sin\\theta = ${texSigFigs(gauge, sf)}\\sin ${texSigFigs(degrees, sf)}^\\circ = ${texSigFigs(height, sf)}\\ \\mathrm{m}`, "raise the outer rail by this and the train leans into the bend on its own").done(height)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The fastest a vehicle can take a BANKED bend that also has friction.
|
|
86
|
+
*
|
|
87
|
+
* Both help: the bank leans the normal force inward and friction adds to it. The denominator is
|
|
88
|
+
* what makes this interesting, because `cos θ − μ sin θ` goes to zero at `μ = cot θ` and the
|
|
89
|
+
* predicted speed goes to infinity. That is not a bug in the algebra, it is the statement that a
|
|
90
|
+
* bend banked steeply enough, with grippy enough tyres, cannot be slid out of at any speed. Real
|
|
91
|
+
* tracks do not go that far, and the function says so rather than returning Infinity quietly.
|
|
92
|
+
*/
|
|
93
|
+
function maxSpeedBanked(radius, angleDeg, mu, g = G_EARTH, sf = 3) {
|
|
94
|
+
if (radius <= 0) throw new Error("The radius must be positive.");
|
|
95
|
+
const theta = toRadians(angleDeg);
|
|
96
|
+
const denominator = Math.cos(theta) - mu * Math.sin(theta);
|
|
97
|
+
if (denominator <= 1e-9) throw new Error(`With a bank of ${angleDeg}° and μ = ${mu}, cos θ − μ sin θ is zero or negative, so this model predicts no upper speed limit at all: the bank and the grip together can hold any speed. That is the algebra being honest about an extreme case, not a defect.`);
|
|
98
|
+
const speed = Math.sqrt(radius * g * (Math.sin(theta) + mu * Math.cos(theta)) / denominator);
|
|
99
|
+
return {
|
|
100
|
+
speed,
|
|
101
|
+
worked: calc().step("v \\leq \\sqrt{\\frac{rg(\\sin\\theta + \\mu\\cos\\theta)}{\\cos\\theta - \\mu\\sin\\theta}}", "the bank and the friction both help, so the two effects appear together").step(`v_{\\max} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`).done(speed)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The tension in a string whirling a mass in a VERTICAL circle, at any angle from the top.
|
|
106
|
+
*
|
|
107
|
+
* `T = mv²/r − mg cos φ` measuring `φ` from the top, so the string is slackest at the top and
|
|
108
|
+
* tightest at the bottom, with the difference `2mg`. Gravity helps provide the centripetal force at
|
|
109
|
+
* the top and fights it at the bottom, and that single sentence is the whole of the topic.
|
|
110
|
+
*/
|
|
111
|
+
function verticalCircleTension(mass, speed, radius, angleFromTopDeg, g = G_EARTH) {
|
|
112
|
+
return mass * centripetalAcceleration(speed, radius) - mass * g * Math.cos(toRadians(angleFromTopDeg));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The slowest a mass can go round a vertical circle without the string going slack at the top.
|
|
116
|
+
*
|
|
117
|
+
* At the critical speed the string carries nothing and gravity alone supplies the whole centripetal
|
|
118
|
+
* requirement: `mg = mv²/r`, so `v = √(gr)`. Below it the string cannot push, so the mass leaves
|
|
119
|
+
* the circular path, which is why a bucket of water must be swung fast enough and not merely swung.
|
|
120
|
+
*/
|
|
121
|
+
function minimumSpeedAtTop(radius, g = G_EARTH, sf = 3) {
|
|
122
|
+
if (radius <= 0) throw new Error("The radius must be positive.");
|
|
123
|
+
const speed = Math.sqrt(g * radius);
|
|
124
|
+
return {
|
|
125
|
+
speed,
|
|
126
|
+
worked: calc().step("T + mg = \\frac{mv^2}{r}", "at the top, gravity points the same way as the centripetal requirement").step("T = 0 \\;\\Rightarrow\\; mg = \\frac{mv^2}{r}", "the critical case is the string carrying nothing at all").step(`v_{\\min} = \\sqrt{gr} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`, "any slower and the string would have to PUSH, which a string cannot do, so the mass falls inward").done(speed)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
export { bankingAngle, centripetalAcceleration, centripetalForce, centripetalFromOmega, maxSpeedBanked, maxSpeedFlat, minimumSpeedAtTop, railCant, verticalCircleTension };
|