@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.
Files changed (431) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/atomic/aufbau.d.mts +144 -0
  3. package/dist/atomic/aufbau.mjs +384 -0
  4. package/dist/atomic/elements.d.mts +67 -0
  5. package/dist/atomic/elements.mjs +785 -0
  6. package/dist/atomic/emission.d.mts +112 -0
  7. package/dist/atomic/emission.mjs +179 -0
  8. package/dist/atomic/index.d.mts +8 -0
  9. package/dist/atomic/index.mjs +9 -0
  10. package/dist/atomic/periodic.d.mts +82 -0
  11. package/dist/atomic/periodic.mjs +231 -0
  12. package/dist/atomic/properties.d.mts +100 -0
  13. package/dist/atomic/properties.mjs +574 -0
  14. package/dist/atomic/shells.d.mts +137 -0
  15. package/dist/atomic/shells.mjs +170 -0
  16. package/dist/atomic/trends.d.mts +148 -0
  17. package/dist/atomic/trends.mjs +225 -0
  18. package/dist/chem/chromatography.d.mts +66 -0
  19. package/dist/chem/chromatography.mjs +63 -0
  20. package/dist/chem/complex.d.mts +114 -0
  21. package/dist/chem/complex.mjs +234 -0
  22. package/dist/chem/cycle.d.mts +75 -0
  23. package/dist/chem/cycle.mjs +145 -0
  24. package/dist/chem/equation.d.mts +86 -0
  25. package/dist/chem/equation.mjs +168 -0
  26. package/dist/chem/formula.d.mts +90 -0
  27. package/dist/chem/formula.mjs +201 -0
  28. package/dist/chem/functional-groups.d.mts +31 -0
  29. package/dist/chem/functional-groups.mjs +187 -0
  30. package/dist/chem/hazard.d.mts +94 -0
  31. package/dist/chem/hazard.mjs +329 -0
  32. package/dist/chem/index.d.mts +34 -33
  33. package/dist/chem/index.mjs +34 -28
  34. package/dist/chem/ionic.d.mts +98 -0
  35. package/dist/chem/ionic.mjs +156 -0
  36. package/dist/chem/layout.d.mts +46 -0
  37. package/dist/chem/layout.mjs +342 -0
  38. package/dist/chem/lewis.d.mts +79 -0
  39. package/dist/chem/lewis.mjs +163 -0
  40. package/dist/chem/molecular-orbital.d.mts +114 -0
  41. package/dist/chem/molecular-orbital.mjs +201 -0
  42. package/dist/chem/molecule.d.mts +154 -0
  43. package/dist/chem/molecule.mjs +282 -0
  44. package/dist/chem/nmr.d.mts +153 -0
  45. package/dist/chem/nmr.mjs +165 -0
  46. package/dist/chem/polymer.d.mts +65 -0
  47. package/dist/chem/polymer.mjs +179 -0
  48. package/dist/chem/redox.d.mts +138 -0
  49. package/dist/chem/redox.mjs +328 -0
  50. package/dist/chem/relations.d.mts +183 -0
  51. package/dist/chem/relations.mjs +299 -0
  52. package/dist/chem/skeleton.d.mts +51 -0
  53. package/dist/chem/skeleton.mjs +186 -0
  54. package/dist/chem/solution.d.mts +116 -0
  55. package/dist/chem/solution.mjs +186 -0
  56. package/dist/chem/species.d.mts +47 -0
  57. package/dist/chem/species.mjs +128 -0
  58. package/dist/chem/stereo.d.mts +108 -0
  59. package/dist/chem/stereo.mjs +286 -0
  60. package/dist/chem/stoichiometry.d.mts +95 -0
  61. package/dist/chem/stoichiometry.mjs +145 -0
  62. package/dist/chem/synthesis.d.mts +113 -0
  63. package/dist/chem/synthesis.mjs +281 -0
  64. package/dist/chem/vsepr.d.mts +80 -0
  65. package/dist/chem/vsepr.mjs +247 -0
  66. package/dist/circuit/ac.d.mts +163 -0
  67. package/dist/circuit/ac.mjs +452 -0
  68. package/dist/circuit/dc.d.mts +92 -0
  69. package/dist/circuit/dc.mjs +333 -0
  70. package/dist/circuit/index.d.mts +5 -92
  71. package/dist/circuit/index.mjs +5 -332
  72. package/dist/circuit/network.d.mts +99 -0
  73. package/dist/circuit/network.mjs +440 -0
  74. package/dist/circuit/topology.d.mts +102 -0
  75. package/dist/circuit/topology.mjs +143 -0
  76. package/dist/colour/absorption.d.mts +79 -0
  77. package/dist/colour/absorption.mjs +137 -0
  78. package/dist/colour/index.d.mts +6 -0
  79. package/dist/colour/index.mjs +7 -0
  80. package/dist/colour/name.d.mts +14 -0
  81. package/dist/colour/name.mjs +76 -0
  82. package/dist/colour/observer.d.mts +31 -0
  83. package/dist/colour/observer.mjs +46 -0
  84. package/dist/colour/spectrum.d.mts +61 -0
  85. package/dist/colour/spectrum.mjs +108 -0
  86. package/dist/colour/srgb.d.mts +49 -0
  87. package/dist/colour/srgb.mjs +108 -0
  88. package/dist/core/constants.d.mts +138 -0
  89. package/dist/core/constants.mjs +139 -0
  90. package/dist/core/index.d.mts +3 -1
  91. package/dist/core/index.mjs +3 -1
  92. package/dist/core/vec3.d.mts +94 -0
  93. package/dist/core/vec3.mjs +123 -0
  94. package/dist/core/worked.d.mts +35 -0
  95. package/dist/core/worked.mjs +44 -0
  96. package/dist/electro/cell.d.mts +102 -0
  97. package/dist/electro/cell.mjs +170 -0
  98. package/dist/electro/conductivity.d.mts +157 -0
  99. package/dist/electro/conductivity.mjs +156 -0
  100. package/dist/electro/couples.d.mts +114 -0
  101. package/dist/electro/couples.mjs +334 -0
  102. package/dist/electro/electrolysis.d.mts +96 -0
  103. package/dist/electro/electrolysis.mjs +274 -0
  104. package/dist/electro/faraday.d.mts +150 -0
  105. package/dist/electro/faraday.mjs +118 -0
  106. package/dist/electro/index.d.mts +6 -0
  107. package/dist/electro/index.mjs +7 -0
  108. package/dist/finance/accounting/adjustments.d.mts +17 -0
  109. package/dist/finance/accounting/adjustments.mjs +202 -0
  110. package/dist/finance/accounting/analysis.d.mts +8 -0
  111. package/dist/finance/accounting/analysis.mjs +205 -0
  112. package/dist/finance/accounting/clubs.d.mts +21 -0
  113. package/dist/finance/accounting/clubs.mjs +217 -0
  114. package/dist/finance/accounting/company-statements.d.mts +7 -0
  115. package/dist/finance/accounting/company-statements.mjs +150 -0
  116. package/dist/finance/accounting/harness.d.mts +7 -0
  117. package/dist/finance/accounting/harness.mjs +45 -0
  118. package/dist/finance/accounting/index.d.mts +18 -0
  119. package/dist/finance/accounting/index.mjs +18 -0
  120. package/dist/finance/accounting/journalize.d.mts +16 -0
  121. package/dist/finance/accounting/journalize.mjs +128 -0
  122. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  123. package/dist/finance/accounting/manufacturing.mjs +236 -0
  124. package/dist/finance/accounting/partnership.d.mts +7 -0
  125. package/dist/finance/accounting/partnership.mjs +152 -0
  126. package/dist/finance/accounting/period-case.d.mts +6 -0
  127. package/dist/finance/accounting/period-case.mjs +71 -0
  128. package/dist/finance/accounting/post.d.mts +9 -0
  129. package/dist/finance/accounting/post.mjs +84 -0
  130. package/dist/finance/accounting/precision.d.mts +9 -0
  131. package/dist/finance/accounting/precision.mjs +15 -0
  132. package/dist/finance/accounting/rules.d.mts +21 -0
  133. package/dist/finance/accounting/rules.mjs +37 -0
  134. package/dist/finance/accounting/solve.d.mts +28 -0
  135. package/dist/finance/accounting/solve.mjs +92 -0
  136. package/dist/finance/accounting/statements.d.mts +7 -0
  137. package/dist/finance/accounting/statements.mjs +142 -0
  138. package/dist/finance/accounting/types.d.mts +649 -0
  139. package/dist/finance/accounting/validate.d.mts +7 -0
  140. package/dist/finance/accounting/validate.mjs +67 -0
  141. package/dist/finance/accounting/verification.d.mts +24 -0
  142. package/dist/finance/accounting/verification.mjs +386 -0
  143. package/dist/finance/bizsim.d.mts +21 -39
  144. package/dist/finance/bizsim.mjs +276 -97
  145. package/dist/finance/index.d.mts +20 -43
  146. package/dist/finance/index.mjs +19 -77
  147. package/dist/finance/investment-math.d.mts +7 -0
  148. package/dist/finance/investment-math.mjs +18 -0
  149. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  150. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  151. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  152. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  153. package/dist/finance/management-accounting/costing.d.mts +8 -0
  154. package/dist/finance/management-accounting/costing.mjs +175 -0
  155. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  156. package/dist/finance/management-accounting/decisions.mjs +164 -0
  157. package/dist/finance/management-accounting/index.d.mts +13 -0
  158. package/dist/finance/management-accounting/index.mjs +13 -0
  159. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  160. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  161. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  162. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  163. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  164. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  165. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  166. package/dist/finance/management-accounting/management-case.mjs +91 -0
  167. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  168. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  169. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  170. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  171. package/dist/finance/management-accounting/types.d.mts +644 -0
  172. package/dist/finance/management-accounting/variances.d.mts +7 -0
  173. package/dist/finance/management-accounting/variances.mjs +150 -0
  174. package/dist/index.d.mts +6 -6
  175. package/dist/index.mjs +1 -1
  176. package/dist/math/analysis.d.mts +61 -0
  177. package/dist/math/analysis.mjs +187 -0
  178. package/dist/math/answer-check.d.mts +50 -0
  179. package/dist/math/answer-check.mjs +106 -0
  180. package/dist/math/calculus.d.mts +4 -9
  181. package/dist/math/calculus.mjs +216 -7
  182. package/dist/math/complex.d.mts +93 -0
  183. package/dist/math/complex.mjs +239 -0
  184. package/dist/math/expr.d.mts +23 -0
  185. package/dist/math/expr.mjs +36 -0
  186. package/dist/math/index.d.mts +8 -22
  187. package/dist/math/index.mjs +8 -37
  188. package/dist/math/latex.mjs +2 -1
  189. package/dist/math/parse.mjs +1 -1
  190. package/dist/math/poly.d.mts +55 -0
  191. package/dist/math/poly.mjs +273 -0
  192. package/dist/math/rearrange.d.mts +14 -0
  193. package/dist/math/rearrange.mjs +125 -0
  194. package/dist/math/solve.d.mts +21 -0
  195. package/dist/math/solve.mjs +75 -0
  196. package/dist/networking/addressing.d.mts +26 -0
  197. package/dist/networking/addressing.mjs +33 -0
  198. package/dist/networking/cloud/access.d.mts +36 -0
  199. package/dist/networking/cloud/access.mjs +95 -0
  200. package/dist/networking/cloud/containers.d.mts +43 -0
  201. package/dist/networking/cloud/containers.mjs +54 -0
  202. package/dist/networking/cloud/edge.d.mts +17 -0
  203. package/dist/networking/cloud/edge.mjs +31 -0
  204. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  205. package/dist/networking/cloud/failure-domains.mjs +22 -0
  206. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  207. package/dist/networking/cloud/geo-routing.mjs +64 -0
  208. package/dist/networking/cloud/index.d.mts +18 -0
  209. package/dist/networking/cloud/index.mjs +19 -0
  210. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  211. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  212. package/dist/networking/cloud/inference.d.mts +118 -0
  213. package/dist/networking/cloud/inference.mjs +179 -0
  214. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  215. package/dist/networking/cloud/infrastructure.mjs +96 -0
  216. package/dist/networking/cloud/observability.d.mts +24 -0
  217. package/dist/networking/cloud/observability.mjs +34 -0
  218. package/dist/networking/cloud/orchestration.d.mts +32 -0
  219. package/dist/networking/cloud/orchestration.mjs +38 -0
  220. package/dist/networking/cloud/recovery.d.mts +21 -0
  221. package/dist/networking/cloud/recovery.mjs +27 -0
  222. package/dist/networking/cloud/releases.d.mts +42 -0
  223. package/dist/networking/cloud/releases.mjs +135 -0
  224. package/dist/networking/cloud/scaling.d.mts +25 -0
  225. package/dist/networking/cloud/scaling.mjs +65 -0
  226. package/dist/networking/cloud/secrets.d.mts +39 -0
  227. package/dist/networking/cloud/secrets.mjs +68 -0
  228. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  229. package/dist/networking/cloud/server-deployment.mjs +72 -0
  230. package/dist/networking/cloud/storage.d.mts +16 -0
  231. package/dist/networking/cloud/storage.mjs +58 -0
  232. package/dist/networking/cloud/vpc.d.mts +18 -0
  233. package/dist/networking/cloud/vpc.mjs +100 -0
  234. package/dist/networking/delivery.d.mts +34 -0
  235. package/dist/networking/delivery.mjs +52 -0
  236. package/dist/networking/index.d.mts +47 -0
  237. package/dist/networking/index.mjs +47 -0
  238. package/dist/networking/ipv6.d.mts +28 -0
  239. package/dist/networking/ipv6.mjs +17 -0
  240. package/dist/networking/journeys.d.mts +83 -0
  241. package/dist/networking/journeys.mjs +161 -0
  242. package/dist/networking/models/airtime.d.mts +87 -0
  243. package/dist/networking/models/airtime.mjs +130 -0
  244. package/dist/networking/models/cellular.d.mts +157 -0
  245. package/dist/networking/models/cellular.mjs +252 -0
  246. package/dist/networking/models/encapsulation.d.mts +98 -0
  247. package/dist/networking/models/encapsulation.mjs +132 -0
  248. package/dist/networking/models/handover.d.mts +116 -0
  249. package/dist/networking/models/handover.mjs +209 -0
  250. package/dist/networking/models/handshake.d.mts +90 -0
  251. package/dist/networking/models/handshake.mjs +122 -0
  252. package/dist/networking/models/index.d.mts +14 -0
  253. package/dist/networking/models/index.mjs +15 -0
  254. package/dist/networking/models/media.d.mts +82 -0
  255. package/dist/networking/models/media.mjs +188 -0
  256. package/dist/networking/models/satellite.d.mts +86 -0
  257. package/dist/networking/models/satellite.mjs +121 -0
  258. package/dist/networking/models/spectrum.d.mts +83 -0
  259. package/dist/networking/models/spectrum.mjs +235 -0
  260. package/dist/networking/models/switch.d.mts +80 -0
  261. package/dist/networking/models/switch.mjs +155 -0
  262. package/dist/networking/models/vlan.d.mts +62 -0
  263. package/dist/networking/models/vlan.mjs +100 -0
  264. package/dist/networking/models/vpn.d.mts +66 -0
  265. package/dist/networking/models/vpn.mjs +125 -0
  266. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  267. package/dist/networking/models/wifi-privacy.mjs +130 -0
  268. package/dist/networking/models/wifi.d.mts +240 -0
  269. package/dist/networking/models/wifi.mjs +562 -0
  270. package/dist/networking/nat-traversal.d.mts +24 -0
  271. package/dist/networking/nat-traversal.mjs +38 -0
  272. package/dist/networking/protocols.d.mts +17 -0
  273. package/dist/networking/protocols.mjs +57 -0
  274. package/dist/networking/queue.d.mts +12 -0
  275. package/dist/networking/queue.mjs +18 -0
  276. package/dist/networking/route-learning.d.mts +23 -0
  277. package/dist/networking/route-learning.mjs +43 -0
  278. package/dist/networking/routing.d.mts +11 -0
  279. package/dist/networking/routing.mjs +25 -0
  280. package/dist/networking/signals.d.mts +26 -0
  281. package/dist/networking/signals.mjs +35 -0
  282. package/dist/networking/subnet.d.mts +49 -0
  283. package/dist/networking/subnet.mjs +89 -0
  284. package/dist/networking/tcp-reliability.d.mts +24 -0
  285. package/dist/networking/tcp-reliability.mjs +38 -0
  286. package/dist/networking/topology/contract.d.mts +123 -0
  287. package/dist/networking/topology/index.d.mts +4 -0
  288. package/dist/networking/topology/index.mjs +4 -0
  289. package/dist/networking/topology/presets.d.mts +7 -0
  290. package/dist/networking/topology/presets.mjs +302 -0
  291. package/dist/networking/topology/simulation.d.mts +8 -0
  292. package/dist/networking/topology/simulation.mjs +179 -0
  293. package/dist/networking/wireless.d.mts +11 -0
  294. package/dist/networking/wireless.mjs +17 -0
  295. package/dist/optics/imaging.d.mts +218 -0
  296. package/dist/optics/imaging.mjs +276 -0
  297. package/dist/optics/index.d.mts +7 -0
  298. package/dist/optics/index.mjs +8 -0
  299. package/dist/optics/laws.d.mts +70 -0
  300. package/dist/optics/laws.mjs +195 -0
  301. package/dist/optics/prism.d.mts +148 -0
  302. package/dist/optics/prism.mjs +197 -0
  303. package/dist/optics/refraction.d.mts +201 -0
  304. package/dist/optics/refraction.mjs +270 -0
  305. package/dist/optics/wave-optics.d.mts +171 -0
  306. package/dist/optics/wave-optics.mjs +259 -0
  307. package/dist/physics/ac/index.d.mts +183 -0
  308. package/dist/physics/ac/index.mjs +203 -0
  309. package/dist/physics/dynamics/forces.d.mts +98 -0
  310. package/dist/physics/dynamics/forces.mjs +153 -0
  311. package/dist/physics/dynamics/friction.d.mts +76 -0
  312. package/dist/physics/dynamics/friction.mjs +119 -0
  313. package/dist/physics/dynamics/system.d.mts +68 -0
  314. package/dist/physics/dynamics/system.mjs +125 -0
  315. package/dist/physics/electrostatics/index.d.mts +169 -0
  316. package/dist/physics/electrostatics/index.mjs +249 -0
  317. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  318. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  319. package/dist/physics/energy/conservation.d.mts +81 -0
  320. package/dist/physics/energy/conservation.mjs +129 -0
  321. package/dist/physics/energy/power.d.mts +90 -0
  322. package/dist/physics/energy/power.mjs +167 -0
  323. package/dist/physics/energy/spring.d.mts +73 -0
  324. package/dist/physics/energy/spring.mjs +129 -0
  325. package/dist/physics/energy/store.d.mts +63 -0
  326. package/dist/physics/energy/store.mjs +108 -0
  327. package/dist/physics/energy/theorem.d.mts +65 -0
  328. package/dist/physics/energy/theorem.mjs +113 -0
  329. package/dist/physics/energy/work.d.mts +114 -0
  330. package/dist/physics/energy/work.mjs +219 -0
  331. package/dist/physics/gravitation/body.d.mts +85 -0
  332. package/dist/physics/gravitation/body.mjs +168 -0
  333. package/dist/physics/gravitation/kepler.d.mts +127 -0
  334. package/dist/physics/gravitation/kepler.mjs +216 -0
  335. package/dist/physics/gravitation/law.d.mts +117 -0
  336. package/dist/physics/gravitation/law.mjs +175 -0
  337. package/dist/physics/gravitation/orbit.d.mts +119 -0
  338. package/dist/physics/gravitation/orbit.mjs +202 -0
  339. package/dist/physics/gravitation/potential.d.mts +114 -0
  340. package/dist/physics/gravitation/potential.mjs +202 -0
  341. package/dist/physics/gravitation/variation.d.mts +97 -0
  342. package/dist/physics/gravitation/variation.mjs +175 -0
  343. package/dist/physics/index.d.mts +35 -0
  344. package/dist/physics/index.mjs +36 -0
  345. package/dist/physics/integral-sweep.d.mts +63 -0
  346. package/dist/physics/integral-sweep.mjs +126 -0
  347. package/dist/physics/kinematics/equations.d.mts +47 -0
  348. package/dist/physics/kinematics/equations.mjs +126 -0
  349. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  350. package/dist/physics/kinematics/free-fall.mjs +71 -0
  351. package/dist/physics/kinematics/given.d.mts +16 -0
  352. package/dist/physics/kinematics/given.mjs +55 -0
  353. package/dist/physics/kinematics/roots.d.mts +41 -0
  354. package/dist/physics/kinematics/roots.mjs +72 -0
  355. package/dist/physics/kinematics/solve.d.mts +52 -0
  356. package/dist/physics/kinematics/solve.mjs +172 -0
  357. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  358. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  359. package/dist/physics/magnetism/flux.d.mts +94 -0
  360. package/dist/physics/magnetism/flux.mjs +313 -0
  361. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  362. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  363. package/dist/physics/magnetism/index.d.mts +12 -0
  364. package/dist/physics/magnetism/index.mjs +74 -0
  365. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  366. package/dist/physics/magnetism/lorentz.mjs +88 -0
  367. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  368. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  369. package/dist/physics/momentum/collide.d.mts +77 -0
  370. package/dist/physics/momentum/collide.mjs +115 -0
  371. package/dist/physics/momentum/impulse.d.mts +89 -0
  372. package/dist/physics/momentum/impulse.mjs +159 -0
  373. package/dist/physics/momentum/planar.d.mts +60 -0
  374. package/dist/physics/momentum/planar.mjs +110 -0
  375. package/dist/physics/projectile.d.mts +107 -0
  376. package/dist/physics/projectile.mjs +185 -0
  377. package/dist/physics/rotation/angular.d.mts +85 -0
  378. package/dist/physics/rotation/angular.mjs +130 -0
  379. package/dist/physics/rotation/circular.d.mts +79 -0
  380. package/dist/physics/rotation/circular.mjs +131 -0
  381. package/dist/physics/rotation/inertia.d.mts +164 -0
  382. package/dist/physics/rotation/inertia.mjs +332 -0
  383. package/dist/physics/rotation/torque.d.mts +65 -0
  384. package/dist/physics/rotation/torque.mjs +134 -0
  385. package/dist/physics/vectors.d.mts +64 -0
  386. package/dist/physics/vectors.mjs +114 -0
  387. package/dist/quantity/index.d.mts +119 -0
  388. package/dist/quantity/index.mjs +417 -0
  389. package/dist/relation/derive.d.mts +74 -0
  390. package/dist/relation/derive.mjs +73 -0
  391. package/dist/relation/index.d.mts +56 -0
  392. package/dist/relation/index.mjs +234 -0
  393. package/dist/scene/evaluators.mjs +1 -1
  394. package/dist/sim/thermal.mjs +45 -20
  395. package/dist/thermo/calorimetry.d.mts +207 -0
  396. package/dist/thermo/calorimetry.mjs +345 -0
  397. package/dist/thermo/cycles.d.mts +142 -0
  398. package/dist/thermo/cycles.mjs +256 -0
  399. package/dist/thermo/entropy.d.mts +87 -0
  400. package/dist/thermo/entropy.mjs +140 -0
  401. package/dist/thermo/expansion.d.mts +130 -0
  402. package/dist/thermo/expansion.mjs +178 -0
  403. package/dist/thermo/gas.d.mts +197 -0
  404. package/dist/thermo/gas.mjs +279 -0
  405. package/dist/thermo/heat-transfer.d.mts +164 -0
  406. package/dist/thermo/heat-transfer.mjs +217 -0
  407. package/dist/thermo/index.d.mts +9 -82
  408. package/dist/thermo/index.mjs +9 -132
  409. package/dist/thermo/processes.d.mts +95 -0
  410. package/dist/thermo/processes.mjs +154 -0
  411. package/dist/thermo/temperature.d.mts +174 -0
  412. package/dist/thermo/temperature.mjs +236 -0
  413. package/dist/waves/damping.d.mts +224 -0
  414. package/dist/waves/damping.mjs +317 -0
  415. package/dist/waves/doppler.d.mts +72 -0
  416. package/dist/waves/doppler.mjs +125 -0
  417. package/dist/waves/index.d.mts +10 -0
  418. package/dist/waves/index.mjs +10 -0
  419. package/dist/waves/pendulum.d.mts +130 -0
  420. package/dist/waves/pendulum.mjs +211 -0
  421. package/dist/waves/pitch.d.mts +125 -0
  422. package/dist/waves/pitch.mjs +158 -0
  423. package/dist/waves/shm.d.mts +170 -0
  424. package/dist/waves/shm.mjs +279 -0
  425. package/dist/waves/springs.d.mts +103 -0
  426. package/dist/waves/springs.mjs +176 -0
  427. package/dist/waves/superposition.d.mts +124 -0
  428. package/dist/waves/superposition.mjs +196 -0
  429. package/dist/waves/wave.d.mts +154 -0
  430. package/dist/waves/wave.mjs +178 -0
  431. package/package.json +74 -2
@@ -0,0 +1,201 @@
1
+ //#region src/optics/refraction.d.ts
2
+ /**
3
+ * Refraction: light crossing a boundary, and everything that follows from it.
4
+ *
5
+ * THE MODEL. One law does the whole of this file:
6
+ *
7
+ * n₁ sin θ₁ = n₂ sin θ₂ (Snell)
8
+ *
9
+ * with n = c/v, the factor by which a medium slows light down. Written that way
10
+ * rather than as a pair of "denser/rarer" rules, because the symmetry is the
11
+ * point: reverse the ray and the same equation describes it, which is why a
12
+ * critical angle exists at all and why it exists only going the other way.
13
+ *
14
+ * WHAT SNELL'S LAW RETURNS WHEN THERE IS NO ANSWER. Solving for θ₂ needs
15
+ * arcsin((n₁/n₂)·sin θ₁), and past the critical angle that argument exceeds 1.
16
+ * That is not a numerical accident to be clamped away: it is TOTAL INTERNAL
17
+ * REFLECTION, the physical statement that no refracted ray exists. So
18
+ * `refractAngleDeg` returns `null` rather than NaN or a clamped 90 degrees, and
19
+ * `refract` returns a result that says which case happened. A clamp here would
20
+ * draw a refracted ray grazing along the surface forever, which is a picture of
21
+ * something that does not happen.
22
+ *
23
+ * ANGLES ARE IN DEGREES at this boundary, because every syllabus, every
24
+ * protractor and every worked answer is, and a kernel that took radians would
25
+ * push a conversion into every single call site. Internally it converts once.
26
+ *
27
+ * SCOPE. Geometric optics: rays, not beams. No amplitude, so nothing here says
28
+ * how MUCH light reflects at a boundary (that is Fresnel, and it is not on
29
+ * either syllabus). Non-dispersive unless a caller passes a per-colour index;
30
+ * `prism.ts` is where dispersion is handled properly.
31
+ */
32
+ /**
33
+ * Refractive indices at roughly 589 nm (the sodium D line), which is the
34
+ * wavelength every table is quoted at.
35
+ *
36
+ * Air is 1.000293 and is almost always taken as 1. Both are here: the exact
37
+ * value so a lesson about why we round it has something to point at, and the
38
+ * rounding left to the caller rather than baked in.
39
+ */
40
+ declare const MEDIA: Record<string, number>;
41
+ /** Speed of light in a medium, m/s: v = c/n. */
42
+ declare function speedInMedium(n: number): number;
43
+ /**
44
+ * Wavelength inside a medium, given the vacuum wavelength: λ = λ₀/n.
45
+ *
46
+ * The FREQUENCY does not change, and that is the whole reason refraction
47
+ * happens: the wave crests arrive at the boundary at a fixed rate, so if they
48
+ * travel more slowly on the far side they must be closer together, and a train
49
+ * of wavefronts meeting the boundary at an angle pivots. Colour is frequency,
50
+ * which is why light does not change colour on entering water.
51
+ */
52
+ declare function wavelengthInMedium(vacuumWavelength: number, n: number): number;
53
+ /**
54
+ * The refractive index of medium b relative to medium a: ₐn_b = n_b/n_a.
55
+ *
56
+ * The relative index is what Snell's law actually contains, which is why the
57
+ * chain ₐn_b × _bn_c × _cn_a = 1 holds: each factor is a ratio and the ratios
58
+ * telescope. That identity is a standard exam question and it is also the
59
+ * cheapest possible check that a table of indices is self-consistent.
60
+ */
61
+ declare function relativeIndex(from: number, to: number): number;
62
+ interface Refraction {
63
+ /** The angle of incidence given, degrees from the normal. */
64
+ incidenceDeg: number;
65
+ /** The refracted angle, degrees from the normal, or `null` under total internal reflection. */
66
+ refractionDeg: number | null;
67
+ /** True when no refracted ray exists and all the light reflects back. */
68
+ totalInternalReflection: boolean;
69
+ /**
70
+ * The critical angle for this pair, degrees, or `null` when there is none.
71
+ *
72
+ * Only exists going from denser to rarer. Reported even when the ray is below
73
+ * it, because "how much further could I tilt this before the ray vanishes" is
74
+ * the question the number answers.
75
+ */
76
+ criticalAngleDeg: number | null;
77
+ /** Index of the medium the light starts in. */
78
+ fromIndex: number;
79
+ /** Index of the medium it enters. */
80
+ toIndex: number;
81
+ }
82
+ /**
83
+ * Refract a ray across a boundary, reporting what happened rather than only the
84
+ * angle.
85
+ *
86
+ * Returns the critical angle alongside, so a caller drawing the boundary does
87
+ * not have to ask a second function to know how close it is to losing the ray.
88
+ */
89
+ declare function refract(incidenceDeg: number, fromIndex: number, toIndex: number): Refraction;
90
+ /** Just the refracted angle in degrees, or `null` under total internal reflection. */
91
+ declare function refractAngleDeg(incidenceDeg: number, fromIndex: number, toIndex: number): number | null;
92
+ /**
93
+ * The critical angle in degrees: sin C = n_rare/n_dense.
94
+ *
95
+ * Throws when the light is going the easy way, because there is no critical
96
+ * angle from rare to dense and returning one would invent a boundary that is
97
+ * not there. That refusal is the lesson: total internal reflection is a
98
+ * one-way phenomenon, which is why an optical fibre works and why it has to be
99
+ * made of a dense core in a less dense cladding rather than the other way
100
+ * round.
101
+ */
102
+ declare function criticalAngleDeg(denseIndex: number, rareIndex?: number): number;
103
+ /** One layer of a stack of transparent media, for the apparent-depth sum. */
104
+ interface DepthLayer {
105
+ label?: string;
106
+ /** True thickness of this layer. */
107
+ thickness: number;
108
+ /** Refractive index of this layer. */
109
+ index: number;
110
+ }
111
+ interface ApparentDepth {
112
+ /** The total real depth, the sum of the layers. */
113
+ realDepth: number;
114
+ /** The depth the bottom appears to be at, viewed from directly above. */
115
+ apparentDepth: number;
116
+ /** How much closer the bottom looks: real minus apparent. */
117
+ apparentShift: number;
118
+ /** Each layer's contribution to the apparent depth. */
119
+ layers: {
120
+ label: string;
121
+ thickness: number;
122
+ index: number;
123
+ apparent: number;
124
+ }[];
125
+ }
126
+ /**
127
+ * How deep a stack of transparent layers appears, viewed from straight above.
128
+ *
129
+ * Each layer contributes its own thickness divided by its own index, and the
130
+ * apparent depths simply add:
131
+ *
132
+ * d_apparent = Σ dᵢ / nᵢ
133
+ *
134
+ * That they add is worth pausing on, because the refractions do not: the ray
135
+ * bends at every boundary, and the bends do not sum to anything tidy. It is the
136
+ * near-normal limit that makes this exact, where every sine may be replaced by
137
+ * its angle, and this function is therefore only right for looking STRAIGHT
138
+ * DOWN. A fish watched from a shallow angle is not where this says it is.
139
+ *
140
+ * Handles one layer as easily as five, which is the usual case: a coin under
141
+ * water is `apparentDepth([{ thickness: 0.4, index: 1.333 }])`.
142
+ */
143
+ declare function apparentDepth(layers: readonly DepthLayer[]): ApparentDepth;
144
+ /**
145
+ * The refractive index measured by the apparent-depth method: n = real/apparent.
146
+ *
147
+ * The simplest quantitative optics experiment there is, and the inverse of the
148
+ * single-layer case above.
149
+ */
150
+ declare function indexFromDepths(realDepth: number, apparentDepthValue: number): number;
151
+ interface SlabPassage {
152
+ /** The refracted angle inside the slab, degrees. */
153
+ refractionDeg: number;
154
+ /** Sideways displacement of the emerging ray from the original line. */
155
+ lateralShift: number;
156
+ /** Path length travelled inside the slab. */
157
+ pathLength: number;
158
+ /** Time spent inside the slab, seconds, if the thickness is in metres. */
159
+ timeInside: number;
160
+ }
161
+ /**
162
+ * A ray through a parallel-sided slab: how far it is shifted, and how long it
163
+ * takes.
164
+ *
165
+ * x = d · sin(i − r) / cos r
166
+ *
167
+ * The emerging ray is PARALLEL to the one that went in, never bent overall,
168
+ * because the second boundary undoes exactly what the first did. All a glass
169
+ * block does is move the ray sideways, which is why a window does not distort
170
+ * the view and why a thick one seen at a glancing angle does.
171
+ *
172
+ * `timeInside` uses the slowed speed c/n, so it is longer than the same path in
173
+ * air. Keep the thickness in metres for that to be in seconds.
174
+ */
175
+ declare function throughSlab(thickness: number, incidenceDeg: number, slabIndex: number, outsideIndex?: number): SlabPassage;
176
+ /**
177
+ * Brewster's angle, degrees: tan θ_p = n₂/n₁.
178
+ *
179
+ * The one angle of incidence at which the reflected light is completely plane
180
+ * polarised. At it, the reflected and refracted rays are exactly 90 degrees
181
+ * apart, which is the reason rather than a coincidence: the reflected ray is
182
+ * driven by the oscillation of charges in the second medium, and a dipole
183
+ * radiates nothing along its own axis.
184
+ *
185
+ * Polaroid sunglasses cut glare off water because that glare is reflected near
186
+ * this angle and is therefore polarised horizontally.
187
+ */
188
+ declare function brewsterAngleDeg(toIndex: number, fromIndex?: number): number;
189
+ /**
190
+ * The refractive index from the two angles a rod makes at a liquid surface:
191
+ *
192
+ * n = tan θ / tan φ
193
+ *
194
+ * θ is the angle the rod makes with the surface, φ the angle the rod's IMAGE
195
+ * appears to make. This is the "a stick in water looks bent" measurement made
196
+ * quantitative, and it is a tangent rather than a sine because both angles are
197
+ * read off the surface rather than off the normal.
198
+ */
199
+ declare function indexFromRodAngles(rodDeg: number, imageDeg: number): number;
200
+ //#endregion
201
+ export { ApparentDepth, DepthLayer, MEDIA, Refraction, SlabPassage, apparentDepth, brewsterAngleDeg, criticalAngleDeg, indexFromDepths, indexFromRodAngles, refract, refractAngleDeg, relativeIndex, speedInMedium, throughSlab, wavelengthInMedium };
@@ -0,0 +1,270 @@
1
+ import { SPEED_OF_LIGHT } from "../core/constants.mjs";
2
+
3
+ //#region src/optics/refraction.ts
4
+ /**
5
+ * Refraction: light crossing a boundary, and everything that follows from it.
6
+ *
7
+ * THE MODEL. One law does the whole of this file:
8
+ *
9
+ * n₁ sin θ₁ = n₂ sin θ₂ (Snell)
10
+ *
11
+ * with n = c/v, the factor by which a medium slows light down. Written that way
12
+ * rather than as a pair of "denser/rarer" rules, because the symmetry is the
13
+ * point: reverse the ray and the same equation describes it, which is why a
14
+ * critical angle exists at all and why it exists only going the other way.
15
+ *
16
+ * WHAT SNELL'S LAW RETURNS WHEN THERE IS NO ANSWER. Solving for θ₂ needs
17
+ * arcsin((n₁/n₂)·sin θ₁), and past the critical angle that argument exceeds 1.
18
+ * That is not a numerical accident to be clamped away: it is TOTAL INTERNAL
19
+ * REFLECTION, the physical statement that no refracted ray exists. So
20
+ * `refractAngleDeg` returns `null` rather than NaN or a clamped 90 degrees, and
21
+ * `refract` returns a result that says which case happened. A clamp here would
22
+ * draw a refracted ray grazing along the surface forever, which is a picture of
23
+ * something that does not happen.
24
+ *
25
+ * ANGLES ARE IN DEGREES at this boundary, because every syllabus, every
26
+ * protractor and every worked answer is, and a kernel that took radians would
27
+ * push a conversion into every single call site. Internally it converts once.
28
+ *
29
+ * SCOPE. Geometric optics: rays, not beams. No amplitude, so nothing here says
30
+ * how MUCH light reflects at a boundary (that is Fresnel, and it is not on
31
+ * either syllabus). Non-dispersive unless a caller passes a per-colour index;
32
+ * `prism.ts` is where dispersion is handled properly.
33
+ */
34
+ const DEG = Math.PI / 180;
35
+ const toRad = (deg) => deg * DEG;
36
+ const toDeg = (rad) => rad / DEG;
37
+ const finite = (value, what) => {
38
+ if (!Number.isFinite(value)) throw new RangeError(`${what} must be a finite number.`);
39
+ return value;
40
+ };
41
+ /**
42
+ * Guard for a refractive index.
43
+ *
44
+ * Refuses anything below 1, because n = c/v and nothing carries light faster
45
+ * than light does. A caller who has passed 0.9 has swapped two media or typed a
46
+ * reciprocal, and both mistakes produce believable angles if allowed through.
47
+ */
48
+ const index = (value, what = "A refractive index") => {
49
+ if (!Number.isFinite(value) || value < 1) throw new RangeError(`${what} must be at least 1 (got ${value}); n = c/v, and nothing outruns light in vacuum.`);
50
+ return value;
51
+ };
52
+ /** An angle measured from the NORMAL, in degrees, as every optics convention does. */
53
+ const angle = (value, what = "An angle") => {
54
+ if (!Number.isFinite(value) || value < 0 || value > 90) throw new RangeError(`${what} is measured from the normal and lies in [0, 90] degrees (got ${value}).`);
55
+ return value;
56
+ };
57
+ /**
58
+ * Refractive indices at roughly 589 nm (the sodium D line), which is the
59
+ * wavelength every table is quoted at.
60
+ *
61
+ * Air is 1.000293 and is almost always taken as 1. Both are here: the exact
62
+ * value so a lesson about why we round it has something to point at, and the
63
+ * rounding left to the caller rather than baked in.
64
+ */
65
+ const MEDIA = {
66
+ vacuum: 1,
67
+ air: 1.000293,
68
+ ice: 1.31,
69
+ water: 1.333,
70
+ ethanol: 1.361,
71
+ glycerol: 1.473,
72
+ perspex: 1.495,
73
+ crownGlass: 1.52,
74
+ glass: 1.5,
75
+ flintGlass: 1.62,
76
+ sapphire: 1.77,
77
+ diamond: 2.417
78
+ };
79
+ /** Speed of light in a medium, m/s: v = c/n. */
80
+ function speedInMedium(n) {
81
+ return SPEED_OF_LIGHT / index(n);
82
+ }
83
+ /**
84
+ * Wavelength inside a medium, given the vacuum wavelength: λ = λ₀/n.
85
+ *
86
+ * The FREQUENCY does not change, and that is the whole reason refraction
87
+ * happens: the wave crests arrive at the boundary at a fixed rate, so if they
88
+ * travel more slowly on the far side they must be closer together, and a train
89
+ * of wavefronts meeting the boundary at an angle pivots. Colour is frequency,
90
+ * which is why light does not change colour on entering water.
91
+ */
92
+ function wavelengthInMedium(vacuumWavelength, n) {
93
+ return finite(vacuumWavelength, "A wavelength") / index(n);
94
+ }
95
+ /**
96
+ * The refractive index of medium b relative to medium a: ₐn_b = n_b/n_a.
97
+ *
98
+ * The relative index is what Snell's law actually contains, which is why the
99
+ * chain ₐn_b × _bn_c × _cn_a = 1 holds: each factor is a ratio and the ratios
100
+ * telescope. That identity is a standard exam question and it is also the
101
+ * cheapest possible check that a table of indices is self-consistent.
102
+ */
103
+ function relativeIndex(from, to) {
104
+ return index(to, "The index of the second medium") / index(from, "The index of the first medium");
105
+ }
106
+ /**
107
+ * Refract a ray across a boundary, reporting what happened rather than only the
108
+ * angle.
109
+ *
110
+ * Returns the critical angle alongside, so a caller drawing the boundary does
111
+ * not have to ask a second function to know how close it is to losing the ray.
112
+ */
113
+ function refract(incidenceDeg, fromIndex, toIndex) {
114
+ const i = angle(incidenceDeg, "The angle of incidence");
115
+ const n1 = index(fromIndex, "The index of the first medium");
116
+ const n2 = index(toIndex, "The index of the second medium");
117
+ const critical = n1 > n2 ? toDeg(Math.asin(n2 / n1)) : null;
118
+ const sinR = n1 / n2 * Math.sin(toRad(i));
119
+ if (sinR > 1.000000000001) return {
120
+ incidenceDeg: i,
121
+ refractionDeg: null,
122
+ totalInternalReflection: true,
123
+ criticalAngleDeg: critical,
124
+ fromIndex: n1,
125
+ toIndex: n2
126
+ };
127
+ return {
128
+ incidenceDeg: i,
129
+ refractionDeg: toDeg(Math.asin(Math.min(1, sinR))),
130
+ totalInternalReflection: false,
131
+ criticalAngleDeg: critical,
132
+ fromIndex: n1,
133
+ toIndex: n2
134
+ };
135
+ }
136
+ /** Just the refracted angle in degrees, or `null` under total internal reflection. */
137
+ function refractAngleDeg(incidenceDeg, fromIndex, toIndex) {
138
+ return refract(incidenceDeg, fromIndex, toIndex).refractionDeg;
139
+ }
140
+ /**
141
+ * The critical angle in degrees: sin C = n_rare/n_dense.
142
+ *
143
+ * Throws when the light is going the easy way, because there is no critical
144
+ * angle from rare to dense and returning one would invent a boundary that is
145
+ * not there. That refusal is the lesson: total internal reflection is a
146
+ * one-way phenomenon, which is why an optical fibre works and why it has to be
147
+ * made of a dense core in a less dense cladding rather than the other way
148
+ * round.
149
+ */
150
+ function criticalAngleDeg(denseIndex, rareIndex = 1) {
151
+ const dense = index(denseIndex, "The index of the dense medium");
152
+ const rare = index(rareIndex, "The index of the rare medium");
153
+ if (dense <= rare) throw new RangeError(`No critical angle from n = ${dense} into n = ${rare}: total internal reflection only happens going from denser to rarer.`);
154
+ return toDeg(Math.asin(rare / dense));
155
+ }
156
+ /**
157
+ * How deep a stack of transparent layers appears, viewed from straight above.
158
+ *
159
+ * Each layer contributes its own thickness divided by its own index, and the
160
+ * apparent depths simply add:
161
+ *
162
+ * d_apparent = Σ dᵢ / nᵢ
163
+ *
164
+ * That they add is worth pausing on, because the refractions do not: the ray
165
+ * bends at every boundary, and the bends do not sum to anything tidy. It is the
166
+ * near-normal limit that makes this exact, where every sine may be replaced by
167
+ * its angle, and this function is therefore only right for looking STRAIGHT
168
+ * DOWN. A fish watched from a shallow angle is not where this says it is.
169
+ *
170
+ * Handles one layer as easily as five, which is the usual case: a coin under
171
+ * water is `apparentDepth([{ thickness: 0.4, index: 1.333 }])`.
172
+ */
173
+ function apparentDepth(layers) {
174
+ if (layers.length === 0) throw new RangeError("There is nothing to look through.");
175
+ const resolved = layers.map((layer, i) => {
176
+ const thickness = finite(layer.thickness, "A layer thickness");
177
+ if (thickness < 0) throw new RangeError("A layer cannot have a negative thickness.");
178
+ const n = index(layer.index, `Layer ${i + 1}'s refractive index`);
179
+ return {
180
+ label: layer.label ?? `layer ${i + 1}`,
181
+ thickness,
182
+ index: n,
183
+ apparent: thickness / n
184
+ };
185
+ });
186
+ const realDepth = resolved.reduce((sum, l) => sum + l.thickness, 0);
187
+ const apparent = resolved.reduce((sum, l) => sum + l.apparent, 0);
188
+ return {
189
+ realDepth,
190
+ apparentDepth: apparent,
191
+ apparentShift: realDepth - apparent,
192
+ layers: resolved
193
+ };
194
+ }
195
+ /**
196
+ * The refractive index measured by the apparent-depth method: n = real/apparent.
197
+ *
198
+ * The simplest quantitative optics experiment there is, and the inverse of the
199
+ * single-layer case above.
200
+ */
201
+ function indexFromDepths(realDepth, apparentDepthValue) {
202
+ const real = finite(realDepth, "The real depth");
203
+ const apparent = finite(apparentDepthValue, "The apparent depth");
204
+ if (apparent <= 0) throw new RangeError("The apparent depth must be positive.");
205
+ if (real < apparent) throw new RangeError("The bottom always looks CLOSER than it is, so the real depth cannot be the smaller of the two.");
206
+ return real / apparent;
207
+ }
208
+ /**
209
+ * A ray through a parallel-sided slab: how far it is shifted, and how long it
210
+ * takes.
211
+ *
212
+ * x = d · sin(i − r) / cos r
213
+ *
214
+ * The emerging ray is PARALLEL to the one that went in, never bent overall,
215
+ * because the second boundary undoes exactly what the first did. All a glass
216
+ * block does is move the ray sideways, which is why a window does not distort
217
+ * the view and why a thick one seen at a glancing angle does.
218
+ *
219
+ * `timeInside` uses the slowed speed c/n, so it is longer than the same path in
220
+ * air. Keep the thickness in metres for that to be in seconds.
221
+ */
222
+ function throughSlab(thickness, incidenceDeg, slabIndex, outsideIndex = 1) {
223
+ const d = finite(thickness, "The slab thickness");
224
+ if (d < 0) throw new RangeError("A slab cannot have a negative thickness.");
225
+ const i = angle(incidenceDeg, "The angle of incidence");
226
+ const result = refract(i, outsideIndex, slabIndex);
227
+ if (result.refractionDeg === null) throw new RangeError("No ray enters the slab, so it has no passage through it.");
228
+ const r = result.refractionDeg;
229
+ const pathLength = d / Math.cos(toRad(r));
230
+ return {
231
+ refractionDeg: r,
232
+ lateralShift: d * Math.sin(toRad(i - r)) / Math.cos(toRad(r)),
233
+ pathLength,
234
+ timeInside: pathLength / speedInMedium(slabIndex)
235
+ };
236
+ }
237
+ /**
238
+ * Brewster's angle, degrees: tan θ_p = n₂/n₁.
239
+ *
240
+ * The one angle of incidence at which the reflected light is completely plane
241
+ * polarised. At it, the reflected and refracted rays are exactly 90 degrees
242
+ * apart, which is the reason rather than a coincidence: the reflected ray is
243
+ * driven by the oscillation of charges in the second medium, and a dipole
244
+ * radiates nothing along its own axis.
245
+ *
246
+ * Polaroid sunglasses cut glare off water because that glare is reflected near
247
+ * this angle and is therefore polarised horizontally.
248
+ */
249
+ function brewsterAngleDeg(toIndex, fromIndex = 1) {
250
+ return toDeg(Math.atan(index(toIndex, "The index of the second medium") / index(fromIndex, "The index of the first medium")));
251
+ }
252
+ /**
253
+ * The refractive index from the two angles a rod makes at a liquid surface:
254
+ *
255
+ * n = tan θ / tan φ
256
+ *
257
+ * θ is the angle the rod makes with the surface, φ the angle the rod's IMAGE
258
+ * appears to make. This is the "a stick in water looks bent" measurement made
259
+ * quantitative, and it is a tangent rather than a sine because both angles are
260
+ * read off the surface rather than off the normal.
261
+ */
262
+ function indexFromRodAngles(rodDeg, imageDeg) {
263
+ const theta = finite(rodDeg, "The rod angle");
264
+ const phi = finite(imageDeg, "The image angle");
265
+ if (theta <= 0 || theta >= 90 || phi <= 0 || phi >= 90) throw new RangeError("Both angles are measured from the liquid surface and lie strictly between 0 and 90 degrees.");
266
+ return Math.tan(toRad(theta)) / Math.tan(toRad(phi));
267
+ }
268
+
269
+ //#endregion
270
+ export { MEDIA, apparentDepth, brewsterAngleDeg, criticalAngleDeg, indexFromDepths, indexFromRodAngles, refract, refractAngleDeg, relativeIndex, speedInMedium, throughSlab, wavelengthInMedium };
@@ -0,0 +1,171 @@
1
+ import { pathFromPhase, phaseFromPath } from "../waves/wave.mjs";
2
+
3
+ //#region src/optics/wave-optics.d.ts
4
+ /**
5
+ * Fringe spacing in Young's experiment: w = λD/a.
6
+ *
7
+ * The workhorse, and the reason the experiment is the classic measurement of a
8
+ * wavelength: every quantity on the right is measurable with a ruler, and the
9
+ * left is a few tenths of a millimetre magnified into something you can count.
10
+ *
11
+ * The slit separation `a` is in the DENOMINATOR, which is the counter-intuitive
12
+ * part: pushing the slits closer together spreads the fringes apart.
13
+ */
14
+ declare function fringeSpacing(wavelength: number, screenDistance: number, slitSeparation: number): number;
15
+ /** Wavelength from a measured fringe spacing, the inverse of `fringeSpacing`. */
16
+ declare function wavelengthFromFringes(fringeWidth: number, screenDistance: number, slitSeparation: number): number;
17
+ /**
18
+ * Distance from the centre of the pattern to the nth BRIGHT fringe, metres.
19
+ *
20
+ * `n = 0` is the central maximum, which sits at zero path difference and is
21
+ * therefore in the same place for every wavelength. That is why the centre of a
22
+ * white-light interference pattern is white and everything either side is
23
+ * coloured.
24
+ */
25
+ declare function brightFringePosition(n: number, wavelength: number, screenDistance: number, slitSeparation: number): number;
26
+ /**
27
+ * Distance to the nth DARK fringe, metres, with `n = 0` the first one out from
28
+ * the centre.
29
+ *
30
+ * Half a fringe width further out than the bright one of the same index, which
31
+ * is the (n + ½) in the textbook formula written where it cannot be misread as
32
+ * (2n+1)/2 applied to the wrong thing.
33
+ */
34
+ declare function darkFringePosition(n: number, wavelength: number, screenDistance: number, slitSeparation: number): number;
35
+ /**
36
+ * The exact angle to the nth bright fringe, degrees, from a sin θ = nλ.
37
+ *
38
+ * No small-angle assumption, so it stays right where `fringeSpacing` starts to
39
+ * drift. Returns `null` when the order does not exist, which happens once
40
+ * nλ exceeds the slit separation.
41
+ */
42
+ declare function fringeAngleDeg(n: number, wavelength: number, slitSeparation: number): number | null;
43
+ /**
44
+ * Relative intensity of a two-slit pattern at a phase difference φ:
45
+ * I = I₀·cos²(φ/2).
46
+ *
47
+ * Note the pattern's peaks are FOUR times one slit's intensity, not twice, and
48
+ * the average is twice. Energy is conserved by redistribution, not by creation:
49
+ * the light missing from the dark fringes is exactly the excess in the bright
50
+ * ones.
51
+ */
52
+ declare const twoSlitIntensity: (peakIntensity: number, phase: number) => number;
53
+ /**
54
+ * The single-slit ENVELOPE at an angle, normalised to 1 straight ahead:
55
+ *
56
+ * I/I₀ = (sin α / α)² with α = πa·sinθ/λ
57
+ *
58
+ * The shape every diffraction pattern sits inside. `α = 0` is 0/0 and the limit
59
+ * is 1, handled explicitly rather than left to produce NaN on the axis, which
60
+ * is the one point every plot draws.
61
+ *
62
+ * Note the contrast with the two-slit fringe term: the same algebra
63
+ * `a sinθ = nλ` gives a MINIMUM here and a MAXIMUM there. Confusing the two is
64
+ * the commonest error in the topic.
65
+ */
66
+ declare function singleSlitEnvelope(thetaDeg: number, wavelength: number, slitWidth: number): number;
67
+ /**
68
+ * The full two-slit pattern at an angle, normalised to 1 straight ahead:
69
+ * the envelope times the fringes.
70
+ *
71
+ * Two independent effects multiplied, and that product is the insight the
72
+ * pattern exists to deliver. The slit WIDTH sets the broad envelope, which
73
+ * decides how bright each fringe is; the slit SEPARATION sets the fine fringes
74
+ * inside it. Students routinely attribute both to one number, and a lab that
75
+ * draws only the fringe term cannot show them otherwise.
76
+ *
77
+ * `interfere: false` drops the fringe term and leaves the envelope, which is
78
+ * what covering one slit looks like, and what a which-path measurement does to
79
+ * the quantum version.
80
+ */
81
+ declare function doubleSlitPattern(thetaDeg: number, wavelength: number, slitSeparation: number, slitWidth: number, options?: {
82
+ readonly interfere?: boolean;
83
+ }): number;
84
+ /**
85
+ * Angle to the nth diffraction MINIMUM of a single slit, degrees: a sin θ = nλ.
86
+ *
87
+ * `n` starts at 1; there is no n = 0 minimum, because straight ahead every
88
+ * contribution across the slit arrives in phase and that is the central
89
+ * maximum. Returns `null` when the order does not exist.
90
+ */
91
+ declare function singleSlitMinimumDeg(n: number, wavelength: number, slitWidth: number): number | null;
92
+ /**
93
+ * Angular half-width of the central diffraction maximum, degrees.
94
+ *
95
+ * The central bright band is TWICE this wide, and twice as wide as every other
96
+ * band, which is the single most recognisable feature of a diffraction pattern.
97
+ */
98
+ declare function centralMaximumHalfWidthDeg(wavelength: number, slitWidth: number): number | null;
99
+ /**
100
+ * Width of the central maximum on a screen, metres, in the small-angle limit:
101
+ * 2λD/a.
102
+ *
103
+ * Narrowing the slit WIDENS the patch. Push it to a slit comparable with the
104
+ * wavelength and the light spreads through most of a hemisphere, which is the
105
+ * observation that rules out light being a stream of particles travelling in
106
+ * straight lines.
107
+ */
108
+ declare function centralMaximumWidth(wavelength: number, screenDistance: number, slitWidth: number): number;
109
+ /** Slit spacing from a ruling density: d = 1/N, with N lines per metre. */
110
+ declare const gratingSpacing: (linesPerMetre: number) => number;
111
+ /**
112
+ * Angle of the nth order from a grating, degrees: d sin θ = nλ.
113
+ *
114
+ * Returns `null` when that order does not exist, rather than NaN, because
115
+ * "which orders can I see" is the question and a missing order is an answer to
116
+ * it.
117
+ */
118
+ declare function gratingAngleDeg(n: number, wavelength: number, spacing: number): number | null;
119
+ /**
120
+ * The highest order a grating can show: floor(d/λ).
121
+ *
122
+ * Because sin θ cannot exceed 1. A subtlety worth the comment: the order at
123
+ * exactly d/λ would sit at 90 degrees, grazing along the grating and carrying
124
+ * no light, so when d/λ is a whole number the highest OBSERVABLE order is one
125
+ * less. That edge is handled rather than rounded past.
126
+ */
127
+ declare function maximumGratingOrder(wavelength: number, spacing: number): number;
128
+ /**
129
+ * Wavelength from a grating measurement: λ = d sin θ / n.
130
+ *
131
+ * The grating's advantage over two slits is that many slits make each maximum
132
+ * very sharp, so the angle can be read precisely, which is why spectrometers
133
+ * use gratings rather than double slits.
134
+ */
135
+ declare function wavelengthFromGrating(n: number, angleDeg: number, spacing: number): number;
136
+ /**
137
+ * Malus's law: I = I₀·cos²θ, with θ between the analyser and the polarisation.
138
+ *
139
+ * Crossed polarisers pass nothing, and a third one inserted between them at 45
140
+ * degrees lets light through again, which is impossible to explain if
141
+ * polarisers are filters that merely remove things. They do not filter, they
142
+ * PROJECT, and cos² is the projection.
143
+ */
144
+ declare function malusIntensity(incidentIntensity: number, analyserAngleDeg: number): number;
145
+ /**
146
+ * Intensity after unpolarised light passes one ideal polariser: exactly half.
147
+ *
148
+ * Half rather than cos² of anything, because unpolarised light carries every
149
+ * orientation equally and the average of cos² over all angles is a half. The
150
+ * first polariser is the one that loses half; the second loses by Malus.
151
+ */
152
+ declare const unpolarisedThroughPolariser: (intensity: number) => number;
153
+ /**
154
+ * Intensity at a distance from a point source: I = P/(4πr²).
155
+ *
156
+ * The inverse square is geometry, not a property of light: the same power
157
+ * spread over a sphere whose area grows as r².
158
+ */
159
+ declare function pointSourceIntensity(power: number, distance: number): number;
160
+ /**
161
+ * The Rayleigh criterion, radians: θ = 1.22·λ/D.
162
+ *
163
+ * Two point sources are just resolved when the first's diffraction maximum
164
+ * falls on the other's first minimum. The 1.22 is the first zero of a Bessel
165
+ * function, and it is there because the aperture is a CIRCLE; a slit gives
166
+ * exactly 1. This is the hard limit on every telescope and microscope, and the
167
+ * reason bigger mirrors see finer detail quite apart from gathering more light.
168
+ */
169
+ declare function rayleighResolutionRad(wavelength: number, aperture: number): number;
170
+ //#endregion
171
+ export { brightFringePosition, centralMaximumHalfWidthDeg, centralMaximumWidth, darkFringePosition, doubleSlitPattern, fringeAngleDeg, fringeSpacing, gratingAngleDeg, gratingSpacing, malusIntensity, maximumGratingOrder, pointSourceIntensity, rayleighResolutionRad, singleSlitEnvelope, singleSlitMinimumDeg, twoSlitIntensity, unpolarisedThroughPolariser, wavelengthFromFringes, wavelengthFromGrating };