@classytic/stage 0.3.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/dist/_virtual/_rolldown/runtime.mjs +18 -0
- 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/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 +3 -1
- package/dist/core/index.mjs +3 -1
- 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 +21 -39
- package/dist/finance/bizsim.mjs +276 -97
- package/dist/finance/index.d.mts +20 -43
- package/dist/finance/index.mjs +19 -77
- 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 +6 -6
- package/dist/index.mjs +1 -1
- 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 +4 -9
- package/dist/math/calculus.mjs +216 -7
- 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 +8 -22
- package/dist/math/index.mjs +8 -37
- package/dist/math/latex.mjs +2 -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/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/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/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 +74 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { relation } from "../relation/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/optics/laws.ts
|
|
4
|
+
/**
|
|
5
|
+
* The laws of optics, DECLARED once rather than written as functions.
|
|
6
|
+
*
|
|
7
|
+
* ## Why this file exists beside the others
|
|
8
|
+
*
|
|
9
|
+
* `refraction.ts`, `imaging.ts`, `prism.ts` and `wave-optics.ts` compute. They
|
|
10
|
+
* take the quantities a question gives and return the one it asks for, in the
|
|
11
|
+
* direction that question happened to run.
|
|
12
|
+
*
|
|
13
|
+
* This file declares the same physics as EQUATIONS, through
|
|
14
|
+
* `@classytic/stage/relation`, and gets three things a function cannot give:
|
|
15
|
+
*
|
|
16
|
+
* 1. **Any direction.** `snellsLaw().solve({ n1, i, r })` returns n₂;
|
|
17
|
+
* `solve({ n1, i, n2 })` returns r. One declaration, not two functions,
|
|
18
|
+
* and no chance of the pair drifting apart.
|
|
19
|
+
* 2. **The working.** `.steps({...})` returns the substitution line by line
|
|
20
|
+
* as LaTeX, so a lesson can SHOW the solution rather than assert the
|
|
21
|
+
* answer. Every number in it came from the caller, so a generated
|
|
22
|
+
* derivation cannot divide by a quantity the question never mentioned.
|
|
23
|
+
* 3. **A units check at declaration.** A relation whose dimensions do not
|
|
24
|
+
* balance is refused here, before any lesson can be written against it.
|
|
25
|
+
*
|
|
26
|
+
* Solving an angle out of these became possible only once `math/rearrange`
|
|
27
|
+
* learned to undo trigonometry. Before that, every law ending in an angle could
|
|
28
|
+
* be solved for its indices and for nothing else.
|
|
29
|
+
*
|
|
30
|
+
* ## What is NOT here, and why
|
|
31
|
+
*
|
|
32
|
+
* Isolation peels operations off a variable that appears EXACTLY ONCE. The
|
|
33
|
+
* prism's `n = sin((A + δm)/2) / sin(A/2)` has A twice, so it cannot be
|
|
34
|
+
* declared usefully and lives in `prism.ts` as a numeric solve instead. That
|
|
35
|
+
* boundary is stated rather than hidden, because a relation that silently
|
|
36
|
+
* refused half its directions would be worse than no relation.
|
|
37
|
+
*
|
|
38
|
+
* ## Angles are in RADIANS here
|
|
39
|
+
*
|
|
40
|
+
* Unlike the computing modules, which take degrees because protractors do.
|
|
41
|
+
* `relation` checks dimensions, and an angle has to be the dimensionless thing
|
|
42
|
+
* a sine can accept. `DEG` is exported so a call site can convert in place and
|
|
43
|
+
* stay readable.
|
|
44
|
+
*/
|
|
45
|
+
/** Multiply a value in degrees by this to get radians, for use in a `solve`. */
|
|
46
|
+
const DEG = Math.PI / 180;
|
|
47
|
+
/** Build once, on first use, matching the pattern in `chem/relations.ts`. */
|
|
48
|
+
function lazy(build) {
|
|
49
|
+
let made;
|
|
50
|
+
return () => made ??= build();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* `n1 * sin(i) = n2 * sin(r)`, Snell's law.
|
|
54
|
+
*
|
|
55
|
+
* Solvable for either index and, since trigonometry inverts, for either angle.
|
|
56
|
+
*
|
|
57
|
+
* Asking for `r` past the critical angle THROWS, because no such angle exists:
|
|
58
|
+
* the engine evaluates its own rearrangement, sees NaN and refuses rather than
|
|
59
|
+
* handing back a number-shaped nothing. That is the right failure for a
|
|
60
|
+
* declared equation, but it is not an explanation, so a lab that needs to SHOW
|
|
61
|
+
* total internal reflection calls `refraction.ts` `refract()`, which names the
|
|
62
|
+
* case and reports the critical angle alongside.
|
|
63
|
+
*/
|
|
64
|
+
const snellsLaw = lazy(() => relation("n1 * sin(i) = n2 * sin(r)", {
|
|
65
|
+
n1: "1",
|
|
66
|
+
i: "rad",
|
|
67
|
+
n2: "1",
|
|
68
|
+
r: "rad"
|
|
69
|
+
}, "Snell's law"));
|
|
70
|
+
/** `sin(c) = n2 / n1`, the critical angle for light leaving the denser medium. */
|
|
71
|
+
const criticalAngleLaw = lazy(() => relation("sin(c) = n2 / n1", {
|
|
72
|
+
c: "rad",
|
|
73
|
+
n2: "1",
|
|
74
|
+
n1: "1"
|
|
75
|
+
}, "the critical angle"));
|
|
76
|
+
/** `n = c / v`, refractive index as the factor by which a medium slows light. */
|
|
77
|
+
const indexFromSpeed = lazy(() => relation("n = c / v", {
|
|
78
|
+
n: "1",
|
|
79
|
+
c: "m/s",
|
|
80
|
+
v: "m/s"
|
|
81
|
+
}, "refractive index from speed"));
|
|
82
|
+
/** `n = d / a`, refractive index by the apparent-depth method. */
|
|
83
|
+
const apparentDepthLaw = lazy(() => relation("n = d / a", {
|
|
84
|
+
n: "1",
|
|
85
|
+
d: "m",
|
|
86
|
+
a: "m"
|
|
87
|
+
}, "refractive index from apparent depth"));
|
|
88
|
+
/** `n = tan(p)`, Brewster's law for the polarising angle. */
|
|
89
|
+
const brewstersLaw = lazy(() => relation("n = tan(p)", {
|
|
90
|
+
n: "1",
|
|
91
|
+
p: "rad"
|
|
92
|
+
}, "Brewster's law"));
|
|
93
|
+
/**
|
|
94
|
+
* `1 / v - 1 / u = 1 / f`, the thin lens equation in the Cartesian convention.
|
|
95
|
+
*
|
|
96
|
+
* Each variable appears once, so it solves for any of the three. Note that `u`
|
|
97
|
+
* must be given as the NEGATIVE number the convention requires, which is the
|
|
98
|
+
* price of a declaration that is literally the textbook equation;
|
|
99
|
+
* `imaging.ts` `thinLens()` is the one that takes a positive distance and
|
|
100
|
+
* handles the sign.
|
|
101
|
+
*/
|
|
102
|
+
const thinLensEquation = lazy(() => relation("1 / v - 1 / u = 1 / f", {
|
|
103
|
+
v: "m",
|
|
104
|
+
u: "m",
|
|
105
|
+
f: "m"
|
|
106
|
+
}, "the thin lens equation"));
|
|
107
|
+
/** `1 / v + 1 / u = 1 / f`, the mirror equation with distances as positive lengths. */
|
|
108
|
+
const mirrorEquation = lazy(() => relation("1 / v + 1 / u = 1 / f", {
|
|
109
|
+
v: "m",
|
|
110
|
+
u: "m",
|
|
111
|
+
f: "m"
|
|
112
|
+
}, "the mirror equation"));
|
|
113
|
+
/** `m = h2 / h1`, linear magnification as a height ratio. */
|
|
114
|
+
const magnificationLaw = lazy(() => relation("m = h2 / h1", {
|
|
115
|
+
m: "1",
|
|
116
|
+
h2: "m",
|
|
117
|
+
h1: "m"
|
|
118
|
+
}, "linear magnification"));
|
|
119
|
+
/** `P = 1 / f`, lens power in dioptres from a focal length in metres. */
|
|
120
|
+
const lensPowerLaw = lazy(() => relation("P = 1 / f", {
|
|
121
|
+
P: "1/m",
|
|
122
|
+
f: "m"
|
|
123
|
+
}, "lens power"));
|
|
124
|
+
/** `d = (n - 1) * A`, a thin prism's deviation. */
|
|
125
|
+
const thinPrismLaw = lazy(() => relation("d = (n - 1) * A", {
|
|
126
|
+
d: "rad",
|
|
127
|
+
n: "1",
|
|
128
|
+
A: "rad"
|
|
129
|
+
}, "thin prism deviation"));
|
|
130
|
+
/** `w = lam * D / a`, the fringe spacing in Young's double-slit experiment. */
|
|
131
|
+
const fringeSpacingLaw = lazy(() => relation("w = lam * D / a", {
|
|
132
|
+
w: "m",
|
|
133
|
+
lam: "m",
|
|
134
|
+
D: "m",
|
|
135
|
+
a: "m"
|
|
136
|
+
}, "Young fringe spacing"));
|
|
137
|
+
/**
|
|
138
|
+
* `d * sin(t) = k * lam`, the diffraction grating equation.
|
|
139
|
+
*
|
|
140
|
+
* The order is `k` rather than the conventional `n`, because `n` is a
|
|
141
|
+
* refractive index everywhere else in this file and one symbol meaning two
|
|
142
|
+
* things across one module is how a wrong substitution gets written.
|
|
143
|
+
*/
|
|
144
|
+
const gratingLaw = lazy(() => relation("d * sin(t) = k * lam", {
|
|
145
|
+
d: "m",
|
|
146
|
+
t: "rad",
|
|
147
|
+
k: "1",
|
|
148
|
+
lam: "m"
|
|
149
|
+
}, "the grating equation"));
|
|
150
|
+
/** `I = I0 * cos(t)^2`, Malus's law for light through an analyser. */
|
|
151
|
+
const malusLaw = lazy(() => relation("I = I0 * cos(t)^2", {
|
|
152
|
+
I: "W/m^2",
|
|
153
|
+
I0: "W/m^2",
|
|
154
|
+
t: "rad"
|
|
155
|
+
}, "Malus's law"));
|
|
156
|
+
/** `v = f * lam`, the wave equation, which underlies all of the above. */
|
|
157
|
+
const waveEquation = lazy(() => relation("v = f * lam", {
|
|
158
|
+
v: "m/s",
|
|
159
|
+
f: "1/s",
|
|
160
|
+
lam: "m"
|
|
161
|
+
}, "the wave equation"));
|
|
162
|
+
/** `E = h * c / lam`, the energy of a photon of a given wavelength. */
|
|
163
|
+
const photonEnergyLaw = lazy(() => relation("E = h * c / lam", {
|
|
164
|
+
E: "J",
|
|
165
|
+
h: "J*s",
|
|
166
|
+
c: "m/s",
|
|
167
|
+
lam: "m"
|
|
168
|
+
}, "photon energy"));
|
|
169
|
+
/**
|
|
170
|
+
* Every declared optical law, for a gate that wants to walk them.
|
|
171
|
+
*
|
|
172
|
+
* Built on demand like the rest: touching this array declares all of them,
|
|
173
|
+
* which is exactly what a test that checks they all parse and balance wants,
|
|
174
|
+
* and exactly what a lesson importing one of them does not.
|
|
175
|
+
*/
|
|
176
|
+
const OPTICS_LAWS = () => [
|
|
177
|
+
snellsLaw(),
|
|
178
|
+
criticalAngleLaw(),
|
|
179
|
+
indexFromSpeed(),
|
|
180
|
+
apparentDepthLaw(),
|
|
181
|
+
brewstersLaw(),
|
|
182
|
+
thinLensEquation(),
|
|
183
|
+
mirrorEquation(),
|
|
184
|
+
magnificationLaw(),
|
|
185
|
+
lensPowerLaw(),
|
|
186
|
+
thinPrismLaw(),
|
|
187
|
+
fringeSpacingLaw(),
|
|
188
|
+
gratingLaw(),
|
|
189
|
+
malusLaw(),
|
|
190
|
+
waveEquation(),
|
|
191
|
+
photonEnergyLaw()
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
//#endregion
|
|
195
|
+
export { DEG, OPTICS_LAWS, apparentDepthLaw, brewstersLaw, criticalAngleLaw, fringeSpacingLaw, gratingLaw, indexFromSpeed, lensPowerLaw, magnificationLaw, malusLaw, mirrorEquation, photonEnergyLaw, snellsLaw, thinLensEquation, thinPrismLaw, waveEquation };
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
//#region src/optics/prism.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Prisms: deviation, minimum deviation, and dispersion.
|
|
4
|
+
*
|
|
5
|
+
* THE MODEL. A ray crossing both faces of a prism of apex angle A obeys two
|
|
6
|
+
* geometric identities and Snell's law twice:
|
|
7
|
+
*
|
|
8
|
+
* A = r₁ + r₂ the refraction angles inside sum to the apex
|
|
9
|
+
* δ = i₁ + i₂ − A the deviation is what the ray lost overall
|
|
10
|
+
*
|
|
11
|
+
* Deviation falls, bottoms out, and rises again as the ray is tilted. At the
|
|
12
|
+
* bottom the path is SYMMETRIC (i₁ = i₂, r₁ = r₂ = A/2), and that symmetry
|
|
13
|
+
* gives the measurement every refractometer is built on:
|
|
14
|
+
*
|
|
15
|
+
* n = sin((A + δ_min)/2) / sin(A/2)
|
|
16
|
+
*
|
|
17
|
+
* WHY THE MINIMUM EXISTS. δ is symmetric under swapping i₁ and i₂, because
|
|
18
|
+
* reversing a light path is always allowed. A smooth function symmetric about a
|
|
19
|
+
* point is stationary there, so the turning point is forced by reversibility
|
|
20
|
+
* rather than by any property of glass.
|
|
21
|
+
*
|
|
22
|
+
* WHERE ISOLATION RUNS OUT. Every relation above can be rearranged for any one
|
|
23
|
+
* of its variables except one: solving `n = sin((A+δm)/2)/sin(A/2)` for A is
|
|
24
|
+
* impossible by isolation, because A appears TWICE and the symbolic solver
|
|
25
|
+
* peels operations off a single occurrence. That is not a gap to paper over,
|
|
26
|
+
* it is the honest boundary of the method, so `prismAngleFromMinimumDeviation`
|
|
27
|
+
* brackets and bisects with the shared numeric root finder instead. It is the
|
|
28
|
+
* one function here that needs the maths engine rather than a formula.
|
|
29
|
+
*
|
|
30
|
+
* Angles in DEGREES throughout, matching `refraction.ts`.
|
|
31
|
+
*/
|
|
32
|
+
interface PrismPath {
|
|
33
|
+
/** Angle of incidence on the first face, degrees. */
|
|
34
|
+
incidenceDeg: number;
|
|
35
|
+
/** Refraction angle inside the first face, degrees. */
|
|
36
|
+
firstRefractionDeg: number;
|
|
37
|
+
/** Incidence angle on the second face from inside, degrees. */
|
|
38
|
+
secondRefractionDeg: number;
|
|
39
|
+
/** Emergence angle from the second face, degrees, or `null` if the ray never gets out. */
|
|
40
|
+
emergenceDeg: number | null;
|
|
41
|
+
/** Total deviation, degrees, or `null` when the ray is trapped. */
|
|
42
|
+
deviationDeg: number | null;
|
|
43
|
+
/**
|
|
44
|
+
* True when the ray hits the second face beyond the critical angle and
|
|
45
|
+
* reflects instead of emerging.
|
|
46
|
+
*
|
|
47
|
+
* Not an error: it is how a 45-45-90 prism turns light through a right angle
|
|
48
|
+
* in binoculars and periscopes, using total internal reflection rather than a
|
|
49
|
+
* silvered surface because it loses no light at all.
|
|
50
|
+
*/
|
|
51
|
+
totalInternalReflection: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Trace a ray through a prism from one angle of incidence.
|
|
55
|
+
*
|
|
56
|
+
* Returns the whole path rather than only the deviation, because a lab drawing
|
|
57
|
+
* the ray needs all four angles and recomputing them from the deviation is
|
|
58
|
+
* neither possible nor sensible.
|
|
59
|
+
*/
|
|
60
|
+
declare function prismPath(apexDeg: number, incidenceDeg: number, n: number, outsideIndex?: number): PrismPath;
|
|
61
|
+
/**
|
|
62
|
+
* The minimum deviation, degrees: δ_min = 2·asin(n·sin(A/2)) − A.
|
|
63
|
+
*
|
|
64
|
+
* From the symmetric path, so it needs no search. Throws when n·sin(A/2) > 1,
|
|
65
|
+
* which means the apex angle is too wide for any ray to get through this prism
|
|
66
|
+
* at all: see `maximumApexAngleDeg`.
|
|
67
|
+
*/
|
|
68
|
+
declare function minimumDeviationDeg(apexDeg: number, n: number): number;
|
|
69
|
+
/** The incidence angle that produces minimum deviation: i = (A + δ_min)/2. */
|
|
70
|
+
declare const minimumDeviationIncidenceDeg: (apexDeg: number, n: number) => number;
|
|
71
|
+
/**
|
|
72
|
+
* Refractive index from the prism formula: n = sin((A + δm)/2) / sin(A/2).
|
|
73
|
+
*
|
|
74
|
+
* The standard spectrometer measurement, and the most accurate way of getting a
|
|
75
|
+
* refractive index in a school laboratory, because both angles are read off one
|
|
76
|
+
* divided circle.
|
|
77
|
+
*/
|
|
78
|
+
declare function indexFromMinimumDeviation(apexDeg: number, minimumDeviation: number): number;
|
|
79
|
+
/**
|
|
80
|
+
* The apex angle that gives a stated minimum deviation for a known index.
|
|
81
|
+
*
|
|
82
|
+
* THE ONE THAT NEEDS THE NUMERIC SOLVER. A appears on both sides of
|
|
83
|
+
* n·sin(A/2) = sin((A + δm)/2), so it cannot be isolated; the shared
|
|
84
|
+
* bracket-and-bisect root finder from `math/analysis` does it instead. Kept as
|
|
85
|
+
* a real function rather than left to the caller because "what apex angle do I
|
|
86
|
+
* grind" is a genuine question and hand-solving it is a page of trigonometry.
|
|
87
|
+
*/
|
|
88
|
+
declare function prismAngleFromMinimumDeviation(minimumDeviation: number, n: number): number;
|
|
89
|
+
/**
|
|
90
|
+
* The widest apex angle a prism of this index can transmit: A_max = 2·C.
|
|
91
|
+
*
|
|
92
|
+
* Past it, r₂ = A − r₁ exceeds the critical angle for every possible r₁, so the
|
|
93
|
+
* ray is always trapped at the second face however it enters. It is why prisms
|
|
94
|
+
* are 60 degrees rather than 90.
|
|
95
|
+
*/
|
|
96
|
+
declare const maximumApexAngleDeg: (n: number) => number;
|
|
97
|
+
/**
|
|
98
|
+
* A thin prism's deviation: δ = (n − 1)·A.
|
|
99
|
+
*
|
|
100
|
+
* Valid for a few degrees of apex, where every sine may be replaced by its
|
|
101
|
+
* angle. Independent of the angle of incidence, which is exactly why thin
|
|
102
|
+
* prisms are the ones used in spectacles and in achromatic combinations: the
|
|
103
|
+
* deviation is a property of the prism rather than of how you hold it.
|
|
104
|
+
*/
|
|
105
|
+
declare function thinPrismDeviationDeg(apexDeg: number, n: number): number;
|
|
106
|
+
interface Dispersion {
|
|
107
|
+
/** Deviation of the violet end, degrees. */
|
|
108
|
+
violetDeviationDeg: number;
|
|
109
|
+
/** Deviation of the red end, degrees. */
|
|
110
|
+
redDeviationDeg: number;
|
|
111
|
+
/** Deviation of the mean (yellow) ray, degrees. */
|
|
112
|
+
meanDeviationDeg: number;
|
|
113
|
+
/** Angular dispersion, the spread between the ends: θ = δ_v − δ_r. */
|
|
114
|
+
angularDispersionDeg: number;
|
|
115
|
+
/**
|
|
116
|
+
* Dispersive power ω = (n_v − n_r)/(n_mean − 1), a pure number.
|
|
117
|
+
*
|
|
118
|
+
* A property of the MATERIAL alone, with the apex angle cancelled out, which
|
|
119
|
+
* is what makes it the right thing to tabulate and the right thing to combine
|
|
120
|
+
* when cancelling dispersion between two glasses.
|
|
121
|
+
*/
|
|
122
|
+
dispersivePower: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* A thin prism's dispersion, given the index at each end of the spectrum.
|
|
126
|
+
*
|
|
127
|
+
* Violet is deviated more than red because glass has a higher index for shorter
|
|
128
|
+
* wavelengths, and that single fact is the rainbow, the chromatic aberration
|
|
129
|
+
* that ruined early telescopes, and the reason a spectrometer works.
|
|
130
|
+
*
|
|
131
|
+
* `meanIndex` defaults to the average of the two, which is what a question that
|
|
132
|
+
* gives only the extremes intends.
|
|
133
|
+
*/
|
|
134
|
+
declare function dispersion(apexDeg: number, violetIndex: number, redIndex: number, meanIndex?: number): Dispersion;
|
|
135
|
+
/**
|
|
136
|
+
* The apex angle of a second prism that cancels the first's DISPERSION while
|
|
137
|
+
* leaving some deviation: an achromatic combination.
|
|
138
|
+
*
|
|
139
|
+
* A₂ = −A₁ · (n_v1 − n_r1) / (n_v2 − n_r2)
|
|
140
|
+
*
|
|
141
|
+
* Returned as a positive angle, with the understanding that the second prism is
|
|
142
|
+
* inverted relative to the first. Achromatic doublets in lenses are the same
|
|
143
|
+
* idea: pair a crown and a flint so their dispersions subtract and their
|
|
144
|
+
* powers do not.
|
|
145
|
+
*/
|
|
146
|
+
declare function achromaticApexDeg(apexDeg: number, violet1: number, red1: number, violet2: number, red2: number): number;
|
|
147
|
+
//#endregion
|
|
148
|
+
export { Dispersion, PrismPath, achromaticApexDeg, dispersion, indexFromMinimumDeviation, maximumApexAngleDeg, minimumDeviationDeg, minimumDeviationIncidenceDeg, prismAngleFromMinimumDeviation, prismPath, thinPrismDeviationDeg };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { roots } from "../math/analysis.mjs";
|
|
2
|
+
import { criticalAngleDeg, refract } from "./refraction.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/optics/prism.ts
|
|
5
|
+
/**
|
|
6
|
+
* Prisms: deviation, minimum deviation, and dispersion.
|
|
7
|
+
*
|
|
8
|
+
* THE MODEL. A ray crossing both faces of a prism of apex angle A obeys two
|
|
9
|
+
* geometric identities and Snell's law twice:
|
|
10
|
+
*
|
|
11
|
+
* A = r₁ + r₂ the refraction angles inside sum to the apex
|
|
12
|
+
* δ = i₁ + i₂ − A the deviation is what the ray lost overall
|
|
13
|
+
*
|
|
14
|
+
* Deviation falls, bottoms out, and rises again as the ray is tilted. At the
|
|
15
|
+
* bottom the path is SYMMETRIC (i₁ = i₂, r₁ = r₂ = A/2), and that symmetry
|
|
16
|
+
* gives the measurement every refractometer is built on:
|
|
17
|
+
*
|
|
18
|
+
* n = sin((A + δ_min)/2) / sin(A/2)
|
|
19
|
+
*
|
|
20
|
+
* WHY THE MINIMUM EXISTS. δ is symmetric under swapping i₁ and i₂, because
|
|
21
|
+
* reversing a light path is always allowed. A smooth function symmetric about a
|
|
22
|
+
* point is stationary there, so the turning point is forced by reversibility
|
|
23
|
+
* rather than by any property of glass.
|
|
24
|
+
*
|
|
25
|
+
* WHERE ISOLATION RUNS OUT. Every relation above can be rearranged for any one
|
|
26
|
+
* of its variables except one: solving `n = sin((A+δm)/2)/sin(A/2)` for A is
|
|
27
|
+
* impossible by isolation, because A appears TWICE and the symbolic solver
|
|
28
|
+
* peels operations off a single occurrence. That is not a gap to paper over,
|
|
29
|
+
* it is the honest boundary of the method, so `prismAngleFromMinimumDeviation`
|
|
30
|
+
* brackets and bisects with the shared numeric root finder instead. It is the
|
|
31
|
+
* one function here that needs the maths engine rather than a formula.
|
|
32
|
+
*
|
|
33
|
+
* Angles in DEGREES throughout, matching `refraction.ts`.
|
|
34
|
+
*/
|
|
35
|
+
const DEG = Math.PI / 180;
|
|
36
|
+
const toRad = (d) => d * DEG;
|
|
37
|
+
const toDeg = (r) => r / DEG;
|
|
38
|
+
const apex = (value) => {
|
|
39
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 180) throw new RangeError(`A prism's apex angle lies strictly between 0 and 180 degrees (got ${value}).`);
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
const index = (value, what = "A refractive index") => {
|
|
43
|
+
if (!Number.isFinite(value) || value < 1) throw new RangeError(`${what} must be at least 1 (got ${value}).`);
|
|
44
|
+
return value;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Trace a ray through a prism from one angle of incidence.
|
|
48
|
+
*
|
|
49
|
+
* Returns the whole path rather than only the deviation, because a lab drawing
|
|
50
|
+
* the ray needs all four angles and recomputing them from the deviation is
|
|
51
|
+
* neither possible nor sensible.
|
|
52
|
+
*/
|
|
53
|
+
function prismPath(apexDeg, incidenceDeg, n, outsideIndex = 1) {
|
|
54
|
+
const A = apex(apexDeg);
|
|
55
|
+
const nPrism = index(n, "The prism's refractive index");
|
|
56
|
+
const r1 = refract(incidenceDeg, outsideIndex, nPrism).refractionDeg;
|
|
57
|
+
const r2 = A - r1;
|
|
58
|
+
if (r2 < 0 || r2 > 90) return {
|
|
59
|
+
incidenceDeg,
|
|
60
|
+
firstRefractionDeg: r1,
|
|
61
|
+
secondRefractionDeg: r2,
|
|
62
|
+
emergenceDeg: null,
|
|
63
|
+
deviationDeg: null,
|
|
64
|
+
totalInternalReflection: true
|
|
65
|
+
};
|
|
66
|
+
const second = refract(r2, nPrism, outsideIndex);
|
|
67
|
+
if (second.totalInternalReflection || second.refractionDeg === null) return {
|
|
68
|
+
incidenceDeg,
|
|
69
|
+
firstRefractionDeg: r1,
|
|
70
|
+
secondRefractionDeg: r2,
|
|
71
|
+
emergenceDeg: null,
|
|
72
|
+
deviationDeg: null,
|
|
73
|
+
totalInternalReflection: true
|
|
74
|
+
};
|
|
75
|
+
const i2 = second.refractionDeg;
|
|
76
|
+
return {
|
|
77
|
+
incidenceDeg,
|
|
78
|
+
firstRefractionDeg: r1,
|
|
79
|
+
secondRefractionDeg: r2,
|
|
80
|
+
emergenceDeg: i2,
|
|
81
|
+
deviationDeg: incidenceDeg + i2 - A,
|
|
82
|
+
totalInternalReflection: false
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The minimum deviation, degrees: δ_min = 2·asin(n·sin(A/2)) − A.
|
|
87
|
+
*
|
|
88
|
+
* From the symmetric path, so it needs no search. Throws when n·sin(A/2) > 1,
|
|
89
|
+
* which means the apex angle is too wide for any ray to get through this prism
|
|
90
|
+
* at all: see `maximumApexAngleDeg`.
|
|
91
|
+
*/
|
|
92
|
+
function minimumDeviationDeg(apexDeg, n) {
|
|
93
|
+
const A = apex(apexDeg);
|
|
94
|
+
const nPrism = index(n, "The prism's refractive index");
|
|
95
|
+
const s = nPrism * Math.sin(toRad(A / 2));
|
|
96
|
+
if (s > 1) throw new RangeError(`No ray can pass a prism of apex ${A} degrees with n = ${nPrism}: every ray is totally internally reflected at the second face. The limit is ${maximumApexAngleDeg(nPrism).toFixed(1)} degrees.`);
|
|
97
|
+
return 2 * toDeg(Math.asin(s)) - A;
|
|
98
|
+
}
|
|
99
|
+
/** The incidence angle that produces minimum deviation: i = (A + δ_min)/2. */
|
|
100
|
+
const minimumDeviationIncidenceDeg = (apexDeg, n) => (apex(apexDeg) + minimumDeviationDeg(apexDeg, n)) / 2;
|
|
101
|
+
/**
|
|
102
|
+
* Refractive index from the prism formula: n = sin((A + δm)/2) / sin(A/2).
|
|
103
|
+
*
|
|
104
|
+
* The standard spectrometer measurement, and the most accurate way of getting a
|
|
105
|
+
* refractive index in a school laboratory, because both angles are read off one
|
|
106
|
+
* divided circle.
|
|
107
|
+
*/
|
|
108
|
+
function indexFromMinimumDeviation(apexDeg, minimumDeviation) {
|
|
109
|
+
const A = apex(apexDeg);
|
|
110
|
+
if (!Number.isFinite(minimumDeviation) || minimumDeviation < 0) throw new RangeError("A minimum deviation cannot be negative.");
|
|
111
|
+
return Math.sin(toRad((A + minimumDeviation) / 2)) / Math.sin(toRad(A / 2));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The apex angle that gives a stated minimum deviation for a known index.
|
|
115
|
+
*
|
|
116
|
+
* THE ONE THAT NEEDS THE NUMERIC SOLVER. A appears on both sides of
|
|
117
|
+
* n·sin(A/2) = sin((A + δm)/2), so it cannot be isolated; the shared
|
|
118
|
+
* bracket-and-bisect root finder from `math/analysis` does it instead. Kept as
|
|
119
|
+
* a real function rather than left to the caller because "what apex angle do I
|
|
120
|
+
* grind" is a genuine question and hand-solving it is a page of trigonometry.
|
|
121
|
+
*/
|
|
122
|
+
function prismAngleFromMinimumDeviation(minimumDeviation, n) {
|
|
123
|
+
const dm = minimumDeviation;
|
|
124
|
+
const nPrism = index(n, "The prism's refractive index");
|
|
125
|
+
if (!Number.isFinite(dm) || dm <= 0) throw new RangeError("The minimum deviation must be positive.");
|
|
126
|
+
const residual = (A) => Math.sin(toRad((A + dm) / 2)) - nPrism * Math.sin(toRad(A / 2));
|
|
127
|
+
const found = roots(residual, .5, 179.5, {
|
|
128
|
+
steps: 720,
|
|
129
|
+
tol: 1e-12
|
|
130
|
+
});
|
|
131
|
+
if (found.length === 0) throw new RangeError(`No prism of index ${nPrism} has a minimum deviation of ${dm} degrees.`);
|
|
132
|
+
return found[0];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The widest apex angle a prism of this index can transmit: A_max = 2·C.
|
|
136
|
+
*
|
|
137
|
+
* Past it, r₂ = A − r₁ exceeds the critical angle for every possible r₁, so the
|
|
138
|
+
* ray is always trapped at the second face however it enters. It is why prisms
|
|
139
|
+
* are 60 degrees rather than 90.
|
|
140
|
+
*/
|
|
141
|
+
const maximumApexAngleDeg = (n) => 2 * criticalAngleDeg(index(n));
|
|
142
|
+
/**
|
|
143
|
+
* A thin prism's deviation: δ = (n − 1)·A.
|
|
144
|
+
*
|
|
145
|
+
* Valid for a few degrees of apex, where every sine may be replaced by its
|
|
146
|
+
* angle. Independent of the angle of incidence, which is exactly why thin
|
|
147
|
+
* prisms are the ones used in spectacles and in achromatic combinations: the
|
|
148
|
+
* deviation is a property of the prism rather than of how you hold it.
|
|
149
|
+
*/
|
|
150
|
+
function thinPrismDeviationDeg(apexDeg, n) {
|
|
151
|
+
return (index(n, "The prism's refractive index") - 1) * apex(apexDeg);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* A thin prism's dispersion, given the index at each end of the spectrum.
|
|
155
|
+
*
|
|
156
|
+
* Violet is deviated more than red because glass has a higher index for shorter
|
|
157
|
+
* wavelengths, and that single fact is the rainbow, the chromatic aberration
|
|
158
|
+
* that ruined early telescopes, and the reason a spectrometer works.
|
|
159
|
+
*
|
|
160
|
+
* `meanIndex` defaults to the average of the two, which is what a question that
|
|
161
|
+
* gives only the extremes intends.
|
|
162
|
+
*/
|
|
163
|
+
function dispersion(apexDeg, violetIndex, redIndex, meanIndex = (violetIndex + redIndex) / 2) {
|
|
164
|
+
const A = apex(apexDeg);
|
|
165
|
+
const nv = index(violetIndex, "The violet refractive index");
|
|
166
|
+
const nr = index(redIndex, "The red refractive index");
|
|
167
|
+
const nm = index(meanIndex, "The mean refractive index");
|
|
168
|
+
if (nv < nr) throw new RangeError("Violet is refracted MORE than red in every ordinary transparent material, so the violet index cannot be the smaller one.");
|
|
169
|
+
const meanDeviationDeg = (nm - 1) * A;
|
|
170
|
+
if (nm === 1) throw new RangeError("A medium of index 1 deviates nothing, so it has no dispersive power.");
|
|
171
|
+
return {
|
|
172
|
+
violetDeviationDeg: (nv - 1) * A,
|
|
173
|
+
redDeviationDeg: (nr - 1) * A,
|
|
174
|
+
meanDeviationDeg,
|
|
175
|
+
angularDispersionDeg: (nv - nr) * A,
|
|
176
|
+
dispersivePower: (nv - nr) / (nm - 1)
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The apex angle of a second prism that cancels the first's DISPERSION while
|
|
181
|
+
* leaving some deviation: an achromatic combination.
|
|
182
|
+
*
|
|
183
|
+
* A₂ = −A₁ · (n_v1 − n_r1) / (n_v2 − n_r2)
|
|
184
|
+
*
|
|
185
|
+
* Returned as a positive angle, with the understanding that the second prism is
|
|
186
|
+
* inverted relative to the first. Achromatic doublets in lenses are the same
|
|
187
|
+
* idea: pair a crown and a flint so their dispersions subtract and their
|
|
188
|
+
* powers do not.
|
|
189
|
+
*/
|
|
190
|
+
function achromaticApexDeg(apexDeg, violet1, red1, violet2, red2) {
|
|
191
|
+
const spread2 = index(violet2, "The second violet index") - index(red2, "The second red index");
|
|
192
|
+
if (spread2 === 0) throw new RangeError("The second prism has no dispersion, so it cannot cancel any.");
|
|
193
|
+
return apex(apexDeg) * (index(violet1, "The first violet index") - index(red1, "The first red index")) / spread2;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
//#endregion
|
|
197
|
+
export { achromaticApexDeg, dispersion, indexFromMinimumDeviation, maximumApexAngleDeg, minimumDeviationDeg, minimumDeviationIncidenceDeg, prismAngleFromMinimumDeviation, prismPath, thinPrismDeviationDeg };
|