@photivra/engine 2.19.0 → 2.21.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 (242) hide show
  1. package/CHANGELOG.md +289 -1
  2. package/CITATION.cff +1 -1
  3. package/NODE_SUPPORT.md +7 -5
  4. package/README.md +7 -6
  5. package/SECURITY.md +1 -1
  6. package/THIRD_PARTY.md +21 -10
  7. package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
  8. package/dist/capture/dng-lens-correction-opcodes.js +119 -0
  9. package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
  10. package/dist/capture/exposure-build-up-stage.d.ts +16 -0
  11. package/dist/capture/exposure-build-up-stage.js +4 -0
  12. package/dist/capture/exposure-build-up-stage.js.map +1 -0
  13. package/dist/capture/native-environment-lean.d.ts +2 -1
  14. package/dist/capture/native-environment-lean.js +42 -78
  15. package/dist/capture/native-environment-lean.js.map +1 -1
  16. package/dist/capture/native-environment-tabulated.js +4 -3
  17. package/dist/capture/native-environment-tabulated.js.map +1 -1
  18. package/dist/capture/native-raw-dng.d.ts +6 -0
  19. package/dist/capture/native-raw-dng.js +16 -2
  20. package/dist/capture/native-raw-dng.js.map +1 -1
  21. package/dist/capture/native-raw.d.ts +3 -2
  22. package/dist/capture/native-raw.js +5 -4
  23. package/dist/capture/native-raw.js.map +1 -1
  24. package/dist/capture/sensor-raw-producer.d.ts +4 -1
  25. package/dist/capture/sensor-raw-producer.js +15 -8
  26. package/dist/capture/sensor-raw-producer.js.map +1 -1
  27. package/dist/core/shared-helpers.d.ts +2 -0
  28. package/dist/core/shared-helpers.js +4 -0
  29. package/dist/core/shared-helpers.js.map +1 -1
  30. package/dist/core/version.d.ts +1 -1
  31. package/dist/core/version.js +1 -1
  32. package/dist/core/version.js.map +1 -1
  33. package/dist/equipment/generic-lens-catalogue.d.ts +11 -4
  34. package/dist/equipment/generic-lens-catalogue.js +49 -7
  35. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  36. package/dist/equipment/generic-tier-assets.d.ts +32 -0
  37. package/dist/equipment/generic-tier-assets.js +18 -14
  38. package/dist/equipment/generic-tier-assets.js.map +1 -1
  39. package/dist/equipment/generic-tier-presets.js +2 -3
  40. package/dist/equipment/generic-tier-presets.js.map +1 -1
  41. package/dist/equipment/sensor-profile-body.d.ts +78 -0
  42. package/dist/equipment/sensor-profile-body.js +77 -0
  43. package/dist/equipment/sensor-profile-body.js.map +1 -0
  44. package/dist/equipment/sensor-profiles.d.ts +8 -0
  45. package/dist/equipment/sensor-profiles.js +82 -0
  46. package/dist/equipment/sensor-profiles.js.map +1 -0
  47. package/dist/facade/catalogue-lens-signal.d.ts +2 -2
  48. package/dist/facade/catalogue-lens-signal.js +58 -71
  49. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  50. package/dist/facade/chart-radiance-batch.js +2 -1
  51. package/dist/facade/chart-radiance-batch.js.map +1 -1
  52. package/dist/facade/defocus-image-space-provider.d.ts +7 -0
  53. package/dist/facade/defocus-image-space-provider.js +64 -76
  54. package/dist/facade/defocus-image-space-provider.js.map +1 -1
  55. package/dist/facade/display-view-gpu-session.js +2 -0
  56. package/dist/facade/display-view-gpu-session.js.map +1 -1
  57. package/dist/facade/display-view-gpu.d.ts +13 -5
  58. package/dist/facade/display-view-gpu.js +4 -4
  59. package/dist/facade/display-view-gpu.js.map +1 -1
  60. package/dist/facade/display-view-lens-signal.d.ts +1 -1
  61. package/dist/facade/display-view-lens-signal.js +30 -26
  62. package/dist/facade/display-view-lens-signal.js.map +1 -1
  63. package/dist/facade/display-view.d.ts +3 -1
  64. package/dist/facade/display-view.js +6 -24
  65. package/dist/facade/display-view.js.map +1 -1
  66. package/dist/facade/expected-signal-setup.d.ts +3 -1
  67. package/dist/facade/expected-signal-setup.js +1 -1
  68. package/dist/facade/expected-signal-setup.js.map +1 -1
  69. package/dist/facade/expected-signal.d.ts +47 -14
  70. package/dist/facade/expected-signal.js +117 -112
  71. package/dist/facade/expected-signal.js.map +1 -1
  72. package/dist/facade/exposure-build-up.d.ts +70 -0
  73. package/dist/facade/exposure-build-up.js +164 -0
  74. package/dist/facade/exposure-build-up.js.map +1 -0
  75. package/dist/facade/fast-methods.d.ts +50 -0
  76. package/dist/facade/fast-methods.js +58 -0
  77. package/dist/facade/fast-methods.js.map +1 -0
  78. package/dist/facade/fast-resolution.d.ts +12 -0
  79. package/dist/facade/fast-resolution.js +18 -0
  80. package/dist/facade/fast-resolution.js.map +1 -0
  81. package/dist/facade/generic-lens-capture.d.ts +5 -4
  82. package/dist/facade/generic-lens-capture.js +5 -4
  83. package/dist/facade/generic-lens-capture.js.map +1 -1
  84. package/dist/facade/image-plane-enable.d.ts +7 -0
  85. package/dist/facade/image-plane-enable.js +17 -0
  86. package/dist/facade/image-plane-enable.js.map +1 -0
  87. package/dist/facade/image-plane-lattice-data.d.ts +6 -0
  88. package/dist/facade/image-plane-lattice-data.js +10 -0
  89. package/dist/facade/image-plane-lattice-data.js.map +1 -0
  90. package/dist/facade/image-plane-support.d.ts +33 -0
  91. package/dist/facade/image-plane-support.js +11 -0
  92. package/dist/facade/image-plane-support.js.map +1 -0
  93. package/dist/facade/image-plane.d.ts +36 -0
  94. package/dist/facade/image-plane.js +353 -0
  95. package/dist/facade/image-plane.js.map +1 -0
  96. package/dist/facade/mixed-illumination.d.ts +108 -0
  97. package/dist/facade/mixed-illumination.js +174 -0
  98. package/dist/facade/mixed-illumination.js.map +1 -0
  99. package/dist/facade/representative-light-sources.d.ts +72 -0
  100. package/dist/facade/representative-light-sources.js +124 -0
  101. package/dist/facade/representative-light-sources.js.map +1 -0
  102. package/dist/facade/scene-radiance.d.ts +129 -4
  103. package/dist/facade/scene-radiance.js +48 -13
  104. package/dist/facade/scene-radiance.js.map +1 -1
  105. package/dist/facade/simulate-capture.d.ts +88 -19
  106. package/dist/facade/simulate-capture.js +374 -145
  107. package/dist/facade/simulate-capture.js.map +1 -1
  108. package/dist/facade/simulate-display-view.d.ts +3 -2
  109. package/dist/facade/simulate-display-view.js +36 -18
  110. package/dist/facade/simulate-display-view.js.map +1 -1
  111. package/dist/gpu/chart-composite-gpu.d.ts +13 -1
  112. package/dist/gpu/chart-composite-gpu.js +48 -9
  113. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  114. package/dist/gpu/chart-radiance-gpu.js +4 -30
  115. package/dist/gpu/chart-radiance-gpu.js.map +1 -1
  116. package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
  117. package/dist/gpu/display-view-composite-material-module.js +39 -13
  118. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  119. package/dist/gpu/display-view-image-material-module.d.ts +86 -0
  120. package/dist/gpu/display-view-image-material-module.js +339 -0
  121. package/dist/gpu/display-view-image-material-module.js.map +1 -0
  122. package/dist/gpu/display-view-image-quality.d.ts +45 -0
  123. package/dist/gpu/display-view-image-quality.js +380 -0
  124. package/dist/gpu/display-view-image-quality.js.map +1 -0
  125. package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
  126. package/dist/gpu/display-view-quality-gpu.js +136 -205
  127. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  128. package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
  129. package/dist/gpu/display-view-speed-gpu.js +131 -93
  130. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  131. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
  132. package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
  133. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  134. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
  135. package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
  136. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  137. package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
  138. package/dist/gpu/wgsl-exact-sum.js +42 -0
  139. package/dist/gpu/wgsl-exact-sum.js.map +1 -0
  140. package/dist/index.d.ts +18 -3
  141. package/dist/index.js +12 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/motion/subject-motion.d.ts +66 -0
  144. package/dist/motion/subject-motion.js +52 -0
  145. package/dist/motion/subject-motion.js.map +1 -0
  146. package/dist/optics/aperture-diameter.d.ts +47 -0
  147. package/dist/optics/aperture-diameter.js +50 -0
  148. package/dist/optics/aperture-diameter.js.map +1 -0
  149. package/dist/optics/detail-limit.d.ts +182 -0
  150. package/dist/optics/detail-limit.js +336 -0
  151. package/dist/optics/detail-limit.js.map +1 -0
  152. package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
  153. package/dist/optics/generic-lens-lateral-color.js +77 -0
  154. package/dist/optics/generic-lens-lateral-color.js.map +1 -0
  155. package/dist/optics/generic-lens-psf.d.ts +18 -2
  156. package/dist/optics/generic-lens-psf.js +79 -48
  157. package/dist/optics/generic-lens-psf.js.map +1 -1
  158. package/dist/optics/lens-psf-profile.d.ts +7 -0
  159. package/dist/optics/lens-psf-profile.js +2 -1
  160. package/dist/optics/lens-psf-profile.js.map +1 -1
  161. package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
  162. package/dist/optics/scene-to-sensor-irradiance.js +7 -0
  163. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  164. package/dist/output/crop-to-match-focal-length.d.ts +62 -0
  165. package/dist/output/crop-to-match-focal-length.js +63 -0
  166. package/dist/output/crop-to-match-focal-length.js.map +1 -0
  167. package/dist/output/developed-lens-corrections.d.ts +19 -5
  168. package/dist/output/developed-lens-corrections.js +30 -11
  169. package/dist/output/developed-lens-corrections.js.map +1 -1
  170. package/dist/output/generic-lens-corrections.d.ts +41 -3
  171. package/dist/output/generic-lens-corrections.js +57 -9
  172. package/dist/output/generic-lens-corrections.js.map +1 -1
  173. package/dist/output/lens-corrections.d.ts +12 -2
  174. package/dist/output/lens-corrections.js +22 -7
  175. package/dist/output/lens-corrections.js.map +1 -1
  176. package/dist/output/print-contrast-reference.js +1 -1
  177. package/dist/output/print-contrast-reference.js.map +1 -1
  178. package/dist/output/print-plan.d.ts +41 -5
  179. package/dist/output/print-plan.js +59 -14
  180. package/dist/output/print-plan.js.map +1 -1
  181. package/dist/output/print-size-blur-noise.d.ts +110 -0
  182. package/dist/output/print-size-blur-noise.js +138 -0
  183. package/dist/output/print-size-blur-noise.js.map +1 -0
  184. package/dist/sensor/binomial-sample.d.ts +3 -0
  185. package/dist/sensor/binomial-sample.js +86 -0
  186. package/dist/sensor/binomial-sample.js.map +1 -0
  187. package/dist/sensor/eqe-electron-rate.js +1 -7
  188. package/dist/sensor/eqe-electron-rate.js.map +1 -1
  189. package/dist/sensor/exposure-window.d.ts +2 -0
  190. package/dist/sensor/exposure-window.js +2 -2
  191. package/dist/sensor/exposure-window.js.map +1 -1
  192. package/dist/sensor/readout-timing.js +2 -23
  193. package/dist/sensor/readout-timing.js.map +1 -1
  194. package/dist/sensor/response-application-compatibility.js +1 -6
  195. package/dist/sensor/response-application-compatibility.js.map +1 -1
  196. package/dist/sensor/responsivity-photocurrent.js +1 -7
  197. package/dist/sensor/responsivity-photocurrent.js.map +1 -1
  198. package/dist/sensor/sensor-characteristics.d.ts +147 -0
  199. package/dist/sensor/sensor-characteristics.js +126 -0
  200. package/dist/sensor/sensor-characteristics.js.map +1 -0
  201. package/dist/sensor/spatial-sample-reduction.js +1 -5
  202. package/dist/sensor/spatial-sample-reduction.js.map +1 -1
  203. package/dist/sensor/spectral-quadrature.js +1 -6
  204. package/dist/sensor/spectral-quadrature.js.map +1 -1
  205. package/dist/sensor/temporal-photo-signal.d.ts +3 -0
  206. package/dist/sensor/temporal-photo-signal.js +5 -2
  207. package/dist/sensor/temporal-photo-signal.js.map +1 -1
  208. package/dist/stabilization/system.d.ts +9 -0
  209. package/dist/stabilization/system.js +5 -6
  210. package/dist/stabilization/system.js.map +1 -1
  211. package/docs/AGENT_GUIDE.md +5 -0
  212. package/docs/API_REFERENCE.md +173 -2
  213. package/docs/QUICK_START.md +213 -6
  214. package/docs/USAGE.md +157 -3
  215. package/docs/api/capture-native-raw-dng.md +6 -0
  216. package/docs/api/core-version.md +1 -1
  217. package/docs/api/equipment-generic-lens-catalogue.md +17 -7
  218. package/docs/api/equipment-sensor-profile-body.md +64 -0
  219. package/docs/api/equipment-sensor-profiles.md +86 -0
  220. package/docs/api/exports.json +357 -2
  221. package/docs/api/facade-display-view-gpu.md +5 -2
  222. package/docs/api/facade-exposure-build-up.md +105 -0
  223. package/docs/api/facade-fast-methods.md +99 -0
  224. package/docs/api/facade-image-plane-enable.md +16 -0
  225. package/docs/api/facade-mixed-illumination.md +67 -0
  226. package/docs/api/facade-representative-light-sources.md +131 -0
  227. package/docs/api/facade-scene-radiance.md +54 -3
  228. package/docs/api/facade-simulate-capture.md +60 -15
  229. package/docs/api/facade-simulate-display-view.md +3 -2
  230. package/docs/api/motion-subject-motion.md +23 -0
  231. package/docs/api/optics-aperture-diameter.md +51 -0
  232. package/docs/api/optics-detail-limit.md +203 -0
  233. package/docs/api/optics-generic-lens-lateral-color.md +79 -0
  234. package/docs/api/output-crop-to-match-focal-length.md +67 -0
  235. package/docs/api/output-developed-lens-corrections.md +10 -1
  236. package/docs/api/output-generic-lens-corrections.md +40 -2
  237. package/docs/api/output-lens-corrections.md +11 -1
  238. package/docs/api/output-print-plan.md +35 -1
  239. package/docs/api/output-print-size-blur-noise.md +115 -0
  240. package/docs/api/sensor-sensor-characteristics.md +105 -0
  241. package/llms.txt +6 -0
  242. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject-motion.js","sourceRoot":"","sources":["../../src/motion/subject-motion.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Subject motion (#551, 2.22.0): the whole scene, or one declared rectangle of it, moving on the scene plane during the\n * exposure, over a still background. Translation in m/s on the plane and, optionally, a constant rotation about an axis\n * parallel to the optical axis (through the plane's origin for the whole scene, through the rectangle's centre for a\n * region). Times are seconds from the first opening reference, the camera rotation's time reference, so each site's own\n * exposure window (shifted by its rolling-shutter offset) sees the subject where it is during that window.\n *\n * The scene at plane point p and time t: a point of the subject at rest point q is at R(θ)(q − c) + c + d at time t\n * (d = v·t, θ = ω·t, c the centre), so p shows the subject's q = R(−θ)(p − c − d) + c when q lies in the subject; else\n * a region's rest rectangle shows a neutral 18 % background (what the subject revealed), and anywhere else the still scene at p. Exact for this\n * model (rigid motion of a planar layer); the blur is the capture's temporal midpoint quadrature.\n * @see docs/QUICK_START.md, \"Subject motion\".\n */\n\nimport type { PlanarSceneRadianceProvider } from \"../facade/scene-radiance.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\n\n/** `motion.subject` of `simulateCapture`: a moving subject on the scene plane (#551). */\nexport interface SimulateCaptureSubjectMotion {\n /** Velocity on the scene plane, m/s: +x right, +y up as seen from the camera. Missing components are 0. */\n velocityMPerSec?: { x?: number; y?: number };\n /** Rotation about the optical axis direction, rad/s, counter-clockwise as seen from the camera (+x toward +y). Default 0. */\n angularVelocityRadPerSec?: number;\n /**\n * The moving part: a rectangle on the scene plane at rest (at the first opening reference), its centre and size in metres\n * (+x right, +y up from the optical axis). Omitted: the whole scene moves.\n */\n region?: { centerXM: number; centerYM: number; widthM: number; heightM: number };\n /** Exact or fast (2.20.0 convention): fast takes fewer temporal midpoints when the subject's streak is short (see the docs). */\n fast?: boolean;\n}\n\n/** Internal: a validated subject motion (simulate-capture.ts parses it). */\nexport interface SubjectMotion {\n vx: number; vy: number; omega: number;\n /** The region's centre and half sizes in metres, or undefined for the whole scene. */\n region: { cx: number; cy: number; hw: number; hh: number } | undefined;\n}\n\n/**\n * The farthest any subject point travels on the plane during `seconds`, in metres (translation plus rotation at the subject's\n * farthest point from its centre; `reachM` is the whole scene's reach from the axis when no region is declared).\n */\nexport function subjectTravelM(motion: SubjectMotion, seconds: number, reachM: number): number {\n const r = motion.region, arm = r ? Math.hypot(r.hw, r.hh) : reachM;\n return (Math.hypot(motion.vx, motion.vy) + Math.abs(motion.omega) * arm) * seconds;\n}\n\n/**\n * The plane point that shows at (x, y) at time t (in the motion's length unit), written to out[0], out[1]; returns false where a region's rest\n * rectangle shows the revealed background. Without motion at t (d = 0, θ = 0) the point is (x, y) unchanged, bit for bit.\n */\nexport function subjectSourcePoint(motion: SubjectMotion, x: number, y: number, t: number, out: Float64Array): boolean {\n const r = motion.region, th = motion.omega * t;\n let qx = x - motion.vx * t, qy = y - motion.vy * t;\n if (th !== 0) {\n const cx = r ? r.cx : 0, cy = r ? r.cy : 0, c = Math.cos(th), s = Math.sin(th), dx = qx - cx, dy = qy - cy;\n qx = c * dx + s * dy + cx; qy = c * dy - s * dx + cy;\n }\n if (r && !(Math.abs(qx - r.cx) <= r.hw && Math.abs(qy - r.cy) <= r.hh)) {\n out[0] = x; out[1] = y;\n return !(Math.abs(x - r.cx) <= r.hw && Math.abs(y - r.cy) <= r.hh);\n }\n out[0] = qx; out[1] = qy;\n return true;\n}\n\n/**\n * The scene of `base` with the subject moving: `evaluateRadiance` reads each query at its request time (the base result, with the\n * radiance read where the subject shows), and `radianceAt` takes the time as a fourth argument (default 0) for the image-space\n * lattices and the display view. It has no chart material access, so renderers read radiance. `revealedRadiance` is the revealed\n * background's spectral radiance at a plane point in frame units (an 18 % neutral reflectance under the irradiance there).\n */\nexport function createSubjectMotionProvider(base: PlanarSceneRadianceProvider, motion: SubjectMotion, distanceM: number, scale: number,\n revealedRadiance: (u: number, v: number, nm: number) => number): PlanarSceneRadianceProvider {\n // The motion in frame units, so a still instant reads the base at the queried point itself.\n const r = motion.region, framed: SubjectMotion = { vx: motion.vx / scale, vy: motion.vy / scale, omega: motion.omega,\n region: r && { cx: r.cx / scale, cy: r.cy / scale, hw: r.hw / scale, hh: r.hh / scale } }, point = new Float64Array(2);\n const radianceAt = (u: number, v: number, nm: number, t = 0): number =>\n subjectSourcePoint(framed, u, v, t, point) ? base.radianceAt(point[0]!, point[1]!, nm) : revealedRadiance(u, v, nm);\n return { sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt, evaluateApertureRadiance: base.evaluateApertureRadiance,\n evaluateRadiance(request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult {\n const result = base.evaluateRadiance(request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n if (!(o.z < 0)) return result;\n // The base provider's own plane-point arithmetic for this direction.\n const t = distanceM / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: radianceAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers, request.timeSecondsFromExposureStart) };\n } };\n}\n"]}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Entrance-pupil (aperture) diameter of a lens from its focal length and f-number.
3
+ *
4
+ * The f-number is defined as N = f/D, with f the focal length and D the entrance-pupil diameter,
5
+ * for an object at infinity (Greivenkamp, OPTI-502 course notes, sec. 12 (Objectives), free:
6
+ * https://wp.optics.arizona.edu/jgreivenkamp/wp-content/uploads/sites/11/2019/08/502-12-Objectives.pdf).
7
+ * So D = f/N is exact by that definition. It is the diameter of the entrance pupil, the image of
8
+ * the aperture stop seen from the front of the lens, not of the physical diaphragm opening.
9
+ *
10
+ * At close focus the f-number that sets exposure and diffraction is the working f-number
11
+ * N_w = N·(1 + m/P), with m the magnification and P the pupil magnification (exit-pupil over
12
+ * entrance-pupil diameter); a lens that focuses by changing its focal length changes f, and with
13
+ * it D at the same marked N. Neither is modeled here; the
14
+ * engine's own close-focus light factor, N·(1 + m) with unit pupil magnification, is in
15
+ * `calculateSceneRadianceToSensorIrradiance`.
16
+ * @see docs/PHYSICS_FOUNDATION.md "Aperture (entrance-pupil) diameter".
17
+ */
18
+ import { type CalculationResult } from "../core/calculation-result.js";
19
+ export interface CalculateApertureDiameterInput {
20
+ /** Focal length of the lens in millimetres (the physical focal length, not a 35 mm equivalent). */
21
+ focalLengthMm: number;
22
+ /** f-number set on the lens (N = focal length / entrance-pupil diameter). */
23
+ fNumber: number;
24
+ }
25
+ export interface ApertureDiameter {
26
+ /** Focal length supplied by the caller, in millimetres. */
27
+ focalLengthMm: number;
28
+ /** f-number supplied by the caller. */
29
+ fNumber: number;
30
+ /** Entrance-pupil diameter D = focalLengthMm / fNumber, in millimetres. */
31
+ entrancePupilDiameterMm: number;
32
+ }
33
+ /**
34
+ * Entrance-pupil (aperture) diameter in millimetres: focal length ÷ f-number.
35
+ *
36
+ * Exact by the definition of the f-number for an ideal lens focused at infinity. It is the
37
+ * entrance pupil (the aperture stop as seen from the front), not the diaphragm's physical
38
+ * opening. Close focus (working f-number N·(1 + m/P) with pupil magnification P) and focal-length
39
+ * changes while focusing are not modelled.
40
+ *
41
+ * Example: 50 mm at f/2 gives 25 mm; at f/4, 12.5 mm (half the diameter, a quarter of the area:
42
+ * two stops).
43
+ *
44
+ * @param input Focal length in millimetres and f-number.
45
+ * @returns The entrance-pupil diameter with the inputs.
46
+ */
47
+ export declare function calculateApertureDiameter(input: CalculateApertureDiameterInput): CalculationResult<ApertureDiameter>;
@@ -0,0 +1,50 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Entrance-pupil (aperture) diameter of a lens from its focal length and f-number.
4
+ *
5
+ * The f-number is defined as N = f/D, with f the focal length and D the entrance-pupil diameter,
6
+ * for an object at infinity (Greivenkamp, OPTI-502 course notes, sec. 12 (Objectives), free:
7
+ * https://wp.optics.arizona.edu/jgreivenkamp/wp-content/uploads/sites/11/2019/08/502-12-Objectives.pdf).
8
+ * So D = f/N is exact by that definition. It is the diameter of the entrance pupil, the image of
9
+ * the aperture stop seen from the front of the lens, not of the physical diaphragm opening.
10
+ *
11
+ * At close focus the f-number that sets exposure and diffraction is the working f-number
12
+ * N_w = N·(1 + m/P), with m the magnification and P the pupil magnification (exit-pupil over
13
+ * entrance-pupil diameter); a lens that focuses by changing its focal length changes f, and with
14
+ * it D at the same marked N. Neither is modeled here; the
15
+ * engine's own close-focus light factor, N·(1 + m) with unit pupil magnification, is in
16
+ * `calculateSceneRadianceToSensorIrradiance`.
17
+ * @see docs/PHYSICS_FOUNDATION.md "Aperture (entrance-pupil) diameter".
18
+ */
19
+ import { calculatedResult } from "../core/calculation-result.js";
20
+ import { requireInputKeys } from "../core/record-validation.js";
21
+ import { InvalidScientificResultError, requirePositiveFinite } from "../core/validation.js";
22
+ /**
23
+ * Entrance-pupil (aperture) diameter in millimetres: focal length ÷ f-number.
24
+ *
25
+ * Exact by the definition of the f-number for an ideal lens focused at infinity. It is the
26
+ * entrance pupil (the aperture stop as seen from the front), not the diaphragm's physical
27
+ * opening. Close focus (working f-number N·(1 + m/P) with pupil magnification P) and focal-length
28
+ * changes while focusing are not modelled.
29
+ *
30
+ * Example: 50 mm at f/2 gives 25 mm; at f/4, 12.5 mm (half the diameter, a quarter of the area:
31
+ * two stops).
32
+ *
33
+ * @param input Focal length in millimetres and f-number.
34
+ * @returns The entrance-pupil diameter with the inputs.
35
+ */
36
+ export function calculateApertureDiameter(input) {
37
+ requireInputKeys(input, "calculateApertureDiameter", ["focalLengthMm", "fNumber"]);
38
+ requirePositiveFinite("focalLengthMm", input.focalLengthMm);
39
+ requirePositiveFinite("fNumber", input.fNumber);
40
+ const entrancePupilDiameterMm = input.focalLengthMm / input.fNumber;
41
+ if (!(entrancePupilDiameterMm > 0) || !Number.isFinite(entrancePupilDiameterMm)) {
42
+ throw new InvalidScientificResultError("entrancePupilDiameterMm must be a finite number greater than zero.");
43
+ }
44
+ return calculatedResult({ focalLengthMm: input.focalLengthMm, fNumber: input.fNumber, entrancePupilDiameterMm }, "aperture-diameter", "1.0.0", [
45
+ "Entrance-pupil diameter D = f/N, exact by the definition of the f-number for an object at infinity.",
46
+ "Ideal lens focused at infinity: close-focus working f-number N·(1 + m/P), pupil magnification P and focus breathing are not modelled.",
47
+ "D is the entrance pupil (the aperture stop seen from the front of the lens), not the physical diaphragm opening."
48
+ ]);
49
+ }
50
+ //# sourceMappingURL=aperture-diameter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aperture-diameter.js","sourceRoot":"","sources":["../../src/optics/aperture-diameter.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,gBAAgB,EAA0B,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAkB5F;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAqC;IAErC,gBAAgB,CAAC,KAAK,EAAE,2BAA2B,EAAE,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;IACnF,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5D,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,uBAAuB,GAAG,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC;IACpE,IAAI,CAAC,CAAC,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,4BAA4B,CAAC,oEAAoE,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,gBAAgB,CACrB,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,uBAAuB,EAAE,EACvF,mBAAmB,EACnB,OAAO,EACP;QACE,qGAAqG;QACrG,uIAAuI;QACvI,kHAAkH;KACnH,CACF,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Entrance-pupil (aperture) diameter of a lens from its focal length and f-number.\n *\n * The f-number is defined as N = f/D, with f the focal length and D the entrance-pupil diameter,\n * for an object at infinity (Greivenkamp, OPTI-502 course notes, sec. 12 (Objectives), free:\n * https://wp.optics.arizona.edu/jgreivenkamp/wp-content/uploads/sites/11/2019/08/502-12-Objectives.pdf).\n * So D = f/N is exact by that definition. It is the diameter of the entrance pupil, the image of\n * the aperture stop seen from the front of the lens, not of the physical diaphragm opening.\n *\n * At close focus the f-number that sets exposure and diffraction is the working f-number\n * N_w = N·(1 + m/P), with m the magnification and P the pupil magnification (exit-pupil over\n * entrance-pupil diameter); a lens that focuses by changing its focal length changes f, and with\n * it D at the same marked N. Neither is modeled here; the\n * engine's own close-focus light factor, N·(1 + m) with unit pupil magnification, is in\n * `calculateSceneRadianceToSensorIrradiance`.\n * @see docs/PHYSICS_FOUNDATION.md \"Aperture (entrance-pupil) diameter\".\n */\n\nimport { calculatedResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidScientificResultError, requirePositiveFinite } from \"../core/validation.js\";\n\nexport interface CalculateApertureDiameterInput {\n /** Focal length of the lens in millimetres (the physical focal length, not a 35 mm equivalent). */\n focalLengthMm: number;\n /** f-number set on the lens (N = focal length / entrance-pupil diameter). */\n fNumber: number;\n}\n\nexport interface ApertureDiameter {\n /** Focal length supplied by the caller, in millimetres. */\n focalLengthMm: number;\n /** f-number supplied by the caller. */\n fNumber: number;\n /** Entrance-pupil diameter D = focalLengthMm / fNumber, in millimetres. */\n entrancePupilDiameterMm: number;\n}\n\n/**\n * Entrance-pupil (aperture) diameter in millimetres: focal length ÷ f-number.\n *\n * Exact by the definition of the f-number for an ideal lens focused at infinity. It is the\n * entrance pupil (the aperture stop as seen from the front), not the diaphragm's physical\n * opening. Close focus (working f-number N·(1 + m/P) with pupil magnification P) and focal-length\n * changes while focusing are not modelled.\n *\n * Example: 50 mm at f/2 gives 25 mm; at f/4, 12.5 mm (half the diameter, a quarter of the area:\n * two stops).\n *\n * @param input Focal length in millimetres and f-number.\n * @returns The entrance-pupil diameter with the inputs.\n */\nexport function calculateApertureDiameter(\n input: CalculateApertureDiameterInput\n): CalculationResult<ApertureDiameter> {\n requireInputKeys(input, \"calculateApertureDiameter\", [\"focalLengthMm\", \"fNumber\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"fNumber\", input.fNumber);\n const entrancePupilDiameterMm = input.focalLengthMm / input.fNumber;\n if (!(entrancePupilDiameterMm > 0) || !Number.isFinite(entrancePupilDiameterMm)) {\n throw new InvalidScientificResultError(\"entrancePupilDiameterMm must be a finite number greater than zero.\");\n }\n return calculatedResult(\n { focalLengthMm: input.focalLengthMm, fNumber: input.fNumber, entrancePupilDiameterMm },\n \"aperture-diameter\",\n \"1.0.0\",\n [\n \"Entrance-pupil diameter D = f/N, exact by the definition of the f-number for an object at infinity.\",\n \"Ideal lens focused at infinity: close-focus working f-number N·(1 + m/P), pupil magnification P and focus breathing are not modelled.\",\n \"D is the entrance pupil (the aperture stop seen from the front of the lens), not the physical diaphragm opening.\"\n ]\n );\n}\n"]}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Which limits detail for given settings: the lens (diffraction at this f-number, aberrations, defocus) or the sensor's pixel
3
+ * pitch (#575, for the app's Learn section).
4
+ *
5
+ * Model (`detail-limit` 1.0.0; the decision rule is an approximation, see below):
6
+ * - **Optics.** The incoherent optical transfer function of a uniformly lit circular pupil carrying the wavefront W (in waves)
7
+ * is the normalized autocorrelation of the pupil function P = exp(i·2π·W):
8
+ * OTF(s) = (1/π)∫∫ P(ρ + s·e)·P*(ρ − s·e) d²ρ over the overlap of the two unit discs, s = ν/ν_c, ν_c = 1/(λ·N_w), N_w the
9
+ * working f-number (thin-lens image distance / pupil diameter). With W = 0 it is the diffraction-limited
10
+ * (2/π)(acos s − s√(1 − s²)) (MIT OpenCourseWare 2.71 Optics, Spring 2009, lectures 21–22, free; also see Goodman,
11
+ * Introduction to Fourier Optics, 4th ed., §7.3–7.4). The integral is evaluated by Gauss–Legendre quadrature on a smooth
12
+ * parametrisation of the overlap (√ edge removed), with node counts that grow with the phase variation; MTF = |OTF|.
13
+ * - **Wavefront.** `lens.ideal`: none. `lens.catalogue`: the lens's resolved Seidel terms (`resolveGenericLens`, the same
14
+ * expansion as its PSF: Hopkins 1950; Wyant & Creath 1992, Applied Optics and Optical Engineering XI ch. 1, free author copy)
15
+ * at the field height H, with axial color at the wavelength. Defocus of a subject away from the focus distance adds
16
+ * W020 = dz/(8·N_w²), dz = sensor minus image distance (thin lens; `calculateDefocusWavefront`, Wyant & Creath eq. 18).
17
+ * - **Sampling.** Nyquist frequency 1/(2p) for pixel pitch p (exact for the lattice); a Bayer filter's red and blue sites
18
+ * repeat every 2p, so their Nyquist frequency is 1/(4p), while its green sites still sample rows and columns up to 1/(2p).
19
+ * Pixel aperture MTF |sinc(ν·p)| for a square, fully sensitive site (fill factor 1, an idealisation).
20
+ * - **Decision (approximation).** The sensor limits when the optics still pass at least 50 % contrast at the Nyquist
21
+ * frequency (optics MTF50 ≥ 1/(2p)): a denser sensor would record finer detail. Otherwise the lens limits, and the cause is
22
+ * diffraction when the wavefront error is within the Maréchal criterion (RMS ≤ λ/14, Strehl ≈ 0.8; Wyant & Creath 1992
23
+ * eq. 67), else aberrations or defocus, whichever has the larger RMS wavefront error.
24
+ * @see docs/PHYSICS_FOUNDATION.md "Which limits detail: the lens or the sensor" for the equations, exactness and limits.
25
+ */
26
+ import { type CalculationResult } from "../core/calculation-result.js";
27
+ /**
28
+ * Limits of `calculateDetailLimit`: the wavelength range and the largest wavefront (sum of the magnitudes of its terms, in
29
+ * waves) whose transfer function is integrated. Beyond it the blur is geometric and the quadrature would grow without
30
+ * bound; use `calculateDefocusCircle` for such a blur.
31
+ */
32
+ export declare const DETAIL_LIMIT_LIMITS: Readonly<{
33
+ minimumWavelengthNm: 380;
34
+ maximumWavelengthNm: 780;
35
+ maximumWavefrontWaves: 64;
36
+ }>;
37
+ /** A lens with no aberrations (diffraction only). */
38
+ export interface DetailLimitIdealLens {
39
+ kind: "ideal";
40
+ /** Physical focal length in millimeters (for the working f-number and the defocus of a subject off the focus distance). */
41
+ focalLengthMm: number;
42
+ }
43
+ /** A generic catalogue lens (`GENERIC_LENS_IDS`), resolved for the sensor as `resolveGenericLens` does. */
44
+ export interface DetailLimitCatalogueLens {
45
+ kind: "catalogue";
46
+ lensId: string;
47
+ }
48
+ export interface CalculateDetailLimitInput {
49
+ /** Active imaging area and horizontal pixel count; pitch = widthMm / pixelWidth. */
50
+ sensor: {
51
+ widthMm: number;
52
+ heightMm: number;
53
+ pixelWidth: number;
54
+ /** Default `"bayer"`. `"none"`: every site records full detail (a monochrome sensor). */
55
+ colorFilterArray?: "bayer" | "none";
56
+ };
57
+ lens: DetailLimitIdealLens | DetailLimitCatalogueLens;
58
+ /** f-number set on the lens. */
59
+ fNumber: number;
60
+ /**
61
+ * Focus and subject distances from the lens in meters. Omitted: focused at infinity, subject in focus. `subjectDistanceM`
62
+ * omitted: the subject is at the focus distance.
63
+ */
64
+ focus?: {
65
+ focusDistanceM: number;
66
+ subjectDistanceM?: number;
67
+ };
68
+ /** Field height as a fraction of the half-diagonal, 0 (center, default) to 1 (corner). Only aberrations depend on it. */
69
+ fieldPosition?: number;
70
+ /** Wavelength in nanometres, 380–780. Default 550. */
71
+ wavelengthNm?: number;
72
+ }
73
+ /** Which component limits detail. */
74
+ export type DetailLimitedBy = "lens" | "sensor";
75
+ /** What limits it: the lens's diffraction, aberrations or defocus, or the sensor's pixel pitch. */
76
+ export type DetailLimitingFactor = "diffraction" | "aberrations" | "defocus" | "pixel-pitch";
77
+ export interface DetailLimitOptics {
78
+ /** Working f-number N_w = N·v/f (thin-lens image distance v; N at infinity focus). */
79
+ workingFNumber: number;
80
+ /** Diffraction cut-off 1/(λ·N_w) in cycles/mm: no optics passes detail beyond it. */
81
+ cutoffCyclesPerMm: number;
82
+ /** Frequency where the optics' MTF falls to 0.5, the lower of the two directions, cycles/mm. */
83
+ mtf50CyclesPerMm: number;
84
+ /** MTF50 for detail along the radius from the image center (tangential), cycles/mm. */
85
+ tangentialMtf50CyclesPerMm: number;
86
+ /** MTF50 for detail across the radius (sagittal), cycles/mm. Equal to the tangential value at the center. */
87
+ sagittalMtf50CyclesPerMm: number;
88
+ /** MTF50 of an aberration-free lens in focus at the same working f-number (0.40397·cut-off), cycles/mm. */
89
+ diffractionMtf50CyclesPerMm: number;
90
+ /** Optics MTF at the sensor's Nyquist frequency (lower direction). */
91
+ mtfAtNyquist: number;
92
+ /** RMS wavefront error in waves at the wavelength: of the aberrations, of the defocus, and of both together. */
93
+ rmsWavefrontErrorWaves: {
94
+ aberrations: number;
95
+ defocus: number;
96
+ total: number;
97
+ };
98
+ /** Whether the total RMS wavefront error is within the Maréchal criterion λ/14. */
99
+ withinMarechalCriterion: boolean;
100
+ /** Geometric blur-circle diameter of the defocus on the sensor, mm (0 in focus). */
101
+ defocusBlurDiameterMm: number;
102
+ }
103
+ export interface DetailLimitSampling {
104
+ colorFilterArray: "bayer" | "none";
105
+ /** Pixel pitch in micrometres: widthMm / pixelWidth. */
106
+ pixelPitchMicrometers: number;
107
+ /** 1/(2p), cycles/mm: the finest detail the pixel grid records without aliasing (Bayer green sites too, along rows and columns). */
108
+ nyquistCyclesPerMm: number;
109
+ /** Bayer only: 1/(4p), the Nyquist frequency of the red and blue sites. Null without a color filter array. */
110
+ redBlueNyquistCyclesPerMm: number | null;
111
+ /** Pixel aperture MTF at the Nyquist frequency: sinc(1/2) = 2/π. */
112
+ pixelApertureMtfAtNyquist: number;
113
+ /** Frequency where the pixel aperture MTF falls to 0.5 (0.60335/p), cycles/mm: beyond the Nyquist frequency. */
114
+ pixelApertureMtf50CyclesPerMm: number;
115
+ }
116
+ export interface DetailLimitSystem {
117
+ /** MTF50 of optics × pixel aperture (lower direction), cycles/mm. Detail above the Nyquist frequency aliases. */
118
+ mtf50CyclesPerMm: number;
119
+ /** The same in line pairs per picture height (cycles/mm × heightMm). */
120
+ mtf50LinePairsPerPictureHeight: number;
121
+ /** System MTF at the Nyquist frequency (lower direction). */
122
+ mtfAtNyquist: number;
123
+ }
124
+ /** Whether a quantity is exact under its stated conditions or an approximation. */
125
+ export interface DetailLimitBasis {
126
+ kind: "exact" | "approximation";
127
+ statement: string;
128
+ }
129
+ export interface DetailLimit {
130
+ /** The lens or the sensor. */
131
+ limitedBy: DetailLimitedBy;
132
+ /** Diffraction, aberrations or defocus (the lens), or the pixel pitch (the sensor). */
133
+ limitingFactor: DetailLimitingFactor;
134
+ /** Optics MTF50 / Nyquist frequency: at least 1 when the sensor limits. */
135
+ opticsToNyquistRatio: number;
136
+ fNumber: number;
137
+ wavelengthNm: number;
138
+ /** Physical focal length used (the catalogue lens's on this sensor), mm. */
139
+ focalLengthMm: number;
140
+ fieldPosition: number;
141
+ optics: DetailLimitOptics;
142
+ sampling: DetailLimitSampling;
143
+ system: DetailLimitSystem;
144
+ /**
145
+ * The f-number at which an aberration-free lens in focus has its MTF50 at the Nyquist frequency (2·p·0.40397/λ at
146
+ * infinity focus): from it on, diffraction limits detail on this sensor whatever the lens.
147
+ */
148
+ diffractionLimitedFNumber: number;
149
+ basis: Readonly<Record<"optics" | "sampling" | "system" | "limitedBy", DetailLimitBasis>>;
150
+ }
151
+ /** @internal Seidel and defocus terms of the wavefront in waves at the wavelength, field along +y. */
152
+ export interface DetailLimitWavefront {
153
+ defocus: number;
154
+ spherical: number;
155
+ coma: number;
156
+ astigmatism: number;
157
+ fieldCurvature: number;
158
+ }
159
+ /**
160
+ * @internal |OTF| at normalized frequency s (0 ≤ s < 1) along the pupil's x axis (`tangential` false) or y axis (true). The overlap
161
+ * |ρ ± s·e| ≤ 1 is |a| ≤ 1 − s, |b| ≤ √(1 − (|a| + s)²) in coordinates (a along e, b across); |a| = (1 − s)(1 − τ²) removes
162
+ * the square-root edge, so the integrand is smooth in τ and in b/b_max.
163
+ */
164
+ export declare function detailLimitOpticsMtf(w: DetailLimitWavefront, s: number, tangential: boolean, nodeScale?: number): number;
165
+ /**
166
+ * Which limits detail for given settings: the lens (diffraction at this f-number, aberrations, defocus) or the sensor's pixel
167
+ * pitch. Returns the optics' resolution (MTF50 and the diffraction cut-off, cycles/mm), the sampling's (Nyquist frequency
168
+ * and, with a Bayer filter, the red and blue sites'), the system MTF50 (optics × pixel aperture), the f-number from which
169
+ * diffraction limits on this sensor, and which one limits.
170
+ *
171
+ * The sensor limits when the optics still pass 50 % contrast at the Nyquist frequency 1/(2p); otherwise the lens does,
172
+ * through diffraction when its wavefront error is within the Maréchal criterion (RMS ≤ λ/14), else through aberrations or
173
+ * defocus. The optics MTF is the exact scalar OTF of the stated wavefront at one wavelength; the decision rule and the
174
+ * catalogue lenses' wavefronts are approximations.
175
+ *
176
+ * Example: an ideal 50 mm lens at f/22 on a 36 × 24 mm, 6000-pixel-wide sensor (6 µm) is limited by diffraction (optics
177
+ * MTF50 ≈ 33 cycles/mm against a Nyquist frequency of ≈ 83); at f/4 the pixel pitch limits.
178
+ *
179
+ * @param input Sensor, lens, f-number, and optional focus, field position and wavelength.
180
+ * @returns The resolution of the optics and of the sampling, and which limits detail.
181
+ */
182
+ export declare function calculateDetailLimit(input: CalculateDetailLimitInput): CalculationResult<DetailLimit>;