@photivra/engine 2.18.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +179 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +14 -10
- package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
- package/dist/capture/dng-lens-correction-opcodes.js +119 -0
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +2 -6
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +6 -0
- package/dist/capture/native-raw-dng.js +16 -2
- package/dist/capture/native-raw-dng.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +3 -5
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +35 -0
- package/dist/core/shared-helpers.js +38 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +8 -2
- package/dist/equipment/generic-lens-catalogue.js +31 -2
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.js +2 -3
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.js +2 -3
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/display-view-gpu.d.ts +7 -4
- package/dist/facade/display-view-gpu.js +4 -4
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +1 -1
- package/dist/facade/display-view-lens-signal.js +5 -3
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.d.ts +3 -1
- package/dist/facade/display-view.js +1 -1
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +50 -0
- package/dist/facade/fast-methods.js.map +1 -0
- package/dist/facade/fast-resolution.d.ts +12 -0
- package/dist/facade/fast-resolution.js +18 -0
- package/dist/facade/fast-resolution.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +6 -3
- package/dist/facade/generic-lens-capture.js +6 -3
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -16
- package/dist/facade/simulate-capture.js +279 -153
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +3 -2
- package/dist/facade/simulate-display-view.js +22 -12
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/aperture-diameter.d.ts +47 -0
- package/dist/optics/aperture-diameter.js +50 -0
- package/dist/optics/aperture-diameter.js.map +1 -0
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/detail-limit.d.ts +182 -0
- package/dist/optics/detail-limit.js +336 -0
- package/dist/optics/detail-limit.js.map +1 -0
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +25 -2
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +11 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/crop-to-match-focal-length.d.ts +62 -0
- package/dist/output/crop-to-match-focal-length.js +63 -0
- package/dist/output/crop-to-match-focal-length.js.map +1 -0
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +5 -7
- package/dist/output/generic-lens-corrections.js +11 -10
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +12 -2
- package/dist/output/lens-corrections.js +22 -7
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/print-contrast-reference.js +1 -1
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-size-blur-noise.d.ts +110 -0
- package/dist/output/print-size-blur-noise.js +138 -0
- package/dist/output/print-size-blur-noise.js.map +1 -0
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -41
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +7 -0
- package/dist/sensor/exposure-window.js +9 -24
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +4 -79
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +4 -35
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -114
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/sensor-characteristics.d.ts +137 -0
- package/dist/sensor/sensor-characteristics.js +115 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +3 -24
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +3 -41
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +3 -0
- package/dist/sensor/temporal-photo-signal.js +5 -2
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.d.ts +9 -0
- package/dist/stabilization/system.js +7 -86
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +116 -3
- package/docs/QUICK_START.md +178 -14
- package/docs/USAGE.md +111 -3
- package/docs/api/capture-native-raw-dng.md +6 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +7 -2
- package/docs/api/exports.json +203 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-fast-methods.md +91 -0
- package/docs/api/facade-simulate-capture.md +72 -16
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +3 -10
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +5 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zernike-wavefront.js","sourceRoot":"","sources":["../../src/optics/zernike-wavefront.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Describes lens aberrations as a wavefront, for the complex-pupil PSF (point-spread function)\n * reference.\n *\n * This module builds the declared pupil grid: relative amplitude plus optical path difference (OPD)\n * in micrometres. calculateLensComplexPupilPsf() uses that grid unchanged. This module does no light\n * propagation itself.\n *\n * Zernike polynomials use Noll's single index j >= 1 and Noll's normalisation (Noll 1976, JOSA\n * 66:207):\n * - m = 0: Z_j = sqrt(n + 1) R_n^0(rho)\n * - m != 0: Z_j = sqrt(2 (n + 1)) R_n^|m|(rho) cos(m theta) for even j, or sin(m theta) for odd j\n * So each term has an RMS of 1 over the unit disk. The RMS wavefront error of sum_j c_j Z_j (piston\n * excluded) is sqrt(sum_{j>=2} c_j^2). The radial polynomial R_n^m is the standard one in Noll's\n * nomenclature (Mathar, arXiv:0809.2368, eq. 1, free). Also see: Born & Wolf, Principles of Optics,\n * 7th ed., sec. 9.2 and app. VII.\n *\n * Primary (Seidel) aberrations use the wave-aberration expansion in normalised field height H and\n * normalised pupil coordinates (rho, phi), phi measured from the field direction (Hopkins 1950,\n * Wave Theory of Aberrations; Wyant & Creath 1992, Applied Optics and Optical Engineering XI ch. 1):\n * W = W020 rho^2 + W111 H rho cos(phi) + W040 rho^4 + W131 H rho^3 cos(phi)\n * + W222 H^2 rho^2 cos^2(phi) + W220 H^2 rho^2 + W311 H^3 rho cos(phi).\n *\n * Paraxial defocus: an image-plane defocus dz at working f-number N gives W020 = dz / (8 N^2)\n * (Wyant & Creath 1992, Applied Optics and Optical Engineering XI ch. 1, eq. 18, free author copy.\n * Also see: Goodman, Introduction to Fourier Optics, 3rd ed., sec. 6.4; Mahajan, Optical Imaging and\n * Aberrations Part I, sec. 3.4). That is a Zernike Z4 coefficient of W020 / (2 sqrt 3).\n *\n * Marechal/Mahajan approximation: Strehl ratio ~ exp(-(2 pi sigma / lambda)^2) for a small RMS\n * wavefront error sigma (Marechal 1947; Mahajan 1982 JOSA 72:1258; free: Wyant & Creath 1992,\n * ch. 1, eq. 67). It is an approximation, valid\n * roughly for Strehl ratios above 0.3.\n *\n * Pupil coordinates are in metric units, aligned with the image plane (+X right, +Y up). theta is\n * measured counter-clockwise from +X.\n * @see docs/PSF_FOUNDATION.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport {\n approximationResult,\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport type { LensComplexPupilGrid } from \"./complex-pupil-psf.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Largest supported Noll index (radial order n <= 10). */\nexport const ZERNIKE_MAXIMUM_NOLL_INDEX = 66;\n/** Largest odd pupil grid width: 63 x 63 = 3969 samples, within the complex-pupil 4096 limit. */\nexport const ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS = 63;\n\nexport interface ZernikeOrder {\n nollIndex: number;\n /** Radial order n. */\n radialOrder: number;\n /** Signed azimuthal frequency m. Positive means cos(m theta); negative means sin(|m| theta). */\n azimuthalFrequency: number;\n}\n\nexport interface ZernikeCoefficient {\n nollIndex: number;\n /** Coefficient of the unit-RMS Noll polynomial, in micrometres of optical path difference. */\n coefficientMicrometers: number;\n}\n\n/** Peak Seidel wave-aberration coefficients in micrometres of optical path difference. */\nexport interface SeidelWavefrontCoefficients {\n /** Defocus rho^2. */\n w020Micrometers?: number;\n /** Tilt H rho cos(phi). */\n w111Micrometers?: number;\n /** Spherical aberration rho^4. */\n w040Micrometers?: number;\n /** Coma H rho^3 cos(phi). */\n w131Micrometers?: number;\n /** Astigmatism H^2 rho^2 cos^2(phi). */\n w222Micrometers?: number;\n /** Field curvature H^2 rho^2. */\n w220Micrometers?: number;\n /** Distortion H^3 rho cos(phi). */\n w311Micrometers?: number;\n}\n\nexport interface SeidelFieldPosition {\n /** Normalised field height H in [0, 1]. */\n normalizedFieldHeight: number;\n /** Image-plane direction of the field point, degrees counter-clockwise from +X. */\n fieldAzimuthDegrees: number;\n}\n\nexport interface CreateWavefrontPupilGridInput {\n /** Pupil diameter in mm; rho = 1 at radius pupilDiameterMm / 2. */\n pupilDiameterMm: number;\n /** Odd number of samples across the pupil diameter, from 3 to 63. */\n samplesAcross: number;\n zernikeCoefficients?: readonly ZernikeCoefficient[];\n seidelCoefficients?: SeidelWavefrontCoefficients;\n /** Required when any field-dependent Seidel coefficient is non-zero. */\n seidelField?: SeidelFieldPosition;\n /**\n * Optional additional aperture mask: a simple polygon in pupil-plane mm (for example the\n * cat's-eye pupil from calculateMechanicalVignetting). Samples outside it get zero amplitude.\n */\n apertureMaskVerticesMm?: readonly { x: number; y: number }[];\n}\n\nexport interface WavefrontPupilGrid {\n /** Grid for LensComplexPupilProfile.grid. Amplitude is 1 inside and 0 outside; OPD is in micrometres. */\n grid: LensComplexPupilGrid;\n pupilDiameterMm: number;\n /** Number of samples with non-zero amplitude. */\n openSampleCount: number;\n /** sqrt(sum c_j^2, j >= 2): RMS of the Zernike terms alone over the continuous unit disk. */\n zernikeRmsMicrometers: number;\n /** RMS of the sampled OPD over open samples, with piston removed (all terms). */\n sampledRmsMicrometers: number;\n /** Peak-to-valley of the sampled OPD over open samples. */\n sampledPeakToValleyMicrometers: number;\n}\n\nexport interface CalculateDefocusWavefrontInput {\n /** Signed image-plane defocus, sensor minus image distance, in micrometres. */\n signedDefocusImagePlaneMicrometers: number;\n /** Image-side working f-number (image distance / pupil diameter). */\n workingFNumber: number;\n}\n\nexport interface DefocusWavefront {\n signedDefocusImagePlaneMicrometers: number;\n workingFNumber: number;\n /** Peak defocus coefficient W020 = dz / (8 N^2), micrometres. */\n w020Micrometers: number;\n /** Equivalent Noll Z4 coefficient W020 / (2 sqrt 3), micrometres (equals the RMS). */\n zernikeZ4Micrometers: number;\n}\n\nexport interface EstimateMarechalStrehlRatioInput {\n rmsWavefrontErrorMicrometers: number;\n wavelengthNm: number;\n}\n\nfunction requireFinite(name: string, value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new InvalidScientificInputError(`${name} must be finite.`);\n }\n return value;\n}\n\nfunction requireNollIndex(value: unknown): number {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < 1 ||\n value > ZERNIKE_MAXIMUM_NOLL_INDEX\n ) {\n throw new InvalidScientificInputError(\n `nollIndex must be an integer from 1 through ${ZERNIKE_MAXIMUM_NOLL_INDEX}.`\n );\n }\n return value;\n}\n\n/** Converts a Noll index to radial order n and signed azimuthal frequency m (Noll 1976). */\nexport function resolveZernikeNollOrder(nollIndex: number): ZernikeOrder {\n const j = requireNollIndex(nollIndex);\n let n = 0;\n while (((n + 1) * (n + 2)) / 2 < j) {\n n += 1;\n }\n // Position within radial order n; |m| increases with it, two indices per non-zero |m|.\n const k = j - (n * (n + 1)) / 2 - 1;\n const absoluteM =\n n % 2 === 0 ? 2 * Math.floor((k + 1) / 2) : 2 * Math.floor(k / 2) + 1;\n return {\n nollIndex: j,\n radialOrder: n,\n azimuthalFrequency:\n absoluteM === 0 ? 0 : j % 2 === 0 ? absoluteM : -absoluteM\n };\n}\n\nfunction factorial(value: number): number {\n let result = 1;\n for (let k = 2; k <= value; k += 1) result *= k;\n return result;\n}\n\nfunction radialPolynomial(n: number, m: number, rho: number): number {\n let sum = 0;\n for (let k = 0; k <= (n - m) / 2; k += 1) {\n const coefficient =\n ((k % 2 === 0 ? 1 : -1) * factorial(n - k)) /\n (factorial(k) * factorial((n + m) / 2 - k) * factorial((n - m) / 2 - k));\n sum += coefficient * rho ** (n - 2 * k);\n }\n return sum;\n}\n\n/** Evaluates the unit-RMS Noll Zernike polynomial at normalised pupil polar coordinates. */\nexport function evaluateZernikePolynomial(\n nollIndex: number,\n normalizedRadius: number,\n azimuthRadians: number\n): number {\n const order = resolveZernikeNollOrder(nollIndex);\n const rho = requireFinite(\"normalizedRadius\", normalizedRadius);\n const theta = requireFinite(\"azimuthRadians\", azimuthRadians);\n if (rho < 0 || rho > 1 + 1e-12) {\n throw new InvalidScientificInputError(\n \"normalizedRadius must lie in [0, 1].\"\n );\n }\n const n = order.radialOrder;\n const m = Math.abs(order.azimuthalFrequency);\n const radial = radialPolynomial(n, m, Math.min(1, rho));\n if (m === 0) {\n return Math.sqrt(n + 1) * radial;\n }\n const angular =\n order.azimuthalFrequency > 0 ? Math.cos(m * theta) : Math.sin(m * theta);\n return Math.sqrt(2 * (n + 1)) * radial * angular;\n}\n\nfunction parseZernike(\n value: readonly ZernikeCoefficient[] | undefined\n): ZernikeCoefficient[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\"zernikeCoefficients must be an array.\");\n }\n const seen = new Set<number>();\n return value.map((entry, index) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw new InvalidConfigurationError(`zernikeCoefficients[${index}] must be an object.`);\n }\n const nollIndex = requireNollIndex(entry.nollIndex);\n if (seen.has(nollIndex)) {\n throw new InvalidScientificInputError(\"zernikeCoefficients must not repeat a nollIndex.\");\n }\n seen.add(nollIndex);\n return {\n nollIndex,\n coefficientMicrometers: requireFinite(\n `zernikeCoefficients[${index}].coefficientMicrometers`,\n entry.coefficientMicrometers\n )\n };\n });\n}\n\nconst SEIDEL_KEYS = [\n \"w020Micrometers\",\n \"w111Micrometers\",\n \"w040Micrometers\",\n \"w131Micrometers\",\n \"w222Micrometers\",\n \"w220Micrometers\",\n \"w311Micrometers\"\n] as const;\n\nfunction parseSeidel(\n value: SeidelWavefrontCoefficients | undefined\n): Required<SeidelWavefrontCoefficients> {\n const result = {\n w020Micrometers: 0,\n w111Micrometers: 0,\n w040Micrometers: 0,\n w131Micrometers: 0,\n w222Micrometers: 0,\n w220Micrometers: 0,\n w311Micrometers: 0\n };\n if (value === undefined) return result;\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(\"seidelCoefficients must be an object.\");\n }\n for (const key of Object.keys(value)) {\n if (!(SEIDEL_KEYS as readonly string[]).includes(key)) {\n throw new InvalidConfigurationError(`seidelCoefficients.${key} is not supported.`);\n }\n }\n for (const key of SEIDEL_KEYS) {\n if (value[key] !== undefined) {\n result[key] = requireFinite(`seidelCoefficients.${key}`, value[key]);\n }\n }\n return result;\n}\n\nfunction pointInPolygon(\n x: number,\n y: number,\n vertices: readonly { x: number; y: number }[]\n): boolean {\n let inside = false;\n for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i, i += 1) {\n const a = vertices[i]!;\n const b = vertices[j]!;\n if (\n a.y > y !== b.y > y &&\n x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x\n ) {\n inside = !inside;\n }\n }\n return inside;\n}\n\nfunction parseMask(\n value: readonly { x: number; y: number }[] | undefined\n): readonly { x: number; y: number }[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.length < 3 || value.length > 4096) {\n throw new InvalidScientificInputError(\n \"apertureMaskVerticesMm must contain 3 through 4096 vertices.\"\n );\n }\n return value.map((vertex, index) => {\n if (typeof vertex !== \"object\" || vertex === null) {\n throw new InvalidConfigurationError(`apertureMaskVerticesMm[${index}] must be an object.`);\n }\n return {\n x: requireFinite(`apertureMaskVerticesMm[${index}].x`, vertex.x),\n y: requireFinite(`apertureMaskVerticesMm[${index}].y`, vertex.y)\n };\n });\n}\n\n/**\n * Builds a complex-pupil grid: a circular pupil, an optional polygon mask, and an OPD from Zernike\n * coefficients, Seidel coefficients or both. If every coefficient is zero, the OPD is exactly zero,\n * so the PSF equals the existing aberration-free circular-pupil reference.\n */\nexport function createWavefrontPupilGrid(\n input: CreateWavefrontPupilGridInput\n): CalculationResult<WavefrontPupilGrid> {\n requireInputKeys(input, \"createWavefrontPupilGrid\", [\"pupilDiameterMm\", \"samplesAcross\", \"zernikeCoefficients\", \"seidelCoefficients\", \"seidelField\", \"apertureMaskVerticesMm\"]);\n requirePositiveFinite(\"pupilDiameterMm\", input.pupilDiameterMm);\n const n = input.samplesAcross;\n if (\n !Number.isSafeInteger(n) ||\n n < 3 ||\n n > ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS ||\n n % 2 === 0\n ) {\n throw new InvalidScientificInputError(\n `samplesAcross must be an odd integer from 3 through ${ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS}.`\n );\n }\n const zernike = parseZernike(input.zernikeCoefficients);\n const seidel = parseSeidel(input.seidelCoefficients);\n const mask = parseMask(input.apertureMaskVerticesMm);\n const fieldDependent =\n seidel.w111Micrometers !== 0 ||\n seidel.w131Micrometers !== 0 ||\n seidel.w222Micrometers !== 0 ||\n seidel.w220Micrometers !== 0 ||\n seidel.w311Micrometers !== 0;\n let fieldHeight = 0;\n let fieldAzimuth = 0;\n if (input.seidelField !== undefined) {\n if (typeof input.seidelField !== \"object\" || input.seidelField === null) {\n throw new InvalidConfigurationError(\"seidelField must be an object.\");\n }\n fieldHeight = requireFinite(\n \"seidelField.normalizedFieldHeight\",\n input.seidelField.normalizedFieldHeight\n );\n if (fieldHeight < 0 || fieldHeight > 1) {\n throw new InvalidScientificInputError(\n \"seidelField.normalizedFieldHeight must lie in [0, 1].\"\n );\n }\n fieldAzimuth =\n (requireFinite(\"seidelField.fieldAzimuthDegrees\", input.seidelField.fieldAzimuthDegrees) *\n Math.PI) /\n 180;\n } else if (fieldDependent) {\n throw new InvalidScientificInputError(\n \"seidelField is required when a field-dependent Seidel coefficient is non-zero.\"\n );\n }\n\n const radiusMm = input.pupilDiameterMm / 2;\n const pitch = input.pupilDiameterMm / (n - 1);\n const center = (n - 1) / 2;\n const amplitude: number[] = [];\n const opd: number[] = [];\n const open: number[] = [];\n for (let row = 0; row < n; row += 1) {\n for (let column = 0; column < n; column += 1) {\n const xMm = (column - center) * pitch;\n const yMm = (row - center) * pitch;\n const rho = Math.hypot(xMm, yMm) / radiusMm;\n const inside =\n rho <= 1 + 1e-12 && (mask === undefined || pointInPolygon(xMm, yMm, mask));\n if (!inside) {\n amplitude.push(0);\n opd.push(0);\n continue;\n }\n const r = Math.min(1, rho);\n const theta = Math.atan2(yMm, xMm);\n let w = 0;\n for (const term of zernike) {\n if (term.coefficientMicrometers !== 0) {\n w += term.coefficientMicrometers * evaluateZernikePolynomial(term.nollIndex, r, theta);\n }\n }\n const cosPhi = Math.cos(theta - fieldAzimuth);\n const r2 = r * r;\n w +=\n seidel.w020Micrometers * r2 +\n seidel.w040Micrometers * r2 * r2 +\n seidel.w111Micrometers * fieldHeight * r * cosPhi +\n seidel.w131Micrometers * fieldHeight * r2 * r * cosPhi +\n seidel.w222Micrometers * fieldHeight * fieldHeight * r2 * cosPhi * cosPhi +\n seidel.w220Micrometers * fieldHeight * fieldHeight * r2 +\n seidel.w311Micrometers * fieldHeight ** 3 * r * cosPhi;\n amplitude.push(1);\n opd.push(w);\n open.push(w);\n }\n }\n if (open.length === 0) {\n throw new InvalidScientificInputError(\n \"The aperture mask leaves no open pupil samples.\"\n );\n }\n const mean = open.reduce((sum, value) => sum + value, 0) / open.length;\n const variance =\n open.reduce((sum, value) => sum + (value - mean) ** 2, 0) / open.length;\n const zernikeRms = Math.sqrt(\n zernike\n .filter((term) => term.nollIndex >= 2)\n .reduce((sum, term) => sum + term.coefficientMicrometers ** 2, 0)\n );\n\n return approximationResult(\n {\n grid: {\n widthSamples: n,\n heightSamples: n,\n pupilSamplePitchMmX: pitch,\n pupilSamplePitchMmY: pitch,\n centerSampleX: center,\n centerSampleY: center,\n relativeAmplitude: amplitude,\n opticalPathDifferenceMicrometers: opd\n },\n pupilDiameterMm: input.pupilDiameterMm,\n openSampleCount: open.length,\n zernikeRmsMicrometers: zernikeRms,\n sampledRmsMicrometers: Math.sqrt(variance),\n sampledPeakToValleyMicrometers: Math.max(...open) - Math.min(...open)\n },\n \"zernike-seidel-wavefront-pupil-grid\",\n \"1.0.0\",\n [\n \"Uniform unit amplitude inside the circular pupil (and inside the optional polygon mask); zero outside\",\n \"Noll-indexed, unit-RMS Zernike polynomials over the unit disk; Seidel terms are peak wave-aberration coefficients\",\n \"Pupil coordinates are metric and aligned with the image plane (+X right, +Y up)\",\n \"Sampled RMS differs slightly from the continuous Zernike RMS because the disk is represented by discrete samples\",\n \"Coefficients are caller inputs; no named-lens calibration is implied\"\n ]\n );\n}\n\n/**\n * Converts a signed paraxial image-plane defocus into the defocus wave aberration\n * W020 = dz / (8 N^2) and its Noll Z4 coefficient W020 / (2 sqrt 3).\n *\n * Sign convention: dz = sensor distance minus image distance. Positive W020 means the image lies in\n * front of the sensor. With pure defocus, the PSF intensity does not depend on the sign.\n */\nexport function calculateDefocusWavefront(\n input: CalculateDefocusWavefrontInput\n): CalculationResult<DefocusWavefront> {\n requireInputKeys(input, \"calculateDefocusWavefront\", [\"signedDefocusImagePlaneMicrometers\", \"workingFNumber\"]);\n const dz = requireFinite(\n \"signedDefocusImagePlaneMicrometers\",\n input.signedDefocusImagePlaneMicrometers\n );\n requirePositiveFinite(\"workingFNumber\", input.workingFNumber);\n const w020 = dz / (8 * input.workingFNumber * input.workingFNumber);\n return calculatedResult(\n {\n signedDefocusImagePlaneMicrometers: dz,\n workingFNumber: input.workingFNumber,\n w020Micrometers: w020,\n zernikeZ4Micrometers: w020 / (2 * Math.sqrt(3))\n },\n \"paraxial-defocus-wavefront\",\n \"1.0.0\",\n [\n \"Paraxial (small-angle) relation between longitudinal image-plane defocus and the rho^2 wave aberration\",\n \"Sign convention: defocus is sensor minus image distance\"\n ]\n );\n}\n\n/**\n * Marechal/Mahajan approximation of the Strehl ratio: exp(-(2 pi sigma / lambda)^2). Valid only for a\n * small RMS wavefront error (Strehl roughly above 0.3). It is not an exact PSF calculation.\n */\nexport function estimateMarechalStrehlRatio(\n input: EstimateMarechalStrehlRatioInput\n): CalculationResult<{ strehlRatio: number; rmsWaves: number }> {\n requireInputKeys(input, \"estimateMarechalStrehlRatio\", [\"rmsWavefrontErrorMicrometers\", \"wavelengthNm\"]);\n const sigma = requireFinite(\n \"rmsWavefrontErrorMicrometers\",\n input.rmsWavefrontErrorMicrometers\n );\n if (sigma < 0) {\n throw new InvalidScientificInputError(\n \"rmsWavefrontErrorMicrometers must be non-negative.\"\n );\n }\n requirePositiveFinite(\"wavelengthNm\", input.wavelengthNm);\n const rmsWaves = sigma / (input.wavelengthNm / 1000);\n return approximationResult(\n {\n strehlRatio: Math.exp(-((2 * Math.PI * rmsWaves) ** 2)),\n rmsWaves\n },\n \"marechal-mahajan-strehl-approximation\",\n \"1.0.0\",\n [\n \"Strehl ratio approximated as exp(-(2 pi sigma / lambda)^2) (Marechal 1947; Mahajan 1982)\",\n \"Valid for small RMS wavefront error, roughly Strehl above 0.3; it is not an exact PSF evaluation\"\n ]\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"zernike-wavefront.js","sourceRoot":"","sources":["../../src/optics/zernike-wavefront.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Describes lens aberrations as a wavefront, for the complex-pupil PSF (point-spread function)\n * reference.\n *\n * This module builds the declared pupil grid: relative amplitude plus optical path difference (OPD)\n * in micrometres. calculateLensComplexPupilPsf() uses that grid unchanged. This module does no light\n * propagation itself.\n *\n * Zernike polynomials use Noll's single index j >= 1 and Noll's normalisation (Noll 1976, JOSA\n * 66:207):\n * - m = 0: Z_j = sqrt(n + 1) R_n^0(rho)\n * - m != 0: Z_j = sqrt(2 (n + 1)) R_n^|m|(rho) cos(m theta) for even j, or sin(m theta) for odd j\n * So each term has an RMS of 1 over the unit disk. The RMS wavefront error of sum_j c_j Z_j (piston\n * excluded) is sqrt(sum_{j>=2} c_j^2). The radial polynomial R_n^m is the standard one in Noll's\n * nomenclature (Mathar, arXiv:0809.2368, eq. 1, free). Also see: Born & Wolf, Principles of Optics,\n * 7th ed., sec. 9.2 and app. VII.\n *\n * Primary (Seidel) aberrations use the wave-aberration expansion in normalised field height H and\n * normalised pupil coordinates (rho, phi), phi measured from the field direction (Hopkins 1950,\n * Wave Theory of Aberrations; Wyant & Creath 1992, Applied Optics and Optical Engineering XI ch. 1):\n * W = W020 rho^2 + W111 H rho cos(phi) + W040 rho^4 + W131 H rho^3 cos(phi)\n * + W222 H^2 rho^2 cos^2(phi) + W220 H^2 rho^2 + W311 H^3 rho cos(phi).\n *\n * Paraxial defocus: an image-plane defocus dz at working f-number N gives W020 = dz / (8 N^2)\n * (Wyant & Creath 1992, Applied Optics and Optical Engineering XI ch. 1, eq. 18, free author copy.\n * Also see: Goodman, Introduction to Fourier Optics, 3rd ed., sec. 6.4; Mahajan, Optical Imaging and\n * Aberrations Part I, sec. 3.4). That is a Zernike Z4 coefficient of W020 / (2 sqrt 3).\n *\n * Marechal/Mahajan approximation: Strehl ratio ~ exp(-(2 pi sigma / lambda)^2) for a small RMS\n * wavefront error sigma (Marechal 1947; Mahajan 1982 JOSA 72:1258; free: Wyant & Creath 1992,\n * ch. 1, eq. 67). It is an approximation, valid\n * roughly for Strehl ratios above 0.3.\n *\n * Pupil coordinates are in metric units, aligned with the image plane (+X right, +Y up). theta is\n * measured counter-clockwise from +X.\n * @see docs/PSF_FOUNDATION.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport {\n approximationResult,\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport type { LensComplexPupilGrid } from \"./complex-pupil-psf.js\";\nimport { requireInputKeys, requireNamedFinite as requireFinite } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Largest supported Noll index (radial order n <= 10). */\nexport const ZERNIKE_MAXIMUM_NOLL_INDEX = 66;\n/** Largest odd pupil grid width: 63 x 63 = 3969 samples, within the complex-pupil 4096 limit. */\nexport const ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS = 63;\n\nexport interface ZernikeOrder {\n nollIndex: number;\n /** Radial order n. */\n radialOrder: number;\n /** Signed azimuthal frequency m. Positive means cos(m theta); negative means sin(|m| theta). */\n azimuthalFrequency: number;\n}\n\nexport interface ZernikeCoefficient {\n nollIndex: number;\n /** Coefficient of the unit-RMS Noll polynomial, in micrometres of optical path difference. */\n coefficientMicrometers: number;\n}\n\n/** Peak Seidel wave-aberration coefficients in micrometres of optical path difference. */\nexport interface SeidelWavefrontCoefficients {\n /** Defocus rho^2. */\n w020Micrometers?: number;\n /** Tilt H rho cos(phi). */\n w111Micrometers?: number;\n /** Spherical aberration rho^4. */\n w040Micrometers?: number;\n /** Coma H rho^3 cos(phi). */\n w131Micrometers?: number;\n /** Astigmatism H^2 rho^2 cos^2(phi). */\n w222Micrometers?: number;\n /** Field curvature H^2 rho^2. */\n w220Micrometers?: number;\n /** Distortion H^3 rho cos(phi). */\n w311Micrometers?: number;\n}\n\nexport interface SeidelFieldPosition {\n /** Normalised field height H in [0, 1]. */\n normalizedFieldHeight: number;\n /** Image-plane direction of the field point, degrees counter-clockwise from +X. */\n fieldAzimuthDegrees: number;\n}\n\nexport interface CreateWavefrontPupilGridInput {\n /** Pupil diameter in mm; rho = 1 at radius pupilDiameterMm / 2. */\n pupilDiameterMm: number;\n /** Odd number of samples across the pupil diameter, from 3 to 63. */\n samplesAcross: number;\n zernikeCoefficients?: readonly ZernikeCoefficient[];\n seidelCoefficients?: SeidelWavefrontCoefficients;\n /** Required when any field-dependent Seidel coefficient is non-zero. */\n seidelField?: SeidelFieldPosition;\n /**\n * Optional additional aperture mask: a simple polygon in pupil-plane mm (for example the\n * cat's-eye pupil from calculateMechanicalVignetting). Samples outside it get zero amplitude.\n */\n apertureMaskVerticesMm?: readonly { x: number; y: number }[];\n}\n\nexport interface WavefrontPupilGrid {\n /** Grid for LensComplexPupilProfile.grid. Amplitude is 1 inside and 0 outside; OPD is in micrometres. */\n grid: LensComplexPupilGrid;\n pupilDiameterMm: number;\n /** Number of samples with non-zero amplitude. */\n openSampleCount: number;\n /** sqrt(sum c_j^2, j >= 2): RMS of the Zernike terms alone over the continuous unit disk. */\n zernikeRmsMicrometers: number;\n /** RMS of the sampled OPD over open samples, with piston removed (all terms). */\n sampledRmsMicrometers: number;\n /** Peak-to-valley of the sampled OPD over open samples. */\n sampledPeakToValleyMicrometers: number;\n}\n\nexport interface CalculateDefocusWavefrontInput {\n /** Signed image-plane defocus, sensor minus image distance, in micrometres. */\n signedDefocusImagePlaneMicrometers: number;\n /** Image-side working f-number (image distance / pupil diameter). */\n workingFNumber: number;\n}\n\nexport interface DefocusWavefront {\n signedDefocusImagePlaneMicrometers: number;\n workingFNumber: number;\n /** Peak defocus coefficient W020 = dz / (8 N^2), micrometres. */\n w020Micrometers: number;\n /** Equivalent Noll Z4 coefficient W020 / (2 sqrt 3), micrometres (equals the RMS). */\n zernikeZ4Micrometers: number;\n}\n\nexport interface EstimateMarechalStrehlRatioInput {\n rmsWavefrontErrorMicrometers: number;\n wavelengthNm: number;\n}\n\nfunction requireNollIndex(value: unknown): number {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < 1 ||\n value > ZERNIKE_MAXIMUM_NOLL_INDEX\n ) {\n throw new InvalidScientificInputError(\n `nollIndex must be an integer from 1 through ${ZERNIKE_MAXIMUM_NOLL_INDEX}.`\n );\n }\n return value;\n}\n\n/** Converts a Noll index to radial order n and signed azimuthal frequency m (Noll 1976). */\nexport function resolveZernikeNollOrder(nollIndex: number): ZernikeOrder {\n const j = requireNollIndex(nollIndex);\n let n = 0;\n while (((n + 1) * (n + 2)) / 2 < j) {\n n += 1;\n }\n // Position within radial order n; |m| increases with it, two indices per non-zero |m|.\n const k = j - (n * (n + 1)) / 2 - 1;\n const absoluteM =\n n % 2 === 0 ? 2 * Math.floor((k + 1) / 2) : 2 * Math.floor(k / 2) + 1;\n return {\n nollIndex: j,\n radialOrder: n,\n azimuthalFrequency:\n absoluteM === 0 ? 0 : j % 2 === 0 ? absoluteM : -absoluteM\n };\n}\n\nfunction factorial(value: number): number {\n let result = 1;\n for (let k = 2; k <= value; k += 1) result *= k;\n return result;\n}\n\nfunction radialPolynomial(n: number, m: number, rho: number): number {\n let sum = 0;\n for (let k = 0; k <= (n - m) / 2; k += 1) {\n const coefficient =\n ((k % 2 === 0 ? 1 : -1) * factorial(n - k)) /\n (factorial(k) * factorial((n + m) / 2 - k) * factorial((n - m) / 2 - k));\n sum += coefficient * rho ** (n - 2 * k);\n }\n return sum;\n}\n\n/** Evaluates the unit-RMS Noll Zernike polynomial at normalised pupil polar coordinates. */\nexport function evaluateZernikePolynomial(\n nollIndex: number,\n normalizedRadius: number,\n azimuthRadians: number\n): number {\n const order = resolveZernikeNollOrder(nollIndex);\n const rho = requireFinite(\"normalizedRadius\", normalizedRadius);\n const theta = requireFinite(\"azimuthRadians\", azimuthRadians);\n if (rho < 0 || rho > 1 + 1e-12) {\n throw new InvalidScientificInputError(\n \"normalizedRadius must lie in [0, 1].\"\n );\n }\n const n = order.radialOrder;\n const m = Math.abs(order.azimuthalFrequency);\n const radial = radialPolynomial(n, m, Math.min(1, rho));\n if (m === 0) {\n return Math.sqrt(n + 1) * radial;\n }\n const angular =\n order.azimuthalFrequency > 0 ? Math.cos(m * theta) : Math.sin(m * theta);\n return Math.sqrt(2 * (n + 1)) * radial * angular;\n}\n\nfunction parseZernike(\n value: readonly ZernikeCoefficient[] | undefined\n): ZernikeCoefficient[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\"zernikeCoefficients must be an array.\");\n }\n const seen = new Set<number>();\n return value.map((entry, index) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw new InvalidConfigurationError(`zernikeCoefficients[${index}] must be an object.`);\n }\n const nollIndex = requireNollIndex(entry.nollIndex);\n if (seen.has(nollIndex)) {\n throw new InvalidScientificInputError(\"zernikeCoefficients must not repeat a nollIndex.\");\n }\n seen.add(nollIndex);\n return {\n nollIndex,\n coefficientMicrometers: requireFinite(\n `zernikeCoefficients[${index}].coefficientMicrometers`,\n entry.coefficientMicrometers\n )\n };\n });\n}\n\nconst SEIDEL_KEYS = [\n \"w020Micrometers\",\n \"w111Micrometers\",\n \"w040Micrometers\",\n \"w131Micrometers\",\n \"w222Micrometers\",\n \"w220Micrometers\",\n \"w311Micrometers\"\n] as const;\n\nfunction parseSeidel(\n value: SeidelWavefrontCoefficients | undefined\n): Required<SeidelWavefrontCoefficients> {\n const result = {\n w020Micrometers: 0,\n w111Micrometers: 0,\n w040Micrometers: 0,\n w131Micrometers: 0,\n w222Micrometers: 0,\n w220Micrometers: 0,\n w311Micrometers: 0\n };\n if (value === undefined) return result;\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(\"seidelCoefficients must be an object.\");\n }\n for (const key of Object.keys(value)) {\n if (!(SEIDEL_KEYS as readonly string[]).includes(key)) {\n throw new InvalidConfigurationError(`seidelCoefficients.${key} is not supported.`);\n }\n }\n for (const key of SEIDEL_KEYS) {\n if (value[key] !== undefined) {\n result[key] = requireFinite(`seidelCoefficients.${key}`, value[key]);\n }\n }\n return result;\n}\n\nfunction pointInPolygon(\n x: number,\n y: number,\n vertices: readonly { x: number; y: number }[]\n): boolean {\n let inside = false;\n for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i, i += 1) {\n const a = vertices[i]!;\n const b = vertices[j]!;\n if (\n a.y > y !== b.y > y &&\n x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x\n ) {\n inside = !inside;\n }\n }\n return inside;\n}\n\nfunction parseMask(\n value: readonly { x: number; y: number }[] | undefined\n): readonly { x: number; y: number }[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.length < 3 || value.length > 4096) {\n throw new InvalidScientificInputError(\n \"apertureMaskVerticesMm must contain 3 through 4096 vertices.\"\n );\n }\n return value.map((vertex, index) => {\n if (typeof vertex !== \"object\" || vertex === null) {\n throw new InvalidConfigurationError(`apertureMaskVerticesMm[${index}] must be an object.`);\n }\n return {\n x: requireFinite(`apertureMaskVerticesMm[${index}].x`, vertex.x),\n y: requireFinite(`apertureMaskVerticesMm[${index}].y`, vertex.y)\n };\n });\n}\n\n/**\n * Builds a complex-pupil grid: a circular pupil, an optional polygon mask, and an OPD from Zernike\n * coefficients, Seidel coefficients or both. If every coefficient is zero, the OPD is exactly zero,\n * so the PSF equals the existing aberration-free circular-pupil reference.\n */\nexport function createWavefrontPupilGrid(\n input: CreateWavefrontPupilGridInput\n): CalculationResult<WavefrontPupilGrid> {\n requireInputKeys(input, \"createWavefrontPupilGrid\", [\"pupilDiameterMm\", \"samplesAcross\", \"zernikeCoefficients\", \"seidelCoefficients\", \"seidelField\", \"apertureMaskVerticesMm\"]);\n requirePositiveFinite(\"pupilDiameterMm\", input.pupilDiameterMm);\n const n = input.samplesAcross;\n if (\n !Number.isSafeInteger(n) ||\n n < 3 ||\n n > ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS ||\n n % 2 === 0\n ) {\n throw new InvalidScientificInputError(\n `samplesAcross must be an odd integer from 3 through ${ZERNIKE_PUPIL_MAXIMUM_SAMPLES_ACROSS}.`\n );\n }\n const zernike = parseZernike(input.zernikeCoefficients);\n const seidel = parseSeidel(input.seidelCoefficients);\n const mask = parseMask(input.apertureMaskVerticesMm);\n const fieldDependent =\n seidel.w111Micrometers !== 0 ||\n seidel.w131Micrometers !== 0 ||\n seidel.w222Micrometers !== 0 ||\n seidel.w220Micrometers !== 0 ||\n seidel.w311Micrometers !== 0;\n let fieldHeight = 0;\n let fieldAzimuth = 0;\n if (input.seidelField !== undefined) {\n if (typeof input.seidelField !== \"object\" || input.seidelField === null) {\n throw new InvalidConfigurationError(\"seidelField must be an object.\");\n }\n fieldHeight = requireFinite(\n \"seidelField.normalizedFieldHeight\",\n input.seidelField.normalizedFieldHeight\n );\n if (fieldHeight < 0 || fieldHeight > 1) {\n throw new InvalidScientificInputError(\n \"seidelField.normalizedFieldHeight must lie in [0, 1].\"\n );\n }\n fieldAzimuth =\n (requireFinite(\"seidelField.fieldAzimuthDegrees\", input.seidelField.fieldAzimuthDegrees) *\n Math.PI) /\n 180;\n } else if (fieldDependent) {\n throw new InvalidScientificInputError(\n \"seidelField is required when a field-dependent Seidel coefficient is non-zero.\"\n );\n }\n\n const radiusMm = input.pupilDiameterMm / 2;\n const pitch = input.pupilDiameterMm / (n - 1);\n const center = (n - 1) / 2;\n const amplitude: number[] = [];\n const opd: number[] = [];\n const open: number[] = [];\n for (let row = 0; row < n; row += 1) {\n for (let column = 0; column < n; column += 1) {\n const xMm = (column - center) * pitch;\n const yMm = (row - center) * pitch;\n const rho = Math.hypot(xMm, yMm) / radiusMm;\n const inside =\n rho <= 1 + 1e-12 && (mask === undefined || pointInPolygon(xMm, yMm, mask));\n if (!inside) {\n amplitude.push(0);\n opd.push(0);\n continue;\n }\n const r = Math.min(1, rho);\n const theta = Math.atan2(yMm, xMm);\n let w = 0;\n for (const term of zernike) {\n if (term.coefficientMicrometers !== 0) {\n w += term.coefficientMicrometers * evaluateZernikePolynomial(term.nollIndex, r, theta);\n }\n }\n const cosPhi = Math.cos(theta - fieldAzimuth);\n const r2 = r * r;\n w +=\n seidel.w020Micrometers * r2 +\n seidel.w040Micrometers * r2 * r2 +\n seidel.w111Micrometers * fieldHeight * r * cosPhi +\n seidel.w131Micrometers * fieldHeight * r2 * r * cosPhi +\n seidel.w222Micrometers * fieldHeight * fieldHeight * r2 * cosPhi * cosPhi +\n seidel.w220Micrometers * fieldHeight * fieldHeight * r2 +\n seidel.w311Micrometers * fieldHeight ** 3 * r * cosPhi;\n amplitude.push(1);\n opd.push(w);\n open.push(w);\n }\n }\n if (open.length === 0) {\n throw new InvalidScientificInputError(\n \"The aperture mask leaves no open pupil samples.\"\n );\n }\n const mean = open.reduce((sum, value) => sum + value, 0) / open.length;\n const variance =\n open.reduce((sum, value) => sum + (value - mean) ** 2, 0) / open.length;\n const zernikeRms = Math.sqrt(\n zernike\n .filter((term) => term.nollIndex >= 2)\n .reduce((sum, term) => sum + term.coefficientMicrometers ** 2, 0)\n );\n\n return approximationResult(\n {\n grid: {\n widthSamples: n,\n heightSamples: n,\n pupilSamplePitchMmX: pitch,\n pupilSamplePitchMmY: pitch,\n centerSampleX: center,\n centerSampleY: center,\n relativeAmplitude: amplitude,\n opticalPathDifferenceMicrometers: opd\n },\n pupilDiameterMm: input.pupilDiameterMm,\n openSampleCount: open.length,\n zernikeRmsMicrometers: zernikeRms,\n sampledRmsMicrometers: Math.sqrt(variance),\n sampledPeakToValleyMicrometers: Math.max(...open) - Math.min(...open)\n },\n \"zernike-seidel-wavefront-pupil-grid\",\n \"1.0.0\",\n [\n \"Uniform unit amplitude inside the circular pupil (and inside the optional polygon mask); zero outside\",\n \"Noll-indexed, unit-RMS Zernike polynomials over the unit disk; Seidel terms are peak wave-aberration coefficients\",\n \"Pupil coordinates are metric and aligned with the image plane (+X right, +Y up)\",\n \"Sampled RMS differs slightly from the continuous Zernike RMS because the disk is represented by discrete samples\",\n \"Coefficients are caller inputs; no named-lens calibration is implied\"\n ]\n );\n}\n\n/**\n * Converts a signed paraxial image-plane defocus into the defocus wave aberration\n * W020 = dz / (8 N^2) and its Noll Z4 coefficient W020 / (2 sqrt 3).\n *\n * Sign convention: dz = sensor distance minus image distance. Positive W020 means the image lies in\n * front of the sensor. With pure defocus, the PSF intensity does not depend on the sign.\n */\nexport function calculateDefocusWavefront(\n input: CalculateDefocusWavefrontInput\n): CalculationResult<DefocusWavefront> {\n requireInputKeys(input, \"calculateDefocusWavefront\", [\"signedDefocusImagePlaneMicrometers\", \"workingFNumber\"]);\n const dz = requireFinite(\n \"signedDefocusImagePlaneMicrometers\",\n input.signedDefocusImagePlaneMicrometers\n );\n requirePositiveFinite(\"workingFNumber\", input.workingFNumber);\n const w020 = dz / (8 * input.workingFNumber * input.workingFNumber);\n return calculatedResult(\n {\n signedDefocusImagePlaneMicrometers: dz,\n workingFNumber: input.workingFNumber,\n w020Micrometers: w020,\n zernikeZ4Micrometers: w020 / (2 * Math.sqrt(3))\n },\n \"paraxial-defocus-wavefront\",\n \"1.0.0\",\n [\n \"Paraxial (small-angle) relation between longitudinal image-plane defocus and the rho^2 wave aberration\",\n \"Sign convention: defocus is sensor minus image distance\"\n ]\n );\n}\n\n/**\n * Marechal/Mahajan approximation of the Strehl ratio: exp(-(2 pi sigma / lambda)^2). Valid only for a\n * small RMS wavefront error (Strehl roughly above 0.3). It is not an exact PSF calculation.\n */\nexport function estimateMarechalStrehlRatio(\n input: EstimateMarechalStrehlRatioInput\n): CalculationResult<{ strehlRatio: number; rmsWaves: number }> {\n requireInputKeys(input, \"estimateMarechalStrehlRatio\", [\"rmsWavefrontErrorMicrometers\", \"wavelengthNm\"]);\n const sigma = requireFinite(\n \"rmsWavefrontErrorMicrometers\",\n input.rmsWavefrontErrorMicrometers\n );\n if (sigma < 0) {\n throw new InvalidScientificInputError(\n \"rmsWavefrontErrorMicrometers must be non-negative.\"\n );\n }\n requirePositiveFinite(\"wavelengthNm\", input.wavelengthNm);\n const rmsWaves = sigma / (input.wavelengthNm / 1000);\n return approximationResult(\n {\n strehlRatio: Math.exp(-((2 * Math.PI * rmsWaves) ** 2)),\n rmsWaves\n },\n \"marechal-mahajan-strehl-approximation\",\n \"1.0.0\",\n [\n \"Strehl ratio approximated as exp(-(2 pi sigma / lambda)^2) (Marechal 1947; Mahajan 1982)\",\n \"Valid for small RMS wavefront error, roughly Strehl above 0.3; it is not an exact PSF evaluation\"\n ]\n );\n}\n"]}
|
|
@@ -15,6 +15,7 @@ import { InvalidScientificInputError, requirePositiveFinite, requirePositiveInte
|
|
|
15
15
|
import {} from "../sensor/sensor-geometry.js";
|
|
16
16
|
import { requireInputKeys, requireInputObject } from "../core/record-validation.js";
|
|
17
17
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
18
|
+
import { fullRect } from "../core/shared-helpers.js";
|
|
18
19
|
const CAPTURE_ORIENTATIONS = new Set([
|
|
19
20
|
"landscape",
|
|
20
21
|
"portrait-clockwise",
|
|
@@ -117,14 +118,6 @@ function normalizePhysicalCoordinateToUv(name, value, minimum, maximum) {
|
|
|
117
118
|
const clamped = Math.max(minimum, Math.min(maximum, value));
|
|
118
119
|
return (clamped - minimum) / span;
|
|
119
120
|
}
|
|
120
|
-
function fullRect(raster) {
|
|
121
|
-
return {
|
|
122
|
-
x: 0,
|
|
123
|
-
y: 0,
|
|
124
|
-
width: raster.pixelWidth,
|
|
125
|
-
height: raster.pixelHeight
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
121
|
function orientRaster(raster, orientation) {
|
|
129
122
|
return orientation === "portrait-clockwise" ||
|
|
130
123
|
orientation === "portrait-counter-clockwise"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-geometry.js","sourceRoot":"","sources":["../../src/output/capture-geometry.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Capture geometry: how the native sensor, the active capture area, the camera's physical\n * orientation and the final output crop relate to each other.\n *\n * It converts points, vectors and rectangles between native and oriented pixel coordinates,\n * maps oriented positions to the optical image plane and back, and computes field of view (FOV)\n * for the active capture and the final output.\n * @see docs/PHYSICS_FOUNDATION.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n calculateFieldOfViewBounds\n} from \"../camera/field-of-view.js\";\nimport {\n calculatedResult,\n type CalculationProvenance,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport {\n type NativeImageRaster,\n type RasterDimensions,\n type SensorImagingArea\n} from \"../sensor/sensor-geometry.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\nexport type CaptureOrientation =\n | \"landscape\"\n | \"portrait-clockwise\"\n | \"landscape-inverted\"\n | \"portrait-counter-clockwise\";\n\nconst CAPTURE_ORIENTATIONS = new Set<CaptureOrientation>([\n \"landscape\",\n \"portrait-clockwise\",\n \"landscape-inverted\",\n \"portrait-counter-clockwise\"\n]);\n\nexport interface RasterPoint {\n x: number;\n y: number;\n}\n\nexport interface RasterVector {\n x: number;\n y: number;\n}\n\n/**\n * Integer half-open rectangle in raster coordinates.\n *\n * Coordinates use a top-left origin with +X to the right and +Y downward.\n * The covered extent is [x, x + width) × [y, y + height).\n */\nexport interface RasterRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface PhysicalBoundsFromOpticalAxisMm {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface NormalizedRasterUv {\n /** 0 at the left edge, 1 at the right edge. */\n u: number;\n /** 0 at the top edge, 1 at the bottom edge. */\n v: number;\n}\n\n/**\n * A point on the optical image plane, in millimetres, before camera orientation is applied.\n *\n * The origin is the optical axis. +X points right and +Y points up.\n */\nexport interface ImagePlaneMetricPointMm {\n x: number;\n y: number;\n}\n\nexport interface MapOrientedPhysicalUvToImagePlaneInput {\n uv: NormalizedRasterUv;\n /**\n * Physical region represented by the normalized raster, after physical\n * camera orientation, using the capture contract's +Y-down physical basis.\n */\n orientedPhysicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n orientation: CaptureOrientation;\n}\n\nexport interface MapImagePlanePointToOrientedPhysicalUvInput {\n imagePlanePointMm: ImagePlaneMetricPointMm;\n /**\n * Physical region represented by the normalized raster, after physical\n * camera orientation, using the capture contract's +Y-down physical basis.\n */\n orientedPhysicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n orientation: CaptureOrientation;\n}\n\nexport interface ResolveCaptureGeometryInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n /**\n * Active capture rectangle in native sensor raster coordinates.\n *\n * Defaults to the full native raster.\n */\n activeCaptureRect?: RasterRect;\n /**\n * Final digital (output) crop, in oriented active-capture pixel coordinates.\n *\n * Defaults to the full oriented active capture.\n */\n outputCropRect?: RasterRect;\n /**\n * Final output image size after the optional digital crop and resampling.\n *\n * Defaults to the output-crop size. The output must keep the crop's aspect\n * ratio, allowing only a small tolerance for integer rounding.\n */\n outputRaster?: RasterDimensions;\n}\n\nexport interface ResolvedCaptureGeometry {\n native: {\n imagingArea: SensorImagingArea;\n raster: NativeImageRaster;\n };\n activeCapture: {\n nativeRect: RasterRect;\n imagingArea: SensorImagingArea;\n /**\n * Top-left active-area offset from the native imaging-area top-left.\n */\n physicalOffsetMm: {\n x: number;\n y: number;\n };\n /** Active-area center relative to the native optical axis. */\n centerOffsetFromOpticalAxisMm: RasterVector;\n /** Native physical bounds relative to the optical axis. */\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n /**\n * The current generic model assumes the native pixels evenly cover the\n * declared physical imaging area.\n */\n imagingAreaDerivation: \"uniform-native-raster\";\n raster: RasterDimensions;\n };\n orientedCapture: {\n orientation: CaptureOrientation;\n imagingArea: SensorImagingArea;\n /** Oriented physical bounds relative to the optical axis. */\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n raster: RasterDimensions;\n };\n output: {\n /**\n * Digital (output) crop, in oriented active-capture coordinates.\n *\n * This crop does not change the physical sensor or the active-capture\n * geometry.\n */\n cropRect: RasterRect;\n raster: RasterDimensions;\n /** Physical region retained by the digital/output crop. */\n imagingArea: SensorImagingArea;\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n centerOffsetFromOpticalAxisMm: RasterVector;\n sourceRetainedAreaFraction: number;\n /** Pixel resampling from the oriented active capture to the output image. */\n orientedCaptureToOutputScale: {\n x: number;\n y: number;\n axisRelativeDifference: number;\n };\n };\n}\n\nexport interface TransformRasterPointInput {\n point: RasterPoint;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n}\n\nexport interface TransformRasterVectorInput {\n vector: RasterVector;\n orientation: CaptureOrientation;\n}\n\nexport interface TransformRasterRectInput {\n rect: RasterRect;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n}\n\nexport interface CalculateActiveCaptureFieldOfViewInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n activeCaptureRect?: RasterRect;\n focalLengthMm: number;\n focusDistanceM?: number;\n}\n\nexport interface CalculateOutputFieldOfViewInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n activeCaptureRect?: RasterRect;\n outputCropRect?: RasterRect;\n focalLengthMm: number;\n focusDistanceM?: number;\n}\n\nexport interface ActiveCaptureFieldOfView {\n orientation: CaptureOrientation;\n horizontalDegrees: number;\n verticalDegrees: number;\n /**\n * The larger of the two corner-to-corner diagonal angles. For a centred\n * crop the two diagonals are equal.\n */\n diagonalDegrees: number;\n horizontalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n verticalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n activeImagingArea: SensorImagingArea;\n centerOffsetFromOpticalAxisMm: RasterVector;\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n}\n\nexport interface OutputFieldOfView {\n orientation: CaptureOrientation;\n horizontalDegrees: number;\n verticalDegrees: number;\n diagonalDegrees: number;\n horizontalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n verticalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n outputImagingArea: SensorImagingArea;\n centerOffsetFromOpticalAxisMm: RasterVector;\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n}\n\nfunction requireCaptureOrientation(\n value: unknown\n): asserts value is CaptureOrientation {\n if (\n typeof value !== \"string\" ||\n !CAPTURE_ORIENTATIONS.has(value as CaptureOrientation)\n ) {\n throw new InvalidConfigurationError(\"orientation is invalid.\");\n }\n}\n\nfunction requireRasterDimensions(\n name: string,\n raster: RasterDimensions\n): void {\n requireInputObject(raster, name);\n requirePositiveInteger(`${name}.pixelWidth`, raster.pixelWidth);\n requirePositiveInteger(`${name}.pixelHeight`, raster.pixelHeight);\n}\n\nfunction requireNonNegativeInteger(name: string, value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new InvalidScientificInputError(\n `${name} must be a non-negative safe integer.`\n );\n }\n}\n\nfunction validateRasterRect(\n name: string,\n rect: RasterRect,\n bounds: RasterDimensions\n): void {\n requireInputObject(rect, name);\n requireNonNegativeInteger(`${name}.x`, rect.x);\n requireNonNegativeInteger(`${name}.y`, rect.y);\n requirePositiveInteger(`${name}.width`, rect.width);\n requirePositiveInteger(`${name}.height`, rect.height);\n\n if (\n rect.x + rect.width > bounds.pixelWidth ||\n rect.y + rect.height > bounds.pixelHeight\n ) {\n throw new InvalidScientificInputError(\n `${name} must fit entirely within its raster bounds.`\n );\n }\n}\n\nfunction validateRasterPoint(\n name: string,\n point: RasterPoint,\n bounds: RasterDimensions\n): void {\n requireInputObject(point, name);\n if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n if (\n point.x < 0 ||\n point.y < 0 ||\n point.x > bounds.pixelWidth ||\n point.y > bounds.pixelHeight\n ) {\n throw new InvalidScientificInputError(\n `${name} must lie within the raster edge-coordinate bounds.`\n );\n }\n}\n\nfunction validateRasterVector(name: string, vector: RasterVector): void {\n requireInputObject(vector, name);\n if (!Number.isFinite(vector.x) || !Number.isFinite(vector.y)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n}\n\nconst PHYSICAL_EDGE_TOLERANCE_ULPS = 16;\n\nfunction physicalCoordinateTolerance(\n value: number,\n minimum: number,\n maximum: number\n): number {\n const span = maximum - minimum;\n const scale = Math.max(\n Math.abs(value),\n Math.abs(minimum),\n Math.abs(maximum),\n Math.abs(span),\n Number.MIN_VALUE\n );\n return Number.EPSILON * PHYSICAL_EDGE_TOLERANCE_ULPS * scale;\n}\n\nfunction validatePhysicalBounds(\n name: string,\n bounds: PhysicalBoundsFromOpticalAxisMm\n): void {\n requireInputObject(bounds, name);\n for (const key of [\"left\", \"right\", \"top\", \"bottom\"] as const) {\n if (!Number.isFinite(bounds[key])) {\n throw new InvalidScientificInputError(\n `${name}.${key} must be finite.`\n );\n }\n }\n if (bounds.right <= bounds.left) {\n throw new InvalidScientificInputError(\n `${name} must have right greater than left.`\n );\n }\n if (bounds.bottom <= bounds.top) {\n throw new InvalidScientificInputError(\n `${name} must have bottom greater than top.`\n );\n }\n\n const horizontalSpan = bounds.right - bounds.left;\n const verticalSpan = bounds.bottom - bounds.top;\n if (\n !Number.isFinite(horizontalSpan) ||\n !Number.isFinite(verticalSpan) ||\n horizontalSpan <=\n physicalCoordinateTolerance(bounds.left, bounds.left, bounds.right) ||\n verticalSpan <=\n physicalCoordinateTolerance(bounds.top, bounds.top, bounds.bottom)\n ) {\n throw new InvalidScientificInputError(\n `${name} must have numerically resolvable finite spans relative to the optical-axis coordinate magnitude.`\n );\n }\n}\n\nfunction validateNormalizedUv(name: string, uv: NormalizedRasterUv): void {\n requireInputObject(uv, name);\n if (!Number.isFinite(uv.u) || !Number.isFinite(uv.v)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n if (uv.u < 0 || uv.u > 1 || uv.v < 0 || uv.v > 1) {\n throw new InvalidScientificInputError(\n `${name} coordinates must lie within [0, 1].`\n );\n }\n}\n\nfunction normalizePhysicalCoordinateToUv(\n name: string,\n value: number,\n minimum: number,\n maximum: number\n): number {\n if (!Number.isFinite(value)) {\n throw new InvalidScientificInputError(`${name} must be finite.`);\n }\n\n const span = maximum - minimum;\n const tolerance = physicalCoordinateTolerance(\n value,\n minimum,\n maximum\n );\n\n if (value < minimum - tolerance || value > maximum + tolerance) {\n throw new InvalidScientificInputError(\n `${name} must lie within the supplied oriented physical bounds.`\n );\n }\n\n const clamped = Math.max(minimum, Math.min(maximum, value));\n return (clamped - minimum) / span;\n}\n\nfunction fullRect(raster: RasterDimensions): RasterRect {\n return {\n x: 0,\n y: 0,\n width: raster.pixelWidth,\n height: raster.pixelHeight\n };\n}\n\nfunction orientRaster(\n raster: RasterDimensions,\n orientation: CaptureOrientation\n): RasterDimensions {\n return orientation === \"portrait-clockwise\" ||\n orientation === \"portrait-counter-clockwise\"\n ? {\n pixelWidth: raster.pixelHeight,\n pixelHeight: raster.pixelWidth\n }\n : {\n pixelWidth: raster.pixelWidth,\n pixelHeight: raster.pixelHeight\n };\n}\n\nfunction rotateVector(\n vector: RasterVector,\n orientation: CaptureOrientation\n): RasterVector {\n switch (orientation) {\n case \"landscape\":\n return { x: vector.x, y: vector.y };\n case \"portrait-clockwise\":\n return { x: -vector.y, y: vector.x };\n case \"landscape-inverted\":\n return { x: -vector.x, y: -vector.y };\n case \"portrait-counter-clockwise\":\n return { x: vector.y, y: -vector.x };\n }\n}\n\nfunction inverseRotateVector(\n vector: RasterVector,\n orientation: CaptureOrientation\n): RasterVector {\n switch (orientation) {\n case \"landscape\":\n return { x: vector.x, y: vector.y };\n case \"portrait-clockwise\":\n return { x: vector.y, y: -vector.x };\n case \"landscape-inverted\":\n return { x: -vector.x, y: -vector.y };\n case \"portrait-counter-clockwise\":\n return { x: -vector.y, y: vector.x };\n }\n}\n\n/**\n * Converts a point in native pixel coordinates to oriented capture coordinates.\n * Coordinates are continuous and measured from pixel edges, so a pixel centre is at +0.5.\n */\nexport function transformNativeRasterPointToOriented(\n input: TransformRasterPointInput\n): RasterPoint {\n requireInputKeys(input, \"transformNativeRasterPointToOriented\", [\"point\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n validateRasterPoint(\"point\", input.point, input.nativeRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.point };\n case \"portrait-clockwise\":\n return { x: height - input.point.y, y: input.point.x };\n case \"landscape-inverted\":\n return { x: width - input.point.x, y: height - input.point.y };\n case \"portrait-counter-clockwise\":\n return { x: input.point.y, y: width - input.point.x };\n }\n}\n\n/** Converts a point in oriented pixel coordinates (measured from pixel edges) back to native coordinates. */\nexport function transformOrientedRasterPointToNative(\n input: TransformRasterPointInput\n): RasterPoint {\n requireInputKeys(input, \"transformOrientedRasterPointToNative\", [\"point\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n const orientedRaster = orientRaster(input.nativeRaster, input.orientation);\n validateRasterPoint(\"point\", input.point, orientedRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.point };\n case \"portrait-clockwise\":\n return { x: input.point.y, y: height - input.point.x };\n case \"landscape-inverted\":\n return { x: width - input.point.x, y: height - input.point.y };\n case \"portrait-counter-clockwise\":\n return { x: width - input.point.y, y: input.point.x };\n }\n}\n\n/** Rotates a native raster vector into oriented coordinates. */\nexport function transformNativeRasterVectorToOriented(\n input: TransformRasterVectorInput\n): RasterVector {\n requireInputKeys(input, \"transformNativeRasterVectorToOriented\", [\"vector\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"vector\", input.vector);\n return rotateVector(input.vector, input.orientation);\n}\n\n/** Rotates an oriented raster vector back into native coordinates. */\nexport function transformOrientedRasterVectorToNative(\n input: TransformRasterVectorInput\n): RasterVector {\n requireInputKeys(input, \"transformOrientedRasterVectorToNative\", [\"vector\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"vector\", input.vector);\n return inverseRotateVector(input.vector, input.orientation);\n}\n\n/**\n * Maps normalized (0–1) coordinates in an oriented physical image region to the\n * optical image plane used by the lens-field and camera-mapping APIs, before\n * camera orientation.\n *\n * The input bounds are after camera orientation and use +Y down. The returned\n * point has its origin on the optical axis, with +X right and +Y up. No lens or\n * projection equation is applied.\n */\nexport function mapOrientedPhysicalUvToImagePlanePoint(\n input: MapOrientedPhysicalUvToImagePlaneInput\n): ImagePlaneMetricPointMm {\n requireInputKeys(input, \"mapOrientedPhysicalUvToImagePlanePoint\", [\"uv\", \"orientedPhysicalBoundsFromOpticalAxisMm\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateNormalizedUv(\"uv\", input.uv);\n validatePhysicalBounds(\n \"orientedPhysicalBoundsFromOpticalAxisMm\",\n input.orientedPhysicalBoundsFromOpticalAxisMm\n );\n\n const bounds = input.orientedPhysicalBoundsFromOpticalAxisMm;\n const orientedPhysicalPoint = {\n x: bounds.left + input.uv.u * (bounds.right - bounds.left),\n y: bounds.top + input.uv.v * (bounds.bottom - bounds.top)\n };\n const nativePhysicalPoint = inverseRotateVector(\n orientedPhysicalPoint,\n input.orientation\n );\n\n return {\n x: nativePhysicalPoint.x,\n y: -nativePhysicalPoint.y\n };\n}\n\n/**\n * Maps an optical image-plane point (before camera orientation) to normalized\n * coordinates in an oriented physical image region.\n *\n * This is the exact inverse of mapOrientedPhysicalUvToImagePlanePoint(). A point\n * outside the region is rejected. A tiny tolerance only absorbs floating-point\n * round-trip error at an edge.\n */\nexport function mapImagePlanePointToOrientedPhysicalUv(\n input: MapImagePlanePointToOrientedPhysicalUvInput\n): NormalizedRasterUv {\n requireInputKeys(input, \"mapImagePlanePointToOrientedPhysicalUv\", [\"imagePlanePointMm\", \"orientedPhysicalBoundsFromOpticalAxisMm\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"imagePlanePointMm\", input.imagePlanePointMm);\n validatePhysicalBounds(\n \"orientedPhysicalBoundsFromOpticalAxisMm\",\n input.orientedPhysicalBoundsFromOpticalAxisMm\n );\n\n const bounds = input.orientedPhysicalBoundsFromOpticalAxisMm;\n const nativePhysicalPoint = {\n x: input.imagePlanePointMm.x,\n y: -input.imagePlanePointMm.y\n };\n const orientedPhysicalPoint = rotateVector(\n nativePhysicalPoint,\n input.orientation\n );\n return {\n u: normalizePhysicalCoordinateToUv(\n \"imagePlanePointMm.x\",\n orientedPhysicalPoint.x,\n bounds.left,\n bounds.right\n ),\n v: normalizePhysicalCoordinateToUv(\n \"imagePlanePointMm.y\",\n orientedPhysicalPoint.y,\n bounds.top,\n bounds.bottom\n )\n };\n}\n\n/** Transforms an integer half-open native raster rectangle into oriented coordinates. */\nexport function transformNativeRasterRectToOriented(\n input: TransformRasterRectInput\n): RasterRect {\n requireInputKeys(input, \"transformNativeRasterRectToOriented\", [\"rect\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n validateRasterRect(\"rect\", input.rect, input.nativeRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n const { x, y, width: rectWidth, height: rectHeight } = input.rect;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.rect };\n case \"portrait-clockwise\":\n return {\n x: height - (y + rectHeight),\n y: x,\n width: rectHeight,\n height: rectWidth\n };\n case \"landscape-inverted\":\n return {\n x: width - (x + rectWidth),\n y: height - (y + rectHeight),\n width: rectWidth,\n height: rectHeight\n };\n case \"portrait-counter-clockwise\":\n return {\n x: y,\n y: width - (x + rectWidth),\n width: rectHeight,\n height: rectWidth\n };\n }\n}\n\n/** Transforms an oriented integer half-open rectangle back to native coordinates. */\nexport function transformOrientedRasterRectToNative(\n input: TransformRasterRectInput\n): RasterRect {\n requireInputKeys(input, \"transformOrientedRasterRectToNative\", [\"rect\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n const orientedRaster = orientRaster(input.nativeRaster, input.orientation);\n validateRasterRect(\"rect\", input.rect, orientedRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n const { x, y, width: rectWidth, height: rectHeight } = input.rect;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.rect };\n case \"portrait-clockwise\":\n return {\n x: y,\n y: height - (x + rectWidth),\n width: rectHeight,\n height: rectWidth\n };\n case \"landscape-inverted\":\n return {\n x: width - (x + rectWidth),\n y: height - (y + rectHeight),\n width: rectWidth,\n height: rectHeight\n };\n case \"portrait-counter-clockwise\":\n return {\n x: width - (y + rectHeight),\n y: x,\n width: rectHeight,\n height: rectWidth\n };\n }\n}\n\nfunction nativePhysicalBoundsFromRect(\n imagingArea: SensorImagingArea,\n nativeRaster: NativeImageRaster,\n rect: RasterRect\n): PhysicalBoundsFromOpticalAxisMm {\n const pitchX = imagingArea.widthMm / nativeRaster.pixelWidth;\n const pitchY = imagingArea.heightMm / nativeRaster.pixelHeight;\n\n return {\n left: rect.x * pitchX - imagingArea.widthMm / 2,\n right:\n (rect.x + rect.width) * pitchX - imagingArea.widthMm / 2,\n top: rect.y * pitchY - imagingArea.heightMm / 2,\n bottom:\n (rect.y + rect.height) * pitchY - imagingArea.heightMm / 2\n };\n}\n\nfunction orientPhysicalBounds(\n bounds: PhysicalBoundsFromOpticalAxisMm,\n orientation: CaptureOrientation\n): PhysicalBoundsFromOpticalAxisMm {\n const corners = [\n { x: bounds.left, y: bounds.top },\n { x: bounds.right, y: bounds.top },\n { x: bounds.right, y: bounds.bottom },\n { x: bounds.left, y: bounds.bottom }\n ].map((corner) => rotateVector(corner, orientation));\n\n return {\n left: Math.min(...corners.map((corner) => corner.x)),\n right: Math.max(...corners.map((corner) => corner.x)),\n top: Math.min(...corners.map((corner) => corner.y)),\n bottom: Math.max(...corners.map((corner) => corner.y))\n };\n}\n\nfunction physicalBoundsFromRectWithinBounds(\n sourceBounds: PhysicalBoundsFromOpticalAxisMm,\n sourceRaster: RasterDimensions,\n rect: RasterRect\n): PhysicalBoundsFromOpticalAxisMm {\n const pitchX =\n (sourceBounds.right - sourceBounds.left) / sourceRaster.pixelWidth;\n const pitchY =\n (sourceBounds.bottom - sourceBounds.top) / sourceRaster.pixelHeight;\n\n return {\n left: sourceBounds.left + rect.x * pitchX,\n right: sourceBounds.left + (rect.x + rect.width) * pitchX,\n top: sourceBounds.top + rect.y * pitchY,\n bottom: sourceBounds.top + (rect.y + rect.height) * pitchY\n };\n}\n\nfunction validateOutputAspectRatio(\n cropRect: RasterRect,\n outputRaster: RasterDimensions\n): void {\n // Keep one scale factor for both axes. Allow only the sub-pixel mismatch that\n // comes from rounding an ideal scaled size to whole pixels. A fixed percentage\n // tolerance would allow visible stretching along one axis at large sizes.\n const widthScaleMinimum =\n (outputRaster.pixelWidth - 0.5) / cropRect.width;\n const widthScaleMaximum =\n (outputRaster.pixelWidth + 0.5) / cropRect.width;\n const heightScaleMinimum =\n (outputRaster.pixelHeight - 0.5) / cropRect.height;\n const heightScaleMaximum =\n (outputRaster.pixelHeight + 0.5) / cropRect.height;\n\n const minimumCommonScale = Math.max(\n widthScaleMinimum,\n heightScaleMinimum\n );\n const maximumCommonScale = Math.min(\n widthScaleMaximum,\n heightScaleMaximum\n );\n\n if (minimumCommonScale > maximumCommonScale) {\n throw new InvalidScientificInputError(\n \"outputRaster must preserve outputCropRect aspect ratio within nearest-integer raster rounding; implicit geometric stretching is not supported.\"\n );\n }\n}\n\nfunction angleBetweenSensorRaysDegrees(\n first: RasterVector,\n second: RasterVector,\n projectionDistanceMm: number\n): number {\n const firstLength = Math.hypot(\n first.x,\n first.y,\n projectionDistanceMm\n );\n const secondLength = Math.hypot(\n second.x,\n second.y,\n projectionDistanceMm\n );\n const dot =\n first.x * second.x +\n first.y * second.y +\n projectionDistanceMm * projectionDistanceMm;\n const cosine = Math.max(\n -1,\n Math.min(1, dot / (firstLength * secondLength))\n );\n return (Math.acos(cosine) * 180) / Math.PI;\n}\n\nfunction calculateBoundsFieldOfView(\n bounds: PhysicalBoundsFromOpticalAxisMm,\n focalLengthMm: number,\n focusDistanceM: number | undefined\n): {\n horizontalDegrees: number;\n verticalDegrees: number;\n diagonalDegrees: number;\n horizontalBoundsDegrees: { minimum: number; maximum: number };\n verticalBoundsDegrees: { minimum: number; maximum: number };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n} {\n const fovInput = {\n focalLengthMm,\n ...(focusDistanceM === undefined ? {} : { focusDistanceM })\n };\n const horizontal = calculateFieldOfViewBounds({\n ...fovInput,\n minimumSensorCoordinateMm: bounds.left,\n maximumSensorCoordinateMm: bounds.right\n });\n const vertical = calculateFieldOfViewBounds({\n ...fovInput,\n minimumSensorCoordinateMm: bounds.top,\n maximumSensorCoordinateMm: bounds.bottom\n });\n const projectionDistanceMm = horizontal.value.projectionDistanceMm;\n const topLeft = { x: bounds.left, y: bounds.top };\n const topRight = { x: bounds.right, y: bounds.top };\n const bottomRight = { x: bounds.right, y: bounds.bottom };\n const bottomLeft = { x: bounds.left, y: bounds.bottom };\n const topLeftToBottomRight = angleBetweenSensorRaysDegrees(\n topLeft,\n bottomRight,\n projectionDistanceMm\n );\n const topRightToBottomLeft = angleBetweenSensorRaysDegrees(\n topRight,\n bottomLeft,\n projectionDistanceMm\n );\n\n return {\n horizontalDegrees: horizontal.value.degrees,\n verticalDegrees: vertical.value.degrees,\n diagonalDegrees: Math.max(\n topLeftToBottomRight,\n topRightToBottomLeft\n ),\n horizontalBoundsDegrees: {\n minimum: horizontal.value.minimumDegrees,\n maximum: horizontal.value.maximumDegrees\n },\n verticalBoundsDegrees: {\n minimum: vertical.value.minimumDegrees,\n maximum: vertical.value.maximumDegrees\n },\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight,\n topRightToBottomLeft\n },\n projection: {\n projectionDistanceMm,\n provenance: horizontal.provenance\n }\n };\n}\n\n/**\n * Resolves native sensor geometry, active capture area, physical camera orientation\n * and final digital (output) geometry, keeping each one distinct.\n */\nexport function resolveCaptureGeometry(\n input: ResolveCaptureGeometryInput\n): CalculationResult<ResolvedCaptureGeometry> {\n requireInputKeys(input, \"resolveCaptureGeometry\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"outputCropRect\", \"outputRaster\"]);\n requireCaptureOrientation(input.orientation);\n requireInputObject(input.imagingArea, \"imagingArea\");\n requirePositiveFinite(\"imagingArea.widthMm\", input.imagingArea.widthMm);\n requirePositiveFinite(\"imagingArea.heightMm\", input.imagingArea.heightMm);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n\n const activeCaptureRect =\n input.activeCaptureRect ?? fullRect(input.nativeRaster);\n validateRasterRect(\n \"activeCaptureRect\",\n activeCaptureRect,\n input.nativeRaster\n );\n\n const nativeBounds = nativePhysicalBoundsFromRect(\n input.imagingArea,\n input.nativeRaster,\n activeCaptureRect\n );\n const activeImagingArea: SensorImagingArea = {\n widthMm: nativeBounds.right - nativeBounds.left,\n heightMm: nativeBounds.bottom - nativeBounds.top\n };\n const activeRaster: RasterDimensions = {\n pixelWidth: activeCaptureRect.width,\n pixelHeight: activeCaptureRect.height\n };\n const orientedBounds = orientPhysicalBounds(\n nativeBounds,\n input.orientation\n );\n const orientedRaster = orientRaster(activeRaster, input.orientation);\n const orientedImagingArea: SensorImagingArea = {\n widthMm: orientedBounds.right - orientedBounds.left,\n heightMm: orientedBounds.bottom - orientedBounds.top\n };\n\n const outputCropRect =\n input.outputCropRect ?? fullRect(orientedRaster);\n validateRasterRect(\n \"outputCropRect\",\n outputCropRect,\n orientedRaster\n );\n\n const outputRaster: RasterDimensions = input.outputRaster ?? {\n pixelWidth: outputCropRect.width,\n pixelHeight: outputCropRect.height\n };\n requireRasterDimensions(\"outputRaster\", outputRaster);\n validateOutputAspectRatio(outputCropRect, outputRaster);\n\n const outputBounds = physicalBoundsFromRectWithinBounds(\n orientedBounds,\n orientedRaster,\n outputCropRect\n );\n const outputImagingArea: SensorImagingArea = {\n widthMm: outputBounds.right - outputBounds.left,\n heightMm: outputBounds.bottom - outputBounds.top\n };\n const outputScaleX = outputRaster.pixelWidth / outputCropRect.width;\n const outputScaleY = outputRaster.pixelHeight / outputCropRect.height;\n const outputScaleAxisRelativeDifference =\n Math.abs(outputScaleX - outputScaleY) /\n ((outputScaleX + outputScaleY) / 2);\n\n return calculatedResult(\n {\n native: {\n imagingArea: { ...input.imagingArea },\n raster: { ...input.nativeRaster }\n },\n activeCapture: {\n nativeRect: { ...activeCaptureRect },\n imagingArea: activeImagingArea,\n physicalOffsetMm: {\n x: nativeBounds.left + input.imagingArea.widthMm / 2,\n y: nativeBounds.top + input.imagingArea.heightMm / 2\n },\n centerOffsetFromOpticalAxisMm: {\n x: (nativeBounds.left + nativeBounds.right) / 2,\n y: (nativeBounds.top + nativeBounds.bottom) / 2\n },\n physicalBoundsFromOpticalAxisMm: nativeBounds,\n imagingAreaDerivation: \"uniform-native-raster\",\n raster: activeRaster\n },\n orientedCapture: {\n orientation: input.orientation,\n imagingArea: orientedImagingArea,\n physicalBoundsFromOpticalAxisMm: orientedBounds,\n raster: orientedRaster\n },\n output: {\n cropRect: { ...outputCropRect },\n raster: { ...outputRaster },\n imagingArea: outputImagingArea,\n physicalBoundsFromOpticalAxisMm: outputBounds,\n centerOffsetFromOpticalAxisMm: {\n x: (outputBounds.left + outputBounds.right) / 2,\n y: (outputBounds.top + outputBounds.bottom) / 2\n },\n sourceRetainedAreaFraction:\n (outputCropRect.width * outputCropRect.height) /\n (orientedRaster.pixelWidth * orientedRaster.pixelHeight),\n orientedCaptureToOutputScale: {\n x: outputScaleX,\n y: outputScaleY,\n axisRelativeDifference: outputScaleAxisRelativeDifference\n }\n }\n },\n \"capture-geometry-pipeline\",\n \"1.2.0\",\n [\n \"Native sensor raster coordinates use a top-left origin with +X right and +Y down.\",\n \"Raster rectangles are integer half-open extents.\",\n \"Physical camera orientation does not rotate or redefine the native sensor coordinate system.\",\n \"The generic active physical area is derived by assuming native image samples uniformly span the declared physical imaging area.\",\n \"Output crop/resampling is digital geometry and does not mutate physical sensor or active-capture identity.\",\n \"The physical image region retained by output crop is tracked explicitly for final framing and equivalent-viewing calculations.\",\n \"Output raster aspect ratio must remain consistent with the output crop; implicit geometric stretching is rejected.\"\n ]\n );\n}\n\n/**\n * Calculates the field of view (FOV) of the active physical capture area after\n * camera orientation. Horizontal and vertical FOV can be asymmetric about the\n * optical axis; both corner-to-corner diagonals are reported.\n *\n * The final digital (output) crop is deliberately not included.\n */\nexport function calculateActiveCaptureFieldOfView(\n input: CalculateActiveCaptureFieldOfViewInput\n): CalculationResult<ActiveCaptureFieldOfView> {\n requireInputKeys(input, \"calculateActiveCaptureFieldOfView\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"focalLengthMm\", \"focusDistanceM\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n\n const geometry = resolveCaptureGeometry({\n imagingArea: input.imagingArea,\n nativeRaster: input.nativeRaster,\n orientation: input.orientation,\n ...(input.activeCaptureRect === undefined\n ? {}\n : { activeCaptureRect: input.activeCaptureRect })\n }).value;\n\n const bounds =\n geometry.orientedCapture.physicalBoundsFromOpticalAxisMm;\n const fieldOfView = calculateBoundsFieldOfView(\n bounds,\n input.focalLengthMm,\n input.focusDistanceM\n );\n\n return calculatedResult(\n {\n orientation: input.orientation,\n ...fieldOfView,\n activeImagingArea: {\n ...geometry.orientedCapture.imagingArea\n },\n centerOffsetFromOpticalAxisMm: rotateVector(\n geometry.activeCapture.centerOffsetFromOpticalAxisMm,\n input.orientation\n )\n },\n \"oriented-active-capture-field-of-view\",\n \"1.1.0\",\n [\n \"Rectilinear projection is evaluated from signed active-area bounds relative to the optical axis.\",\n \"Off-center active crops preserve asymmetric angular bounds rather than being treated as centered.\",\n \"Camera orientation rotates physical bounds while leaving the native sensor coordinate system unchanged.\",\n \"For off-center rectangles the two opposite-corner diagonal spans may differ; diagonalDegrees reports the larger span.\",\n \"Final digital/output crop is excluded from active-capture FOV.\"\n ]\n );\n}\n\n/**\n * Calculates the final visible field of view after the active capture area,\n * orientation and digital (output) crop. Output resolution does not affect it.\n */\nexport function calculateOutputFieldOfView(\n input: CalculateOutputFieldOfViewInput\n): CalculationResult<OutputFieldOfView> {\n requireInputKeys(input, \"calculateOutputFieldOfView\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"outputCropRect\", \"focalLengthMm\", \"focusDistanceM\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n\n const geometry = resolveCaptureGeometry({\n imagingArea: input.imagingArea,\n nativeRaster: input.nativeRaster,\n orientation: input.orientation,\n ...(input.activeCaptureRect === undefined\n ? {}\n : { activeCaptureRect: input.activeCaptureRect }),\n ...(input.outputCropRect === undefined\n ? {}\n : { outputCropRect: input.outputCropRect })\n }).value;\n const fieldOfView = calculateBoundsFieldOfView(\n geometry.output.physicalBoundsFromOpticalAxisMm,\n input.focalLengthMm,\n input.focusDistanceM\n );\n\n return calculatedResult(\n {\n orientation: input.orientation,\n ...fieldOfView,\n outputImagingArea: { ...geometry.output.imagingArea },\n centerOffsetFromOpticalAxisMm: {\n ...geometry.output.centerOffsetFromOpticalAxisMm\n }\n },\n \"oriented-output-field-of-view\",\n \"1.0.0\",\n [\n \"Final visible FOV is derived from the physical image region retained by active capture and digital/output crop.\",\n \"Output raster resolution does not change field of view.\",\n \"Off-center output crops preserve asymmetric angular bounds.\",\n \"Physical sensor identity and active-capture 35 mm-equivalent focal length are unchanged by final digital crop.\"\n ]\n );\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"capture-geometry.js","sourceRoot":"","sources":["../../src/output/capture-geometry.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Capture geometry: how the native sensor, the active capture area, the camera's physical\n * orientation and the final output crop relate to each other.\n *\n * It converts points, vectors and rectangles between native and oriented pixel coordinates,\n * maps oriented positions to the optical image plane and back, and computes field of view (FOV)\n * for the active capture and the final output.\n * @see docs/PHYSICS_FOUNDATION.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n calculateFieldOfViewBounds\n} from \"../camera/field-of-view.js\";\nimport {\n calculatedResult,\n type CalculationProvenance,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport {\n type NativeImageRaster,\n type RasterDimensions,\n type SensorImagingArea\n} from \"../sensor/sensor-geometry.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { fullRect } from \"../core/shared-helpers.js\";\n\nexport type CaptureOrientation =\n | \"landscape\"\n | \"portrait-clockwise\"\n | \"landscape-inverted\"\n | \"portrait-counter-clockwise\";\n\nconst CAPTURE_ORIENTATIONS = new Set<CaptureOrientation>([\n \"landscape\",\n \"portrait-clockwise\",\n \"landscape-inverted\",\n \"portrait-counter-clockwise\"\n]);\n\nexport interface RasterPoint {\n x: number;\n y: number;\n}\n\nexport interface RasterVector {\n x: number;\n y: number;\n}\n\n/**\n * Integer half-open rectangle in raster coordinates.\n *\n * Coordinates use a top-left origin with +X to the right and +Y downward.\n * The covered extent is [x, x + width) × [y, y + height).\n */\nexport interface RasterRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface PhysicalBoundsFromOpticalAxisMm {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface NormalizedRasterUv {\n /** 0 at the left edge, 1 at the right edge. */\n u: number;\n /** 0 at the top edge, 1 at the bottom edge. */\n v: number;\n}\n\n/**\n * A point on the optical image plane, in millimetres, before camera orientation is applied.\n *\n * The origin is the optical axis. +X points right and +Y points up.\n */\nexport interface ImagePlaneMetricPointMm {\n x: number;\n y: number;\n}\n\nexport interface MapOrientedPhysicalUvToImagePlaneInput {\n uv: NormalizedRasterUv;\n /**\n * Physical region represented by the normalized raster, after physical\n * camera orientation, using the capture contract's +Y-down physical basis.\n */\n orientedPhysicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n orientation: CaptureOrientation;\n}\n\nexport interface MapImagePlanePointToOrientedPhysicalUvInput {\n imagePlanePointMm: ImagePlaneMetricPointMm;\n /**\n * Physical region represented by the normalized raster, after physical\n * camera orientation, using the capture contract's +Y-down physical basis.\n */\n orientedPhysicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n orientation: CaptureOrientation;\n}\n\nexport interface ResolveCaptureGeometryInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n /**\n * Active capture rectangle in native sensor raster coordinates.\n *\n * Defaults to the full native raster.\n */\n activeCaptureRect?: RasterRect;\n /**\n * Final digital (output) crop, in oriented active-capture pixel coordinates.\n *\n * Defaults to the full oriented active capture.\n */\n outputCropRect?: RasterRect;\n /**\n * Final output image size after the optional digital crop and resampling.\n *\n * Defaults to the output-crop size. The output must keep the crop's aspect\n * ratio, allowing only a small tolerance for integer rounding.\n */\n outputRaster?: RasterDimensions;\n}\n\nexport interface ResolvedCaptureGeometry {\n native: {\n imagingArea: SensorImagingArea;\n raster: NativeImageRaster;\n };\n activeCapture: {\n nativeRect: RasterRect;\n imagingArea: SensorImagingArea;\n /**\n * Top-left active-area offset from the native imaging-area top-left.\n */\n physicalOffsetMm: {\n x: number;\n y: number;\n };\n /** Active-area center relative to the native optical axis. */\n centerOffsetFromOpticalAxisMm: RasterVector;\n /** Native physical bounds relative to the optical axis. */\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n /**\n * The current generic model assumes the native pixels evenly cover the\n * declared physical imaging area.\n */\n imagingAreaDerivation: \"uniform-native-raster\";\n raster: RasterDimensions;\n };\n orientedCapture: {\n orientation: CaptureOrientation;\n imagingArea: SensorImagingArea;\n /** Oriented physical bounds relative to the optical axis. */\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n raster: RasterDimensions;\n };\n output: {\n /**\n * Digital (output) crop, in oriented active-capture coordinates.\n *\n * This crop does not change the physical sensor or the active-capture\n * geometry.\n */\n cropRect: RasterRect;\n raster: RasterDimensions;\n /** Physical region retained by the digital/output crop. */\n imagingArea: SensorImagingArea;\n physicalBoundsFromOpticalAxisMm: PhysicalBoundsFromOpticalAxisMm;\n centerOffsetFromOpticalAxisMm: RasterVector;\n sourceRetainedAreaFraction: number;\n /** Pixel resampling from the oriented active capture to the output image. */\n orientedCaptureToOutputScale: {\n x: number;\n y: number;\n axisRelativeDifference: number;\n };\n };\n}\n\nexport interface TransformRasterPointInput {\n point: RasterPoint;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n}\n\nexport interface TransformRasterVectorInput {\n vector: RasterVector;\n orientation: CaptureOrientation;\n}\n\nexport interface TransformRasterRectInput {\n rect: RasterRect;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n}\n\nexport interface CalculateActiveCaptureFieldOfViewInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n activeCaptureRect?: RasterRect;\n focalLengthMm: number;\n focusDistanceM?: number;\n}\n\nexport interface CalculateOutputFieldOfViewInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n orientation: CaptureOrientation;\n activeCaptureRect?: RasterRect;\n outputCropRect?: RasterRect;\n focalLengthMm: number;\n focusDistanceM?: number;\n}\n\nexport interface ActiveCaptureFieldOfView {\n orientation: CaptureOrientation;\n horizontalDegrees: number;\n verticalDegrees: number;\n /**\n * The larger of the two corner-to-corner diagonal angles. For a centred\n * crop the two diagonals are equal.\n */\n diagonalDegrees: number;\n horizontalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n verticalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n activeImagingArea: SensorImagingArea;\n centerOffsetFromOpticalAxisMm: RasterVector;\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n}\n\nexport interface OutputFieldOfView {\n orientation: CaptureOrientation;\n horizontalDegrees: number;\n verticalDegrees: number;\n diagonalDegrees: number;\n horizontalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n verticalBoundsDegrees: {\n minimum: number;\n maximum: number;\n };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n outputImagingArea: SensorImagingArea;\n centerOffsetFromOpticalAxisMm: RasterVector;\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n}\n\nfunction requireCaptureOrientation(\n value: unknown\n): asserts value is CaptureOrientation {\n if (\n typeof value !== \"string\" ||\n !CAPTURE_ORIENTATIONS.has(value as CaptureOrientation)\n ) {\n throw new InvalidConfigurationError(\"orientation is invalid.\");\n }\n}\n\nfunction requireRasterDimensions(\n name: string,\n raster: RasterDimensions\n): void {\n requireInputObject(raster, name);\n requirePositiveInteger(`${name}.pixelWidth`, raster.pixelWidth);\n requirePositiveInteger(`${name}.pixelHeight`, raster.pixelHeight);\n}\n\nfunction requireNonNegativeInteger(name: string, value: number): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new InvalidScientificInputError(\n `${name} must be a non-negative safe integer.`\n );\n }\n}\n\nfunction validateRasterRect(\n name: string,\n rect: RasterRect,\n bounds: RasterDimensions\n): void {\n requireInputObject(rect, name);\n requireNonNegativeInteger(`${name}.x`, rect.x);\n requireNonNegativeInteger(`${name}.y`, rect.y);\n requirePositiveInteger(`${name}.width`, rect.width);\n requirePositiveInteger(`${name}.height`, rect.height);\n\n if (\n rect.x + rect.width > bounds.pixelWidth ||\n rect.y + rect.height > bounds.pixelHeight\n ) {\n throw new InvalidScientificInputError(\n `${name} must fit entirely within its raster bounds.`\n );\n }\n}\n\nfunction validateRasterPoint(\n name: string,\n point: RasterPoint,\n bounds: RasterDimensions\n): void {\n requireInputObject(point, name);\n if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n if (\n point.x < 0 ||\n point.y < 0 ||\n point.x > bounds.pixelWidth ||\n point.y > bounds.pixelHeight\n ) {\n throw new InvalidScientificInputError(\n `${name} must lie within the raster edge-coordinate bounds.`\n );\n }\n}\n\nfunction validateRasterVector(name: string, vector: RasterVector): void {\n requireInputObject(vector, name);\n if (!Number.isFinite(vector.x) || !Number.isFinite(vector.y)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n}\n\nconst PHYSICAL_EDGE_TOLERANCE_ULPS = 16;\n\nfunction physicalCoordinateTolerance(\n value: number,\n minimum: number,\n maximum: number\n): number {\n const span = maximum - minimum;\n const scale = Math.max(\n Math.abs(value),\n Math.abs(minimum),\n Math.abs(maximum),\n Math.abs(span),\n Number.MIN_VALUE\n );\n return Number.EPSILON * PHYSICAL_EDGE_TOLERANCE_ULPS * scale;\n}\n\nfunction validatePhysicalBounds(\n name: string,\n bounds: PhysicalBoundsFromOpticalAxisMm\n): void {\n requireInputObject(bounds, name);\n for (const key of [\"left\", \"right\", \"top\", \"bottom\"] as const) {\n if (!Number.isFinite(bounds[key])) {\n throw new InvalidScientificInputError(\n `${name}.${key} must be finite.`\n );\n }\n }\n if (bounds.right <= bounds.left) {\n throw new InvalidScientificInputError(\n `${name} must have right greater than left.`\n );\n }\n if (bounds.bottom <= bounds.top) {\n throw new InvalidScientificInputError(\n `${name} must have bottom greater than top.`\n );\n }\n\n const horizontalSpan = bounds.right - bounds.left;\n const verticalSpan = bounds.bottom - bounds.top;\n if (\n !Number.isFinite(horizontalSpan) ||\n !Number.isFinite(verticalSpan) ||\n horizontalSpan <=\n physicalCoordinateTolerance(bounds.left, bounds.left, bounds.right) ||\n verticalSpan <=\n physicalCoordinateTolerance(bounds.top, bounds.top, bounds.bottom)\n ) {\n throw new InvalidScientificInputError(\n `${name} must have numerically resolvable finite spans relative to the optical-axis coordinate magnitude.`\n );\n }\n}\n\nfunction validateNormalizedUv(name: string, uv: NormalizedRasterUv): void {\n requireInputObject(uv, name);\n if (!Number.isFinite(uv.u) || !Number.isFinite(uv.v)) {\n throw new InvalidScientificInputError(\n `${name} coordinates must be finite.`\n );\n }\n if (uv.u < 0 || uv.u > 1 || uv.v < 0 || uv.v > 1) {\n throw new InvalidScientificInputError(\n `${name} coordinates must lie within [0, 1].`\n );\n }\n}\n\nfunction normalizePhysicalCoordinateToUv(\n name: string,\n value: number,\n minimum: number,\n maximum: number\n): number {\n if (!Number.isFinite(value)) {\n throw new InvalidScientificInputError(`${name} must be finite.`);\n }\n\n const span = maximum - minimum;\n const tolerance = physicalCoordinateTolerance(\n value,\n minimum,\n maximum\n );\n\n if (value < minimum - tolerance || value > maximum + tolerance) {\n throw new InvalidScientificInputError(\n `${name} must lie within the supplied oriented physical bounds.`\n );\n }\n\n const clamped = Math.max(minimum, Math.min(maximum, value));\n return (clamped - minimum) / span;\n}\n\nfunction orientRaster(\n raster: RasterDimensions,\n orientation: CaptureOrientation\n): RasterDimensions {\n return orientation === \"portrait-clockwise\" ||\n orientation === \"portrait-counter-clockwise\"\n ? {\n pixelWidth: raster.pixelHeight,\n pixelHeight: raster.pixelWidth\n }\n : {\n pixelWidth: raster.pixelWidth,\n pixelHeight: raster.pixelHeight\n };\n}\n\nfunction rotateVector(\n vector: RasterVector,\n orientation: CaptureOrientation\n): RasterVector {\n switch (orientation) {\n case \"landscape\":\n return { x: vector.x, y: vector.y };\n case \"portrait-clockwise\":\n return { x: -vector.y, y: vector.x };\n case \"landscape-inverted\":\n return { x: -vector.x, y: -vector.y };\n case \"portrait-counter-clockwise\":\n return { x: vector.y, y: -vector.x };\n }\n}\n\nfunction inverseRotateVector(\n vector: RasterVector,\n orientation: CaptureOrientation\n): RasterVector {\n switch (orientation) {\n case \"landscape\":\n return { x: vector.x, y: vector.y };\n case \"portrait-clockwise\":\n return { x: vector.y, y: -vector.x };\n case \"landscape-inverted\":\n return { x: -vector.x, y: -vector.y };\n case \"portrait-counter-clockwise\":\n return { x: -vector.y, y: vector.x };\n }\n}\n\n/**\n * Converts a point in native pixel coordinates to oriented capture coordinates.\n * Coordinates are continuous and measured from pixel edges, so a pixel centre is at +0.5.\n */\nexport function transformNativeRasterPointToOriented(\n input: TransformRasterPointInput\n): RasterPoint {\n requireInputKeys(input, \"transformNativeRasterPointToOriented\", [\"point\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n validateRasterPoint(\"point\", input.point, input.nativeRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.point };\n case \"portrait-clockwise\":\n return { x: height - input.point.y, y: input.point.x };\n case \"landscape-inverted\":\n return { x: width - input.point.x, y: height - input.point.y };\n case \"portrait-counter-clockwise\":\n return { x: input.point.y, y: width - input.point.x };\n }\n}\n\n/** Converts a point in oriented pixel coordinates (measured from pixel edges) back to native coordinates. */\nexport function transformOrientedRasterPointToNative(\n input: TransformRasterPointInput\n): RasterPoint {\n requireInputKeys(input, \"transformOrientedRasterPointToNative\", [\"point\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n const orientedRaster = orientRaster(input.nativeRaster, input.orientation);\n validateRasterPoint(\"point\", input.point, orientedRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.point };\n case \"portrait-clockwise\":\n return { x: input.point.y, y: height - input.point.x };\n case \"landscape-inverted\":\n return { x: width - input.point.x, y: height - input.point.y };\n case \"portrait-counter-clockwise\":\n return { x: width - input.point.y, y: input.point.x };\n }\n}\n\n/** Rotates a native raster vector into oriented coordinates. */\nexport function transformNativeRasterVectorToOriented(\n input: TransformRasterVectorInput\n): RasterVector {\n requireInputKeys(input, \"transformNativeRasterVectorToOriented\", [\"vector\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"vector\", input.vector);\n return rotateVector(input.vector, input.orientation);\n}\n\n/** Rotates an oriented raster vector back into native coordinates. */\nexport function transformOrientedRasterVectorToNative(\n input: TransformRasterVectorInput\n): RasterVector {\n requireInputKeys(input, \"transformOrientedRasterVectorToNative\", [\"vector\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"vector\", input.vector);\n return inverseRotateVector(input.vector, input.orientation);\n}\n\n/**\n * Maps normalized (0–1) coordinates in an oriented physical image region to the\n * optical image plane used by the lens-field and camera-mapping APIs, before\n * camera orientation.\n *\n * The input bounds are after camera orientation and use +Y down. The returned\n * point has its origin on the optical axis, with +X right and +Y up. No lens or\n * projection equation is applied.\n */\nexport function mapOrientedPhysicalUvToImagePlanePoint(\n input: MapOrientedPhysicalUvToImagePlaneInput\n): ImagePlaneMetricPointMm {\n requireInputKeys(input, \"mapOrientedPhysicalUvToImagePlanePoint\", [\"uv\", \"orientedPhysicalBoundsFromOpticalAxisMm\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateNormalizedUv(\"uv\", input.uv);\n validatePhysicalBounds(\n \"orientedPhysicalBoundsFromOpticalAxisMm\",\n input.orientedPhysicalBoundsFromOpticalAxisMm\n );\n\n const bounds = input.orientedPhysicalBoundsFromOpticalAxisMm;\n const orientedPhysicalPoint = {\n x: bounds.left + input.uv.u * (bounds.right - bounds.left),\n y: bounds.top + input.uv.v * (bounds.bottom - bounds.top)\n };\n const nativePhysicalPoint = inverseRotateVector(\n orientedPhysicalPoint,\n input.orientation\n );\n\n return {\n x: nativePhysicalPoint.x,\n y: -nativePhysicalPoint.y\n };\n}\n\n/**\n * Maps an optical image-plane point (before camera orientation) to normalized\n * coordinates in an oriented physical image region.\n *\n * This is the exact inverse of mapOrientedPhysicalUvToImagePlanePoint(). A point\n * outside the region is rejected. A tiny tolerance only absorbs floating-point\n * round-trip error at an edge.\n */\nexport function mapImagePlanePointToOrientedPhysicalUv(\n input: MapImagePlanePointToOrientedPhysicalUvInput\n): NormalizedRasterUv {\n requireInputKeys(input, \"mapImagePlanePointToOrientedPhysicalUv\", [\"imagePlanePointMm\", \"orientedPhysicalBoundsFromOpticalAxisMm\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n validateRasterVector(\"imagePlanePointMm\", input.imagePlanePointMm);\n validatePhysicalBounds(\n \"orientedPhysicalBoundsFromOpticalAxisMm\",\n input.orientedPhysicalBoundsFromOpticalAxisMm\n );\n\n const bounds = input.orientedPhysicalBoundsFromOpticalAxisMm;\n const nativePhysicalPoint = {\n x: input.imagePlanePointMm.x,\n y: -input.imagePlanePointMm.y\n };\n const orientedPhysicalPoint = rotateVector(\n nativePhysicalPoint,\n input.orientation\n );\n return {\n u: normalizePhysicalCoordinateToUv(\n \"imagePlanePointMm.x\",\n orientedPhysicalPoint.x,\n bounds.left,\n bounds.right\n ),\n v: normalizePhysicalCoordinateToUv(\n \"imagePlanePointMm.y\",\n orientedPhysicalPoint.y,\n bounds.top,\n bounds.bottom\n )\n };\n}\n\n/** Transforms an integer half-open native raster rectangle into oriented coordinates. */\nexport function transformNativeRasterRectToOriented(\n input: TransformRasterRectInput\n): RasterRect {\n requireInputKeys(input, \"transformNativeRasterRectToOriented\", [\"rect\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n validateRasterRect(\"rect\", input.rect, input.nativeRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n const { x, y, width: rectWidth, height: rectHeight } = input.rect;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.rect };\n case \"portrait-clockwise\":\n return {\n x: height - (y + rectHeight),\n y: x,\n width: rectHeight,\n height: rectWidth\n };\n case \"landscape-inverted\":\n return {\n x: width - (x + rectWidth),\n y: height - (y + rectHeight),\n width: rectWidth,\n height: rectHeight\n };\n case \"portrait-counter-clockwise\":\n return {\n x: y,\n y: width - (x + rectWidth),\n width: rectHeight,\n height: rectWidth\n };\n }\n}\n\n/** Transforms an oriented integer half-open rectangle back to native coordinates. */\nexport function transformOrientedRasterRectToNative(\n input: TransformRasterRectInput\n): RasterRect {\n requireInputKeys(input, \"transformOrientedRasterRectToNative\", [\"rect\", \"nativeRaster\", \"orientation\"]);\n requireCaptureOrientation(input.orientation);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n const orientedRaster = orientRaster(input.nativeRaster, input.orientation);\n validateRasterRect(\"rect\", input.rect, orientedRaster);\n\n const { pixelWidth: width, pixelHeight: height } = input.nativeRaster;\n const { x, y, width: rectWidth, height: rectHeight } = input.rect;\n switch (input.orientation) {\n case \"landscape\":\n return { ...input.rect };\n case \"portrait-clockwise\":\n return {\n x: y,\n y: height - (x + rectWidth),\n width: rectHeight,\n height: rectWidth\n };\n case \"landscape-inverted\":\n return {\n x: width - (x + rectWidth),\n y: height - (y + rectHeight),\n width: rectWidth,\n height: rectHeight\n };\n case \"portrait-counter-clockwise\":\n return {\n x: width - (y + rectHeight),\n y: x,\n width: rectHeight,\n height: rectWidth\n };\n }\n}\n\nfunction nativePhysicalBoundsFromRect(\n imagingArea: SensorImagingArea,\n nativeRaster: NativeImageRaster,\n rect: RasterRect\n): PhysicalBoundsFromOpticalAxisMm {\n const pitchX = imagingArea.widthMm / nativeRaster.pixelWidth;\n const pitchY = imagingArea.heightMm / nativeRaster.pixelHeight;\n\n return {\n left: rect.x * pitchX - imagingArea.widthMm / 2,\n right:\n (rect.x + rect.width) * pitchX - imagingArea.widthMm / 2,\n top: rect.y * pitchY - imagingArea.heightMm / 2,\n bottom:\n (rect.y + rect.height) * pitchY - imagingArea.heightMm / 2\n };\n}\n\nfunction orientPhysicalBounds(\n bounds: PhysicalBoundsFromOpticalAxisMm,\n orientation: CaptureOrientation\n): PhysicalBoundsFromOpticalAxisMm {\n const corners = [\n { x: bounds.left, y: bounds.top },\n { x: bounds.right, y: bounds.top },\n { x: bounds.right, y: bounds.bottom },\n { x: bounds.left, y: bounds.bottom }\n ].map((corner) => rotateVector(corner, orientation));\n\n return {\n left: Math.min(...corners.map((corner) => corner.x)),\n right: Math.max(...corners.map((corner) => corner.x)),\n top: Math.min(...corners.map((corner) => corner.y)),\n bottom: Math.max(...corners.map((corner) => corner.y))\n };\n}\n\nfunction physicalBoundsFromRectWithinBounds(\n sourceBounds: PhysicalBoundsFromOpticalAxisMm,\n sourceRaster: RasterDimensions,\n rect: RasterRect\n): PhysicalBoundsFromOpticalAxisMm {\n const pitchX =\n (sourceBounds.right - sourceBounds.left) / sourceRaster.pixelWidth;\n const pitchY =\n (sourceBounds.bottom - sourceBounds.top) / sourceRaster.pixelHeight;\n\n return {\n left: sourceBounds.left + rect.x * pitchX,\n right: sourceBounds.left + (rect.x + rect.width) * pitchX,\n top: sourceBounds.top + rect.y * pitchY,\n bottom: sourceBounds.top + (rect.y + rect.height) * pitchY\n };\n}\n\nfunction validateOutputAspectRatio(\n cropRect: RasterRect,\n outputRaster: RasterDimensions\n): void {\n // Keep one scale factor for both axes. Allow only the sub-pixel mismatch that\n // comes from rounding an ideal scaled size to whole pixels. A fixed percentage\n // tolerance would allow visible stretching along one axis at large sizes.\n const widthScaleMinimum =\n (outputRaster.pixelWidth - 0.5) / cropRect.width;\n const widthScaleMaximum =\n (outputRaster.pixelWidth + 0.5) / cropRect.width;\n const heightScaleMinimum =\n (outputRaster.pixelHeight - 0.5) / cropRect.height;\n const heightScaleMaximum =\n (outputRaster.pixelHeight + 0.5) / cropRect.height;\n\n const minimumCommonScale = Math.max(\n widthScaleMinimum,\n heightScaleMinimum\n );\n const maximumCommonScale = Math.min(\n widthScaleMaximum,\n heightScaleMaximum\n );\n\n if (minimumCommonScale > maximumCommonScale) {\n throw new InvalidScientificInputError(\n \"outputRaster must preserve outputCropRect aspect ratio within nearest-integer raster rounding; implicit geometric stretching is not supported.\"\n );\n }\n}\n\nfunction angleBetweenSensorRaysDegrees(\n first: RasterVector,\n second: RasterVector,\n projectionDistanceMm: number\n): number {\n const firstLength = Math.hypot(\n first.x,\n first.y,\n projectionDistanceMm\n );\n const secondLength = Math.hypot(\n second.x,\n second.y,\n projectionDistanceMm\n );\n const dot =\n first.x * second.x +\n first.y * second.y +\n projectionDistanceMm * projectionDistanceMm;\n const cosine = Math.max(\n -1,\n Math.min(1, dot / (firstLength * secondLength))\n );\n return (Math.acos(cosine) * 180) / Math.PI;\n}\n\nfunction calculateBoundsFieldOfView(\n bounds: PhysicalBoundsFromOpticalAxisMm,\n focalLengthMm: number,\n focusDistanceM: number | undefined\n): {\n horizontalDegrees: number;\n verticalDegrees: number;\n diagonalDegrees: number;\n horizontalBoundsDegrees: { minimum: number; maximum: number };\n verticalBoundsDegrees: { minimum: number; maximum: number };\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight: number;\n topRightToBottomLeft: number;\n };\n projection: {\n projectionDistanceMm: number;\n provenance: CalculationProvenance;\n };\n} {\n const fovInput = {\n focalLengthMm,\n ...(focusDistanceM === undefined ? {} : { focusDistanceM })\n };\n const horizontal = calculateFieldOfViewBounds({\n ...fovInput,\n minimumSensorCoordinateMm: bounds.left,\n maximumSensorCoordinateMm: bounds.right\n });\n const vertical = calculateFieldOfViewBounds({\n ...fovInput,\n minimumSensorCoordinateMm: bounds.top,\n maximumSensorCoordinateMm: bounds.bottom\n });\n const projectionDistanceMm = horizontal.value.projectionDistanceMm;\n const topLeft = { x: bounds.left, y: bounds.top };\n const topRight = { x: bounds.right, y: bounds.top };\n const bottomRight = { x: bounds.right, y: bounds.bottom };\n const bottomLeft = { x: bounds.left, y: bounds.bottom };\n const topLeftToBottomRight = angleBetweenSensorRaysDegrees(\n topLeft,\n bottomRight,\n projectionDistanceMm\n );\n const topRightToBottomLeft = angleBetweenSensorRaysDegrees(\n topRight,\n bottomLeft,\n projectionDistanceMm\n );\n\n return {\n horizontalDegrees: horizontal.value.degrees,\n verticalDegrees: vertical.value.degrees,\n diagonalDegrees: Math.max(\n topLeftToBottomRight,\n topRightToBottomLeft\n ),\n horizontalBoundsDegrees: {\n minimum: horizontal.value.minimumDegrees,\n maximum: horizontal.value.maximumDegrees\n },\n verticalBoundsDegrees: {\n minimum: vertical.value.minimumDegrees,\n maximum: vertical.value.maximumDegrees\n },\n diagonalDegreesByCornerPair: {\n topLeftToBottomRight,\n topRightToBottomLeft\n },\n projection: {\n projectionDistanceMm,\n provenance: horizontal.provenance\n }\n };\n}\n\n/**\n * Resolves native sensor geometry, active capture area, physical camera orientation\n * and final digital (output) geometry, keeping each one distinct.\n */\nexport function resolveCaptureGeometry(\n input: ResolveCaptureGeometryInput\n): CalculationResult<ResolvedCaptureGeometry> {\n requireInputKeys(input, \"resolveCaptureGeometry\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"outputCropRect\", \"outputRaster\"]);\n requireCaptureOrientation(input.orientation);\n requireInputObject(input.imagingArea, \"imagingArea\");\n requirePositiveFinite(\"imagingArea.widthMm\", input.imagingArea.widthMm);\n requirePositiveFinite(\"imagingArea.heightMm\", input.imagingArea.heightMm);\n requireRasterDimensions(\"nativeRaster\", input.nativeRaster);\n\n const activeCaptureRect =\n input.activeCaptureRect ?? fullRect(input.nativeRaster);\n validateRasterRect(\n \"activeCaptureRect\",\n activeCaptureRect,\n input.nativeRaster\n );\n\n const nativeBounds = nativePhysicalBoundsFromRect(\n input.imagingArea,\n input.nativeRaster,\n activeCaptureRect\n );\n const activeImagingArea: SensorImagingArea = {\n widthMm: nativeBounds.right - nativeBounds.left,\n heightMm: nativeBounds.bottom - nativeBounds.top\n };\n const activeRaster: RasterDimensions = {\n pixelWidth: activeCaptureRect.width,\n pixelHeight: activeCaptureRect.height\n };\n const orientedBounds = orientPhysicalBounds(\n nativeBounds,\n input.orientation\n );\n const orientedRaster = orientRaster(activeRaster, input.orientation);\n const orientedImagingArea: SensorImagingArea = {\n widthMm: orientedBounds.right - orientedBounds.left,\n heightMm: orientedBounds.bottom - orientedBounds.top\n };\n\n const outputCropRect =\n input.outputCropRect ?? fullRect(orientedRaster);\n validateRasterRect(\n \"outputCropRect\",\n outputCropRect,\n orientedRaster\n );\n\n const outputRaster: RasterDimensions = input.outputRaster ?? {\n pixelWidth: outputCropRect.width,\n pixelHeight: outputCropRect.height\n };\n requireRasterDimensions(\"outputRaster\", outputRaster);\n validateOutputAspectRatio(outputCropRect, outputRaster);\n\n const outputBounds = physicalBoundsFromRectWithinBounds(\n orientedBounds,\n orientedRaster,\n outputCropRect\n );\n const outputImagingArea: SensorImagingArea = {\n widthMm: outputBounds.right - outputBounds.left,\n heightMm: outputBounds.bottom - outputBounds.top\n };\n const outputScaleX = outputRaster.pixelWidth / outputCropRect.width;\n const outputScaleY = outputRaster.pixelHeight / outputCropRect.height;\n const outputScaleAxisRelativeDifference =\n Math.abs(outputScaleX - outputScaleY) /\n ((outputScaleX + outputScaleY) / 2);\n\n return calculatedResult(\n {\n native: {\n imagingArea: { ...input.imagingArea },\n raster: { ...input.nativeRaster }\n },\n activeCapture: {\n nativeRect: { ...activeCaptureRect },\n imagingArea: activeImagingArea,\n physicalOffsetMm: {\n x: nativeBounds.left + input.imagingArea.widthMm / 2,\n y: nativeBounds.top + input.imagingArea.heightMm / 2\n },\n centerOffsetFromOpticalAxisMm: {\n x: (nativeBounds.left + nativeBounds.right) / 2,\n y: (nativeBounds.top + nativeBounds.bottom) / 2\n },\n physicalBoundsFromOpticalAxisMm: nativeBounds,\n imagingAreaDerivation: \"uniform-native-raster\",\n raster: activeRaster\n },\n orientedCapture: {\n orientation: input.orientation,\n imagingArea: orientedImagingArea,\n physicalBoundsFromOpticalAxisMm: orientedBounds,\n raster: orientedRaster\n },\n output: {\n cropRect: { ...outputCropRect },\n raster: { ...outputRaster },\n imagingArea: outputImagingArea,\n physicalBoundsFromOpticalAxisMm: outputBounds,\n centerOffsetFromOpticalAxisMm: {\n x: (outputBounds.left + outputBounds.right) / 2,\n y: (outputBounds.top + outputBounds.bottom) / 2\n },\n sourceRetainedAreaFraction:\n (outputCropRect.width * outputCropRect.height) /\n (orientedRaster.pixelWidth * orientedRaster.pixelHeight),\n orientedCaptureToOutputScale: {\n x: outputScaleX,\n y: outputScaleY,\n axisRelativeDifference: outputScaleAxisRelativeDifference\n }\n }\n },\n \"capture-geometry-pipeline\",\n \"1.2.0\",\n [\n \"Native sensor raster coordinates use a top-left origin with +X right and +Y down.\",\n \"Raster rectangles are integer half-open extents.\",\n \"Physical camera orientation does not rotate or redefine the native sensor coordinate system.\",\n \"The generic active physical area is derived by assuming native image samples uniformly span the declared physical imaging area.\",\n \"Output crop/resampling is digital geometry and does not mutate physical sensor or active-capture identity.\",\n \"The physical image region retained by output crop is tracked explicitly for final framing and equivalent-viewing calculations.\",\n \"Output raster aspect ratio must remain consistent with the output crop; implicit geometric stretching is rejected.\"\n ]\n );\n}\n\n/**\n * Calculates the field of view (FOV) of the active physical capture area after\n * camera orientation. Horizontal and vertical FOV can be asymmetric about the\n * optical axis; both corner-to-corner diagonals are reported.\n *\n * The final digital (output) crop is deliberately not included.\n */\nexport function calculateActiveCaptureFieldOfView(\n input: CalculateActiveCaptureFieldOfViewInput\n): CalculationResult<ActiveCaptureFieldOfView> {\n requireInputKeys(input, \"calculateActiveCaptureFieldOfView\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"focalLengthMm\", \"focusDistanceM\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n\n const geometry = resolveCaptureGeometry({\n imagingArea: input.imagingArea,\n nativeRaster: input.nativeRaster,\n orientation: input.orientation,\n ...(input.activeCaptureRect === undefined\n ? {}\n : { activeCaptureRect: input.activeCaptureRect })\n }).value;\n\n const bounds =\n geometry.orientedCapture.physicalBoundsFromOpticalAxisMm;\n const fieldOfView = calculateBoundsFieldOfView(\n bounds,\n input.focalLengthMm,\n input.focusDistanceM\n );\n\n return calculatedResult(\n {\n orientation: input.orientation,\n ...fieldOfView,\n activeImagingArea: {\n ...geometry.orientedCapture.imagingArea\n },\n centerOffsetFromOpticalAxisMm: rotateVector(\n geometry.activeCapture.centerOffsetFromOpticalAxisMm,\n input.orientation\n )\n },\n \"oriented-active-capture-field-of-view\",\n \"1.1.0\",\n [\n \"Rectilinear projection is evaluated from signed active-area bounds relative to the optical axis.\",\n \"Off-center active crops preserve asymmetric angular bounds rather than being treated as centered.\",\n \"Camera orientation rotates physical bounds while leaving the native sensor coordinate system unchanged.\",\n \"For off-center rectangles the two opposite-corner diagonal spans may differ; diagonalDegrees reports the larger span.\",\n \"Final digital/output crop is excluded from active-capture FOV.\"\n ]\n );\n}\n\n/**\n * Calculates the final visible field of view after the active capture area,\n * orientation and digital (output) crop. Output resolution does not affect it.\n */\nexport function calculateOutputFieldOfView(\n input: CalculateOutputFieldOfViewInput\n): CalculationResult<OutputFieldOfView> {\n requireInputKeys(input, \"calculateOutputFieldOfView\", [\"imagingArea\", \"nativeRaster\", \"orientation\", \"activeCaptureRect\", \"outputCropRect\", \"focalLengthMm\", \"focusDistanceM\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n\n const geometry = resolveCaptureGeometry({\n imagingArea: input.imagingArea,\n nativeRaster: input.nativeRaster,\n orientation: input.orientation,\n ...(input.activeCaptureRect === undefined\n ? {}\n : { activeCaptureRect: input.activeCaptureRect }),\n ...(input.outputCropRect === undefined\n ? {}\n : { outputCropRect: input.outputCropRect })\n }).value;\n const fieldOfView = calculateBoundsFieldOfView(\n geometry.output.physicalBoundsFromOpticalAxisMm,\n input.focalLengthMm,\n input.focusDistanceM\n );\n\n return calculatedResult(\n {\n orientation: input.orientation,\n ...fieldOfView,\n outputImagingArea: { ...geometry.output.imagingArea },\n centerOffsetFromOpticalAxisMm: {\n ...geometry.output.centerOffsetFromOpticalAxisMm\n }\n },\n \"oriented-output-field-of-view\",\n \"1.0.0\",\n [\n \"Final visible FOV is derived from the physical image region retained by active capture and digital/output crop.\",\n \"Output raster resolution does not change field of view.\",\n \"Off-center output crops preserve asymmetric angular bounds.\",\n \"Physical sensor identity and active-capture 35 mm-equivalent focal length are unchanged by final digital crop.\"\n ]\n );\n}\n\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much to crop an image from a shorter lens so it matches a longer lens's framing, and the
|
|
3
|
+
* pixels that leaves.
|
|
4
|
+
*
|
|
5
|
+
* For an ideal rectilinear lens focused at infinity, a scene point at field angle θ images at
|
|
6
|
+
* height y' = f·tan θ (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
|
+
* From the same camera position the image of focal length F is the image of f scaled by F/f, so a
|
|
9
|
+
* centred crop by the linear factor F/f gives the same framing and the same perspective: exact at
|
|
10
|
+
* infinity focus, to whole pixels.
|
|
11
|
+
*
|
|
12
|
+
* At close focus the thin-lens magnification is m = f/(d − f) for an object distance d from the
|
|
13
|
+
* lens, so at the same d the factor is F·(d − f)/(f·(d − F)), larger than F/f and tending to it when
|
|
14
|
+
* d is much greater than F. That correction, distortion and focus breathing are not modelled.
|
|
15
|
+
* @see docs/PHYSICS_FOUNDATION.md "Crop to match a longer focal length".
|
|
16
|
+
*/
|
|
17
|
+
import { type CalculationResult } from "../core/calculation-result.js";
|
|
18
|
+
export interface CalculateCropToMatchFocalLengthInput {
|
|
19
|
+
/** Focal length the image was taken with, in millimetres. */
|
|
20
|
+
focalLengthMm: number;
|
|
21
|
+
/** Longer focal length whose framing the crop should match, in millimetres. At least `focalLengthMm`. */
|
|
22
|
+
targetFocalLengthMm: number;
|
|
23
|
+
/** Image width in pixels (for example the sensor's output width). */
|
|
24
|
+
pixelWidth: number;
|
|
25
|
+
/** Image height in pixels. */
|
|
26
|
+
pixelHeight: number;
|
|
27
|
+
}
|
|
28
|
+
export interface CropToMatchFocalLength {
|
|
29
|
+
/** Focal length supplied by the caller, in millimetres. */
|
|
30
|
+
focalLengthMm: number;
|
|
31
|
+
/** Target focal length supplied by the caller, in millimetres. */
|
|
32
|
+
targetFocalLengthMm: number;
|
|
33
|
+
/** Linear crop factor targetFocalLengthMm / focalLengthMm (1 means no crop). */
|
|
34
|
+
cropFactor: number;
|
|
35
|
+
/** Width left after the centred crop, in pixels (as `calculateCenteredCrop`). */
|
|
36
|
+
pixelWidth: number;
|
|
37
|
+
/** Height left after the centred crop, in pixels. */
|
|
38
|
+
pixelHeight: number;
|
|
39
|
+
/** Pixels left, in millions. */
|
|
40
|
+
megapixels: number;
|
|
41
|
+
/** Megapixels of the uncropped image. */
|
|
42
|
+
sourceMegapixels: number;
|
|
43
|
+
/** Fraction of the original pixel area retained, about 1 / cropFactor². */
|
|
44
|
+
retainedAreaFraction: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The centred crop that makes an image from a shorter lens match a longer lens's framing from the
|
|
48
|
+
* same position: crop factor target ÷ focal length, and the pixels and megapixels left.
|
|
49
|
+
*
|
|
50
|
+
* Exact for ideal rectilinear lenses focused at infinity, to whole pixels (the crop is
|
|
51
|
+
* `calculateCenteredCrop`'s, which keeps the aspect ratio). At close focus the matching factor is
|
|
52
|
+
* larger, F·(d − f)/(f·(d − F)) at object distance d (thin lens); that, distortion and focus
|
|
53
|
+
* breathing are not modelled. The crop has the longer lens's framing and perspective but fewer
|
|
54
|
+
* pixels: it records no more detail than the cropped part of the shorter lens's image.
|
|
55
|
+
*
|
|
56
|
+
* Example: a 24 MP (6000 × 4000) image at 50 mm cropped to match 100 mm: factor 2, 3000 × 2000,
|
|
57
|
+
* 6 MP.
|
|
58
|
+
*
|
|
59
|
+
* @param input Focal length, longer target focal length and the image's pixel dimensions.
|
|
60
|
+
* @returns Crop factor and the remaining pixel dimensions.
|
|
61
|
+
*/
|
|
62
|
+
export declare function calculateCropToMatchFocalLength(input: CalculateCropToMatchFocalLengthInput): CalculationResult<CropToMatchFocalLength>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* How much to crop an image from a shorter lens so it matches a longer lens's framing, and the
|
|
4
|
+
* pixels that leaves.
|
|
5
|
+
*
|
|
6
|
+
* For an ideal rectilinear lens focused at infinity, a scene point at field angle θ images at
|
|
7
|
+
* height y' = f·tan θ (Greivenkamp, OPTI-502 course notes, sec. 12 (Objectives), free:
|
|
8
|
+
* https://wp.optics.arizona.edu/jgreivenkamp/wp-content/uploads/sites/11/2019/08/502-12-Objectives.pdf).
|
|
9
|
+
* From the same camera position the image of focal length F is the image of f scaled by F/f, so a
|
|
10
|
+
* centred crop by the linear factor F/f gives the same framing and the same perspective: exact at
|
|
11
|
+
* infinity focus, to whole pixels.
|
|
12
|
+
*
|
|
13
|
+
* At close focus the thin-lens magnification is m = f/(d − f) for an object distance d from the
|
|
14
|
+
* lens, so at the same d the factor is F·(d − f)/(f·(d − F)), larger than F/f and tending to it when
|
|
15
|
+
* d is much greater than F. That correction, distortion and focus breathing are not modelled.
|
|
16
|
+
* @see docs/PHYSICS_FOUNDATION.md "Crop to match a longer focal length".
|
|
17
|
+
*/
|
|
18
|
+
import { calculatedResult } from "../core/calculation-result.js";
|
|
19
|
+
import { requireInputKeys } from "../core/record-validation.js";
|
|
20
|
+
import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
|
|
21
|
+
import { calculateCenteredCrop } from "./crop.js";
|
|
22
|
+
/**
|
|
23
|
+
* The centred crop that makes an image from a shorter lens match a longer lens's framing from the
|
|
24
|
+
* same position: crop factor target ÷ focal length, and the pixels and megapixels left.
|
|
25
|
+
*
|
|
26
|
+
* Exact for ideal rectilinear lenses focused at infinity, to whole pixels (the crop is
|
|
27
|
+
* `calculateCenteredCrop`'s, which keeps the aspect ratio). At close focus the matching factor is
|
|
28
|
+
* larger, F·(d − f)/(f·(d − F)) at object distance d (thin lens); that, distortion and focus
|
|
29
|
+
* breathing are not modelled. The crop has the longer lens's framing and perspective but fewer
|
|
30
|
+
* pixels: it records no more detail than the cropped part of the shorter lens's image.
|
|
31
|
+
*
|
|
32
|
+
* Example: a 24 MP (6000 × 4000) image at 50 mm cropped to match 100 mm: factor 2, 3000 × 2000,
|
|
33
|
+
* 6 MP.
|
|
34
|
+
*
|
|
35
|
+
* @param input Focal length, longer target focal length and the image's pixel dimensions.
|
|
36
|
+
* @returns Crop factor and the remaining pixel dimensions.
|
|
37
|
+
*/
|
|
38
|
+
export function calculateCropToMatchFocalLength(input) {
|
|
39
|
+
requireInputKeys(input, "calculateCropToMatchFocalLength", ["focalLengthMm", "targetFocalLengthMm", "pixelWidth", "pixelHeight"]);
|
|
40
|
+
requirePositiveFinite("focalLengthMm", input.focalLengthMm);
|
|
41
|
+
requirePositiveFinite("targetFocalLengthMm", input.targetFocalLengthMm);
|
|
42
|
+
if (input.targetFocalLengthMm < input.focalLengthMm) {
|
|
43
|
+
throw new InvalidScientificInputError("targetFocalLengthMm must be greater than or equal to focalLengthMm: a crop cannot widen the framing.");
|
|
44
|
+
}
|
|
45
|
+
const cropFactor = input.targetFocalLengthMm / input.focalLengthMm;
|
|
46
|
+
const crop = calculateCenteredCrop({ pixelWidth: input.pixelWidth, pixelHeight: input.pixelHeight, cropFactor }).value;
|
|
47
|
+
return calculatedResult({
|
|
48
|
+
focalLengthMm: input.focalLengthMm,
|
|
49
|
+
targetFocalLengthMm: input.targetFocalLengthMm,
|
|
50
|
+
cropFactor,
|
|
51
|
+
pixelWidth: crop.pixelWidth,
|
|
52
|
+
pixelHeight: crop.pixelHeight,
|
|
53
|
+
megapixels: crop.megapixels,
|
|
54
|
+
sourceMegapixels: (input.pixelWidth * input.pixelHeight) / 1_000_000,
|
|
55
|
+
retainedAreaFraction: crop.retainedAreaFraction
|
|
56
|
+
}, "crop-to-match-focal-length", "1.0.0", [
|
|
57
|
+
"Crop factor = target focal length / focal length: exact for ideal rectilinear lenses focused at infinity, from the same camera position.",
|
|
58
|
+
"At close focus the thin-lens matching factor is F·(d − f)/(f·(d − F)) at object distance d, larger than F/f; not modelled.",
|
|
59
|
+
"Distortion and focus breathing are not modelled.",
|
|
60
|
+
"Centred crop that keeps the aspect ratio to whole pixels (calculateCenteredCrop)."
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=crop-to-match-focal-length.js.map
|